kdelibs/kdeui/kernel/kstyle.cpp

4484 lines
182 KiB
C++
Raw Normal View History

2014-11-13 01:04:59 +02:00
/**
* KStyle for KDE4
* Copyright (C) 2004-2005 Maksim Orlovich <maksim@kde.org>
* Copyright (C) 2005,2006 Sandro Giessl <giessl@kde.org>
*
* Based in part on the following software:
* KStyle for KDE3
* Copyright (C) 2001-2002 Karol Szwed <gallium@kde.org>
* Portions (C) 1998-2000 TrollTech AS
* Keramik for KDE3,
* Copyright (C) 2002 Malte Starostik <malte@kde.org>
* (C) 2002-2003 Maksim Orlovich <maksim@kde.org>
* Portions (C) 2001-2002 Karol Szwed <gallium@kde.org>
* (C) 2001-2002 Fredrik Höglund <fredrik@kde.org>
* (C) 2000 Daniel M. Duley <mosfet@kde.org>
* (C) 2000 Dirk Mueller <mueller@kde.org>
* (C) 2001 Martijn Klingens <klingens@kde.org>
* (C) 2003 Sandro Giessl <sandro@giessl.com>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* Many thanks to Bradley T. Hughes for the 3 button scrollbar code.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "kstyle.h"
#include "moc_kstyle.cpp"
2014-11-13 01:04:59 +02:00
#include <QtCore/qalgorithms.h>
#include <QtCore/QCache>
#include <QtCore/QEvent>
#include <QtCore/QVariant>
#include <QtGui/QAbstractItemView>
#include <QtGui/QApplication>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QFormLayout>
#include <QtGui/QIcon>
#include <QtGui/QLabel>
#include <QtGui/QKeyEvent>
#include <QtGui/QPainter>
#include <QtGui/QScrollBar>
#include <QtGui/QStyleOption>
#include <kcomponentdata.h>
#include <kglobal.h>
#include <kconfiggroup.h>
#include <kdebug.h>
#include <kicon.h>
#include <kiconloader.h>
#include "kglobalsettings.h"
//### FIXME: Who to credit these to?
static const qint32 u_arrow[]={-1,-3, 0,-3, -2,-2, 1,-2, -3,-1, 2,-1, -4,0, 3,0, -4,1, 3,1};
static const qint32 d_arrow[]={-4,-2, 3,-2, -4,-1, 3,-1, -3,0, 2,0, -2,1, 1,1, -1,2, 0,2};
static const qint32 l_arrow[]={-3,-1, -3,0, -2,-2, -2,1, -1,-3, -1,2, 0,-4, 0,3, 1,-4, 1,3};
static const qint32 r_arrow[]={-2,-4, -2,3, -1,-4, -1,3, 0,-3, 0,2, 1,-2, 1,1, 2,-1, 2,0};
#define QCOORDARRLEN(x) sizeof(x)/(sizeof(qint32)*2)
/**
TODO: lots of missing widgets, SH_ settings, etc.
Minor stuff:
ProgressBar::Precision handling
*/
// ----------------------------------------------------------------------------
// For item view selections
struct SelectionTiles
{
QPixmap left, center, right;
};
// ----------------------------------------------------------------------------
static const QStyle::StyleHint SH_KCustomStyleElement = (QStyle::StyleHint)0xff000001;
static const int X_KdeBase = 0xff000000;
class KStylePrivate
{
public:
KStylePrivate();
QCache<quint64, SelectionTiles> selectionCache;
KComponentData m_componentData;
QHash<QString, int> styleElements;
int hintCounter, controlCounter, subElementCounter;
};
KStylePrivate::KStylePrivate() : m_componentData()
{
if(KGlobal::hasMainComponent())
{
m_componentData = KGlobal::mainComponent();
} else
{
QString name(QApplication::applicationName());
if(name.isEmpty())
name=qAppName();
if(name.isEmpty())
name="KStyle";
m_componentData = KComponentData(name.toLatin1(), name.toLatin1(), KComponentData::SkipMainComponentRegistration);
}
selectionCache.setMaxCost(10);
controlCounter = subElementCounter = X_KdeBase;
hintCounter = X_KdeBase+1; //sic! X_KdeBase is covered by SH_KCustomStyleElement
}
// ----------------------------------------------------------------------------
KStyle::KStyle() : clickedLabel(0), d(new KStylePrivate)
{
//Set up some default metrics...
setWidgetLayoutProp(WT_Generic, Generic::DefaultFrameWidth, 2);
setWidgetLayoutProp(WT_Generic, Generic::DefaultLayoutSpacing, 6);
setWidgetLayoutProp(WT_Generic, Generic::DefaultLayoutMargin, 9);
setWidgetLayoutProp(WT_PushButton, PushButton::ContentsMargin, 5);
setWidgetLayoutProp(WT_PushButton, PushButton::FocusMargin, 3);
setWidgetLayoutProp(WT_PushButton, PushButton::PressedShiftHorizontal, 2);
setWidgetLayoutProp(WT_PushButton, PushButton::PressedShiftVertical, 2);
setWidgetLayoutProp(WT_PushButton, PushButton::MenuIndicatorSize, 8);
setWidgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, 6);
setWidgetLayoutProp(WT_Splitter, Splitter::Width, 6); //As KStyle in KDE3
setWidgetLayoutProp(WT_CheckBox, CheckBox::Size, 16);
setWidgetLayoutProp(WT_CheckBox, CheckBox::BoxTextSpace, 6);
setWidgetLayoutProp(WT_CheckBox, CheckBox::NoLabelFocusMargin, 1);
setWidgetLayoutProp(WT_RadioButton, RadioButton::Size, 16);
setWidgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, 6);
setWidgetLayoutProp(WT_DockWidget, DockWidget::TitleTextColor,
ColorMode(QPalette::HighlightedText));
setWidgetLayoutProp(WT_DockWidget, DockWidget::TitleMargin, 2);
setWidgetLayoutProp(WT_DockWidget, DockWidget::FrameWidth, 3);
setWidgetLayoutProp(WT_DockWidget, DockWidget::SeparatorExtent, 6);
setWidgetLayoutProp(WT_ProgressBar, ProgressBar::GrooveMargin, 2);
setWidgetLayoutProp(WT_ProgressBar, ProgressBar::SideTextSpace, 3); //(Matches QCommonStyle)
setWidgetLayoutProp(WT_ProgressBar, ProgressBar::MaxBusyIndicatorSize, 10000);
setWidgetLayoutProp(WT_ProgressBar, ProgressBar::BusyIndicatorSize, 10);
setWidgetLayoutProp(WT_ProgressBar, ProgressBar::Precision, 1);
setWidgetLayoutProp(WT_MenuBar, MenuBar::ItemSpacing, 14);
setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin, 2);
setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin + Left, 4);
setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin + Right, 4);
setWidgetLayoutProp(WT_MenuBarItem, MenuBarItem::Margin, 1);
setWidgetLayoutProp(WT_Menu, Menu::FrameWidth, 1);
setWidgetLayoutProp(WT_Menu, Menu::Margin, 3);
setWidgetLayoutProp(WT_Menu, Menu::ScrollerHeight, 10);
setWidgetLayoutProp(WT_Menu, Menu::TearOffHeight, 10);
setWidgetLayoutProp(WT_MenuItem, MenuItem::CheckWidth, 12);
setWidgetLayoutProp(WT_MenuItem, MenuItem::CheckSpace, 3);
setWidgetLayoutProp(WT_MenuItem, MenuItem::IconWidth, 12);
setWidgetLayoutProp(WT_MenuItem, MenuItem::IconSpace, 3);
setWidgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, 11);
setWidgetLayoutProp(WT_MenuItem, MenuItem::ArrowSpace, 3);
setWidgetLayoutProp(WT_MenuItem, MenuItem::Margin, 2);
setWidgetLayoutProp(WT_MenuItem, MenuItem::SeparatorHeight, 0); //the margins give enough rooms
setWidgetLayoutProp(WT_MenuItem, MenuItem::MinHeight, 16);
setWidgetLayoutProp(WT_MenuItem, MenuItem::TextColor, ColorMode(QPalette::Text));
setWidgetLayoutProp(WT_MenuItem, MenuItem::ActiveTextColor, ColorMode(QPalette::HighlightedText));
setWidgetLayoutProp(WT_MenuItem, MenuItem::DisabledTextColor, ColorMode(QPalette::Text));
setWidgetLayoutProp(WT_MenuItem, MenuItem::ActiveDisabledTextColor, ColorMode(QPalette::Text));
setWidgetLayoutProp(WT_MenuItem, MenuItem::AccelSpace, 16);
//KDE default is single top button, double bottom one
setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, 0);
setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, 1);
setWidgetLayoutProp(WT_ScrollBar, ScrollBar::SingleButtonHeight, 16);
setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleButtonHeight, 32);
setWidgetLayoutProp(WT_ScrollBar, ScrollBar::BarWidth, 16);
setWidgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor,
ColorMode(ColorMode::BWAutoContrastMode, QPalette::Button));
setWidgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor,
ColorMode(ColorMode::BWAutoContrastMode, QPalette::ButtonText));
setWidgetLayoutProp(WT_TabBar, TabBar::TabContentsMargin, 6);
setWidgetLayoutProp(WT_TabBar, TabBar::TabFocusMargin, 3);
setWidgetLayoutProp(WT_TabBar, TabBar::TabOverlap, 0);
setWidgetLayoutProp(WT_TabBar, TabBar::BaseHeight, 2);
setWidgetLayoutProp(WT_TabBar, TabBar::BaseOverlap, 2);
setWidgetLayoutProp(WT_TabBar, TabBar::ScrollButtonWidth, 10);
setWidgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, 6);
setWidgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin, 2);
setWidgetLayoutProp(WT_Tree, Tree::MaxExpanderSize, 9);
setWidgetLayoutProp(WT_Slider, Slider::HandleThickness, 20);
setWidgetLayoutProp(WT_Slider, Slider::HandleLength, 16);
setWidgetLayoutProp(WT_SpinBox, SpinBox::FrameWidth, 1);
setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonWidth, 16);
setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonSpacing, 1);
setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin+Right, 1);
setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin+Top, 1);
setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin+Bot, 1);
setWidgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, 1);
setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonWidth, 16);
setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin+Right, 1);
setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin+Top, 1);
setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin+Bot, 1);
setWidgetLayoutProp(WT_ComboBox, ComboBox::FocusMargin, 1);
setWidgetLayoutProp(WT_Header, Header::ContentsMargin, 3);
setWidgetLayoutProp(WT_Header, Header::TextToIconSpace, 3);
setWidgetLayoutProp(WT_Header, Header::MarkSize, 9);
setWidgetLayoutProp(WT_GroupBox, GroupBox::FrameWidth, 2);
setWidgetLayoutProp(WT_GroupBox, GroupBox::TextAlignTop, false);
setWidgetLayoutProp(WT_GroupBox, GroupBox::TitleTextColor, ColorMode(QPalette::Text));
setWidgetLayoutProp(WT_ToolBar, ToolBar::HandleExtent, 6);
setWidgetLayoutProp(WT_ToolBar, ToolBar::SeparatorExtent, 6);
setWidgetLayoutProp(WT_ToolBar, ToolBar::ExtensionExtent, 10);
setWidgetLayoutProp(WT_ToolBar, ToolBar::FrameWidth, 2);
setWidgetLayoutProp(WT_ToolBar, ToolBar::ItemSpacing, 3);
setWidgetLayoutProp(WT_ToolBar, ToolBar::ItemMargin, 1);
setWidgetLayoutProp(WT_ToolButton, ToolButton::ContentsMargin, 5);
setWidgetLayoutProp(WT_ToolButton, ToolButton::FocusMargin, 3);
setWidgetLayoutProp(WT_ToolButton, ToolButton::MenuIndicatorSize, 11);
setWidgetLayoutProp(WT_ToolBoxTab, ToolBoxTab::Margin, 0);
setWidgetLayoutProp(WT_Window, Window::TitleTextColor, ColorMode(QPalette::HighlightedText));
setWidgetLayoutProp(WT_Window, Window::TitleHeight, 20);
setWidgetLayoutProp(WT_Window, Window::TitleMargin, 2);
setWidgetLayoutProp(WT_Window, Window::NoTitleFrame, 0);
setWidgetLayoutProp(WT_Window, Window::ButtonWidth, 16);
setWidgetLayoutProp(WT_Window, Window::ButtonSpace, 2);
setWidgetLayoutProp(WT_Window, Window::ButtonToTextSpace, 3);
}
KStyle::~KStyle()
{
// this is just for stupid msvc compiler to force the creation of
// DoubleButtonOption::defaultOption() inside kstyle lib
// hope the optimizer won't throw it away
const DoubleButtonOption* bOpt = extractOption<const DoubleButtonOption*>(NULL);
Q_UNUSED(bOpt)
#ifdef __GNUC__
#warning "mem leak: need to delete bOpt"
#endif
delete d;
}
/*
Custom Style Element runtime extension:
We reserve one StyleHint to let the effective style inform widgets whether it supports certain
string based style elements.
As this could lead to number conflicts (i.e. an app utilizing one of the hints itself for other
purposes) there're various safety mechanisms to rule out such interference.
1) It's most unlikely that a widget in some 3rd party app will accidentally call a general
QStyle/KStyle styleHint() or draw*() and (unconditionally) expect a valid return, however:
a. The StyleHint is not directly above Qt's custom base, assuming most 3rd party apps would
- in case - make use of such
b. In order to be accepted, the StyleHint query must pass a widget with a perfectly matching
name, containing the typical element prefix ("CE_", etc.) and being supported by the current style
c. Instead using Qt's fragile qstyleoption_cast on the QStyleOption provided to the StyleHint
query, try to dump out a string and hope for the best, we now manipulate the widgets objectName().
Plain Qt dependent widgets can do that themselves and if a widget uses KStyle's convenience access
functions, it won't notice this at all
2) The key problem is that a common KDE widget will run into an apps custom style which will then
falsely respond to the styleHint() call with an invalid value.
To prevent this, supporting styles *must* set a Q_CLASSINFO "X-KDE-CustomElements".
3) If any of the above traps snaps, the returned id is 0 - the QStyle default, indicating
that this element is not supported by the current style.
Obviously, this contains the "diminished clean" action to (temporarily) manipulate the
objectName() of a const QWidget* - but this happens completely inside KStyle or the widget, if
it does not make use of KStyles static convenience functions.
My biggest worry here would be, that in a multithreaded environment a thread (usually not being
owner of the widget) does something crucially relying on the widgets name property...
This however would also have to happen during the widget construction or stylechanges, when
the functions in doubt will typically be called.
So this is imho unlikely causing any trouble, ever.
*/
/*
The functions called by the real style implementation to add support for a certain element.
Checks for well-formed string (containing the element prefix) and returns 0 otherwise.
Checks whether the element is already supported or inserts it otherwise; Returns the proper id
NOTICE: We could check for "X-KDE-CustomElements", but this would bloat style start up times
(if they e.g. register 100 elements or so)
*/
static inline int newStyleElement(const QString &element, const char *check, int &counter, QHash<QString, int> *elements)
{
if (!element.contains(check))
return 0;
int id = elements->value(element, 0);
if (!id) {
++counter;
id = counter;
elements->insert(element, id);
}
return id;
}
QStyle::StyleHint KStyle::newStyleHint(const QString &element)
{
return (StyleHint)newStyleElement(element, "SH_", d->hintCounter, &d->styleElements);
}
QStyle::ControlElement KStyle::newControlElement(const QString &element)
{
return (ControlElement)newStyleElement(element, "CE_", d->controlCounter, &d->styleElements);
}
KStyle::SubElement KStyle::newSubElement(const QString &element)
{
return (SubElement)newStyleElement(element, "SE_", d->subElementCounter, &d->styleElements);
}
QString KStyle::defaultStyle()
{
#if defined(Q_WS_X11) && !defined(Q_WS_MAEMO_5) || defined(Q_WS_WIN)
return QString("oxygen");
#else
return QString(); // native style
#endif
}
/*
The functions called by widgets that request custom element support, passed to the effective style.
Collected in a static inline function due to similarity.
*/
static inline int customStyleElement(QStyle::StyleHint type, const QString &element, QWidget *widget)
{
if (!widget || widget->style()->metaObject()->indexOfClassInfo("X-KDE-CustomElements") < 0)
return 0;
const QString originalName = widget->objectName();
widget->setObjectName(element);
const int id = widget->style()->styleHint(type, 0, widget);
widget->setObjectName(originalName);
return id;
}
QStyle::StyleHint KStyle::customStyleHint(const QString &element, const QWidget *widget)
{
return (StyleHint) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget*>(widget));
}
QStyle::ControlElement KStyle::customControlElement(const QString &element, const QWidget *widget)
{
return (ControlElement) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget*>(widget));
}
QStyle::SubElement KStyle::customSubElement(const QString &element, const QWidget *widget)
{
return (SubElement) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget*>(widget));
}
void KStyle::polish(QWidget *w)
{
if (qobject_cast<QLabel*>(w) ) {
w->installEventFilter(this);
}
// Enable hover effects in all itemviews
if (QAbstractItemView *itemView = qobject_cast<QAbstractItemView*>(w) ) {
itemView->viewport()->setAttribute(Qt::WA_Hover);
}
QCommonStyle::polish(w);
}
void KStyle::unpolish(QWidget *w)
{
if (qobject_cast<QLabel*>(w) ) {
w->removeEventFilter(this);
}
QCommonStyle::unpolish(w);
}
void KStyle::polish(QApplication *a)
{
QCommonStyle::polish(a);
}
void KStyle::unpolish(QApplication *a)
{
QCommonStyle::unpolish(a);
}
void KStyle::polish(QPalette &pal)
{
QCommonStyle::polish(pal);
}
QRect KStyle::itemTextRect(const QFontMetrics &fm, const QRect &r,
int flags, bool enabled,
const QString &text) const
{
return QCommonStyle::itemTextRect(fm, r, flags, enabled, text);
}
QRect KStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const
{
return QCommonStyle::itemPixmapRect(r, flags, pixmap);
}
void KStyle::drawItemText(QPainter *painter, const QRect &rect,
int flags, const QPalette &pal, bool enabled,
const QString &text, QPalette::ColorRole textRole) const
{
QCommonStyle::drawItemText(painter, rect, flags, pal, enabled,
text, textRole);
}
void KStyle::drawItemPixmap(QPainter *painter, const QRect &rect,
int alignment, const QPixmap &pixmap) const
{
QCommonStyle::drawItemPixmap(painter, rect, alignment, pixmap);
}
QPalette KStyle::standardPalette() const
{
return KGlobalSettings::createApplicationPalette(
KSharedConfig::openConfig(d->m_componentData));
}
QIcon KStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option,
const QWidget *widget) const
{
switch (standardIcon) {
case QStyle::SP_DesktopIcon:
return KIcon("user-desktop");
case QStyle::SP_TrashIcon:
return KIcon("user-trash");
case QStyle::SP_ComputerIcon:
return KIcon("computer");
case QStyle::SP_DriveFDIcon:
return KIcon("media-floppy");
case QStyle::SP_DriveHDIcon:
return KIcon("drive-harddisk");
case QStyle::SP_DriveCDIcon:
case QStyle::SP_DriveDVDIcon:
return KIcon("drive-optical");
case QStyle::SP_DriveNetIcon:
return KIcon("folder-remote");
case QStyle::SP_DirHomeIcon:
return KIcon("user-home");
case QStyle::SP_DirOpenIcon:
return KIcon("document-open-folder");
case QStyle::SP_DirClosedIcon:
return KIcon("folder");
case QStyle::SP_DirIcon:
return KIcon("folder");
case QStyle::SP_DirLinkIcon:
return KIcon("folder"); //TODO: generate (!?) folder with link emblem
case QStyle::SP_FileIcon:
return KIcon("text-plain"); //TODO: look for a better icon
case QStyle::SP_FileLinkIcon:
return KIcon("text-plain"); //TODO: generate (!?) file with link emblem
case QStyle::SP_FileDialogStart:
return KIcon("media-playback-start"); //TODO: find correct icon
case QStyle::SP_FileDialogEnd:
return KIcon("media-playback-stop"); //TODO: find correct icon
case QStyle::SP_FileDialogToParent:
return KIcon("go-up");
case QStyle::SP_FileDialogNewFolder:
return KIcon("folder-new");
case QStyle::SP_FileDialogDetailedView:
return KIcon("view-list-details");
case QStyle::SP_FileDialogInfoView:
return KIcon("document-properties");
case QStyle::SP_FileDialogContentsView:
return KIcon("view-list-icons");
case QStyle::SP_FileDialogListView:
return KIcon("view-list-text");
case QStyle::SP_FileDialogBack:
return KIcon("go-previous");
case QStyle::SP_MessageBoxInformation:
return KIcon("dialog-information");
case QStyle::SP_MessageBoxWarning:
return KIcon("dialog-warning");
case QStyle::SP_MessageBoxCritical:
return KIcon("dialog-error");
case QStyle::SP_MessageBoxQuestion:
return KIcon("dialog-information");
case QStyle::SP_DialogOkButton:
return KIcon("dialog-ok");
case QStyle::SP_DialogCancelButton:
return KIcon("dialog-cancel");
case QStyle::SP_DialogHelpButton:
return KIcon("help-contents");
case QStyle::SP_DialogOpenButton:
return KIcon("document-open");
case QStyle::SP_DialogSaveButton:
return KIcon("document-save");
case QStyle::SP_DialogCloseButton:
return KIcon("dialog-close");
case QStyle::SP_DialogApplyButton:
return KIcon("dialog-ok-apply");
case QStyle::SP_DialogResetButton:
return KIcon("document-revert");
case QStyle::SP_DialogDiscardButton:
return KIcon("dialog-cancel");
case QStyle::SP_DialogYesButton:
return KIcon("dialog-ok-apply");
case QStyle::SP_DialogNoButton:
return KIcon("dialog-cancel");
case QStyle::SP_ArrowUp:
return KIcon("go-up");
case QStyle::SP_ArrowDown:
return KIcon("go-down");
case QStyle::SP_ArrowLeft:
return KIcon("go-previous-view");
case QStyle::SP_ArrowRight:
return KIcon("go-next-view");
case QStyle::SP_ArrowBack:
return KIcon("go-previous");
case QStyle::SP_ArrowForward:
return KIcon("go-next");
case QStyle::SP_BrowserReload:
return KIcon("view-refresh");
case QStyle::SP_BrowserStop:
return KIcon("process-stop");
case QStyle::SP_MediaPlay:
return KIcon("media-playback-start");
case QStyle::SP_MediaStop:
return KIcon("media-playback-stop");
case QStyle::SP_MediaPause:
return KIcon("media-playback-pause");
case QStyle::SP_MediaSkipForward:
return KIcon("media-skip-forward");
case QStyle::SP_MediaSkipBackward:
return KIcon("media-skip-backward");
case QStyle::SP_MediaSeekForward:
return KIcon("media-seek-forward");
case QStyle::SP_MediaSeekBackward:
return KIcon("media-seek-backward");
case QStyle::SP_MediaVolume:
return KIcon("audio-volume-medium");
case QStyle::SP_MediaVolumeMuted:
return KIcon("audio-volume-muted");
default:
return QStyle::standardIconImplementation(standardIcon, option, widget);
}
}
QPixmap KStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
const QWidget *widget) const
{
return QCommonStyle::standardPixmap(standardPixmap, opt, widget);
}
QPixmap KStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
const QStyleOption *opt) const
{
return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt);
}
void KStyle::drawInsideRect(QPainter* p, const QRect& r) const
{
p->drawRect(r.x(), r.y(), r.width() - 1, r.height() - 1);
}
QRect KStyle::centerRect(const QRect &in, int w, int h) const
{
return QRect(in.x() + (in.width() - w)/2, in.y() + (in.height() - h)/2, w, h);
}
QRect KStyle::centerRect(const QRect &in, const QSize &size) const
{
return centerRect(in, size.width(), size.height());
}
void KStyle::drawKStylePrimitive(WidgetType widgetType, int primitive,
const QStyleOption* opt,
const QRect &r, const QPalette &pal,
State flags, QPainter* p,
const QWidget* widget,
KStyle::Option* kOpt) const
{
switch (widgetType)
{
case WT_Tree:
{
switch (primitive)
{
case Tree::VerticalBranch:
case Tree::HorizontalBranch:
//### FIXME: set sane color.
p->fillRect(r, QBrush(Qt::Dense4Pattern));
return;
case Tree::ExpanderOpen:
case Tree::ExpanderClosed:
{
p->setPen(pal.text().color());
drawInsideRect(p, r); //the border.
int signLineSize = r.width()/4;
p->drawLine(r.center().x() - signLineSize, r.center().y(),
r.center().x() + signLineSize, r.center().y()); //-
if (primitive == Tree::ExpanderClosed) //vertical line of +
p->drawLine(r.center().x(), r.center().y() - signLineSize,
r.center().x(), r.center().y() + signLineSize);
return;
}
default:
break;
}
break;
}
case WT_SpinBox:
{
switch (primitive)
{
case SpinBox::PlusSymbol:
case SpinBox::MinusSymbol:
{
p->setPen( pal.buttonText().color() );
int l = qMin( r.width()-2, r.height()-2 );
QPoint c = r.center();
p->drawLine( c.x()-l/2, c.y(), c.x()+l/2, c.y() );
if (primitive == SpinBox::PlusSymbol ) {
p->drawLine( c.x(), c.y()-l/2, c.x(), c.y()+l/2 );
}
return;
}
default:
break;
}
break;
}
case WT_GroupBox:
{
if (primitive == GroupBox::FlatFrame) {
QPen oldPen = p->pen();
p->setPen(pal.color(QPalette::WindowText) );
p->drawLine(r.topLeft(), r.topRight() );
p->setPen(oldPen);
}
break;
}
case WT_ToolBoxTab:
{
if (primitive == ToolBoxTab::Panel) {
drawKStylePrimitive(WT_ToolButton, ToolButton::Panel, opt, r, pal, flags, p, widget);
}
break;
}
case WT_DockWidget:
{
switch (primitive)
{
case DockWidget::TitlePanel:
p->fillRect(r, pal.color(QPalette::Highlight) );
return;
case DockWidget::SeparatorHandle:
return;
default:
break;
}
break;
}
case WT_Window:
{
switch (primitive)
{
case Window::TitlePanel:
p->fillRect(r, pal.color(QPalette::Highlight) );
return;
case Window::ButtonMenu:
{
KStyle::TitleButtonOption* tbkOpts =
extractOption<KStyle::TitleButtonOption*>(kOpt);
if (!tbkOpts->icon.isNull()) {
tbkOpts->icon.paint(p, r);
} else {
QStyleOption tool(0);
tool.palette = pal;
// TODO: give it a nice KDE logo.
QPixmap pm = standardPixmap(SP_TitleBarMenuButton, &tool, widget);
tool.rect = r;
p->save();
drawItemPixmap(p, r, Qt::AlignCenter, pm);
p->restore();
}
return;
}
case Window::ButtonMin:
case Window::ButtonMax:
case Window::ButtonRestore:
case Window::ButtonClose:
case Window::ButtonShade:
case Window::ButtonUnshade:
case Window::ButtonHelp:
{
KStyle::TitleButtonOption* tbkOpts =
extractOption<KStyle::TitleButtonOption*>(kOpt);
State bflags = flags;
bflags &= ~State_Sunken;
if (tbkOpts->active)
bflags |= State_Sunken;
drawKStylePrimitive(WT_ToolButton, ToolButton::Panel, opt, r, pal, bflags, p, widget);
return;
}
}
break;
}
case WT_TabBar:
{
// For vertical text fallback, provide the generic text implementation
// a transformed rotated painter, with rect swizzled appropriately
if (primitive == TabBar::EastText || primitive == TabBar::WestText)
{
QTransform tr;
if (primitive == TabBar::WestText)
{
tr.translate(r.x(), r.height() + r.y());
tr.rotate(-90);
}
else
{
tr.translate(r.width() + r.x(), r.y());
tr.rotate(90);
}
p->save();
p->setTransform(tr, true);
drawKStylePrimitive(WT_TabBar, Generic::Text, opt,
QRect(0, 0, r.height(), r.width()), pal, flags, p, widget, kOpt);
p->restore();
}
break;
}
default:
break;
}
if (primitive == Generic::Text)
{
KStyle::TextOption* textOpts = extractOption<KStyle::TextOption*>(kOpt);
//### debug
//p->setPen(Qt::green);
//drawInsideRect(p, r);
QColor col = textOpts->color.color(pal);
QPen old = p->pen();
p->setPen(col);
drawItemText(p, r, Qt::AlignVCenter | Qt::TextShowMnemonic | textOpts->hAlign, pal, flags & State_Enabled,
textOpts->text);
p->setPen(old);
}
else if (primitive == Generic::Icon)
{
KStyle::IconOption* iconOpts = extractOption<KStyle::IconOption*>(kOpt);
QIcon::Mode mode;
QIcon::State iconState;
// Select the correct icon from the iconset
if (flags & State_Enabled)
if (iconOpts->active)
mode = QIcon::Active;
else
mode = QIcon::Normal;
else
mode = QIcon::Disabled;
if( (flags & State_On) || (flags & State_Sunken) )
iconState = QIcon::On;
else
iconState = QIcon::Off;
QSize size = iconOpts->size;
if(!size.isValid())
size = QSize(pixelMetric(PM_SmallIconSize), pixelMetric(PM_SmallIconSize));
QPixmap icon = iconOpts->icon.pixmap(size, mode, iconState);
p->drawPixmap(centerRect(r, icon.size()), icon);
}
else if (primitive == Generic::FocusIndicator)
{
QPen pen;
pen.setWidth(0);
pen.setStyle(Qt::DotLine);
p->setPen(pen);
drawInsideRect(p, r);
}
else if (primitive >= Generic::ArrowUp && primitive <= Generic::ArrowLeft)
{
//### FIXME: Helper for these sorts of things, as Keramik has virtually
//identical code!
KStyle::ColorOption* colorOpt = extractOption<KStyle::ColorOption*>(kOpt);
QColor arrowColor = colorOpt->color.color(pal);
QPolygon poly;
switch (primitive)
{
case Generic::ArrowUp:
poly.setPoints(QCOORDARRLEN(u_arrow), u_arrow);
break;
case Generic::ArrowDown:
poly.setPoints(QCOORDARRLEN(d_arrow), d_arrow);
break;
case Generic::ArrowLeft:
poly.setPoints(QCOORDARRLEN(l_arrow), l_arrow);
break;
default:
poly.setPoints(QCOORDARRLEN(r_arrow), r_arrow);
}
if ( flags & State_Enabled )
{
//CHECKME: Why is the -1 needed?
poly.translate(r.x() + r.width()/2 - 1, r.y() + r.height()/2);
p->setPen(arrowColor);
p->drawPolygon(poly);
}
else
{
//Disabled ones ignore color parameter
poly.translate(r.x() + r.width()/2, r.y() + r.height()/2 + 1);
p->setPen( pal.color( QPalette::Light ) );
p->drawPolygon(poly);
poly.translate(-1,-1);
p->setPen(pal.mid().color());
p->drawPolygon(poly);
}
}
#if 0 //Reenable if you need a debug aid
else
{
p->setPen(Qt::red);
drawInsideRect(p, r);
}
#endif
}
void KStyle::setWidgetLayoutProp(WidgetType widget, int metric, int value)
{
if (metrics.size() <= widget)
metrics.resize(widget + 1);
QVector<int>& widgetMetrics = metrics[widget];
if (widgetMetrics.size() <= metric)
widgetMetrics.resize(metric + 1);
widgetMetrics[metric] = value;
}
int KStyle::widgetLayoutProp(WidgetType widget, int metric,
const QStyleOption* opt,
const QWidget* w ) const
{
Q_UNUSED(opt)
Q_UNUSED(w)
if (metrics.size() <= widget)
return 0;
const QVector<int>& widgetMetrics = metrics[widget];
if (widgetMetrics.size() <= metric)
return 0;
return widgetMetrics[metric];
}
QSize KStyle::expandDim(const QSize& orig, WidgetType wt, int baseMarginMetric,
const QStyleOption* opt, const QWidget* w, bool rotated) const
{
int addWidth = 2*widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w) +
widgetLayoutProp(wt, baseMarginMetric + Left, opt, w) +
widgetLayoutProp(wt, baseMarginMetric + Right, opt, w);
int addHeight = 2*widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w) +
widgetLayoutProp(wt, baseMarginMetric + Top, opt, w) +
widgetLayoutProp(wt, baseMarginMetric + Bot, opt, w);
return QSize(orig.width() + (rotated? addHeight: addWidth),
orig.height() + (rotated? addWidth: addHeight));
}
QRect KStyle::insideMargin(const QRect &orig, WidgetType wt,
int baseMarginMetric,
const QStyleOption* opt, const QWidget* w) const
{
int x1 = orig.topLeft().x();
int y1 = orig.topLeft().y();
int x2 = orig.bottomRight().x();
int y2 = orig.bottomRight().y();
x1 += widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
x1 += widgetLayoutProp(wt, baseMarginMetric + Left, opt, w);
y1 += widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
y1 += widgetLayoutProp(wt, baseMarginMetric + Top, opt, w);
x2 -= widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
x2 -= widgetLayoutProp(wt, baseMarginMetric + Right, opt, w);
y2 -= widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
y2 -= widgetLayoutProp(wt, baseMarginMetric + Bot, opt, w);
return QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
}
QRect KStyle::handleRTL(const QStyleOption* opt, const QRect& subRect) const
{
return visualRect(opt->direction, opt->rect, subRect);
}
QPoint KStyle::handleRTL(const QStyleOption* opt, const QPoint& pos) const
{
return visualPos(opt->direction, opt->rect, pos);
}
void KStyle::drawPrimitive(PrimitiveElement elem, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
{
//Extract the stuff we need out of the option
State flags = option->state;
QRect r = option->rect;
QPalette pal = option->palette;
switch (elem)
{
case PE_FrameFocusRect:
drawKStylePrimitive(WT_Generic, Generic::FocusIndicator, option, r, pal, flags, painter, widget);
return;
case PE_IndicatorArrowUp:
drawKStylePrimitive(WT_Generic, Generic::ArrowUp, option, r, pal, flags, painter, widget);
return;
case PE_IndicatorArrowDown:
drawKStylePrimitive(WT_Generic, Generic::ArrowDown, option, r, pal, flags, painter, widget);
return;
case PE_IndicatorArrowLeft:
drawKStylePrimitive(WT_Generic, Generic::ArrowLeft, option, r, pal, flags, painter, widget);
return;
case PE_IndicatorArrowRight:
drawKStylePrimitive(WT_Generic, Generic::ArrowRight, option, r, pal, flags, painter, widget);
return;
case PE_IndicatorMenuCheckMark:
//### check flags
drawKStylePrimitive(WT_MenuItem, MenuItem::CheckOn, option, r, pal, flags, painter, widget);
return;
case PE_IndicatorCheckBox:
if (flags & State_NoChange)
drawKStylePrimitive(WT_CheckBox, CheckBox::CheckTriState, option, r, pal, flags, painter, widget);
else if (flags & State_On)
drawKStylePrimitive(WT_CheckBox, CheckBox::CheckOn, option, r, pal, flags, painter, widget);
else
drawKStylePrimitive(WT_CheckBox, CheckBox::CheckOff, option, r, pal, flags, painter, widget);
return;
case PE_IndicatorRadioButton:
if (flags & State_On)
drawKStylePrimitive(WT_RadioButton, RadioButton::RadioOn, option, r, pal, flags, painter, widget);
else
drawKStylePrimitive(WT_RadioButton, RadioButton::RadioOff, option, r, pal, flags, painter, widget);
return;
case PE_IndicatorBranch:
{
int centerX = r.x() + r.width()/2;
int centerY = r.y() + r.height()/2;
int expanderAdjust = 0;
//First, determine whether we need to draw an expander.
if (flags & State_Children)
{
//How large should we make it?
int sizeLimit = qMin(qMin(r.width(), r.height()),
widgetLayoutProp(WT_Tree, Tree::MaxExpanderSize, option, widget));
if ((sizeLimit & 1) == 0)
--sizeLimit;
expanderAdjust = sizeLimit/2 + 1;
QRect expanderRect = QRect(centerX - sizeLimit/2, centerY - sizeLimit/2,
sizeLimit, sizeLimit);
drawKStylePrimitive(WT_Tree, flags & State_Open ? Tree::ExpanderOpen : Tree::ExpanderClosed,
option, expanderRect, pal, flags, painter, widget);
}
//Now, draw the branches. The top line gets drawn unless we're completely
//w/o any indication of a neightbor
if (flags & (State_Item | State_Children | State_Sibling))
{
QRect topLine = QRect(QPoint(centerX, r.y()), QPoint(centerX, centerY - expanderAdjust));
drawKStylePrimitive(WT_Tree, Tree::VerticalBranch, option, topLine, pal, flags, painter, widget);
}
//The right/left (depending on dir) line gets drawn if we have an item
if (flags & State_Item)
{
QRect horLine;
if (option->direction == Qt::LeftToRight)
horLine = QRect(QPoint(centerX + expanderAdjust, centerY),
QPoint(r.right(), centerY));
else
horLine = QRect(QPoint(r.left(), centerY),
QPoint(centerX - expanderAdjust, centerY));
drawKStylePrimitive(WT_Tree, Tree::HorizontalBranch, option, horLine, pal, flags, painter, widget);
}
//The bottom if we have a sibling
if (flags & State_Sibling)
{
QRect botLine = QRect(QPoint(centerX, centerY + expanderAdjust),
QPoint(centerX, r.bottom()));
drawKStylePrimitive(WT_Tree, Tree::VerticalBranch, option, botLine, pal, flags, painter, widget);
}
return;
}
case PE_FrameMenu:
drawKStylePrimitive(WT_Menu, Generic::Frame, option, r, pal, flags, painter, widget);
return;
case PE_IndicatorHeaderArrow:
{
const QStyleOptionHeader *hOpt = qstyleoption_cast<const QStyleOptionHeader *>(option);
int primitive = 0;
if (flags&State_UpArrow || (hOpt && hOpt->sortIndicator==QStyleOptionHeader::SortUp))
primitive = Generic::ArrowUp;
else if (flags&State_DownArrow || (hOpt && hOpt->sortIndicator==QStyleOptionHeader::SortDown))
primitive = Generic::ArrowDown;
if (primitive != 0)
drawKStylePrimitive(WT_Header, primitive, option, r, pal, flags, painter, widget);
return;
}
case PE_FrameTabBarBase:
{
drawKStylePrimitive(WT_TabBar, TabBar::BaseFrame,option,r,pal,flags,painter,widget);
return;
}
case PE_IndicatorTabTear:
{
drawKStylePrimitive(WT_TabBar, TabBar::IndicatorTear,option,r,pal,flags,painter,widget);
return;
}
case PE_FrameTabWidget:
{
drawKStylePrimitive(WT_TabWidget, Generic::Frame,option,r,pal,flags,painter,widget);
return;
}
case PE_PanelLineEdit:
{
drawKStylePrimitive(WT_LineEdit, LineEdit::Panel,option,r,pal,flags,painter,widget);
return;
}
case PE_FrameLineEdit:
{
drawKStylePrimitive(WT_LineEdit, Generic::Frame,option,r,pal,flags,painter,widget);
return;
}
case PE_FrameGroupBox:
{
if (const QStyleOptionFrame *fOpt =
qstyleoption_cast<const QStyleOptionFrame *>(option))
{
QStyleOptionFrameV2 fOpt2(*fOpt);
if (fOpt2.features & QStyleOptionFrameV2::Flat) {
drawKStylePrimitive(WT_GroupBox, GroupBox::FlatFrame,option,r,pal,flags,painter,widget);
} else {
drawKStylePrimitive(WT_GroupBox, Generic::Frame,option,r,pal,flags,painter,widget);
}
}
return;
}
case PE_FrameStatusBar:
{
drawKStylePrimitive(WT_StatusBar, Generic::Frame,option,r,pal,flags,painter,widget);
return;
}
case PE_FrameDockWidget:
{
drawKStylePrimitive(WT_DockWidget, Generic::Frame,option,r,pal,flags,painter,widget);
return;
}
case PE_IndicatorDockWidgetResizeHandle:
{
drawKStylePrimitive(WT_DockWidget, DockWidget::SeparatorHandle, option, r, pal, flags,
painter, widget);
return;
}
case PE_FrameWindow:
{
drawKStylePrimitive(WT_Window, Generic::Frame,option,r,pal,flags,painter,widget);
return;
}
case PE_Frame:
{
drawKStylePrimitive(WT_Generic, Generic::Frame,option,r,pal,flags,painter,widget);
return;
}
case PE_IndicatorToolBarHandle:
{
if (flags & State_Horizontal)
drawKStylePrimitive(WT_ToolBar, ToolBar::HandleHor,
option,r,pal,flags,painter,widget);
else
drawKStylePrimitive(WT_ToolBar, ToolBar::HandleVert,
option,r,pal,flags,painter,widget);
return;
}
case PE_IndicatorToolBarSeparator:
drawKStylePrimitive(WT_ToolBar, ToolBar::Separator,option,r,pal,flags,painter,widget);
return;
case PE_PanelButtonCommand:
//case PE_PanelButtonBevel: // ### CHECKME
drawKStylePrimitive(WT_PushButton, PushButton::Panel, option, r, pal, flags, painter, widget);
return;
case PE_FrameDefaultButton:
drawKStylePrimitive(WT_PushButton, PushButton::DefaultButtonFrame, option, r, pal, flags, painter, widget);
return;
case PE_PanelButtonTool:
drawKStylePrimitive(WT_ToolButton, ToolButton::Panel,option,r,pal,flags,painter,widget);
return;
case PE_IndicatorButtonDropDown:
drawKStylePrimitive(WT_ToolButton, Generic::ArrowDown, option, r, pal, flags, painter, widget);
return;
case PE_PanelItemViewItem: {
const QStyleOptionViewItemV4 *opt = qstyleoption_cast<const QStyleOptionViewItemV4*>(option);
const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
bool hover = (option->state & State_MouseOver) && (!view ||
view->selectionMode() != QAbstractItemView::NoSelection);
bool hasCustomBackground = opt->backgroundBrush.style() != Qt::NoBrush &&
!(option->state & State_Selected);
bool hasSolidBackground = !hasCustomBackground || opt->backgroundBrush.style() == Qt::SolidPattern;
const qreal rounding = 2.5;
if (!hover && !(option->state & State_Selected) && !hasCustomBackground &&
!(opt->features & QStyleOptionViewItemV2::Alternate))
return;
QPalette::ColorGroup cg;
if (option->state & State_Enabled)
cg = (option->state & State_Active) ? QPalette::Normal : QPalette::Inactive;
else
cg = QPalette::Disabled;
QColor color;
if (hasCustomBackground && hasSolidBackground)
color = opt->backgroundBrush.color();
else
color = option->palette.color(cg, QPalette::Highlight);
if (hover && !hasCustomBackground) {
if (!(option->state & State_Selected))
color.setAlphaF(.20);
else
color = color.lighter(110);
}
if (opt && (opt->features & QStyleOptionViewItemV2::Alternate))
painter->fillRect(option->rect, option->palette.brush(cg, QPalette::AlternateBase));
if (!hover && !(option->state & State_Selected) && !hasCustomBackground)
return;
quint64 key = quint64(option->rect.height()) << 32 | color.rgba();
SelectionTiles* tiles = d->selectionCache.object(key);
if (!tiles && hasSolidBackground)
{
QImage image(32 + 16, option->rect.height(), QImage::Format_ARGB32_Premultiplied);
image.fill(0);
QRect r = image.rect().adjusted(0, 0, -1, -1);
QPainterPath path1, path2;
path1.addRoundedRect(r, rounding, rounding);
path2.addRoundedRect(r.adjusted(1, 1, -1, -1), rounding - 1, rounding - 1);
// items with custom background brushes always have their background drawn
// regardless of whether they are hovered or selected or neither so
// the gradient effect needs to be more subtle
int lightenAmount = hasCustomBackground ? 110 : 130;
QLinearGradient gradient(0, 0, 0, r.bottom());
gradient.setColorAt(0, color.lighter(lightenAmount));
gradient.setColorAt(1, color);
QPainter p(&image);
p.setRenderHint(QPainter::Antialiasing);
p.translate(.5, .5);
p.setPen(QPen(color, 1));
p.setBrush(gradient);
p.drawPath(path1);
p.strokePath(path2, QPen(QColor(255, 255, 255, 64), 1));
p.end();
QPixmap pixmap = QPixmap::fromImage(image);
tiles = new SelectionTiles;
tiles->left = pixmap.copy(0, 0, 8, image.height());
tiles->center = pixmap.copy(8, 0, 32, image.height());
tiles->right = pixmap.copy(40, 0, 8, image.height());
d->selectionCache.insert(key, tiles);
}
else if (hasCustomBackground && !hasSolidBackground)
{
const QPointF oldBrushOrigin = painter->brushOrigin();
painter->setBrushOrigin(opt->rect.topLeft());
painter->setBrush(opt->backgroundBrush);
painter->setPen(Qt::NoPen);
painter->drawRect(opt->rect);
painter->setBrushOrigin(oldBrushOrigin);
return;
}
bool roundedLeft = false;
bool roundedRight = false;
if (opt) {
roundedLeft = (opt->viewItemPosition == QStyleOptionViewItemV4::Beginning);
roundedRight = (opt->viewItemPosition == QStyleOptionViewItemV4::End);
if (opt->viewItemPosition == QStyleOptionViewItemV4::OnlyOne ||
opt->viewItemPosition == QStyleOptionViewItemV4::Invalid ||
(view && view->selectionBehavior() != QAbstractItemView::SelectRows))
{
roundedLeft = true;
roundedRight = true;
}
}
QRect r = option->rect;
bool reverseLayout = option->direction == Qt::RightToLeft;
if (!reverseLayout ? roundedLeft : roundedRight) {
painter->drawPixmap(r.topLeft(), tiles->left);
r.adjust(8, 0, 0, 0);
}
if (!reverseLayout ? roundedRight : roundedLeft) {
painter->drawPixmap(r.right() - 8 + 1, r.top(), tiles->right);
r.adjust(0, 0, -8, 0);
}
if (r.isValid())
painter->drawTiledPixmap(r, tiles->center);
return;
}
default:
break;
}
QCommonStyle::drawPrimitive(elem, option, painter, widget);
}
void KStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* p, const QWidget* widget) const
{
//Extract the stuff we need out of the option
State flags = option->state;
QRect r = option->rect;
QPalette pal = option->palette;
switch (element)
{
case CE_PushButton:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return;
//Draw the bevel outside
drawControl(CE_PushButtonBevel, option, p, widget);
//Now, draw the label...
QRect labelRect = r;
//Move inside of default indicator margin if need be
if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton))
labelRect = insideMargin(labelRect, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
//now get the contents area
labelRect = insideMargin(labelRect, WT_PushButton, PushButton::ContentsMargin, option, widget);
//### do we do anything for RTL here?
QStyleOptionButton bOptTmp = *bOpt;
bOptTmp.rect = labelRect;
drawControl(CE_PushButtonLabel, &bOptTmp, p, widget);
//Finally, renderer the focus indicator if need be
if (flags & State_HasFocus)
{
QRect focusRect = insideMargin(r, WT_PushButton, PushButton::FocusMargin, option, widget);
QStyleOptionFocusRect foOpts;
foOpts.palette = pal;
foOpts.rect = focusRect;
foOpts.state = flags;
drawKStylePrimitive(WT_PushButton, Generic::FocusIndicator, &foOpts, focusRect, pal, flags, p, widget);
}
return;
}
case CE_PushButtonBevel:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return;
//Check whether we should draw default indicator.
if (bOpt->features & QStyleOptionButton::DefaultButton)
drawPrimitive(PE_FrameDefaultButton, option, p, widget);
QRect bevelRect = r;
//Exclude the margin if default or auto-default
if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton))
bevelRect = insideMargin(r, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
//Now draw the bevel itself.
QStyleOptionButton bOptTmp = *bOpt;
bOptTmp.rect = bevelRect;
drawPrimitive(PE_PanelButtonCommand, &bOptTmp, p, widget);
return;
}
case CE_PushButtonLabel:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return;
//Extract out coordinates for easier manipulation
//(OK, OK, for easier stealing of code from Keramik)
int x, y, w, h;
r.getRect(&x, &y, &w, &h);
//Are we active? If so, shift contents
bool active = (flags & State_On) || (flags & State_Sunken);
if (active)
{
x += widgetLayoutProp(WT_PushButton, PushButton::PressedShiftHorizontal, option, widget);
y += widgetLayoutProp(WT_PushButton, PushButton::PressedShiftVertical, option, widget);
}
//Layout the stuff.
if (bOpt->features & QStyleOptionButton::HasMenu)
{
int indicatorWidth = widgetLayoutProp(WT_PushButton, PushButton::MenuIndicatorSize, option, widget);
int indicatorSpacing = widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget);
w -= indicatorWidth + indicatorSpacing;
//Draw the arrow...
drawKStylePrimitive(WT_PushButton, Generic::ArrowDown, option,
handleRTL(bOpt, QRect(x + w + indicatorSpacing, y, indicatorWidth, h)),
pal, flags, p, widget);
}
// Draw the icon if there is one
if (!bOpt->icon.isNull())
{
IconOption icoOpt;
icoOpt.icon = bOpt->icon;
icoOpt.size = bOpt->iconSize;
icoOpt.active = flags & State_HasFocus;
if (!bOpt->text.isEmpty())
{
int margin = widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget);
//Center text + icon w/margin in between..
//Calculate length of both.
int length = bOpt->iconSize.width() + margin
+ p->fontMetrics().size(Qt::TextShowMnemonic, bOpt->text).width();
//Calculate offset.
int offset = (w - length)/2;
//draw icon
QRect rect = QRect(QPoint(x + offset, y + h/2 - bOpt->iconSize.height()/2), bOpt->iconSize);
drawKStylePrimitive(WT_PushButton, Generic::Icon, option,
handleRTL(bOpt, rect),
pal, flags, p, widget, &icoOpt);
//new bounding rect for the text
x += offset + bOpt->iconSize.width() + margin;
w = length - bOpt->iconSize.width() - margin;
}
else
{
//Icon only. Center it. (Thankfully, they killed the icon + pixmap insanity in Qt4. Whee!
//(no need to do anything for RTL here, it's symmetric)
drawKStylePrimitive(WT_PushButton, Generic::Icon, option,
QRect(x, y, w, h),
pal, flags, p, widget, &icoOpt);
}
}
else
{
//Center the text
int textW = p->fontMetrics().size(Qt::TextShowMnemonic, bOpt->text).width();
x += (w - textW)/2;
w = textW;
}
TextOption lbOpt(bOpt->text);
drawKStylePrimitive(WT_PushButton, Generic::Text, option, handleRTL(bOpt, QRect(x, y, w, h)),
pal, flags, p, widget, &lbOpt);
return;
}
case CE_DockWidgetTitle:
{
const QStyleOptionDockWidget* dwOpt = ::qstyleoption_cast<const QStyleOptionDockWidget*>(option);
if (!dwOpt) return;
QRect textRect = insideMargin(r, WT_DockWidget, DockWidget::TitleMargin, option, widget);
drawKStylePrimitive(WT_DockWidget, DockWidget::TitlePanel, option, r, pal, flags, p, widget);
TextOption lbOpt(dwOpt->title);
lbOpt.color = widgetLayoutProp(WT_DockWidget, DockWidget::TitleTextColor,
option, widget);
drawKStylePrimitive(WT_DockWidget, Generic::Text, option, textRect, pal, flags, p, widget, &lbOpt);
return;
}
case CE_ToolBoxTabShape:
{
drawKStylePrimitive(WT_ToolBoxTab, ToolBoxTab::Panel, option, r, pal, flags, p, widget);
return;
}
/*
case CE_ToolBoxTabLabel:
{
drawKStylePrimitive(WT_ToolBoxTab, Generic::Text, option, r, pal, flags, p, widget);
return;
}
*/
case CE_CheckBox:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return;
//Draw the checkbox
QRect checkBox = subElementRect(SE_CheckBoxIndicator, option, widget);
QStyleOptionButton bOptTmp = *bOpt;
bOptTmp.rect = checkBox;
drawPrimitive(PE_IndicatorCheckBox, &bOptTmp, p, widget);
// pixmap and text label...
bOptTmp.rect = subElementRect(SE_CheckBoxContents, option, widget);
drawControl(CE_CheckBoxLabel, &bOptTmp, p, widget);
//Draw the focus rect...
if (flags & State_HasFocus)
{
QRect focusRect = subElementRect(SE_CheckBoxFocusRect, option, widget);
drawKStylePrimitive(WT_CheckBox, Generic::FocusIndicator, option, focusRect,
pal, flags, p, widget);
}
return;
}
case CE_CheckBoxLabel:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return;
int textShift = 0; // shift text in case there is a label pixmap
// draw the pixmap, if there is one
if (!bOpt->icon.isNull())
{
IconOption icoOpt;
icoOpt.icon = bOpt->icon;
icoOpt.size = bOpt->iconSize;
icoOpt.active = flags & State_HasFocus;
QRect iconRect(r.x(), r.y() + (r.height()-bOpt->iconSize.height())/2,
bOpt->iconSize.width(), bOpt->iconSize.height());
drawKStylePrimitive(WT_CheckBox, Generic::Icon, option,
handleRTL(bOpt, iconRect),
pal, flags, p, widget, &icoOpt);
textShift = bOpt->iconSize.width() +
widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget);
}
if (!bOpt->text.isEmpty() ) {
TextOption lbOpt(bOpt->text);
drawKStylePrimitive(WT_CheckBox, Generic::Text, option,
handleRTL(bOpt, r.adjusted(textShift,0,0,0)),
pal, flags, p, widget, &lbOpt);
}
return;
}
case CE_RadioButton:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return;
//Draw the indicator
QRect indicator = subElementRect(SE_RadioButtonIndicator, option, widget);
QStyleOptionButton bOptTmp = *bOpt;
bOptTmp.rect = indicator;
drawPrimitive(PE_IndicatorRadioButton, &bOptTmp, p, widget);
// pixmap and text label...
bOptTmp.rect = subElementRect(SE_RadioButtonContents, option, widget);
drawControl(CE_RadioButtonLabel, &bOptTmp, p, widget);
//Draw the focus rect...
if (flags & State_HasFocus)
{
QRect focusRect = subElementRect(SE_RadioButtonFocusRect, option, widget);
drawKStylePrimitive(WT_RadioButton, Generic::FocusIndicator, option, focusRect,
pal, flags, p, widget);
}
return;
}
case CE_RadioButtonLabel:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return;
int textShift = 0; // shift text in case there is a label pixmap
// draw the pixmap, if there is one
if (!bOpt->icon.isNull())
{
IconOption icoOpt;
icoOpt.icon = bOpt->icon;
icoOpt.active = flags & State_HasFocus;
icoOpt.size = bOpt->iconSize;
QRect iconRect(r.x(), r.y() + (r.height()-bOpt->iconSize.height())/2,
bOpt->iconSize.width(), bOpt->iconSize.height());
drawKStylePrimitive(WT_RadioButton, Generic::Icon, option,
handleRTL(bOpt, iconRect),
pal, flags, p, widget, &icoOpt);
textShift = bOpt->iconSize.width() +
widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget);
}
TextOption lbOpt(bOpt->text);
drawKStylePrimitive(WT_RadioButton, Generic::Text, option,
handleRTL(bOpt, r.adjusted(textShift,0,0,0)),
pal, flags, p, widget, &lbOpt);
return;
}
//The CE_ProgressBar implementation inside QCommonStyle is acceptible.
//We just implement the subElementRect's it uses
case CE_ProgressBarGroove:
{
drawKStylePrimitive(WT_ProgressBar, ProgressBar::Groove, option, r,
pal, flags, p, widget);
return;
}
case CE_ProgressBarContents:
{
const QStyleOptionProgressBar* pbOpt = qstyleoption_cast<const QStyleOptionProgressBar*>(option);
const QStyleOptionProgressBarV2* pbOpt2 = qstyleoption_cast<const QStyleOptionProgressBarV2*>(option);
if (!pbOpt) return;
//We layout as if LTR, relying on visualRect to fix it up
double progress = pbOpt->progress - pbOpt->minimum;
int steps = qMax(pbOpt->maximum - pbOpt->minimum, 1);
bool busyIndicator = (pbOpt->minimum == 0 && pbOpt->maximum == 0);
bool horizontal = !pbOpt2 || pbOpt2->orientation == Qt::Horizontal;
//Do we have to draw anything?
if (!progress && ! busyIndicator)
return;
//Calculate width fraction
double widthFrac;
if (busyIndicator)
widthFrac = widgetLayoutProp(WT_ProgressBar, ProgressBar::BusyIndicatorSize, option, widget) / 100.0;
else
widthFrac = progress / steps;
//And now the pixel width
int width = qMin(r.width(), (int)(widthFrac * double(r.width())));
int height = qMin(r.height(), (int)(widthFrac * r.height()));
if (busyIndicator)
{
int size = width;
if (!horizontal)
size = height;
//Clamp to upper width limit
if (size > widgetLayoutProp(WT_ProgressBar, ProgressBar::MaxBusyIndicatorSize, option, widget))
size = widgetLayoutProp(WT_ProgressBar, ProgressBar::MaxBusyIndicatorSize, option, widget);
//A busy indicator with width 0 is kind of useless
if (size < 1) size = 1;
int remSize = (horizontal ? r.width() : r.height()) - size; //The space around which we move around...
if (remSize <= 0) remSize = 1; //Do something non-crashy when too small...
int pstep = int(progress)%(2*remSize);
if (pstep > remSize)
{
//Bounce about.. We're remWidth + some delta, we want to be remWidth - delta...
// - ( (remWidth + some delta) - 2* remWidth ) = - (some deleta - remWidth) = remWidth - some delta..
pstep = -(pstep - 2*remSize);
}
QRect indicatorRect;
if (horizontal)
indicatorRect = QRect(r.x() + pstep, r.y(), size, r.height());
else
indicatorRect = QRect(r.x(), r.y() + pstep, r.width(), size);
drawKStylePrimitive(WT_ProgressBar, ProgressBar::BusyIndicator, option, handleRTL(option, indicatorRect),
pal, flags, p, widget);
}
else
{
QRect indicatorRect;
if (horizontal)
indicatorRect = QRect(r.x(), r.y(), width, r.height());
else
indicatorRect = QRect(r.x(), r.bottom()-height+1, r.width(), height);
drawKStylePrimitive(WT_ProgressBar, ProgressBar::Indicator, option, handleRTL(option, indicatorRect),
pal, flags, p, widget);
}
return;
}
case CE_ProgressBarLabel:
{
const QStyleOptionProgressBar* pbOpt = qstyleoption_cast<const QStyleOptionProgressBar*>(option);
const QStyleOptionProgressBarV2* pbOpt2 = qstyleoption_cast<const QStyleOptionProgressBarV2*>(option);
if (pbOpt)
{
TextOption lbOpt(pbOpt->text);
bool horizontal = !pbOpt2 || pbOpt2->orientation == Qt::Horizontal;
bool reverseLayout = option->direction == Qt::RightToLeft;
p->save();
// rotate label for vertical layout
if (!horizontal && !reverseLayout)
{
p->translate(r.topRight());
p->rotate(90.0);
}
else if (!horizontal)
{
p->translate(r.bottomLeft());
p->rotate(-90.0);
}
if (useSideText(pbOpt))
{
lbOpt.color = QPalette::ButtonText;
//### or other way around?
if (option->direction == Qt::LeftToRight)
lbOpt.hAlign = Qt::AlignRight;
else
lbOpt.hAlign = Qt::AlignLeft;
//Handle side margin.
int marWidth = widgetLayoutProp(WT_ProgressBar, ProgressBar::SideTextSpace, option, widget);
drawKStylePrimitive(WT_ProgressBar, Generic::Text, option,
horizontal? r.adjusted(0, marWidth, 0, -marWidth) : QRect(0, marWidth, r.height(), r.width()-marWidth),
pal, flags, p, widget, &lbOpt);
}
else
{
if (pbOpt->textAlignment == Qt::AlignLeft) //TODO: Check BIDI?
lbOpt.hAlign = Qt::AlignHCenter;
else
lbOpt.hAlign = pbOpt->textAlignment;
//Now, we need to figure out the geometry of the indicator.
QRect progressRect;
double progress = pbOpt->progress - pbOpt->minimum;
int steps = qMax(pbOpt->maximum - pbOpt->minimum, 1);
bool busyIndicator = (steps <= 1);
int width;
int height;
if (busyIndicator)
{
//how did this happen? handle as 0%
width = 0;
height = 0;
}
else
{
double widthFrac = progress / steps;;
width = qMin(r.width(), (int)(widthFrac * r.width()));
height = qMin(r.height(), (int)(widthFrac * r.height()));
}
//If there is any indicator, we do two paths, with different
//clipping rects, for the two colors.
if (width || height)
{
if (horizontal)
p->setClipRect(handleRTL(option, QRect(r.x(), r.y(), width, r.height())));
else if (!reverseLayout)
p->setClipRect(QRect(r.height()-height, 0, r.height(), r.width()));
else
p->setClipRect(QRect(0, 0, height, r.width()));
lbOpt.color = QPalette::HighlightedText;
drawKStylePrimitive(WT_ProgressBar, Generic::Text, option,
horizontal? r: QRect(0,0,r.height(),r.width()),
pal, flags, p, widget, &lbOpt);
if (horizontal)
p->setClipRect(handleRTL(option, QRect(r.x() + width, r.y(), r.width() - width, r.height())));
else if (!reverseLayout)
p->setClipRect(QRect(0, 0, r.height()-height, r.width()));
else
p->setClipRect(QRect(height, 0, r.height()-height, r.width()));
lbOpt.color = QPalette::ButtonText;
drawKStylePrimitive(WT_ProgressBar, Generic::Text, option,
horizontal? r: QRect(0,0,r.height(),r.width()),
pal, flags, p, widget, &lbOpt);
p->setClipping(false);
}
else
{
lbOpt.color = QPalette::ButtonText;
drawKStylePrimitive(WT_ProgressBar, Generic::Text, option,
horizontal? r: QRect(0,0,r.height(),r.width()),
pal, flags, p, widget, &lbOpt);
}
}
p->restore();
}
return;
}
case CE_MenuBarItem:
{
const QStyleOptionMenuItem* mOpt = ::qstyleoption_cast<const QStyleOptionMenuItem*>(option);
if (!mOpt) return;
//Bevel...
drawKStylePrimitive(WT_MenuBarItem, MenuBarItem::Panel, option, r,
pal, flags, p, widget);
//Text...
QRect textRect = insideMargin(r, WT_MenuBarItem, MenuBarItem::Margin, option, widget);
TextOption lbOpt(mOpt->text);
drawKStylePrimitive(WT_MenuBarItem, Generic::Text, option, textRect,
pal, flags, p, widget, &lbOpt);
return;
}
case CE_MenuBarEmptyArea:
{
drawKStylePrimitive(WT_MenuBar, MenuBar::EmptyArea, option, r,
pal, flags, p, widget);
return;
}
case CE_MenuEmptyArea:
case CE_MenuVMargin:
case CE_MenuHMargin:
{
drawKStylePrimitive(WT_Menu, Menu::Background, option, r,
pal, flags, p, widget);
return;
}
case CE_MenuItem:
{
//First of all,render the background.
drawKStylePrimitive(WT_Menu, Menu::Background, option, r,
pal, flags, p, widget);
const QStyleOptionMenuItem* miOpt = ::qstyleoption_cast<const QStyleOptionMenuItem*>(option);
if (!miOpt || miOpt->menuItemType == QStyleOptionMenuItem::EmptyArea) return;
//Remove the margin (for everything but the column background)
QRect ir = insideMargin(r, WT_MenuItem, MenuItem::Margin, option, widget);
//First, figure out the left column width. When CheckAlongsideIcon is disabled it's just
// the icon column width. Otherwise it consists of CheckWidth+CheckSpace+icon column width.
int iconColW = miOpt->maxIconWidth;
iconColW = qMax(iconColW, widgetLayoutProp(WT_MenuItem, MenuItem::IconWidth, option, widget));
int checkColW = widgetLayoutProp(WT_MenuItem, MenuItem::CheckWidth, option, widget);
int checkSpace = widgetLayoutProp(WT_MenuItem, MenuItem::CheckSpace, option, widget);
int leftColW = iconColW;
// only use the additional check row if the menu has checkable menuItems.
bool checkAlongsideIcon = (miOpt->menuHasCheckableItems &&
widgetLayoutProp(WT_MenuItem, MenuItem::CheckAlongsideIcon, option, widget) );
if (checkAlongsideIcon)
{
leftColW = checkColW + checkSpace + iconColW;
}
//And the right arrow column...
int rightColW = widgetLayoutProp(WT_MenuItem, MenuItem::ArrowSpace, option, widget) +
widgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, option, widget);
//Render left column background. This is a bit tricky, since we don't use the V margin.
QRect leftColRect(ir.x(), r.y(), leftColW, r.height());
drawKStylePrimitive(WT_MenuItem, MenuItem::CheckColumn, option, handleRTL(option, leftColRect),
pal, flags, p, widget);
//Separators: done with the bg, can paint them and bail them out.
if (miOpt->menuItemType == QStyleOptionMenuItem::Separator)
{
drawKStylePrimitive(WT_MenuItem, MenuItem::Separator, option, ir, pal, flags, p, widget);
return;
}
//Now paint the active indicator --- other stuff goes on top of it
bool active = (flags & State_Selected);
//Active indicator...
if (active)
drawKStylePrimitive(WT_MenuItem, MenuItem::ItemIndicator, option, handleRTL(option, r), pal, flags, p, widget);
ColorMode textColor = (flags & State_Enabled) ? (widgetLayoutProp(WT_MenuItem, active ?
MenuItem::ActiveTextColor :
MenuItem::TextColor, option, widget))
: (widgetLayoutProp(WT_MenuItem, active ?
MenuItem::ActiveDisabledTextColor:
MenuItem::DisabledTextColor, option, widget));
//Readjust the column rectangle back to proper height
leftColRect = QRect(ir.x(), ir.y(), leftColW, ir.height());
// Paint checkbox, etc.
if (!checkAlongsideIcon && !miOpt->icon.isNull() )
{
// there is an icon and the item is checked, so paint a CheckIcon
if (miOpt->checked)
{
drawKStylePrimitive(WT_MenuItem, MenuItem::CheckIcon,
option, handleRTL(option, leftColRect), pal, flags,
p, widget);
}
}
else
{
// paint a normal check- resp. radiomark.
QRect checkColRect;
if (checkAlongsideIcon)
{
checkColRect = QRect(leftColRect.x(), leftColRect.y(),
checkColW, leftColRect.height() );
}
else
{
checkColRect = leftColRect;
}
bool checked = miOpt->checked;
if (miOpt->checkType == QStyleOptionMenuItem::NonExclusive)
{
drawKStylePrimitive(WT_MenuItem, checked ? MenuItem::CheckOn : MenuItem::CheckOff,
option, handleRTL(option, checkColRect), pal, flags,
p, widget);
}
else if (miOpt->checkType == QStyleOptionMenuItem::Exclusive)
{
drawKStylePrimitive(WT_MenuItem, checked ? MenuItem::RadioOn : MenuItem::RadioOff,
option, handleRTL(option, checkColRect), pal, flags,
p, widget);
}
}
// Paint the menu icon.
if (!miOpt->icon.isNull())
{
int iconSize = pixelMetric(PM_SmallIconSize);
QRect iconColRect;
if (checkAlongsideIcon)
{
iconColRect = QRect(leftColRect.x()+checkColW+checkSpace, leftColRect.y(),
leftColRect.width()-(checkColW+checkSpace), leftColRect.height() );
}
else
{
iconColRect = leftColRect;
}
IconOption icoOpt;
icoOpt.icon = miOpt->icon;
icoOpt.active = flags & State_Selected;
drawKStylePrimitive(WT_MenuItem, Generic::Icon, option,
handleRTL(option, centerRect(iconColRect, iconSize, iconSize)),
pal, flags, p, widget, &icoOpt);
}
//Now include the spacing when calculating the next columns
leftColW += widgetLayoutProp(WT_MenuItem, MenuItem::IconSpace, option, widget);
//Render the text, including any accel.
QString text = miOpt->text;
QRect textRect = QRect(ir.x() + leftColW, ir.y(), ir.width() - leftColW - rightColW, ir.height());
QFont font = miOpt->font;
const QFont oldFont = p->font();
p->setFont(font);
int tabPos = miOpt->text.indexOf(QLatin1Char('\t'));
if (tabPos != -1)
{
text = miOpt->text.left(tabPos);
QString accl = miOpt->text.mid (tabPos + 1);
//Draw the accel.
TextOption lbOpt(accl);
lbOpt.color = textColor;
lbOpt.hAlign = Qt::AlignRight;
drawKStylePrimitive(WT_MenuItem, Generic::Text, option, handleRTL(option, textRect),
pal, flags, p, widget, &lbOpt);
}
//Draw the text.
TextOption lbOpt(text);
lbOpt.color = textColor;
drawKStylePrimitive(WT_MenuItem, Generic::Text, option, handleRTL(option, textRect),
pal, flags, p, widget, &lbOpt);
p->setFont(oldFont);
//Render arrow, if need be.
if (miOpt->menuItemType == QStyleOptionMenuItem::SubMenu)
{
ColorOption arrowColor;
arrowColor.color = textColor;
int aw = widgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, option, widget);
QRect arrowRect(ir.x() + ir.width() - aw, ir.y(), aw, ir.height());
drawKStylePrimitive(WT_MenuItem, option->direction == Qt::LeftToRight ?
Generic::ArrowRight : Generic::ArrowLeft,
option, handleRTL(option, arrowRect), pal, flags, p, widget, &arrowColor);
}
return;
}
case CE_ScrollBarAddLine:
case CE_ScrollBarSubLine:
{
const QStyleOptionSlider* slOpt = ::qstyleoption_cast<const QStyleOptionSlider*>(option);
if (!slOpt) return;
//Fix up the rectangle to be what we want
r = internalSubControlRect(CC_ScrollBar, slOpt,
element == CE_ScrollBarAddLine ? SC_ScrollBarAddLine : SC_ScrollBarSubLine, widget);
const_cast<QStyleOption*>(option)->rect = r;
bool doubleButton = false;
//See whether we're a double-button...
if (element == CE_ScrollBarAddLine && widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, option, widget))
doubleButton = true;
if (element == CE_ScrollBarSubLine && widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, option, widget))
doubleButton = true;
if (doubleButton)
{
if (flags & State_Horizontal)
{
DoubleButtonOption::ActiveButton ab = DoubleButtonOption::None;
//Depending on RTL direction, the one on the left is either up or down.
bool leftAdds, rightAdds;
if (slOpt->direction == Qt::LeftToRight)
{
leftAdds = false;
rightAdds = true;
}
else
{
leftAdds = true;
rightAdds = false;
}
//Determine whether any of the buttons is active
if (flags & State_Sunken)
{
if (((slOpt->activeSubControls & SC_ScrollBarAddLine) && leftAdds) ||
((slOpt->activeSubControls & SC_ScrollBarSubLine) && !leftAdds))
ab = DoubleButtonOption::Left;
if (((slOpt->activeSubControls & SC_ScrollBarAddLine) && rightAdds) ||
((slOpt->activeSubControls & SC_ScrollBarSubLine) && !rightAdds))
ab = DoubleButtonOption::Right;
}
DoubleButtonOption bOpt(ab);
drawKStylePrimitive(WT_ScrollBar, ScrollBar::DoubleButtonHor,
option, r, pal, flags, p, widget, &bOpt);
//Draw the left arrow..
QRect leftSubButton = QRect(r.x(), r.y(), r.width()/2, r.height());
ColorOption colOpt;
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
if (ab == DoubleButtonOption::Left)
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
drawKStylePrimitive(WT_ScrollBar, Generic::ArrowLeft, option, leftSubButton, pal,
flags, p, widget, &colOpt);
//Right half..
QRect rightSubButton;
rightSubButton.setBottomRight(r.bottomRight());
rightSubButton.setLeft (leftSubButton.right() + 1);
rightSubButton.setTop (r.top());
//Chose proper color
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
if (ab == DoubleButtonOption::Right)
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
drawKStylePrimitive(WT_ScrollBar, Generic::ArrowRight, option, rightSubButton, pal,
flags, p, widget, &colOpt);
}
else
{
DoubleButtonOption::ActiveButton ab = DoubleButtonOption::None;
//Determine whether any of the buttons is active
//Qt sets both sunken and activeSubControls for active,
//just activeSubControls for hover.
if (flags & State_Sunken)
{
if (slOpt->activeSubControls & SC_ScrollBarSubLine)
ab = DoubleButtonOption::Top;
if (slOpt->activeSubControls & SC_ScrollBarAddLine)
ab = DoubleButtonOption::Bottom;
}
//Paint the bevel
DoubleButtonOption bOpt(ab);
drawKStylePrimitive(WT_ScrollBar, ScrollBar::DoubleButtonVert,
option, r, pal, flags, p, widget, &bOpt);
//Paint top button.
ColorOption colOpt;
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
if (ab == DoubleButtonOption::Top)
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
QRect topSubButton = QRect(r.x(), r.y(), r.width(), r.height()/2);
drawKStylePrimitive(WT_ScrollBar, Generic::ArrowUp, option, topSubButton, pal,
flags, p, widget, &colOpt);
//Paint bot button
QRect botSubButton;
botSubButton.setBottomRight(r.bottomRight());
botSubButton.setLeft (r.left());
botSubButton.setTop (topSubButton.bottom() + 1);
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
if (ab == DoubleButtonOption::Bottom)
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
drawKStylePrimitive(WT_ScrollBar, Generic::ArrowDown, option, botSubButton, pal,
flags, p, widget, &colOpt);
}
}
else
{ // Single button
if (flags & State_Horizontal)
{
drawKStylePrimitive(WT_ScrollBar, ScrollBar::SingleButtonHor,
option, r, pal, flags, p, widget);
int primitive;
bool active = false;
if (element == CE_ScrollBarAddLine)
{
if (slOpt->direction == Qt::LeftToRight)
primitive = Generic::ArrowRight;
else
primitive = Generic::ArrowLeft;
if ((slOpt->activeSubControls & SC_ScrollBarAddLine) && (flags & State_Sunken))
active = true;
}
else
{
if (slOpt->direction == Qt::LeftToRight)
primitive = Generic::ArrowLeft;
else
primitive = Generic::ArrowRight;
if ((slOpt->activeSubControls & SC_ScrollBarSubLine) && (flags & State_Sunken))
active = true;
}
ColorOption colOpt;
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
if (active)
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
drawKStylePrimitive(WT_ScrollBar, primitive, option, r, pal,
flags, p, widget, &colOpt);
}
else
{
drawKStylePrimitive(WT_ScrollBar, ScrollBar::SingleButtonVert,
option, r, pal, flags, p, widget);
int primitive;
bool active = false;
if (element == CE_ScrollBarAddLine)
{
primitive = Generic::ArrowDown;
if ((slOpt->activeSubControls & SC_ScrollBarAddLine) && (flags & State_Sunken))
active = true;
}
else
{
primitive = Generic::ArrowUp;
if ((slOpt->activeSubControls & SC_ScrollBarSubLine) && (flags & State_Sunken))
active = true;
}
ColorOption colOpt;
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
if (active)
colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
drawKStylePrimitive(WT_ScrollBar, primitive, option, r, pal,
flags, p, widget, &colOpt);
}
}
return;
}
// TODO: what about CE_ScrollBarFirst, CE_ScrollBarLast...?
// case CE_ScrollBarFirst:
// case CE_ScrollBarLast:
case CE_ScrollBarSlider:
{
drawKStylePrimitive(WT_ScrollBar,
(flags & State_Horizontal) ? ScrollBar::SliderHor :
ScrollBar::SliderVert,
option, r, pal, flags, p, widget);
return;
}
case CE_ScrollBarAddPage:
{
const QStyleOptionSlider* slOpt = ::qstyleoption_cast<const QStyleOptionSlider*>(option);
if (!slOpt) return;
if (flags & State_Horizontal)
drawKStylePrimitive(WT_ScrollBar,
(slOpt->direction == Qt::LeftToRight) ? ScrollBar::GrooveAreaHorRight :
ScrollBar::GrooveAreaHorLeft,
option, r, pal, flags, p, widget);
else
drawKStylePrimitive(WT_ScrollBar, ScrollBar::GrooveAreaVertBottom,
option, r, pal, flags, p, widget);
return;
}
case CE_ScrollBarSubPage:
{
const QStyleOptionSlider* slOpt = ::qstyleoption_cast<const QStyleOptionSlider*>(option);
if (!slOpt) return;
if (flags & State_Horizontal)
drawKStylePrimitive(WT_ScrollBar,
(slOpt->direction == Qt::LeftToRight) ? ScrollBar::GrooveAreaHorLeft :
ScrollBar::GrooveAreaHorRight,
option, r, pal, flags, p, widget);
else
drawKStylePrimitive(WT_ScrollBar, ScrollBar::GrooveAreaVertTop,
option, r, pal, flags, p, widget);
return;
}
//QCS's CE_TabBarTab is perfectly fine, so we just handle the subbits
case CE_TabBarTabShape:
{
const QStyleOptionTab* tabOpt = qstyleoption_cast<const QStyleOptionTab*>(option);
if (!tabOpt) return;
// TabOverlap handling
int tabOverlap = pixelMetric(PM_TabBarTabOverlap, option, widget);
bool beginning = tabOpt->position == QStyleOptionTab::Beginning;
bool onlyOne = tabOpt->position == QStyleOptionTab::OnlyOneTab;
if (!beginning && !onlyOne) {
switch (tabSide(tabOpt)) {
case North:
case South:
if (option->direction == Qt::LeftToRight)
r.adjust(-tabOverlap, 0, 0, 0);
else
r.adjust(0, 0, tabOverlap, 0);
break;
case East:
case West:
r.adjust(0, -tabOverlap, 0, 0);
default:
break;
}
}
int prim;
switch (tabSide(tabOpt))
{
case North:
prim = TabBar::NorthTab; break;
case South:
prim = TabBar::SouthTab; break;
case East:
prim = TabBar::EastTab; break;
default:
prim = TabBar::WestTab; break;
}
drawKStylePrimitive(WT_TabBar, prim, option, r, pal, flags, p, widget);
return;
}
case CE_TabBarTabLabel:
{
const QStyleOptionTab* tabOpt = qstyleoption_cast<const QStyleOptionTab*>(option);
if (!tabOpt) return;
//First, we get our content region.
QRect labelRect = subElementRect(SE_TabBarTabText, option, widget);
Side tabSd = tabSide(tabOpt);
//Now, what we do, depends on rotation, LTR vs. RTL, and text/icon combinations.
//First, figure out if we have to deal with icons, and place them if need be.
if (!tabOpt->icon.isNull())
{
QStyleOptionTabV3 tabV3(*tabOpt);
QSize iconSize = tabV3.iconSize;
if (!iconSize.isValid()) {
int iconExtent = pixelMetric(PM_SmallIconSize);
iconSize = QSize(iconExtent, iconExtent);
}
IconOption icoOpt;
icoOpt.icon = tabOpt->icon;
icoOpt.active = flags & State_Selected;
icoOpt.size = iconSize;
if (tabOpt->text.isNull())
{
//Icon only. Easy.
drawKStylePrimitive(WT_TabBar, Generic::Icon, option, labelRect,
pal, flags, p, widget, &icoOpt);
return;
}
//OK, we have to stuff both icon and text. So we figure out where to stick the icon.
QRect iconRect;
if (tabSd == North || tabSd == South)
{
//OK, this is simple affair, we just pick a side for the icon
//based on layout direction. (Actually, I guess text
//would be more accurate, but I am -so- not doing BIDI here)
if (tabOpt->direction == Qt::LeftToRight)
{
//We place icon on the left.
iconRect = QRect(labelRect.x(), labelRect.y() + (labelRect.height() - iconSize.height() + 1) / 2,
iconSize.width(), iconSize.height());
//Adjust the text rect.
labelRect.setLeft(labelRect.x() + iconSize.width() +
widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget));
}
else
{
//We place icon on the right
iconRect = QRect(labelRect.x() + labelRect.width() - iconSize.width(),
labelRect.y() + (labelRect.height() - iconSize.height() + 1) / 2, iconSize.width(), iconSize.height());
//Adjust the text rect
labelRect.setWidth(labelRect.width() - iconSize.width() -
widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget));
}
}
else
{
bool aboveIcon = false;
if (tabSd == West && tabOpt->direction == Qt::RightToLeft)
aboveIcon = true;
if (tabSd == East && tabOpt->direction == Qt::LeftToRight)
aboveIcon = true;
if (aboveIcon)
{
iconRect = QRect(labelRect.x() + (labelRect.width() - iconSize.width() + 1) / 2, labelRect.y(),
iconSize.width(), iconSize.height());
labelRect.setTop(labelRect.y() + iconSize.height() +
widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget));
}
else
{
iconRect = QRect(labelRect.x() + (labelRect.width() - iconSize.width() + 1) / 2,
labelRect.y() + labelRect.height() - iconSize.height(),
iconSize.width(), iconSize.height());
labelRect.setHeight(labelRect.height() - iconSize.height() -
widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget));
}
}
//Draw the thing
drawKStylePrimitive(WT_TabBar, Generic::Icon, option, iconRect,
pal, flags, p, widget, &icoOpt);
} //if have icon.
//Draw text
if (!tabOpt->text.isNull())
{
TextOption lbOpt(tabOpt->text);
if (widget)
lbOpt.color = widget->foregroundRole();
int primitive = Generic::Text; // For horizontal tabs
if (tabSd == East)
primitive = TabBar::EastText;
else if (tabSd == West)
primitive = TabBar::WestText;
drawKStylePrimitive(WT_TabBar, primitive, option, labelRect,
pal, flags, p, widget, &lbOpt);
}
//If need be, draw focus rect
if (tabOpt->state & State_HasFocus)
{
QRect focusRect = marginAdjustedTab(tabOpt, TabBar::TabFocusMargin);
drawKStylePrimitive(WT_TabBar, Generic::FocusIndicator, option, focusRect,
pal, flags, p, widget);
}
return;
}
case CE_ToolBar:
{
if (flags & State_Horizontal)
drawKStylePrimitive(WT_ToolBar, ToolBar::PanelHor,option,r,pal,flags,p,widget);
else
drawKStylePrimitive(WT_ToolBar, ToolBar::PanelVert,option,r,pal,flags,p,widget);
return;
}
case CE_HeaderSection:
{
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
drawKStylePrimitive(WT_Header, (header->orientation==Qt::Horizontal)?Header::SectionHor:Header::SectionVert,
option, r, pal, flags, p, widget);
return;
}
}
case CE_HeaderLabel:
{
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
QRect textRect = r;
if (!header->icon.isNull()) {
bool enabled = flags & State_Enabled;
QPixmap pm = header->icon.pixmap(pixelMetric(PM_SmallIconSize), enabled?QIcon::Normal:QIcon::Disabled);
// TODO: respect header->iconAlignment.
bool reverseLayout = header->direction == Qt::RightToLeft;
int iy = r.top()+(r.height()-pm.height())/2;
int ix = reverseLayout ? r.right()-pm.width() : r.left();
QRect iconRect = QRect(ix, iy, pm.width(), pm.height() );
IconOption iconOpt;
iconOpt.icon = pm;
drawKStylePrimitive(WT_Header, Generic::Icon, option, iconRect, pal, flags, p, widget, &iconOpt);
// adjust the rect for the text...
int spacing = widgetLayoutProp(WT_Header, Header::TextToIconSpace, option, widget);
if (reverseLayout)
{
textRect.setRight(r.right()-iconRect.width()-spacing );
}
else
{
textRect.setLeft(r.x()+iconRect.width()+spacing );
}
}
TextOption lbOpt(header->text);
lbOpt.hAlign = header->textAlignment;
drawKStylePrimitive(WT_Header, Generic::Text, option, textRect, pal, flags, p, widget, &lbOpt);
}
return;
}
case CE_Splitter:
{
if (flags&State_Horizontal)
drawKStylePrimitive(WT_Splitter, Splitter::HandleHor, option, r, pal, flags, p, widget);
else
drawKStylePrimitive(WT_Splitter, Splitter::HandleVert, option, r, pal, flags, p, widget);
return;
}
default:
break;
}
QCommonStyle::drawControl(element, option, p, widget);
}
int KStyle::styleHint (StyleHint hint, const QStyleOption* option, const QWidget* widget, QStyleHintReturn* returnData) const
{
switch (hint)
{
case SH_ComboBox_ListMouseTracking:
return true;
case SH_MenuBar_MouseTracking:
case SH_Menu_MouseTracking:
return true;
case SH_Menu_SubMenuPopupDelay:
return 96; // Motif-like delay...
case SH_TitleBar_NoBorder:
return widgetLayoutProp(WT_Window, Window::NoTitleFrame, option, widget);
case SH_GroupBox_TextLabelVerticalAlignment:
if (widgetLayoutProp(WT_GroupBox, GroupBox::TextAlignTop, option, widget) )
return Qt::AlignTop;
else
return Qt::AlignVCenter;
case SH_GroupBox_TextLabelColor:
{
ColorMode cm( widgetLayoutProp(WT_GroupBox, GroupBox::TitleTextColor,
option, widget) );
return cm.color(option ? option->palette : qApp->palette()).rgba();
}
case SH_DialogButtonLayout:
return QDialogButtonBox::KdeLayout;
case SH_ScrollBar_MiddleClickAbsolutePosition:
return true;
// Don't draw the branch as selected in tree views
case SH_ItemView_ShowDecorationSelected:
return false;
case SH_ItemView_ActivateItemOnSingleClick:
return d->m_componentData.config()->group("KDE").readEntry("SingleClick", KDE_DEFAULT_SINGLECLICK );
case SH_KCustomStyleElement:
if (!widget)
return 0;
return d->styleElements.value(widget->objectName(), 0);
// per HIG, align the contents in a form layout to the left
case SH_FormLayoutFormAlignment:
return Qt::AlignLeft | Qt::AlignTop;
// per HIG, align the labels in a form layout to the right
case SH_FormLayoutLabelAlignment:
return Qt::AlignRight;
case SH_FormLayoutFieldGrowthPolicy:
return QFormLayout::ExpandingFieldsGrow;
case SH_FormLayoutWrapPolicy:
return QFormLayout::DontWrapRows;
case SH_MessageBox_TextInteractionFlags:
return true;
case SH_DialogButtonBox_ButtonsHaveIcons:
return KGlobalSettings::showIconsOnPushButtons();
case SH_ItemView_ArrowKeysNavigateIntoChildren:
return true;
default:
break;
};
return QCommonStyle::styleHint(hint, option, widget, returnData);
}
int KStyle::pixelMetric(PixelMetric metric, const QStyleOption* option, const QWidget* widget) const
{
switch (metric)
{
case PM_SmallIconSize:
case PM_ButtonIconSize:
return KIconLoader::global()->currentSize(KIconLoader::Small);
case PM_ToolBarIconSize:
return KIconLoader::global()->currentSize(KIconLoader::Toolbar);
case PM_LargeIconSize:
return KIconLoader::global()->currentSize(KIconLoader::Dialog);
case PM_MessageBoxIconSize:
// TODO return KIconLoader::global()->currentSize(KIconLoader::MessageBox);
return KIconLoader::SizeHuge;
case PM_DefaultFrameWidth:
if (qstyleoption_cast<const QStyleOptionGroupBox *>(option) )
return widgetLayoutProp(WT_GroupBox, GroupBox::FrameWidth, option, widget);
else
return widgetLayoutProp(WT_Generic, Generic::DefaultFrameWidth, option, widget);
case PM_DefaultChildMargin:
case PM_DefaultTopLevelMargin:
return widgetLayoutProp(WT_Generic, Generic::DefaultLayoutMargin, option, widget);
case PM_LayoutHorizontalSpacing:
case PM_LayoutVerticalSpacing:
// use layoutSpacingImplementation
return -1;
case PM_DefaultLayoutSpacing:
return widgetLayoutProp(WT_Generic, Generic::DefaultLayoutSpacing, option, widget);
case PM_LayoutLeftMargin:
case PM_LayoutTopMargin:
case PM_LayoutRightMargin:
case PM_LayoutBottomMargin:
{
PixelMetric marginMetric;
if ((option && (option->state & QStyle::State_Window))
|| (widget && widget->isWindow())) {
marginMetric = PM_DefaultTopLevelMargin;
} else {
marginMetric = PM_DefaultChildMargin;
}
return pixelMetric(marginMetric, option, widget);
}
case PM_ButtonMargin:
return 0; //Better not return anything here since we already
//incorporated this into SE_PushButtonContents
case PM_ButtonDefaultIndicator:
// PushButton::DefaultIndicatorMargin is used throughout KStyle button
// implementation code, so this probably is not necessary.
// return it in case Apps rely on this metric, though.
return widgetLayoutProp(WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
case PM_ButtonShiftHorizontal:
return widgetLayoutProp(WT_PushButton, PushButton::PressedShiftHorizontal, option, widget);
case PM_ButtonShiftVertical:
return widgetLayoutProp(WT_PushButton, PushButton::PressedShiftVertical, option, widget);
case PM_MenuButtonIndicator:
if (qstyleoption_cast<const QStyleOptionToolButton*>(option))
return widgetLayoutProp(WT_ToolButton, ToolButton::MenuIndicatorSize, option, widget);
else
return widgetLayoutProp(WT_PushButton, PushButton::MenuIndicatorSize, option, widget);
case PM_SplitterWidth:
return widgetLayoutProp(WT_Splitter, Splitter::Width, option, widget);
case PM_IndicatorWidth:
case PM_IndicatorHeight:
return widgetLayoutProp(WT_CheckBox, CheckBox::Size, option, widget);
case PM_ExclusiveIndicatorWidth:
case PM_ExclusiveIndicatorHeight:
return widgetLayoutProp(WT_RadioButton, RadioButton::Size, option, widget);
case PM_CheckListControllerSize:
case PM_CheckListButtonSize:
{
int checkBoxSize = widgetLayoutProp(WT_CheckBox, CheckBox::Size, option, widget);
int radioButtonSize = widgetLayoutProp(WT_RadioButton, RadioButton::Size, option, widget);
return qMax(checkBoxSize, radioButtonSize);
}
case PM_DockWidgetFrameWidth:
return widgetLayoutProp(WT_DockWidget, DockWidget::FrameWidth, option, widget);
case PM_DockWidgetSeparatorExtent:
return widgetLayoutProp(WT_DockWidget, DockWidget::SeparatorExtent, option, widget);
// handle extent only used somewhere in Qt3support, don't care.
// case PM_DockWidgetHandleExtent:
case PM_DockWidgetTitleMargin:
return widgetLayoutProp(WT_DockWidget, DockWidget::TitleMargin, option, widget);
case PM_ProgressBarChunkWidth:
return widgetLayoutProp(WT_ProgressBar, ProgressBar::Precision, option, widget);
case PM_MenuBarPanelWidth:
return 0; //Simplification: just one primitive is used and it includes the border
case PM_MenuBarHMargin:
{
//Calculate how much extra space we need besides the frame size. We use the left margin
//here, and adjust the total rect by the difference between it and the right margin
int spaceL = widgetLayoutProp(WT_MenuBar, MenuBar::Margin, option, widget) + widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Left, option, widget);
return spaceL;
}
case PM_MenuBarVMargin:
{
//As above, we return the top one, and fudge the total size for the bottom.
int spaceT = widgetLayoutProp(WT_MenuBar, MenuBar::Margin, option, widget) + widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Top, option, widget);
return spaceT;
}
case PM_MenuBarItemSpacing:
return widgetLayoutProp(WT_MenuBar, MenuBar::ItemSpacing, option, widget);
case PM_MenuDesktopFrameWidth:
return 0; //### CHECKME
case PM_MenuPanelWidth:
return widgetLayoutProp(WT_Menu, Menu::FrameWidth, option, widget);
/* ### seems to trigger Qt bug. So we loose the margins for now
case PM_MenuHMargin:
{
//Calculate how much extra space we need besides the frame size. We use the left margin
//here, and adjust the total rect by the difference between it and the right margin
int spaceL = widgetLayoutProp(WT_Menu, Menu::Margin, option, widget) + widgetLayoutProp(WT_Menu, Menu::Margin + Left, option, widget) -
widgetLayoutProp(WT_Menu, Menu::FrameWidth, option, widget);
return spaceL;
}
case PM_MenuVMargin:
{
//As above, we return the top one, and fudge the total size for the bottom.
int spaceT = widgetLayoutProp(WT_Menu, Menu::Margin, option, widget) + widgetLayoutProp(WT_Menu, Menu::Margin + Top, option, widget) -
widgetLayoutProp(WT_Menu, Menu::FrameWidth, option, widget);
return spaceT;
} */
case PM_MenuScrollerHeight:
return widgetLayoutProp(WT_Menu, Menu::ScrollerHeight, option, widget);
case PM_MenuTearoffHeight:
return widgetLayoutProp(WT_Menu, Menu::TearOffHeight, option, widget);
case PM_TabBarTabHSpace:
{
const QStyleOptionTab* tabOpt = qstyleoption_cast<const QStyleOptionTab*>(option);
if (tabOpt)
{
//Perhaps we can avoid the extra margin...
if (tabOpt->text.isNull() && !tabOpt->icon.isNull())
return 0;
if (tabOpt->icon.isNull() && !tabOpt->text.isNull())
return 0;
}
return widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget);
}
case PM_TabBarTabVSpace:
return 0;
case PM_TabBarBaseHeight:
return widgetLayoutProp(WT_TabBar, TabBar::BaseHeight, option, widget);
case PM_TabBarBaseOverlap:
return widgetLayoutProp(WT_TabBar, TabBar::BaseOverlap, option, widget);
case PM_TabBarTabOverlap:
return widgetLayoutProp(WT_TabBar, TabBar::TabOverlap, option, widget);
case PM_TabBarScrollButtonWidth:
return widgetLayoutProp(WT_TabBar, TabBar::ScrollButtonWidth, option, widget);
case PM_TabBarTabShiftVertical:
return 1;
case PM_TabBarTabShiftHorizontal:
return 0;
case PM_SliderControlThickness:
return widgetLayoutProp(WT_Slider, Slider::HandleThickness, option, widget);
case PM_SliderLength:
return widgetLayoutProp(WT_Slider, Slider::HandleLength, option, widget);
case PM_SliderThickness:
{
// not sure what the difference to PM_SliderControlThickness actually is
return widgetLayoutProp(WT_Slider, Slider::HandleThickness, option, widget);
}
case PM_SpinBoxFrameWidth:
return widgetLayoutProp(WT_SpinBox, SpinBox::FrameWidth, option, widget);
case PM_ComboBoxFrameWidth:
return widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget);
case PM_HeaderMarkSize:
return widgetLayoutProp(WT_Header, Header::MarkSize, option, widget);
case PM_HeaderMargin:
return widgetLayoutProp(WT_Header, Header::TextToIconSpace, option, widget);
case PM_ToolBarFrameWidth:
return widgetLayoutProp(WT_ToolBar, ToolBar::FrameWidth, option, widget);
case PM_ToolBarHandleExtent:
return widgetLayoutProp(WT_ToolBar, ToolBar::HandleExtent, option, widget);
case PM_ToolBarSeparatorExtent:
return widgetLayoutProp(WT_ToolBar, ToolBar::SeparatorExtent, option, widget);
case PM_ToolBarExtensionExtent:
return widgetLayoutProp(WT_ToolBar, ToolBar::ExtensionExtent, option, widget);
case PM_ToolBarItemMargin:
return widgetLayoutProp(WT_ToolBar, ToolBar::ItemMargin, option, widget);
case PM_ToolBarItemSpacing:
return widgetLayoutProp(WT_ToolBar, ToolBar::ItemSpacing, option, widget);
case PM_ScrollBarExtent:
return widgetLayoutProp(WT_ScrollBar, ScrollBar::BarWidth, option, widget);
case PM_TitleBarHeight:
return widgetLayoutProp(WT_Window, Window::TitleHeight, option, widget);
default:
break;
}
return QCommonStyle::pixelMetric(metric, option, widget);
}
int KStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget) const
{
Q_UNUSED(control1); Q_UNUSED(control2); Q_UNUSED(orientation);
return pixelMetric(PM_DefaultLayoutSpacing, option, widget);
}
bool KStyle::isVerticalTab(const QStyleOptionTab* tbOpt) const
{
switch (tbOpt->shape)
{
case QTabBar::RoundedWest:
case QTabBar::RoundedEast:
case QTabBar::TriangularWest:
case QTabBar::TriangularEast:
return true;
default:
return false;
}
}
bool KStyle::isReflectedTab(const QStyleOptionTab* tbOpt) const
{
switch (tbOpt->shape)
{
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
case QTabBar::RoundedSouth:
case QTabBar::TriangularSouth:
return true;
default:
return false;
}
}
KStyle::Side KStyle::tabSide(const QStyleOptionTab* tbOpt) const
{
switch (tbOpt->shape)
{
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
return East;
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
return West;
case QTabBar::RoundedNorth:
case QTabBar::TriangularNorth:
return North;
default:
return South;
}
}
QRect KStyle::marginAdjustedTab(const QStyleOptionTab* tabOpt, int property) const
{
QRect r = tabOpt->rect;
//For region, we first figure out the geometry if it was normal, and adjust.
//this takes some rotating
bool vertical = isVerticalTab (tabOpt);
bool flip = isReflectedTab(tabOpt);
QRect idializedGeometry = vertical ? QRect(0, 0, r.height(), r.width())
: QRect(0, 0, r.width(), r.height());
QRect contentArea = insideMargin(idializedGeometry, WT_TabBar, property, tabOpt, 0);
int leftMargin = contentArea.x();
int rightMargin = idializedGeometry.width() - 1 - contentArea.right();
int topMargin = contentArea.y();
int botMargin = idializedGeometry.height() - 1 - contentArea.bottom();
if (vertical)
{
int t = rightMargin;
rightMargin = topMargin;
topMargin = leftMargin;
leftMargin = botMargin;
botMargin = t;
if (!flip)
qSwap(leftMargin, rightMargin);
}
else if (flip)
{
qSwap(topMargin, botMargin);
//For horizontal tabs, we also want to reverse stuff for RTL!
if (tabOpt->direction == Qt::RightToLeft)
qSwap(leftMargin, rightMargin);
}
QRect geom =
QRect(QPoint(leftMargin, topMargin),
QPoint(r.width() - 1 - rightMargin,
r.height() - 1 - botMargin));
geom.translate(r.topLeft());
return geom;
}
bool KStyle::useSideText(const QStyleOptionProgressBar* pbOpt) const
{
if (widgetLayoutProp(WT_ProgressBar, ProgressBar::SideText) == 0)
return false;
if (!pbOpt) return false; //Paranoia
if (!pbOpt->textVisible) return false; //Don't allocate side margin if text display is off...
if (pbOpt->textAlignment & Qt::AlignHCenter) return false; //### do we want this? we don't
//force indicator to the side outside
//the main otherwise.
if (pbOpt->minimum == pbOpt->maximum) return false;
int widthAlloc = pbOpt->fontMetrics.width(QLatin1String("100%"));
if (pbOpt->fontMetrics.width(pbOpt->text) > widthAlloc)
return false; //Doesn't fit!
return true;
}
int KStyle::sideTextWidth(const QStyleOptionProgressBar* pbOpt) const
{
return pbOpt->fontMetrics.width(QLatin1String("100%")) +
2*widgetLayoutProp(WT_ProgressBar, ProgressBar::SideTextSpace);
}
QRect KStyle::subElementRect(SubElement sr, const QStyleOption* option, const QWidget* widget) const
{
QRect r = option->rect;
switch (sr)
{
case SE_PushButtonContents:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return r;
if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton))
r = insideMargin(r, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
return insideMargin(r, WT_PushButton, PushButton::ContentsMargin, option, widget);
}
case SE_PushButtonFocusRect:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return r;
if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton))
r = insideMargin(r, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
return insideMargin(r, WT_PushButton, PushButton::FocusMargin, option, widget);
}
case SE_ToolBoxTabContents:
{
return insideMargin(r, WT_ToolBoxTab, ToolBoxTab::Margin, option, widget);
}
case SE_CheckBoxContents:
{
r.setX(r.x() + widgetLayoutProp(WT_CheckBox, CheckBox::Size, option, widget) +
widgetLayoutProp(WT_CheckBox, CheckBox::BoxTextSpace, option, widget));
return handleRTL(option, r);
}
case SE_RadioButtonContents:
{
r.setX(r.x() + widgetLayoutProp(WT_RadioButton, RadioButton::Size, option, widget) +
widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget));
return handleRTL(option, r);
}
case SE_CheckBoxFocusRect:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return r;
QRect ret;
if (bOpt->text.isEmpty())
{
// first convert, so we can deal with logical coords
QRect checkRect =
handleRTL(option, subElementRect(SE_CheckBoxIndicator, option, widget) );
ret = insideMargin(checkRect, WT_CheckBox, CheckBox::NoLabelFocusMargin, option, widget);
}
else
{
// first convert, so we can deal with logical coords
QRect contentsRect =
handleRTL(option, subElementRect(SE_CheckBoxContents, option, widget) );
ret = insideMargin(contentsRect, WT_CheckBox, CheckBox::FocusMargin, option, widget);
}
// convert back to screen coords
return handleRTL(option, ret);
}
case SE_RadioButtonFocusRect:
{
// first convert it back to logical coords
QRect contentsRect =
handleRTL(option, subElementRect(SE_RadioButtonContents, option, widget) );
// modify the rect and convert back to screen coords
return handleRTL(option,
insideMargin(contentsRect, WT_RadioButton,
RadioButton::FocusMargin, option, widget) );
}
case SE_ProgressBarGroove:
{
const QStyleOptionProgressBar* pbOpt = ::qstyleoption_cast<const QStyleOptionProgressBar*>(option);
if (useSideText(pbOpt))
{
r.setWidth(r.width() - sideTextWidth(pbOpt));
return r;
}
//Centering mode --- could be forced or side... so the groove area is everything
return r;
}
case SE_ProgressBarContents:
{
QRect grooveRect = subElementRect(SE_ProgressBarGroove, option, widget);
return insideMargin(grooveRect, WT_ProgressBar, ProgressBar::GrooveMargin, option, widget);
}
case SE_ProgressBarLabel:
{
const QStyleOptionProgressBar* pbOpt = ::qstyleoption_cast<const QStyleOptionProgressBar*>(option);
if (useSideText(pbOpt))
{
int width = sideTextWidth(pbOpt);
return QRect(r.x() + r.width() - width, r.y(), width, r.height());
}
//The same as the contents area..
return subElementRect(SE_PushButtonContents, option, widget);
}
// SE_TabWidgetTabPane implementation in QCommonStyle is perfectly fine.
case SE_TabWidgetTabContents:
{
const QStyleOptionTabWidgetFrame* tabOpt = qstyleoption_cast<const QStyleOptionTabWidgetFrame*>(option);
if (!tabOpt) break;
// Don't apply the custom margin when documentMode is enabled.
if (tabOpt->lineWidth == 0) break;
// use QCommonStyle's SE_TabWidgetTabPane, and adjust the result
// according to the custom frame width.
QRect pane = QCommonStyle::subElementRect(SE_TabWidgetTabPane, option, widget);
int m = widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin, option, widget);
int top = m+widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin+Top,
option, widget);
int bot = m+widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin+Bot,
option, widget);
int left = m+widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin+Left,
option, widget);
int right = m+widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin+Right,
option, widget);
switch (tabOpt->shape) {
case QTabBar::RoundedNorth:
case QTabBar::TriangularNorth:
return pane.adjusted(left,top,-right,-bot);
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
return pane.adjusted(bot,left, -top,-right);
case QTabBar::RoundedSouth:
case QTabBar::TriangularSouth:
return pane.adjusted(right,bot, -left,-top);
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
return pane.adjusted(top,right, -bot,-left);
}
}
case SE_TabBarTabText:
{
const QStyleOptionTab* tabOpt = qstyleoption_cast<const QStyleOptionTab*>(option);
if (!tabOpt) return QRect();
QRect r = marginAdjustedTab(tabOpt, TabBar::TabContentsMargin);
QStyleOptionTabV3 tov3(*tabOpt);
switch (tov3.shape)
{
case QTabBar::RoundedNorth:
case QTabBar::TriangularNorth:
case QTabBar::RoundedSouth:
case QTabBar::TriangularSouth:
if (tov3.direction == Qt::LeftToRight)
r.adjust(tov3.leftButtonSize.width(), 0, -tov3.rightButtonSize.width(), 0);
else
r.adjust(tov3.rightButtonSize.width(), 0, -tov3.leftButtonSize.width(), 0);
break;
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
r.adjust(0, tov3.leftButtonSize.width(), 0, -tov3.rightButtonSize.width());
break;
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
r.adjust(0, tov3.rightButtonSize.width(), 0, -tov3.leftButtonSize.width());
break;
}
return r;
}
default:
break;
}
return QCommonStyle::subElementRect(sr, option, widget);
}
void KStyle::drawComplexControl (ComplexControl cc, const QStyleOptionComplex* opt,
QPainter *p, const QWidget* w) const
{
//Extract the stuff we need out of the option
State flags = opt->state;
QRect r = opt->rect;
QPalette pal = opt->palette;
switch (cc)
{
case CC_ScrollBar:
{
QStyleOptionComplex* mutableOpt = const_cast<QStyleOptionComplex*>(opt);
if ((mutableOpt->subControls & SC_ScrollBarSubLine) || (mutableOpt->subControls & SC_ScrollBarAddLine))
{
//If we paint one of the buttons, must paint both!
mutableOpt->subControls |= SC_ScrollBarSubPage | SC_ScrollBarAddLine;
}
//Note: we falldown to the base intentionally
}
break;
case CC_Q3ListView:
{
const QStyleOptionQ3ListView* lvOpt = qstyleoption_cast<const QStyleOptionQ3ListView*>(opt);
Q_ASSERT (lvOpt);
if (lvOpt->subControls & SC_Q3ListView)
QCommonStyle::drawComplexControl(cc, opt, p, w);
if (lvOpt->items.isEmpty())
return;
// If we have a branch or are expanded...
if (lvOpt->subControls & (SC_Q3ListViewBranch | SC_Q3ListViewExpand))
{
QStyleOptionQ3ListViewItem item = lvOpt->items.at(0);
int y = r.y();
QStyleOption opt; //For painting
opt.palette = lvOpt->palette;
opt.direction = Qt::LeftToRight;
//Remap the painter so (0,0) corresponds to the origin
//of the widget, to help out the line align code.
//Extract the paint offset. Here be dragons
//(and not the cute green Patron of the project, either)
int cX = w ? w->property("contentsX").toInt() : 0;
int cY = w ? w->property("contentsY").toInt() : 0;
QPoint adjustCoords = p->matrix().map(QPoint(0,0)) + QPoint(cX, cY);
p->translate(-adjustCoords);
if (lvOpt->activeSubControls == SC_All && (lvOpt->subControls & SC_Q3ListViewExpand)) {
//### CHECKME: this is from KStyle3, and needs to be re-checked/tested
// We only need to draw a vertical line
//Route through the Qt4 style-call.
QStyleOption opt;
opt.rect = QRect(r.topLeft() + adjustCoords, r.size());
opt.state = State_Sibling;
drawPrimitive(PE_IndicatorBranch, &opt, p, 0);
} else {
int childPos = 1;
// Draw all the expand/close boxes, and nearby branches
while (childPos < lvOpt->items.size() && y < r.height())
{
const QStyleOptionQ3ListViewItem& child = lvOpt->items.at(childPos);
if (!(child.features & QStyleOptionQ3ListViewItem::Visible))
{
childPos++;
continue;
}
//Route through the Qt4 style-call.
opt.rect = QRect(r.x() + adjustCoords.x(), y + adjustCoords.y(),
r.width(), child.height);
opt.state = State_Item;
if (child.features & QStyleOptionQ3ListViewItem::Expandable || child.childCount)
{
opt.state |= State_Children;
opt.state |= (child.state & State_Open);
}
//See if we have a visible sibling
int siblingPos = 0;
for (siblingPos = childPos + 1; siblingPos < lvOpt->items.size(); ++siblingPos)
{
if (lvOpt->items.at(siblingPos).features & QStyleOptionQ3ListViewItem::Visible)
{
opt.state |= State_Sibling;
break;
}
}
//If on screen, paint it
if (y + child.height > 0)
drawPrimitive(PE_IndicatorBranch, &opt, p, 0);
if (!siblingPos)
break;
//If we have a sibling, and an expander, also have to draw
//a line for below the immediate area
if ((opt.state & State_Children) && (opt.state & State_Sibling))
{
opt.state = State_Sibling;
opt.rect = QRect(r.x() + adjustCoords.x(),
y + adjustCoords.y() + child.height,
r.width(), child.totalHeight - child.height);
if (opt.rect.height())
drawPrimitive(PE_IndicatorBranch, &opt, p, 0);
}
y += child.totalHeight;
childPos = siblingPos;
} //loop through items
} //complex case
p->translate(adjustCoords);
} //if have branch or expander
} //CC_Q3ListView
break;
case CC_Slider:
{
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt))
{
QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, w);
QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, w);
bool hor = slider->orientation == Qt::Horizontal;
if (slider->subControls & SC_SliderTickmarks)
{
// TODO: make tickmarks customizable with Slider::Tickmark-primitives?
QStyleOptionSlider tmpSlider = *slider;
tmpSlider.subControls = SC_SliderTickmarks;
QCommonStyle::drawComplexControl(cc, &tmpSlider, p, w);
}
if ((slider->subControls & SC_SliderGroove) && groove.isValid())
{
drawKStylePrimitive(WT_Slider, hor ? Slider::GrooveHor : Slider::GrooveVert, opt, groove, pal, flags, p, w);
}
if (slider->subControls & SC_SliderHandle)
{
drawKStylePrimitive(WT_Slider, hor ? Slider::HandleHor : Slider::HandleVert, opt, handle, pal, flags, p, w);
if (slider->state & State_HasFocus) {
QRect focus = subElementRect(SE_SliderFocusRect, slider, w);
drawKStylePrimitive(WT_Slider, Generic::FocusIndicator, opt, focus, pal, flags, p, w, 0);
}
}
} //option OK
return;
} //CC_Slider
case CC_SpinBox:
{
if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt) )
{
bool activeSbUp = sb->activeSubControls&SC_SpinBoxUp && (flags & State_Sunken);
bool activeSbDown = sb->activeSubControls&SC_SpinBoxDown && (flags & State_Sunken);
if (sb->subControls & SC_SpinBoxFrame)
{
drawKStylePrimitive(WT_SpinBox, Generic::Frame, opt, r, pal, flags, p, w);
}
if (sb->subControls & SC_SpinBoxEditField)
{
QRect editField = subControlRect(CC_SpinBox, opt, SC_SpinBoxEditField, w);
drawKStylePrimitive(WT_SpinBox, SpinBox::EditField, opt, editField, pal, flags, p, w);
}
QRect upRect, downRect;
if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown))
{
upRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp, w);
downRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
QRect buttonAreaRect = upRect | downRect;
drawKStylePrimitive(WT_SpinBox, SpinBox::ButtonArea, opt, buttonAreaRect, pal, flags, p, w);
}
if (sb->subControls & SC_SpinBoxUp)
{
// adjust the sunken state flag...
State upFlags = flags;
if (activeSbUp)
upFlags |= State_Sunken;
else
upFlags &= ~State_Sunken;
drawKStylePrimitive(WT_SpinBox, SpinBox::UpButton, opt, upRect, pal, upFlags, p, w);
// draw symbol...
int primitive;
if (sb->buttonSymbols == QAbstractSpinBox::PlusMinus)
primitive = SpinBox::PlusSymbol;
else
primitive = Generic::ArrowUp;
drawKStylePrimitive(WT_SpinBox, primitive, opt, upRect, pal, upFlags, p, w);
}
if (sb->subControls & SC_SpinBoxDown)
{
// adjust the sunken state flag...
State downFlags = flags;
if (activeSbDown)
downFlags |= State_Sunken;
else
downFlags &= ~State_Sunken;
drawKStylePrimitive(WT_SpinBox, SpinBox::DownButton, opt, downRect, pal, downFlags, p, w);
// draw symbol...
int primitive;
if (sb->buttonSymbols == QAbstractSpinBox::PlusMinus)
primitive = SpinBox::MinusSymbol;
else
primitive = Generic::ArrowDown;
drawKStylePrimitive(WT_SpinBox, primitive, opt, downRect, pal, downFlags, p, w);
}
return;
} //option OK
} //CC_SpinBox
case CC_ComboBox:
{
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt) )
{
if (cb->subControls & SC_ComboBoxFrame)
{
drawKStylePrimitive(WT_ComboBox, Generic::Frame, opt, r, pal, flags, p, w);
// focus indicator
if (cb->state & State_HasFocus) {
QRect editField = subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, w);
QRect focusRect = insideMargin(editField, WT_ComboBox, ComboBox::FocusMargin, opt, w);
drawKStylePrimitive(WT_ComboBox, Generic::FocusIndicator, opt, focusRect, pal, flags, p, w, 0);
}
}
if (cb->subControls & SC_ComboBoxEditField)
{
QRect editField = subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, w);
drawKStylePrimitive(WT_ComboBox, ComboBox::EditField, opt, editField, pal, flags, p, w);
}
if (cb->subControls & SC_ComboBoxArrow)
{
QRect buttonRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
drawKStylePrimitive(WT_ComboBox, ComboBox::Button, opt, buttonRect, pal, flags, p, w);
// draw symbol...
drawKStylePrimitive(WT_ComboBox, Generic::ArrowDown, opt, buttonRect, pal, flags, p, w);
}
return;
} //option OK
break;
} //CC_Combo
case CC_ToolButton:
{
if (const QStyleOptionToolButton *tool = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
QRect buttonRect = subControlRect(cc, tool, SC_ToolButton, w);
QRect menuRect = subControlRect(cc, tool, SC_ToolButtonMenu, w);
// State_AutoRaise: only draw button when State_MouseOver
State bflags = tool->state;
if (bflags & State_AutoRaise) {
if (!(bflags & State_MouseOver)) {
bflags &= ~State_Raised;
}
}
State mflags = bflags;
QStyleOption tOpt(0);
tOpt.palette = pal;
if (tool->subControls & SC_ToolButton) {
if (bflags & (State_Sunken | State_On | State_Raised)) {
tOpt.rect = buttonRect;
tOpt.state = bflags;
drawPrimitive(PE_PanelButtonTool, &tOpt, p, w);
}
}
if (tool->subControls & SC_ToolButtonMenu) {
tOpt.rect = menuRect;
tOpt.state = mflags;
drawPrimitive(PE_IndicatorButtonDropDown, &tOpt, p, w);
} else if (tool->features & QStyleOptionToolButton::HasMenu) {
// This is requesting KDE3-style arrow indicator, per Qt 4.4 behavior. Qt 4.3 prefers to hide
// the fact of the menu's existence. Whee! Since we don't know how to paint this right,
// though, we have to have some metrics set for it to look nice.
int size = widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorSize, opt, w);
if (size) {
int xOff = widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorXOff, opt, w);
int yOff = widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorYOff, opt, w);
QRect r = QRect(buttonRect.right() + xOff, buttonRect.bottom() + yOff, size, size);
tOpt.rect = r;
tOpt.state = bflags;
drawPrimitive(PE_IndicatorButtonDropDown, &tOpt, p, w);
}
}
if (flags & State_HasFocus) {
QRect focusRect = insideMargin(r, WT_ToolButton, ToolButton::FocusMargin, opt, w);
tOpt.rect = focusRect;
tOpt.state = bflags;
drawKStylePrimitive(WT_ToolButton, Generic::FocusIndicator, &tOpt, focusRect, pal, bflags, p, w);
}
// CE_ToolButtonLabel expects a readjusted rect, for the button area proper
QStyleOptionToolButton labelOpt = *tool;
labelOpt.rect = buttonRect;
drawControl(CE_ToolButtonLabel, &labelOpt, p, w);
return;
}
break;
} //CC_ToolButton
case CC_TitleBar:
{
const QStyleOptionTitleBar *tb =
qstyleoption_cast<const QStyleOptionTitleBar *>(opt);
if (!tb)
break;
// title bar
drawKStylePrimitive(WT_Window, Window::TitlePanel, opt, r, pal, flags, p, w);
// TODO: different color depending on Active/inactive state
// draw title text
QRect textRect = subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, w);
TextOption textOpt(tb->text);
textOpt.color = widgetLayoutProp(WT_Window, Window::TitleTextColor, opt, w);
drawKStylePrimitive(WT_Window, Generic::Text, opt, textRect,
pal, flags, p, w, &textOpt);
TitleButtonOption buttonKOpt;
buttonKOpt.icon = tb->icon;
if ((tb->subControls & SC_TitleBarSysMenu) &&
(tb->titleBarFlags & Qt::WindowSystemMenuHint))
{
buttonKOpt.active = (tb->activeSubControls & SC_TitleBarSysMenu)
&& (tb->state & State_Sunken);
QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, w);
drawKStylePrimitive(WT_Window, Window::ButtonMenu, opt, br, pal, flags, p, w,
&buttonKOpt);
}
if ((tb->subControls & SC_TitleBarMinButton) &&
(tb->titleBarFlags & Qt::WindowMinimizeButtonHint))
{
buttonKOpt.active = (tb->activeSubControls & SC_TitleBarMinButton)
&& (tb->state & State_Sunken);
QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarMinButton, w);
drawKStylePrimitive(WT_Window, Window::ButtonMin, opt, br, pal, flags, p, w,
&buttonKOpt);
}
if ((tb->subControls & SC_TitleBarMaxButton) &&
(tb->titleBarFlags & Qt::WindowMaximizeButtonHint))
{
buttonKOpt.active = (tb->activeSubControls & SC_TitleBarMaxButton)
&& (tb->state & State_Sunken);
QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarMaxButton, w);
drawKStylePrimitive(WT_Window, Window::ButtonMax, opt, br, pal, flags, p, w,
&buttonKOpt);
}
if ((tb->subControls & SC_TitleBarCloseButton) &&
(tb->titleBarFlags & Qt::WindowSystemMenuHint))
{
// bool hover = (tb->activeSubControls & SC_TitleBarCloseButton)
// && (tb->state & State_MouseOver);
buttonKOpt.active = (tb->activeSubControls & SC_TitleBarCloseButton)
&& (tb->state & State_Sunken);
QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarCloseButton, w);
drawKStylePrimitive(WT_Window, Window::ButtonClose, opt, br, pal, flags, p, w,
&buttonKOpt);
}
if ((tb->subControls & SC_TitleBarNormalButton) &&
(((tb->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
(tb->titleBarState & Qt::WindowMinimized)) ||
((tb->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
(tb->titleBarState & Qt::WindowMaximized))))
{
buttonKOpt.active = (tb->activeSubControls & SC_TitleBarNormalButton)
&& (tb->state & State_Sunken);
QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarNormalButton, w);
drawKStylePrimitive(WT_Window, Window::ButtonRestore, opt, br, pal, flags, p, w,
&buttonKOpt);
}
if (tb->subControls & SC_TitleBarShadeButton)
{
buttonKOpt.active = (tb->activeSubControls & SC_TitleBarShadeButton)
&& (tb->state & State_Sunken);
QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarShadeButton, w);
drawKStylePrimitive(WT_Window, Window::ButtonShade, opt, br, pal, flags, p, w,
&buttonKOpt);
}
if (tb->subControls & SC_TitleBarUnshadeButton)
{
buttonKOpt.active = (tb->activeSubControls & SC_TitleBarUnshadeButton)
&& (tb->state & State_Sunken);
QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarUnshadeButton, w);
drawKStylePrimitive(WT_Window, Window::ButtonUnshade, opt, br, pal, flags, p, w,
&buttonKOpt);
}
if ((tb->subControls & SC_TitleBarContextHelpButton)
&& (tb->titleBarFlags & Qt::WindowContextHelpButtonHint))
{
buttonKOpt.active = (tb->activeSubControls & SC_TitleBarContextHelpButton)
&& (tb->state & State_Sunken);
QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarContextHelpButton, w);
drawKStylePrimitive(WT_Window, Window::ButtonHelp, opt, br, pal, flags, p, w,
&buttonKOpt);
}
return;
} // CC_TitleBar
default:
break;
} //switch
QCommonStyle::drawComplexControl(cc, opt, p, w);
}
QRect KStyle::internalSubControlRect (ComplexControl control, const QStyleOptionComplex* option,
SubControl subControl, const QWidget* widget) const
{
QRect r = option->rect;
if (control == CC_ScrollBar)
{
switch (subControl)
{
//The "top" arrow
case SC_ScrollBarSubLine:
{
int majorSize;
if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, option, widget))
majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleButtonHeight, option, widget);
else
majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::SingleButtonHeight, option, widget);
if (option->state & State_Horizontal)
return handleRTL(option, QRect(r.x(), r.y(), majorSize, r.height()));
else
return handleRTL(option, QRect(r.x(), r.y(), r.width(), majorSize));
}
//The "bottom" arrow
case SC_ScrollBarAddLine:
{
int majorSize;
if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, option, widget))
majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleButtonHeight, option, widget);
else
majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::SingleButtonHeight, option, widget);
if (option->state & State_Horizontal)
return handleRTL(option, QRect(r.right() - majorSize + 1, r.y(), majorSize, r.height()));
else
return handleRTL(option, QRect(r.x(), r.bottom() - majorSize + 1, r.width(), majorSize));
}
default:
break;
}
}
return QRect();
}
QRect KStyle::subControlRect(ComplexControl control, const QStyleOptionComplex* option,
SubControl subControl, const QWidget* widget) const
{
QRect r = option->rect;
switch (control)
{
case CC_ScrollBar:
{
switch (subControl)
{
//For both arrows, we return -everything-,
//to get stuff to repaint right. See internalSubControlRect
//for the real thing
case SC_ScrollBarSubLine:
case SC_ScrollBarAddLine:
return r;
//The main groove area. This is used to compute the others...
case SC_ScrollBarGroove:
{
QRect top = handleRTL(option, internalSubControlRect(control, option, SC_ScrollBarSubLine, widget));
QRect bot = handleRTL(option, internalSubControlRect(control, option, SC_ScrollBarAddLine, widget));
QPoint topLeftCorner, botRightCorner;
if (option->state & State_Horizontal)
{
topLeftCorner = QPoint(top.right() + 1, top.top());
botRightCorner = QPoint(bot.left() - 1, top.bottom());
}
else
{
topLeftCorner = QPoint(top.left(), top.bottom() + 1);
botRightCorner = QPoint(top.right(), bot.top() - 1);
}
return handleRTL(option, QRect(topLeftCorner, botRightCorner));
}
case SC_ScrollBarFirst:
case SC_ScrollBarLast:
return QRect();
case SC_ScrollBarSlider:
{
const QStyleOptionSlider* slOpt = ::qstyleoption_cast<const QStyleOptionSlider*>(option);
//We do handleRTL here to unreflect things if need be
QRect groove = handleRTL(option, subControlRect(control, option, SC_ScrollBarGroove, widget));
Q_ASSERT (slOpt);
if (slOpt->minimum == slOpt->maximum)
return groove;
//Figure out how much room we have..
int space;
if (option->state & State_Horizontal)
space = groove.width();
else
space = groove.height();
//Calculate the portion of this space that the slider should take up.
int sliderSize = int(space * float(slOpt->pageStep) /
(slOpt->maximum - slOpt->minimum + slOpt->pageStep));
if (sliderSize < widgetLayoutProp(WT_ScrollBar, ScrollBar::MinimumSliderHeight, option, widget))
sliderSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::MinimumSliderHeight, option, widget);
if (sliderSize > space)
sliderSize = space;
//What do we have remaining?
space = space - sliderSize;
//uhm, yeah, nothing much
if (space <= 0)
return groove;
int pos = qRound(float(slOpt->sliderPosition - slOpt->minimum)/
(slOpt->maximum - slOpt->minimum)*space);
if (option->state & State_Horizontal)
return handleRTL(option, QRect(groove.x() + pos, groove.y(), sliderSize, groove.height()));
else
return handleRTL(option, QRect(groove.x(), groove.y() + pos, groove.width(), sliderSize));
}
case SC_ScrollBarSubPage:
{
//We do handleRTL here to unreflect things if need be
QRect slider = handleRTL(option, subControlRect(control, option, SC_ScrollBarSlider, widget));
QRect groove = handleRTL(option, subControlRect(control, option, SC_ScrollBarGroove, widget));
//We're above the slider in the groove.
if (option->state & State_Horizontal)
return handleRTL(option, QRect(groove.x(), groove.y(), slider.x() - groove.x(), groove.height()));
else
return handleRTL(option, QRect(groove.x(), groove.y(), groove.width(), slider.y() - groove.y()));
}
case SC_ScrollBarAddPage:
{
//We do handleRTL here to unreflect things if need be
QRect slider = handleRTL(option, subControlRect(control, option, SC_ScrollBarSlider, widget));
QRect groove = handleRTL(option, subControlRect(control, option, SC_ScrollBarGroove, widget));
//We're below the slider in the groove.
if (option->state & State_Horizontal)
return handleRTL(option,
QRect(slider.right() + 1, groove.y(), groove.right() - slider.right(), groove.height()));
else
return handleRTL(option,
QRect(groove.x(), slider.bottom() + 1, groove.width(), groove.bottom() - slider.bottom()));
}
default:
break;
}
} //CC_ScrollBar
case CC_SpinBox:
{
if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
int fw = widgetLayoutProp(WT_SpinBox, SpinBox::FrameWidth, option, widget);
int bw = widgetLayoutProp(WT_SpinBox, SpinBox::ButtonWidth, option, widget);
int bm = widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin, option, widget);
int bml = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Left, option, widget);
int bmr = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Right, option, widget);
int bmt = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Top, option, widget);
int bmb = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Bot, option, widget);
int bs = widgetLayoutProp(WT_SpinBox, SpinBox::ButtonSpacing, option, widget);
bool symmButtons = widgetLayoutProp(WT_SpinBox, SpinBox::SymmetricButtons, option, widget);
bool supportFrameless = widgetLayoutProp(WT_SpinBox, SpinBox::SupportFrameless, option, widget);
// SpinBox without a frame, set the corresponding layout values to 0, reduce button width.
if (supportFrameless && !sb->frame)
{
bw = bw - bmr; // reduce button with as the right button margin will be ignored.
fw = 0;
bmt = bmb = bmr = 0;
}
const int buttonsWidth = bw-bml-bmr;
const int buttonsLeft = r.right()-bw+bml+1;
// compute the height of each button...
int availableButtonHeight = r.height()-bmt-bmb - bs;
if (symmButtons)
{
// make sure the availableButtonHeight is even by reducing the
// button spacing by 1 if necessary. Results in both buttons
// of the same height...
if (availableButtonHeight%2 != 0)
{
--bs;
// recalculate...
availableButtonHeight = r.height()-bmt-bmb - bs;
}
}
int heightUp = availableButtonHeight / 2;
int heightDown = availableButtonHeight - heightUp;
switch (subControl) {
case SC_SpinBoxUp:
return handleRTL(option,
QRect(buttonsLeft, r.top()+bmt, buttonsWidth, heightUp) );
case SC_SpinBoxDown:
return handleRTL(option,
QRect(buttonsLeft, r.bottom()-bmb-heightDown+1, buttonsWidth, heightDown) );
case SC_SpinBoxEditField:
{
QRect labelRect(r.left()+fw, r.top()+fw, r.width()-fw-bw, r.height()-2*fw);
labelRect = insideMargin(labelRect, WT_SpinBox, SpinBox::ContentsMargin, option, widget);
return handleRTL(option, labelRect );
}
case SC_SpinBoxFrame:
return (sb->frame || !supportFrameless) ? r : QRect();
default:
break;
}
} //option ok
} //CC_SpinBox
case CC_ComboBox:
{
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
int fw = widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget);
int bw = widgetLayoutProp(WT_ComboBox, ComboBox::ButtonWidth, option, widget);
int bm = widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin, option, widget);
int bml = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Left, option, widget);
int bmr = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Right, option, widget);
int bmt = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Top, option, widget);
int bmb = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Bot, option, widget);
bool supportFrameless = widgetLayoutProp(WT_ComboBox, ComboBox::SupportFrameless, option, widget);
// ComboBox without a frame, set the corresponding layout values to 0, reduce button width.
if (supportFrameless && !cb->frame)
{
bw = bw - bmr; // reduce button with as the right button margin will be ignored.
fw = 0;
bmt = bmb = bmr = 0;
}
switch (subControl) {
case SC_ComboBoxFrame:
return (cb->frame || !supportFrameless) ? r : QRect();
case SC_ComboBoxArrow:
return handleRTL(option,
QRect(r.right()-bw+bml+1, r.top()+bmt, bw-bml-bmr, r.height()-bmt-bmb) );
case SC_ComboBoxEditField:
{
QRect labelRect(r.left()+fw, r.top()+fw, r.width()-fw-bw, r.height()-2*fw);
labelRect = insideMargin(labelRect, WT_ComboBox, ComboBox::ContentsMargin, option, widget);
return handleRTL(option, labelRect );
}
case SC_ComboBoxListBoxPopup:
// TODO: need to add layoutProps to control the popup rect?
// return cb->popupRect;
// popupRect seems to be empty, so use QStyleOption::rect as Qt's styles do
return r;
default:
break;
}
} //option ok
} //CC_ComboBox
case CC_TitleBar:
{
const QStyleOptionTitleBar *tbOpt =
qstyleoption_cast<const QStyleOptionTitleBar *>(option);
if (!tbOpt)
break;
QRect ret = insideMargin(r, WT_Window, Window::TitleMargin, option, widget);
const int btnHeight = ret.height();
const int btnWidth = widgetLayoutProp(WT_Window, Window::ButtonWidth, option, widget);
const int btnSpace = widgetLayoutProp(WT_Window, Window::ButtonSpace, option, widget);
const int titleSpace = widgetLayoutProp(WT_Window, Window::ButtonToTextSpace, option, widget);
bool isMinimized = tbOpt->titleBarState & Qt::WindowMinimized;
bool isMaximized = tbOpt->titleBarState & Qt::WindowMaximized;
// button layout: menu -title- help,shade,min,max,close
bool menuCloseBtn = tbOpt->titleBarFlags & Qt::WindowSystemMenuHint;
bool minBtn = !isMinimized &&
(tbOpt->titleBarFlags & Qt::WindowMinimizeButtonHint);
bool maxBtn = !isMaximized &&
(tbOpt->titleBarFlags & Qt::WindowMaximizeButtonHint);
bool restoreBtn =
(isMinimized && (tbOpt->titleBarFlags & Qt::WindowMinimizeButtonHint)) ||
(isMaximized && (tbOpt->titleBarFlags & Qt::WindowMaximizeButtonHint));
bool shadeBtn = tbOpt->titleBarFlags & Qt::WindowShadeButtonHint;
bool helpBtn = tbOpt->titleBarFlags & Qt::WindowContextHelpButtonHint;
int btnOffsetCount = 0; // for button rects; count the position in the button bar
switch (subControl) {
case SC_TitleBarLabel:
{
if (tbOpt->titleBarFlags & Qt::WindowTitleHint)
{
int cLeft = 0; // count buttons in the button bar
int cRight = 0;
if (menuCloseBtn) {
// menu and close button
++cLeft;
++cRight;
}
if (minBtn) ++cRight;
if (restoreBtn) ++cRight;
if (maxBtn) ++cRight;
if (shadeBtn) ++cRight;
if (helpBtn) ++cRight;
ret.adjust( cLeft*btnWidth+(cLeft-1)*btnSpace+titleSpace, 0,
-(titleSpace+cRight*btnWidth+(cRight-1)*btnSpace), 0 );
}
break;
}
case SC_TitleBarSysMenu:
{
if (tbOpt->titleBarFlags & Qt::WindowSystemMenuHint) {
ret.setRect(ret.left(), ret.top(), btnWidth, btnHeight);
}
break;
}
case SC_TitleBarContextHelpButton:
if (helpBtn)
++btnOffsetCount;
case SC_TitleBarMinButton:
if (minBtn)
++btnOffsetCount;
else if (subControl == SC_TitleBarMinButton)
return QRect();
case SC_TitleBarNormalButton:
if (restoreBtn)
++btnOffsetCount;
else if (subControl == SC_TitleBarNormalButton)
return QRect();
case SC_TitleBarMaxButton:
if (maxBtn)
++btnOffsetCount;
else if (subControl == SC_TitleBarMaxButton)
return QRect();
case SC_TitleBarShadeButton:
if (!isMinimized && shadeBtn)
++btnOffsetCount;
else if (subControl == SC_TitleBarShadeButton)
return QRect();
case SC_TitleBarUnshadeButton:
if (isMinimized && shadeBtn)
++btnOffsetCount;
else if (subControl == SC_TitleBarUnshadeButton)
return QRect();
case SC_TitleBarCloseButton:
{
if (menuCloseBtn)
++btnOffsetCount;
else if (subControl == SC_TitleBarCloseButton)
return QRect();
// set the rect for all buttons that fell through:
ret.setRect(ret.right()-btnOffsetCount*btnWidth-(btnOffsetCount-1)*btnSpace,
ret.top(), btnWidth, btnHeight);
break;
}
default:
return QRect();
}
return visualRect(tbOpt->direction, tbOpt->rect, ret);
} // CC_TitleBar
default:
break;
}
return QCommonStyle::subControlRect(control, option, subControl, widget);
}
/*
Checks whether the point is before the bound rect for
bound of given orientation
*/
static bool preceeds(const QPoint &pt, const QRect &bound,
const QStyleOption* opt)
{
if (opt->state & QStyle::State_Horizontal)
{
//What's earlier depends on RTL or not
if (opt->direction == Qt::LeftToRight)
return pt.x() < bound.right();
else
return pt.x() > bound.x();
}
else
{
return pt.y() < bound.y();
}
}
static QStyle::SubControl buttonPortion(const QRect &totalRect,
const QPoint &pt,
const QStyleOption* opt)
{
if (opt->state & QStyle::State_Horizontal)
{
//What's earlier depends on RTL or not
if (opt->direction == Qt::LeftToRight)
return pt.x() < totalRect.center().x() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine;
else
return pt.x() > totalRect.center().x() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine;
}
else
{
return pt.y() < totalRect.center().y() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine;
}
}
QStyle::SubControl KStyle::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex* opt,
const QPoint& pt, const QWidget* w) const
{
if (cc == CC_ScrollBar)
{
//First, check whether we're inside the groove or not...
QRect groove = subControlRect(CC_ScrollBar, opt, SC_ScrollBarGroove, w);
if (groove.contains(pt))
{
//Must be either page up/page down, or just click on the slider.
//Grab the slider to compare
QRect slider = subControlRect(CC_ScrollBar, opt, SC_ScrollBarSlider, w);
if (slider.contains(pt))
return SC_ScrollBarSlider;
else if (preceeds(pt, slider, opt))
return SC_ScrollBarSubPage;
else
return SC_ScrollBarAddPage;
}
else
{
//This is one of the up/down buttons. First, decide which one it is.
if (preceeds(pt, groove, opt))
{
//"Upper" button
if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, 0, w))
{
QRect buttonRect = internalSubControlRect(CC_ScrollBar, opt, SC_ScrollBarSubLine, w);
return buttonPortion(buttonRect, pt, opt);
}
else
return SC_ScrollBarSubLine; //Easy one!
}
else
{
//"Bottom" button
if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, 0, w))
{
QRect buttonRect = internalSubControlRect(CC_ScrollBar, opt, SC_ScrollBarAddLine, w);
return buttonPortion(buttonRect, pt, opt);
}
else
return SC_ScrollBarAddLine; //Easy one!
}
}
}
return QCommonStyle::hitTestComplexControl(cc, opt, pt, w);
}
QSize KStyle::sizeFromContents(ContentsType type, const QStyleOption* option, const QSize& contentsSize, const QWidget* widget) const
{
switch (type)
{
case CT_PushButton:
{
const QStyleOptionButton* bOpt = qstyleoption_cast<const QStyleOptionButton*>(option);
if (!bOpt) return contentsSize;
QSize size = contentsSize;
if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton))
size = expandDim(size, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
//### TODO: Handle minimum size limits, extra spacing as in current styles ??
size = expandDim(size, WT_PushButton, PushButton::ContentsMargin, option, widget);
if (bOpt->features & QStyleOptionButton::HasMenu) {
size.setWidth(size.width() + widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget));
}
if (!bOpt->text.isEmpty() && !bOpt->icon.isNull()) {
// Incorporate the spacing between the icon and text. Qt sticks 4 there,
// but we use PushButton::TextToIconSpace.
size.setWidth(size.width() - 4 + widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget));
}
return size;
}
case CT_ToolButton:
{
// We want to avoid super-skiny buttons, for things like "up" when icons + text
// For this, we would like to make width >= height.
// However, once we get here, QToolButton may have already put in the menu area
// (PM_MenuButtonIndicator) into the width. So we may have to take it out, fix things
// up, and add it back in. So much for class-independent rendering...
QSize size = contentsSize;
int menuAreaWidth = 0;
if (const QStyleOptionToolButton* tbOpt = qstyleoption_cast<const QStyleOptionToolButton*>(option)) {
if (tbOpt->features & QStyleOptionToolButton::MenuButtonPopup)
menuAreaWidth = pixelMetric(QStyle::PM_MenuButtonIndicator, option, widget);
else if (tbOpt->features & QStyleOptionToolButton::HasMenu)
size.setWidth(size.width() + widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorSize, tbOpt, widget));
}
size.setWidth(size.width() - menuAreaWidth);
if (size.width() < size.height())
size.setWidth(size.height());
size.setWidth(size.width() + menuAreaWidth);
return expandDim(size, WT_ToolButton, ToolButton::ContentsMargin, option, widget);
}
case CT_CheckBox:
{
//Add size for indicator ### handle empty case differently?
int indicator = widgetLayoutProp(WT_CheckBox, CheckBox::Size, option, widget);
int spacer = widgetLayoutProp(WT_CheckBox, CheckBox::BoxTextSpace, option, widget);
//Make sure we include space for the focus rect margin
QSize size = expandDim(contentsSize, WT_CheckBox, CheckBox::FocusMargin, option, widget);
//Make sure we can fit the indicator (### an extra margin around that?)
size.setHeight(qMax(size.height(), indicator));
//Add space for the indicator and the icon
size.setWidth(size.width() + indicator + spacer);
return size;
}
case CT_RadioButton:
{
//Add size for indicator
int indicator = widgetLayoutProp(WT_RadioButton, RadioButton::Size, option, widget);
int spacer = widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget);
//Make sure we include space for the focus rect margin
QSize size = expandDim(contentsSize, WT_RadioButton, RadioButton::FocusMargin, option, widget);
//Make sure we can fit the indicator (### an extra margin around that?)
size.setHeight(qMax(size.height(), indicator));
//Add space for the indicator and the icon
size.setWidth(size.width() + indicator + spacer);
return size;
}
case CT_ProgressBar:
{
QSize size = contentsSize;
const QStyleOptionProgressBar* pbOpt = ::qstyleoption_cast<const QStyleOptionProgressBar*>(option);
if (useSideText(pbOpt))
{
//Allocate extra room for side text
size.setWidth(size.width() + sideTextWidth(pbOpt));
}
return size;
}
case CT_MenuBar:
{
int extraW = widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Right, option, widget) -
widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Left, option, widget);
int extraH = widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Bot, option, widget) -
widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Top, option, widget);
return QSize(contentsSize.width() + extraW, contentsSize.height() + extraH);
}
case CT_Menu:
{
int extraW = widgetLayoutProp(WT_Menu, Menu::Margin + Right, option, widget) -
widgetLayoutProp(WT_Menu, Menu::Margin + Left, option, widget);
int extraH = widgetLayoutProp(WT_Menu, Menu::Margin + Bot, option, widget) -
widgetLayoutProp(WT_Menu, Menu::Margin + Top, option, widget);
return QSize(contentsSize.width() + extraW, contentsSize.height() + extraH);
}
case CT_MenuItem:
{
const QStyleOptionMenuItem* miOpt = ::qstyleoption_cast<const QStyleOptionMenuItem*>(option);
if (!miOpt) return contentsSize; //Someone is asking for trouble..
//First, we calculate the intrinsic size of the item..
QSize insideSize;
switch (miOpt->menuItemType)
{
case QStyleOptionMenuItem::Normal:
case QStyleOptionMenuItem::DefaultItem: //huh?
case QStyleOptionMenuItem::SubMenu:
{
int iconColW = miOpt->maxIconWidth;
iconColW = qMax(iconColW, widgetLayoutProp(WT_MenuItem, MenuItem::IconWidth, option, widget));
int leftColW = iconColW;
if (miOpt->menuHasCheckableItems &&
widgetLayoutProp(WT_MenuItem, MenuItem::CheckAlongsideIcon, option, widget) )
{
leftColW = widgetLayoutProp(WT_MenuItem, MenuItem::CheckWidth, option, widget) +
widgetLayoutProp(WT_MenuItem, MenuItem::CheckSpace, option, widget) +
iconColW;
}
leftColW += widgetLayoutProp(WT_MenuItem, MenuItem::IconSpace, option, widget);
int rightColW = widgetLayoutProp(WT_MenuItem, MenuItem::ArrowSpace, option, widget) +
widgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, option, widget);
QFontMetrics fm(miOpt->font);
int textW;
int tabPos = miOpt->text.indexOf(QLatin1Char('\t'));
if (tabPos == -1)
{
//No accel..
textW = contentsSize.width();
}
else
{
// The width of the accelerator is not included here since
// Qt will add that on separately after obtaining the
// sizeFromContents() for each menu item in the menu to be shown
// ( see QMenuPrivate::calcActionRects() )
textW = contentsSize.width() +
widgetLayoutProp(WT_MenuItem,MenuItem::AccelSpace,option,widget);
}
int h = qMax(contentsSize.height(), widgetLayoutProp(WT_MenuItem, MenuItem::MinHeight, option, widget));
insideSize = QSize(leftColW + textW + rightColW, h);
break;
}
case QStyleOptionMenuItem::Separator:
{
insideSize = QSize(10, widgetLayoutProp(WT_MenuItem, MenuItem::SeparatorHeight, option, widget));
}
break;
//Double huh if we get those.
case QStyleOptionMenuItem::Scroller:
case QStyleOptionMenuItem::TearOff:
case QStyleOptionMenuItem::Margin:
case QStyleOptionMenuItem::EmptyArea:
return contentsSize;
}
//...now apply the outermost margin.
return expandDim(insideSize, WT_MenuItem, MenuItem::Margin, option, widget);
}
case CT_MenuBarItem:
return expandDim(contentsSize, WT_MenuBarItem, MenuBarItem::Margin, option, widget);
case CT_TabBarTab:
{
//With our PM_TabBarTabHSpace/VSpace, Qt should give us what we want for
//contentsSize, so we just expand that. Qt also takes care of
//the vertical thing.
bool rotated = false; // indicates whether the tab is rotated by 90 degrees
if (const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab*>(option)) {
rotated = isVerticalTab(tabOpt);
}
return expandDim(contentsSize, WT_TabBar, TabBar::TabContentsMargin, option, widget, rotated);
}
case CT_TabWidget:
{
const QStyleOptionTabWidgetFrame* tabOpt = qstyleoption_cast<const QStyleOptionTabWidgetFrame*>(option);
if (!tabOpt) break;
int m = widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin, option, widget);
int vert = 2*m +
widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin+Top, option, widget) +
widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin+Bot, option, widget);
int hor = 2*m +
widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin+Left, option, widget) +
widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin+Right, option, widget);
switch (tabOpt->shape) {
case QTabBar::RoundedNorth:
case QTabBar::TriangularNorth:
case QTabBar::RoundedWest:
case QTabBar::TriangularWest:
return contentsSize + QSize(hor, vert);
case QTabBar::RoundedSouth:
case QTabBar::TriangularSouth:
case QTabBar::RoundedEast:
case QTabBar::TriangularEast:
return contentsSize + QSize(vert,hor);
}
}
case CT_HeaderSection:
{
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
QSize iconSize = header->icon.isNull() ? QSize(0,0) : QSize(22,22);
QSize textSize = header->fontMetrics.size(0, header->text);
int iconSpacing = widgetLayoutProp(WT_Header, Header::TextToIconSpace, option, widget);
int w = iconSize.width() + iconSpacing + textSize.width();
int h = qMax(iconSize.height(), textSize.height() );
return expandDim(QSize(w, h), WT_Header, Header::ContentsMargin, option, widget);
}
}
case CT_ComboBox:
{
// TODO: Figure out what to do with the button margins
QSize size = contentsSize;
// Add the contents margin
size = expandDim(size, WT_ComboBox, ComboBox::ContentsMargin, option, widget);
// Add the button width
size.rwidth() += widgetLayoutProp(WT_ComboBox, ComboBox::ButtonWidth, option, widget);
// Add the frame width
size.rwidth() += widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget) * 2;
size.rheight() += widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget) * 2;
return size;
}
default:
break;
}
return QCommonStyle::sizeFromContents(type, option, contentsSize, widget);
}
bool KStyle::eventFilter(QObject *obj, QEvent *ev)
{
if (QCommonStyle::eventFilter(obj, ev) )
return true;
if (QLabel *lbl = qobject_cast<QLabel*>(obj) ) {
QWidget *buddy = lbl->buddy();
if (buddy) {
switch (ev->type() ) {
case QEvent::MouseButtonPress:
{
QMouseEvent *mev = dynamic_cast<QMouseEvent*>(ev);
if (!mev) break;
if (lbl->rect().contains(mev->pos() ) ) {
clickedLabel = obj;
lbl->repaint();
}
break;
}
case QEvent::MouseButtonRelease:
{
QMouseEvent *mev = dynamic_cast<QMouseEvent*>(ev);
if (!mev) break;
if (clickedLabel) {
clickedLabel = 0;
lbl->update();
}
// set focus to the buddy...
if (lbl->rect().contains(mev->pos() ) ) {
buddy->setFocus(Qt::ShortcutFocusReason);
}
break;
}
case QEvent::Paint:
if (obj == clickedLabel && buddy->isEnabled()) {
// paint focus rect
QPainter p(lbl);
QStyleOptionFocusRect foOpts;
QRect foRect(0,0,lbl->width(),lbl->height());
foOpts.palette = lbl->palette();
foOpts.rect = foRect;
drawKStylePrimitive(WT_Generic, Generic::FocusIndicator, &foOpts,
foRect, lbl->palette(), 0, &p, lbl);
}
break;
default:
break;
}
}
}
return false;
}
KStyle::ColorMode::ColorMode(QPalette::ColorRole _role):
mode(PaletteEntryMode),
role(_role)
{}
KStyle::ColorMode::ColorMode(Mode _mode, QPalette::ColorRole _role):
mode(_mode),
role(_role)
{}
KStyle::ColorMode::operator int() const
{
return int(role) | int(mode);
}
KStyle::ColorMode::ColorMode(int encoded)
{
mode = (encoded & BWAutoContrastMode) ? BWAutoContrastMode : PaletteEntryMode;
role = QPalette::ColorRole(encoded & (~BWAutoContrastMode));
}
QColor KStyle::ColorMode::color(const QPalette& palette)
{
QColor palColor = palette.color(role);
if (mode == BWAutoContrastMode) {
if (qGray(palColor.rgb()) > 128) { //### CHECKME
palColor = Qt::black;
} else {
palColor = Qt::white;
}
}
return palColor;
}
KStyle::TextOption::TextOption()
{
init();
}
KStyle::TextOption::TextOption(const QString& _text):
text(_text)
{
init();
}
void KStyle::TextOption::init()
{
hAlign = Qt::AlignLeft; //NOTE: Check BIDI?
}
// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;