File indexing completed on 2024-04-21 14:55:48

0001 /**
0002  * KStyle for KDE4
0003  * Copyright (C) 2004-2005 Maksim Orlovich <maksim@kde.org>
0004  * Copyright (C) 2005,2006 Sandro Giessl <giessl@kde.org>
0005  *
0006  * Based in part on the following software:
0007  *  KStyle for KDE3
0008  *      Copyright (C) 2001-2002 Karol Szwed <gallium@kde.org>
0009  *      Portions  (C) 1998-2000 TrollTech AS
0010  *  Keramik for KDE3,
0011  *      Copyright (C) 2002      Malte Starostik   <malte@kde.org>
0012  *                (C) 2002-2003 Maksim Orlovich  <maksim@kde.org>
0013  *      Portions  (C) 2001-2002 Karol Szwed     <gallium@kde.org>
0014  *                (C) 2001-2002 Fredrik Höglund <fredrik@kde.org>
0015  *                (C) 2000 Daniel M. Duley       <mosfet@kde.org>
0016  *                (C) 2000 Dirk Mueller         <mueller@kde.org>
0017  *                (C) 2001 Martijn Klingens    <klingens@kde.org>
0018  *                (C) 2003 Sandro Giessl      <sandro@giessl.com>
0019  *  This library is free software; you can redistribute it and/or
0020  *  modify it under the terms of the GNU Library General Public
0021  *  License as published by the Free Software Foundation; either
0022  *  version 2 of the License, or (at your option) any later version.
0023  *
0024  *  This library is distributed in the hope that it will be useful,
0025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0027  *  Library General Public License for more details.
0028  *
0029  * Many thanks to Bradley T. Hughes for the 3 button scrollbar code.
0030  *
0031  * This library is free software; you can redistribute it and/or
0032  * modify it under the terms of the GNU Library General Public
0033  * License version 2 as published by the Free Software Foundation.
0034  *
0035  * This library is distributed in the hope that it will be useful,
0036  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0037  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0038  * Library General Public License for more details.
0039  *
0040  * You should have received a copy of the GNU Library General Public License
0041  * along with this library; see the file COPYING.LIB.  If not, write to
0042  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0043  * Boston, MA 02110-1301, USA.
0044  */
0045 
0046 #include "k4style.h"
0047 
0048 #include <qalgorithms.h>
0049 #include <QCache>
0050 #include <QEvent>
0051 #include <QVariant>
0052 #include <QAbstractItemView>
0053 #include <QApplication>
0054 #include <QDialogButtonBox>
0055 #include <QFormLayout>
0056 #include <QIcon>
0057 #include <QLabel>
0058 #include <QKeyEvent>
0059 #include <QPainter>
0060 #include <QScrollBar>
0061 #include <QStyleOption>
0062 #include <QPainterPath>
0063 
0064 #include <kconfiggroup.h>
0065 #include <QDebug>
0066 #include <kiconloader.h>
0067 #include <kcolorscheme.h>
0068 
0069 //### FIXME: Who to credit these to?
0070 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};
0071 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};
0072 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};
0073 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};
0074 #define QCOORDARRLEN(x) sizeof(x)/(sizeof(qint32)*2)
0075 
0076 /**
0077  TODO: lots of missing widgets, SH_ settings, etc.
0078 
0079  Minor stuff:
0080     ProgressBar::Precision handling
0081 */
0082 
0083 // ----------------------------------------------------------------------------
0084 
0085 // For item view selections
0086 struct SelectionTiles {
0087     QPixmap left, center, right;
0088 };
0089 
0090 // ----------------------------------------------------------------------------
0091 
0092 static const QStyle::StyleHint SH_KCustomStyleElement = (QStyle::StyleHint)0xff000001;
0093 static const int X_KdeBase = 0xff000000;
0094 
0095 class K4StylePrivate
0096 {
0097 public:
0098     K4StylePrivate();
0099     QCache<quint64, SelectionTiles> selectionCache;
0100 
0101     QHash<QString, int> styleElements;
0102     int hintCounter, controlCounter, subElementCounter;
0103 };
0104 
0105 K4StylePrivate::K4StylePrivate()
0106 {
0107     selectionCache.setMaxCost(10);
0108     controlCounter = subElementCounter = X_KdeBase;
0109     hintCounter = X_KdeBase + 1; //sic! X_KdeBase is covered by SH_KCustomStyleElement
0110 }
0111 
0112 // ----------------------------------------------------------------------------
0113 
0114 K4Style::K4Style() : clickedLabel(nullptr), d(new K4StylePrivate)
0115 {
0116     //Set up some default metrics...
0117     setWidgetLayoutProp(WT_Generic, Generic::DefaultFrameWidth, 2);
0118     setWidgetLayoutProp(WT_Generic, Generic::DefaultLayoutSpacing, 6);
0119     setWidgetLayoutProp(WT_Generic, Generic::DefaultLayoutMargin, 9);
0120 
0121     setWidgetLayoutProp(WT_PushButton, PushButton::ContentsMargin, 5);
0122     setWidgetLayoutProp(WT_PushButton, PushButton::FocusMargin,    3);
0123     setWidgetLayoutProp(WT_PushButton, PushButton::PressedShiftHorizontal, 2);
0124     setWidgetLayoutProp(WT_PushButton, PushButton::PressedShiftVertical,   2);
0125     setWidgetLayoutProp(WT_PushButton, PushButton::MenuIndicatorSize,      8);
0126     setWidgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace,        6);
0127 
0128     setWidgetLayoutProp(WT_Splitter, Splitter::Width, 6); //As KStyle in KDE3
0129 
0130     setWidgetLayoutProp(WT_CheckBox, CheckBox::Size, 16);
0131     setWidgetLayoutProp(WT_CheckBox, CheckBox::BoxTextSpace, 6);
0132     setWidgetLayoutProp(WT_CheckBox, CheckBox::NoLabelFocusMargin, 1);
0133 
0134     setWidgetLayoutProp(WT_RadioButton, RadioButton::Size, 16);
0135     setWidgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, 6);
0136 
0137     setWidgetLayoutProp(WT_DockWidget, DockWidget::TitleTextColor,
0138                         ColorMode(QPalette::HighlightedText));
0139     setWidgetLayoutProp(WT_DockWidget, DockWidget::TitleMargin, 2);
0140     setWidgetLayoutProp(WT_DockWidget, DockWidget::FrameWidth, 3);
0141     setWidgetLayoutProp(WT_DockWidget, DockWidget::SeparatorExtent, 6);
0142 
0143     setWidgetLayoutProp(WT_ProgressBar, ProgressBar::GrooveMargin,  2);
0144     setWidgetLayoutProp(WT_ProgressBar, ProgressBar::SideTextSpace, 3); //(Matches QCommonStyle)
0145     setWidgetLayoutProp(WT_ProgressBar, ProgressBar::MaxBusyIndicatorSize, 10000);
0146     setWidgetLayoutProp(WT_ProgressBar, ProgressBar::BusyIndicatorSize,    10);
0147     setWidgetLayoutProp(WT_ProgressBar, ProgressBar::Precision,            1);
0148 
0149     setWidgetLayoutProp(WT_MenuBar, MenuBar::ItemSpacing,   14);
0150     setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin,        2);
0151     setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin + Left,  4);
0152     setWidgetLayoutProp(WT_MenuBar, MenuBar::Margin + Right, 4);
0153 
0154     setWidgetLayoutProp(WT_MenuBarItem, MenuBarItem::Margin, 1);
0155 
0156     setWidgetLayoutProp(WT_Menu, Menu::FrameWidth, 1);
0157     setWidgetLayoutProp(WT_Menu, Menu::Margin,     3);
0158     setWidgetLayoutProp(WT_Menu, Menu::ScrollerHeight, 10);
0159     setWidgetLayoutProp(WT_Menu, Menu::TearOffHeight, 10);
0160 
0161     setWidgetLayoutProp(WT_MenuItem, MenuItem::CheckWidth, 12);
0162     setWidgetLayoutProp(WT_MenuItem, MenuItem::CheckSpace, 3);
0163     setWidgetLayoutProp(WT_MenuItem, MenuItem::IconWidth, 12);
0164     setWidgetLayoutProp(WT_MenuItem, MenuItem::IconSpace, 3);
0165     setWidgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, 11);
0166     setWidgetLayoutProp(WT_MenuItem, MenuItem::ArrowSpace, 3);
0167     setWidgetLayoutProp(WT_MenuItem, MenuItem::Margin,     2);
0168     setWidgetLayoutProp(WT_MenuItem, MenuItem::SeparatorHeight, 0); //the margins give enough rooms
0169     setWidgetLayoutProp(WT_MenuItem, MenuItem::MinHeight,  16);
0170     setWidgetLayoutProp(WT_MenuItem, MenuItem::TextColor, ColorMode(QPalette::Text));
0171     setWidgetLayoutProp(WT_MenuItem, MenuItem::ActiveTextColor, ColorMode(QPalette::HighlightedText));
0172     setWidgetLayoutProp(WT_MenuItem, MenuItem::DisabledTextColor,       ColorMode(QPalette::Text));
0173     setWidgetLayoutProp(WT_MenuItem, MenuItem::ActiveDisabledTextColor, ColorMode(QPalette::Text));
0174     setWidgetLayoutProp(WT_MenuItem, MenuItem::AccelSpace, 16);
0175 
0176     //KDE default is single top button, double bottom one
0177     setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, 0);
0178     setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, 1);
0179     setWidgetLayoutProp(WT_ScrollBar, ScrollBar::SingleButtonHeight, 16);
0180     setWidgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleButtonHeight, 32);
0181     setWidgetLayoutProp(WT_ScrollBar, ScrollBar::BarWidth, 16);
0182     setWidgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor,
0183                         ColorMode(ColorMode::BWAutoContrastMode, QPalette::Button));
0184     setWidgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor,
0185                         ColorMode(ColorMode::BWAutoContrastMode, QPalette::ButtonText));
0186 
0187     setWidgetLayoutProp(WT_TabBar, TabBar::TabContentsMargin, 6);
0188     setWidgetLayoutProp(WT_TabBar, TabBar::TabFocusMargin, 3);
0189     setWidgetLayoutProp(WT_TabBar, TabBar::TabOverlap, 0);
0190     setWidgetLayoutProp(WT_TabBar, TabBar::BaseHeight, 2);
0191     setWidgetLayoutProp(WT_TabBar, TabBar::BaseOverlap, 2);
0192     setWidgetLayoutProp(WT_TabBar, TabBar::ScrollButtonWidth, 10);
0193     setWidgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, 6);
0194 
0195     setWidgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin, 2);
0196 
0197     setWidgetLayoutProp(WT_Tree, Tree::MaxExpanderSize, 9);
0198 
0199     setWidgetLayoutProp(WT_Slider, Slider::HandleThickness, 20);
0200     setWidgetLayoutProp(WT_Slider, Slider::HandleLength, 16);
0201 
0202     setWidgetLayoutProp(WT_SpinBox, SpinBox::FrameWidth, 1);
0203     setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonWidth, 16);
0204     setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonSpacing, 1);
0205     setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Right, 1);
0206     setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Top, 1);
0207     setWidgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Bot, 1);
0208 
0209     setWidgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, 1);
0210     setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonWidth, 16);
0211     setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Right, 1);
0212     setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Top, 1);
0213     setWidgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Bot, 1);
0214     setWidgetLayoutProp(WT_ComboBox, ComboBox::FocusMargin, 1);
0215 
0216     setWidgetLayoutProp(WT_Header, Header::ContentsMargin, 3);
0217     setWidgetLayoutProp(WT_Header, Header::TextToIconSpace, 3);
0218     setWidgetLayoutProp(WT_Header, Header::MarkSize, 9);
0219 
0220     setWidgetLayoutProp(WT_GroupBox, GroupBox::FrameWidth, 2);
0221     setWidgetLayoutProp(WT_GroupBox, GroupBox::TextAlignTop, false);
0222     setWidgetLayoutProp(WT_GroupBox, GroupBox::TitleTextColor, ColorMode(QPalette::Text));
0223 
0224     setWidgetLayoutProp(WT_ToolBar, ToolBar::HandleExtent, 6);
0225     setWidgetLayoutProp(WT_ToolBar, ToolBar::SeparatorExtent, 6);
0226     setWidgetLayoutProp(WT_ToolBar, ToolBar::ExtensionExtent, 10);
0227     setWidgetLayoutProp(WT_ToolBar, ToolBar::FrameWidth, 2);
0228     setWidgetLayoutProp(WT_ToolBar, ToolBar::ItemSpacing, 3);
0229     setWidgetLayoutProp(WT_ToolBar, ToolBar::ItemMargin, 1);
0230 
0231     setWidgetLayoutProp(WT_ToolButton, ToolButton::ContentsMargin, 5);
0232     setWidgetLayoutProp(WT_ToolButton, ToolButton::FocusMargin,    3);
0233     setWidgetLayoutProp(WT_ToolButton, ToolButton::MenuIndicatorSize, 11);
0234 
0235     setWidgetLayoutProp(WT_ToolBoxTab, ToolBoxTab::Margin, 0);
0236 
0237     setWidgetLayoutProp(WT_Window, Window::TitleTextColor, ColorMode(QPalette::HighlightedText));
0238     setWidgetLayoutProp(WT_Window, Window::TitleHeight, 20);
0239     setWidgetLayoutProp(WT_Window, Window::TitleMargin, 2);
0240     setWidgetLayoutProp(WT_Window, Window::NoTitleFrame, 0);
0241     setWidgetLayoutProp(WT_Window, Window::ButtonWidth, 16);
0242     setWidgetLayoutProp(WT_Window, Window::ButtonSpace, 2);
0243     setWidgetLayoutProp(WT_Window, Window::ButtonToTextSpace, 3);
0244 }
0245 
0246 K4Style::~K4Style()
0247 {
0248     // this is just for stupid msvc compiler to force the creation of
0249     // DoubleButtonOption::defaultOption() inside kstyle lib
0250     // hope the optimizer won't throw it away
0251     const DoubleButtonOption *bOpt = extractOption<const DoubleButtonOption *>(nullptr);
0252     Q_UNUSED(bOpt)
0253 #ifdef __GNUC__
0254 #warning "mem leak: need to delete bOpt"
0255 #endif
0256     delete d;
0257 }
0258 
0259 /*
0260     Custom Style Element runtime extension:
0261     We reserve one StyleHint to let the effective style inform widgets whether it supports certain
0262     string based style elements.
0263     As this could lead to number conflicts (i.e. an app utilizing one of the hints itself for other
0264     purposes) there're various safety mechanisms to rule out such interference.
0265 
0266     1) It's most unlikely that a widget in some 3rd party app will accidentally call a general
0267     QStyle/K4Style styleHint() or draw*() and (unconditionally) expect a valid return, however:
0268     a. The StyleHint is not directly above Qt's custom base, assuming most 3rd party apps would
0269     - in case - make use of such
0270     b. In order to be accepted, the StyleHint query must pass a widget with a perfectly matching
0271     name, containing the typical element prefix ("CE_", etc.) and being supported by the current style
0272     c. Instead using Qt's fragile qstyleoption_cast on the QStyleOption provided to the StyleHint
0273     query, try to dump out a string and hope for the best, we now manipulate the widgets objectName().
0274     Plain Qt dependent widgets can do that themselves and if a widget uses K4Style's convenience access
0275     functions, it won't notice this at all
0276 
0277     2) The key problem is that a common KDE widget will run into an apps custom style which will then
0278     falsely respond to the styleHint() call with an invalid value.
0279     To prevent this, supporting styles *must* set a Q_CLASSINFO "X-KDE-CustomElements".
0280 
0281     3) If any of the above traps snaps, the returned id is 0 - the QStyle default, indicating
0282     that this element is not supported by the current style.
0283 
0284     Obviously, this contains the "diminished clean" action to (temporarily) manipulate the
0285     objectName() of a const QWidget* - but this happens completely inside K4Style or the widget, if
0286     it does not make use of K4Styles static convenience functions.
0287     My biggest worry here would be, that in a multithreaded environment a thread (usually not being
0288     owner of the widget) does something crucially relying on the widgets name property...
0289     This however would also have to happen during the widget construction or stylechanges, when
0290     the functions in doubt will typically be called.
0291     So this is imho unlikely causing any trouble, ever.
0292 */
0293 
0294 /*
0295     The functions called by the real style implementation to add support for a certain element.
0296     Checks for well-formed string (containing the element prefix) and returns 0 otherwise.
0297     Checks whether the element is already supported or inserts it otherwise; Returns the proper id
0298     NOTICE: We could check for "X-KDE-CustomElements", but this would bloat style start up times
0299     (if they e.g. register 100 elements or so)
0300 */
0301 
0302 static inline int newStyleElement(const QString &element, const char *check, int &counter, QHash<QString, int> *elements)
0303 {
0304     if (!element.contains(check)) {
0305         return 0;
0306     }
0307     int id = elements->value(element, 0);
0308     if (!id) {
0309         ++counter;
0310         id = counter;
0311         elements->insert(element, id);
0312     }
0313     return id;
0314 }
0315 
0316 QStyle::StyleHint K4Style::newStyleHint(const QString &element)
0317 {
0318     return (StyleHint)newStyleElement(element, "SH_", d->hintCounter, &d->styleElements);
0319 }
0320 
0321 QStyle::ControlElement K4Style::newControlElement(const QString &element)
0322 {
0323     return (ControlElement)newStyleElement(element, "CE_", d->controlCounter, &d->styleElements);
0324 }
0325 
0326 K4Style::SubElement K4Style::newSubElement(const QString &element)
0327 {
0328     return (SubElement)newStyleElement(element, "SE_", d->subElementCounter, &d->styleElements);
0329 }
0330 
0331 QString K4Style::defaultStyle()
0332 {
0333 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
0334     return QString("breeze");
0335 #else
0336     return QString(); // native style
0337 #endif
0338 }
0339 
0340 /*
0341     The functions called by widgets that request custom element support, passed to the effective style.
0342     Collected in a static inline function due to similarity.
0343 */
0344 
0345 static inline int customStyleElement(QStyle::StyleHint type, const QString &element, QWidget *widget)
0346 {
0347     if (!widget || widget->style()->metaObject()->indexOfClassInfo("X-KDE-CustomElements") < 0) {
0348         return 0;
0349     }
0350 
0351     const QString originalName = widget->objectName();
0352     widget->setObjectName(element);
0353     const int id = widget->style()->styleHint(type, nullptr, widget);
0354     widget->setObjectName(originalName);
0355     return id;
0356 }
0357 
0358 QStyle::StyleHint K4Style::customStyleHint(const QString &element, const QWidget *widget)
0359 {
0360     return (StyleHint) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget));
0361 }
0362 
0363 QStyle::ControlElement K4Style::customControlElement(const QString &element, const QWidget *widget)
0364 {
0365     return (ControlElement) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget));
0366 }
0367 
0368 QStyle::SubElement K4Style::customSubElement(const QString &element, const QWidget *widget)
0369 {
0370     return (SubElement) customStyleElement(SH_KCustomStyleElement, element, const_cast<QWidget *>(widget));
0371 }
0372 
0373 void K4Style::polish(QWidget *w)
0374 {
0375     if (qobject_cast<QLabel *>(w)) {
0376         w->installEventFilter(this);
0377     }
0378 
0379     // Enable hover effects in all itemviews
0380     if (QAbstractItemView *itemView = qobject_cast<QAbstractItemView *>(w)) {
0381         itemView->viewport()->setAttribute(Qt::WA_Hover);
0382     }
0383 
0384     QCommonStyle::polish(w);
0385 }
0386 void K4Style::unpolish(QWidget *w)
0387 {
0388     if (qobject_cast<QLabel *>(w)) {
0389         w->removeEventFilter(this);
0390     }
0391 
0392     QCommonStyle::unpolish(w);
0393 }
0394 void K4Style::polish(QApplication *a)
0395 {
0396     QCommonStyle::polish(a);
0397 }
0398 void K4Style::unpolish(QApplication *a)
0399 {
0400     QCommonStyle::unpolish(a);
0401 }
0402 void K4Style::polish(QPalette &pal)
0403 {
0404     QCommonStyle::polish(pal);
0405 }
0406 QRect K4Style::itemTextRect(const QFontMetrics &fm, const QRect &r,
0407                             int flags, bool enabled,
0408                             const QString &text) const
0409 {
0410     return QCommonStyle::itemTextRect(fm, r, flags, enabled, text);
0411 }
0412 QRect K4Style::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const
0413 {
0414     return QCommonStyle::itemPixmapRect(r, flags, pixmap);
0415 }
0416 void K4Style::drawItemText(QPainter *painter, const QRect &rect,
0417                            int flags, const QPalette &pal, bool enabled,
0418                            const QString &text, QPalette::ColorRole textRole) const
0419 {
0420     QCommonStyle::drawItemText(painter, rect, flags, pal, enabled,
0421                                text, textRole);
0422 }
0423 void K4Style::drawItemPixmap(QPainter *painter, const QRect &rect,
0424                              int alignment, const QPixmap &pixmap) const
0425 {
0426     QCommonStyle::drawItemPixmap(painter, rect, alignment, pixmap);
0427 }
0428 QPalette K4Style::standardPalette() const
0429 {
0430     return KColorScheme::createApplicationPalette(KSharedConfig::openConfig());
0431 }
0432 
0433 QIcon K4Style::standardIcon(StandardPixmap standardIcon, const QStyleOption */*option*/,
0434                             const QWidget */*widget*/) const
0435 {
0436     switch (standardIcon) {
0437     case QStyle::SP_DesktopIcon:
0438         return QIcon::fromTheme("user-desktop");
0439     case QStyle::SP_TrashIcon:
0440         return QIcon::fromTheme("user-trash");
0441     case QStyle::SP_ComputerIcon:
0442         return QIcon::fromTheme("computer");
0443     case QStyle::SP_DriveFDIcon:
0444         return QIcon::fromTheme("media-floppy");
0445     case QStyle::SP_DriveHDIcon:
0446         return QIcon::fromTheme("drive-harddisk");
0447     case QStyle::SP_DriveCDIcon:
0448     case QStyle::SP_DriveDVDIcon:
0449         return QIcon::fromTheme("drive-optical");
0450     case QStyle::SP_DriveNetIcon:
0451         return QIcon::fromTheme("folder-remote");
0452     case QStyle::SP_DirHomeIcon:
0453         return QIcon::fromTheme("user-home");
0454     case QStyle::SP_DirOpenIcon:
0455         return QIcon::fromTheme("document-open-folder");
0456     case QStyle::SP_DirClosedIcon:
0457         return QIcon::fromTheme("folder");
0458     case QStyle::SP_DirIcon:
0459         return QIcon::fromTheme("folder");
0460     case QStyle::SP_DirLinkIcon:
0461         return QIcon::fromTheme("folder"); //TODO: generate (!?) folder with link emblem
0462     case QStyle::SP_FileIcon:
0463         return QIcon::fromTheme("text-plain"); //TODO: look for a better icon
0464     case QStyle::SP_FileLinkIcon:
0465         return QIcon::fromTheme("text-plain"); //TODO: generate (!?) file with link emblem
0466     case QStyle::SP_FileDialogStart:
0467         return QIcon::fromTheme("media-playback-start"); //TODO: find correct icon
0468     case QStyle::SP_FileDialogEnd:
0469         return QIcon::fromTheme("media-playback-stop"); //TODO: find correct icon
0470     case QStyle::SP_FileDialogToParent:
0471         return QIcon::fromTheme("go-up");
0472     case QStyle::SP_FileDialogNewFolder:
0473         return QIcon::fromTheme("folder-new");
0474     case QStyle::SP_FileDialogDetailedView:
0475         return QIcon::fromTheme("view-list-details");
0476     case QStyle::SP_FileDialogInfoView:
0477         return QIcon::fromTheme("document-properties");
0478     case QStyle::SP_FileDialogContentsView:
0479         return QIcon::fromTheme("view-list-icons");
0480     case QStyle::SP_FileDialogListView:
0481         return QIcon::fromTheme("view-list-text");
0482     case QStyle::SP_FileDialogBack:
0483         return QIcon::fromTheme("go-previous");
0484     case QStyle::SP_MessageBoxInformation:
0485         return QIcon::fromTheme("dialog-information");
0486     case QStyle::SP_MessageBoxWarning:
0487         return QIcon::fromTheme("dialog-warning");
0488     case QStyle::SP_MessageBoxCritical:
0489         return QIcon::fromTheme("dialog-error");
0490     case QStyle::SP_MessageBoxQuestion:
0491         return QIcon::fromTheme("dialog-information");
0492     case QStyle::SP_DialogOkButton:
0493         return QIcon::fromTheme("dialog-ok");
0494     case QStyle::SP_DialogCancelButton:
0495         return QIcon::fromTheme("dialog-cancel");
0496     case QStyle::SP_DialogHelpButton:
0497         return QIcon::fromTheme("help-contents");
0498     case QStyle::SP_DialogOpenButton:
0499         return QIcon::fromTheme("document-open");
0500     case QStyle::SP_DialogSaveButton:
0501         return QIcon::fromTheme("document-save");
0502     case QStyle::SP_DialogCloseButton:
0503         return QIcon::fromTheme("dialog-close");
0504     case QStyle::SP_DialogApplyButton:
0505         return QIcon::fromTheme("dialog-ok-apply");
0506     case QStyle::SP_DialogResetButton:
0507         return QIcon::fromTheme("document-revert");
0508     case QStyle::SP_DialogDiscardButton:
0509         return QIcon::fromTheme("dialog-cancel");
0510     case QStyle::SP_DialogYesButton:
0511         return QIcon::fromTheme("dialog-ok-apply");
0512     case QStyle::SP_DialogNoButton:
0513         return QIcon::fromTheme("dialog-cancel");
0514     case QStyle::SP_ArrowUp:
0515         return QIcon::fromTheme("go-up");
0516     case QStyle::SP_ArrowDown:
0517         return QIcon::fromTheme("go-down");
0518     case QStyle::SP_ArrowLeft:
0519         return QIcon::fromTheme("go-previous-view");
0520     case QStyle::SP_ArrowRight:
0521         return QIcon::fromTheme("go-next-view");
0522     case QStyle::SP_ArrowBack:
0523         return QIcon::fromTheme("go-previous");
0524     case QStyle::SP_ArrowForward:
0525         return QIcon::fromTheme("go-next");
0526     case QStyle::SP_BrowserReload:
0527         return QIcon::fromTheme("view-refresh");
0528     case QStyle::SP_BrowserStop:
0529         return QIcon::fromTheme("process-stop");
0530     case QStyle::SP_MediaPlay:
0531         return QIcon::fromTheme("media-playback-start");
0532     case QStyle::SP_MediaStop:
0533         return QIcon::fromTheme("media-playback-stop");
0534     case QStyle::SP_MediaPause:
0535         return QIcon::fromTheme("media-playback-pause");
0536     case QStyle::SP_MediaSkipForward:
0537         return QIcon::fromTheme("media-skip-forward");
0538     case QStyle::SP_MediaSkipBackward:
0539         return QIcon::fromTheme("media-skip-backward");
0540     case QStyle::SP_MediaSeekForward:
0541         return QIcon::fromTheme("media-seek-forward");
0542     case QStyle::SP_MediaSeekBackward:
0543         return QIcon::fromTheme("media-seek-backward");
0544     case QStyle::SP_MediaVolume:
0545         return QIcon::fromTheme("audio-volume-medium");
0546     case QStyle::SP_MediaVolumeMuted:
0547         return QIcon::fromTheme("audio-volume-muted");
0548 
0549     default:
0550         return QIcon();
0551     }
0552 }
0553 
0554 QPixmap K4Style::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
0555                                 const QWidget *widget) const
0556 {
0557     return QCommonStyle::standardPixmap(standardPixmap, opt, widget);
0558 }
0559 QPixmap K4Style::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
0560                                      const QStyleOption *opt) const
0561 {
0562     return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt);
0563 }
0564 
0565 void K4Style::drawInsideRect(QPainter *p, const QRect &r) const
0566 {
0567     p->drawRect(r.x(), r.y(), r.width() - 1, r.height() - 1);
0568 }
0569 
0570 QRect K4Style::centerRect(const QRect &in, int w, int h) const
0571 {
0572     return QRect(in.x() + (in.width() - w) / 2, in.y() + (in.height() - h) / 2, w, h);
0573 }
0574 
0575 QRect K4Style::centerRect(const QRect &in, const QSize &size) const
0576 {
0577     return centerRect(in, size.width(), size.height());
0578 }
0579 
0580 void K4Style::drawKStylePrimitive(WidgetType widgetType, int primitive,
0581                                   const QStyleOption *opt,
0582                                   const QRect &r, const QPalette &pal,
0583                                   State flags, QPainter *p,
0584                                   const QWidget *widget,
0585                                   K4Style::Option *kOpt) const
0586 {
0587     switch (widgetType) {
0588     case WT_Tree: {
0589         switch (primitive) {
0590         case Tree::VerticalBranch:
0591         case Tree::HorizontalBranch:
0592             //### FIXME: set sane color.
0593             p->fillRect(r, QBrush(Qt::Dense4Pattern));
0594             return;
0595         case Tree::ExpanderOpen:
0596         case Tree::ExpanderClosed: {
0597             p->setPen(pal.text().color());
0598             drawInsideRect(p, r); //the border.
0599             int signLineSize = r.width() / 4;
0600             p->drawLine(r.center().x() - signLineSize, r.center().y(),
0601                         r.center().x() + signLineSize, r.center().y()); //-
0602             if (primitive == Tree::ExpanderClosed) //vertical line of +
0603                 p->drawLine(r.center().x(), r.center().y() - signLineSize,
0604                             r.center().x(), r.center().y() + signLineSize);
0605             return;
0606         }
0607         default:
0608             break;
0609         }
0610 
0611         break;
0612     }
0613 
0614     case WT_SpinBox: {
0615         switch (primitive) {
0616         case SpinBox::PlusSymbol:
0617         case SpinBox::MinusSymbol: {
0618             p->setPen(pal.buttonText().color());
0619 
0620             int l = qMin(r.width() - 2, r.height() - 2);
0621             QPoint c = r.center();
0622 
0623             p->drawLine(c.x() - l / 2, c.y(), c.x() + l / 2, c.y());
0624             if (primitive == SpinBox::PlusSymbol) {
0625                 p->drawLine(c.x(), c.y() - l / 2, c.x(), c.y() + l / 2);
0626             }
0627 
0628             return;
0629         }
0630         default:
0631             break;
0632         }
0633 
0634         break;
0635     }
0636 
0637     case WT_GroupBox: {
0638         if (primitive == GroupBox::FlatFrame) {
0639             QPen oldPen = p->pen();
0640             p->setPen(pal.color(QPalette::WindowText));
0641             p->drawLine(r.topLeft(), r.topRight());
0642             p->setPen(oldPen);
0643         }
0644 
0645         break;
0646     }
0647 
0648     case WT_ToolBoxTab: {
0649         if (primitive == ToolBoxTab::Panel) {
0650             drawKStylePrimitive(WT_ToolButton, ToolButton::Panel, opt, r, pal, flags, p, widget);
0651         }
0652 
0653         break;
0654     }
0655 
0656     case WT_DockWidget: {
0657         switch (primitive) {
0658         case DockWidget::TitlePanel:
0659             p->fillRect(r, pal.color(QPalette::Highlight));
0660             return;
0661 
0662         case DockWidget::SeparatorHandle:
0663             return;
0664 
0665         default:
0666             break;
0667         }
0668 
0669         break;
0670     }
0671 
0672     case WT_Window: {
0673         switch (primitive) {
0674         case Window::TitlePanel:
0675             p->fillRect(r, pal.color(QPalette::Highlight));
0676             return;
0677 
0678         case Window::ButtonMenu: {
0679             K4Style::TitleButtonOption *tbkOpts =
0680                 extractOption<K4Style::TitleButtonOption *>(kOpt);
0681             if (!tbkOpts->icon.isNull()) {
0682                 tbkOpts->icon.paint(p, r);
0683             } else {
0684                 QStyleOption tool(0);
0685                 tool.palette = pal;
0686                 // TODO: give it a nice KDE logo.
0687                 QPixmap pm = standardPixmap(SP_TitleBarMenuButton, &tool, widget);
0688                 tool.rect = r;
0689                 p->save();
0690                 drawItemPixmap(p, r, Qt::AlignCenter, pm);
0691                 p->restore();
0692             }
0693             return;
0694         }
0695 
0696         case Window::ButtonMin:
0697         case Window::ButtonMax:
0698         case Window::ButtonRestore:
0699         case Window::ButtonClose:
0700         case Window::ButtonShade:
0701         case Window::ButtonUnshade:
0702         case Window::ButtonHelp: {
0703             K4Style::TitleButtonOption *tbkOpts =
0704                 extractOption<K4Style::TitleButtonOption *>(kOpt);
0705             State bflags = flags;
0706             bflags &= ~State_Sunken;
0707             if (tbkOpts->active) {
0708                 bflags |= State_Sunken;
0709             }
0710             drawKStylePrimitive(WT_ToolButton, ToolButton::Panel, opt, r, pal, bflags, p, widget);
0711             return;
0712         }
0713         }
0714 
0715         break;
0716     }
0717 
0718     case WT_TabBar: {
0719         // For vertical text fallback, provide the generic text implementation
0720         // a transformed rotated painter, with rect swizzled appropriately
0721         if (primitive == TabBar::EastText || primitive == TabBar::WestText) {
0722             QTransform tr;
0723 
0724             if (primitive == TabBar::WestText) {
0725                 tr.translate(r.x(), r.height() + r.y());
0726                 tr.rotate(-90);
0727             } else {
0728                 tr.translate(r.width() + r.x(), r.y());
0729                 tr.rotate(90);
0730             }
0731 
0732             p->save();
0733             p->setTransform(tr, true);
0734             drawKStylePrimitive(WT_TabBar, Generic::Text, opt,
0735                                 QRect(0, 0, r.height(), r.width()), pal, flags, p, widget, kOpt);
0736             p->restore();
0737         }
0738         break;
0739     }
0740 
0741     default:
0742         break;
0743     }
0744 
0745     if (primitive == Generic::Text) {
0746         K4Style::TextOption *textOpts = extractOption<K4Style::TextOption *>(kOpt);
0747 
0748         //### debug
0749         //p->setPen(Qt::green);
0750         //drawInsideRect(p, r);
0751 
0752         QColor col = textOpts->color.color(pal);
0753         QPen   old = p->pen();
0754         p->setPen(col);
0755         drawItemText(p, r, Qt::AlignVCenter | Qt::TextShowMnemonic | textOpts->hAlign, pal, flags & State_Enabled,
0756                      textOpts->text);
0757         p->setPen(old);
0758     } else if (primitive == Generic::Icon) {
0759         K4Style::IconOption *iconOpts = extractOption<K4Style::IconOption *>(kOpt);
0760         QIcon::Mode mode;
0761         QIcon::State iconState;
0762 
0763         // Select the correct icon from the iconset
0764         if (flags & State_Enabled)
0765             if (iconOpts->active) {
0766                 mode = QIcon::Active;
0767             } else {
0768                 mode = QIcon::Normal;
0769             }
0770         else {
0771             mode = QIcon::Disabled;
0772         }
0773 
0774         if ((flags & State_On) || (flags & State_Sunken)) {
0775             iconState = QIcon::On;
0776         } else {
0777             iconState = QIcon::Off;
0778         }
0779 
0780         QSize size = iconOpts->size;
0781         if (!size.isValid()) {
0782             size = QSize(pixelMetric(PM_SmallIconSize), pixelMetric(PM_SmallIconSize));
0783         }
0784         QPixmap icon = iconOpts->icon.pixmap(size, mode, iconState);
0785         p->drawPixmap(centerRect(r, icon.size()), icon);
0786     } else if (primitive == Generic::FocusIndicator) {
0787         QPen pen;
0788         pen.setWidth(0);
0789         pen.setStyle(Qt::DotLine);
0790         p->setPen(pen);
0791         drawInsideRect(p, r);
0792     } else if (primitive >= Generic::ArrowUp && primitive <= Generic::ArrowLeft) {
0793         //### FIXME: Helper for these sorts of things, as Keramik has virtually
0794         //identical code!
0795         K4Style::ColorOption *colorOpt   = extractOption<K4Style::ColorOption *>(kOpt);
0796         QColor               arrowColor = colorOpt->color.color(pal);
0797 
0798         QPolygon poly;
0799 
0800         switch (primitive) {
0801         case Generic::ArrowUp:
0802             poly.setPoints(QCOORDARRLEN(u_arrow), u_arrow);
0803             break;
0804 
0805         case Generic::ArrowDown:
0806             poly.setPoints(QCOORDARRLEN(d_arrow), d_arrow);
0807             break;
0808 
0809         case Generic::ArrowLeft:
0810             poly.setPoints(QCOORDARRLEN(l_arrow), l_arrow);
0811             break;
0812 
0813         default:
0814             poly.setPoints(QCOORDARRLEN(r_arrow), r_arrow);
0815         }
0816 
0817         if (flags & State_Enabled) {
0818             //CHECKME: Why is the -1 needed?
0819             poly.translate(r.x() + r.width() / 2 - 1, r.y() + r.height() / 2);
0820 
0821             p->setPen(arrowColor);
0822             p->drawPolygon(poly);
0823         } else {
0824             //Disabled ones ignore color parameter
0825             poly.translate(r.x() + r.width() / 2, r.y() + r.height() / 2 + 1);
0826             p->setPen(pal.color(QPalette::Light));
0827             p->drawPolygon(poly);
0828             poly.translate(-1, -1);
0829             p->setPen(pal.mid().color());
0830             p->drawPolygon(poly);
0831         }
0832 
0833     }
0834 #if 0 //Reenable if you need a debug aid
0835     else {
0836         p->setPen(Qt::red);
0837         drawInsideRect(p, r);
0838     }
0839 #endif
0840 }
0841 
0842 void K4Style::setWidgetLayoutProp(WidgetType widget, int metric, int value)
0843 {
0844     if (metrics.size() <= widget) {
0845         metrics.resize(widget + 1);
0846     }
0847 
0848     QVector<int> &widgetMetrics = metrics[widget];
0849     if (widgetMetrics.size() <= metric) {
0850         widgetMetrics.resize(metric + 1);
0851     }
0852 
0853     widgetMetrics[metric] = value;
0854 }
0855 
0856 int K4Style::widgetLayoutProp(WidgetType widget, int metric,
0857                               const QStyleOption *opt,
0858                               const QWidget *w) const
0859 {
0860     Q_UNUSED(opt)
0861     Q_UNUSED(w)
0862 
0863     if (metrics.size() <= widget) {
0864         return 0;
0865     }
0866 
0867     const QVector<int> &widgetMetrics = metrics[widget];
0868     if (widgetMetrics.size() <= metric) {
0869         return 0;
0870     }
0871 
0872     return widgetMetrics[metric];
0873 }
0874 
0875 QSize K4Style::expandDim(const QSize &orig, WidgetType wt, int baseMarginMetric,
0876                          const QStyleOption *opt, const QWidget *w, bool rotated) const
0877 {
0878     int addWidth =  2 * widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w) +
0879                     widgetLayoutProp(wt, baseMarginMetric + Left, opt, w) +
0880                     widgetLayoutProp(wt, baseMarginMetric + Right, opt, w);
0881 
0882     int addHeight = 2 * widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w) +
0883                     widgetLayoutProp(wt, baseMarginMetric + Top, opt, w) +
0884                     widgetLayoutProp(wt, baseMarginMetric + Bot, opt, w);
0885 
0886     return QSize(orig.width() + (rotated ? addHeight : addWidth),
0887                  orig.height() + (rotated ? addWidth : addHeight));
0888 }
0889 
0890 QRect K4Style::insideMargin(const QRect &orig, WidgetType wt,
0891                             int baseMarginMetric,
0892                             const QStyleOption *opt, const QWidget *w) const
0893 {
0894     int x1 = orig.topLeft().x();
0895     int y1 = orig.topLeft().y();
0896     int x2 = orig.bottomRight().x();
0897     int y2 = orig.bottomRight().y();
0898 
0899     x1 += widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
0900     x1 += widgetLayoutProp(wt, baseMarginMetric + Left, opt, w);
0901 
0902     y1 += widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
0903     y1 += widgetLayoutProp(wt, baseMarginMetric + Top, opt, w);
0904 
0905     x2 -= widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
0906     x2 -= widgetLayoutProp(wt, baseMarginMetric + Right, opt, w);
0907 
0908     y2 -= widgetLayoutProp(wt, baseMarginMetric + MainMargin, opt, w);
0909     y2 -= widgetLayoutProp(wt, baseMarginMetric + Bot, opt, w);
0910 
0911     return QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
0912 }
0913 
0914 QRect K4Style::handleRTL(const QStyleOption *opt, const QRect &subRect) const
0915 {
0916     return visualRect(opt->direction, opt->rect, subRect);
0917 }
0918 
0919 QPoint K4Style::handleRTL(const QStyleOption *opt, const QPoint &pos) const
0920 {
0921     return visualPos(opt->direction, opt->rect, pos);
0922 }
0923 
0924 void K4Style::drawPrimitive(PrimitiveElement elem, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
0925 {
0926     //Extract the stuff we need out of the option
0927     State flags = option->state;
0928     QRect      r     = option->rect;
0929     QPalette   pal   = option->palette;
0930 
0931     switch (elem) {
0932     case PE_FrameFocusRect:
0933         drawKStylePrimitive(WT_Generic, Generic::FocusIndicator, option, r, pal, flags, painter, widget);
0934         return;
0935     case PE_IndicatorArrowUp:
0936         drawKStylePrimitive(WT_Generic, Generic::ArrowUp, option, r, pal, flags, painter, widget);
0937         return;
0938     case PE_IndicatorArrowDown:
0939         drawKStylePrimitive(WT_Generic, Generic::ArrowDown, option, r, pal, flags, painter, widget);
0940         return;
0941     case PE_IndicatorArrowLeft:
0942         drawKStylePrimitive(WT_Generic, Generic::ArrowLeft, option, r, pal, flags, painter, widget);
0943         return;
0944     case PE_IndicatorArrowRight:
0945         drawKStylePrimitive(WT_Generic, Generic::ArrowRight, option, r, pal, flags, painter, widget);
0946         return;
0947     case PE_IndicatorMenuCheckMark:
0948         //### check flags
0949         drawKStylePrimitive(WT_MenuItem, MenuItem::CheckOn, option, r, pal, flags, painter, widget);
0950         return;
0951     case PE_IndicatorCheckBox:
0952         if (flags & State_NoChange) {
0953             drawKStylePrimitive(WT_CheckBox, CheckBox::CheckTriState, option, r, pal, flags, painter, widget);
0954         } else if (flags & State_On) {
0955             drawKStylePrimitive(WT_CheckBox, CheckBox::CheckOn, option, r, pal, flags, painter, widget);
0956         } else {
0957             drawKStylePrimitive(WT_CheckBox, CheckBox::CheckOff, option, r, pal, flags, painter, widget);
0958         }
0959         return;
0960     case PE_IndicatorRadioButton:
0961         if (flags & State_On) {
0962             drawKStylePrimitive(WT_RadioButton, RadioButton::RadioOn, option, r, pal, flags, painter, widget);
0963         } else {
0964             drawKStylePrimitive(WT_RadioButton, RadioButton::RadioOff, option, r, pal, flags, painter, widget);
0965         }
0966         return;
0967     case PE_IndicatorBranch: {
0968         int centerX = r.x() + r.width() / 2;
0969         int centerY = r.y() + r.height() / 2;
0970 
0971         int expanderAdjust = 0;
0972         //First, determine whether we need to draw an expander.
0973         if (flags & State_Children) {
0974             //How large should we make it?
0975             int sizeLimit = qMin(qMin(r.width(), r.height()),
0976                                  widgetLayoutProp(WT_Tree, Tree::MaxExpanderSize, option, widget));
0977             if ((sizeLimit & 1) == 0) {
0978                 --sizeLimit;
0979             }
0980 
0981             expanderAdjust = sizeLimit / 2 + 1;
0982 
0983             QRect expanderRect = QRect(centerX - sizeLimit / 2, centerY - sizeLimit / 2,
0984                                        sizeLimit, sizeLimit);
0985 
0986             drawKStylePrimitive(WT_Tree, flags & State_Open ? Tree::ExpanderOpen : Tree::ExpanderClosed,
0987                                 option, expanderRect, pal, flags, painter, widget);
0988         }
0989 
0990         //Now, draw the branches. The top line gets drawn unless we're completely
0991         //w/o any indication of a neightbor
0992         if (flags & (State_Item | State_Children | State_Sibling)) {
0993             QRect topLine = QRect(QPoint(centerX, r.y()), QPoint(centerX, centerY - expanderAdjust));
0994             drawKStylePrimitive(WT_Tree, Tree::VerticalBranch, option, topLine, pal, flags, painter, widget);
0995         }
0996 
0997         //The right/left (depending on dir) line gets drawn if we have an item
0998         if (flags & State_Item) {
0999             QRect horLine;
1000             if (option->direction == Qt::LeftToRight)
1001                 horLine = QRect(QPoint(centerX + expanderAdjust, centerY),
1002                                 QPoint(r.right(), centerY));
1003             else
1004                 horLine = QRect(QPoint(r.left(), centerY),
1005                                 QPoint(centerX - expanderAdjust, centerY));
1006             drawKStylePrimitive(WT_Tree, Tree::HorizontalBranch, option, horLine, pal, flags, painter, widget);
1007         }
1008 
1009         //The bottom if we have a sibling
1010         if (flags & State_Sibling) {
1011             QRect botLine = QRect(QPoint(centerX, centerY + expanderAdjust),
1012                                   QPoint(centerX, r.bottom()));
1013             drawKStylePrimitive(WT_Tree, Tree::VerticalBranch, option, botLine, pal, flags, painter, widget);
1014         }
1015         return;
1016     }
1017     case PE_FrameMenu:
1018         drawKStylePrimitive(WT_Menu, Generic::Frame, option, r, pal, flags, painter, widget);
1019         return;
1020     case PE_IndicatorHeaderArrow: {
1021         const QStyleOptionHeader *hOpt = qstyleoption_cast<const QStyleOptionHeader *>(option);
1022         int primitive = 0;
1023         if (flags & State_UpArrow || (hOpt && hOpt->sortIndicator == QStyleOptionHeader::SortUp)) {
1024             primitive = Generic::ArrowUp;
1025         } else if (flags & State_DownArrow || (hOpt && hOpt->sortIndicator == QStyleOptionHeader::SortDown)) {
1026             primitive = Generic::ArrowDown;
1027         }
1028         if (primitive != 0) {
1029             drawKStylePrimitive(WT_Header, primitive, option, r, pal, flags, painter, widget);
1030         }
1031         return;
1032     }
1033     case PE_FrameTabBarBase: {
1034         drawKStylePrimitive(WT_TabBar, TabBar::BaseFrame, option, r, pal, flags, painter, widget);
1035         return;
1036     }
1037     case PE_IndicatorTabTear: {
1038         drawKStylePrimitive(WT_TabBar, TabBar::IndicatorTear, option, r, pal, flags, painter, widget);
1039         return;
1040     }
1041     case PE_FrameTabWidget: {
1042         drawKStylePrimitive(WT_TabWidget, Generic::Frame, option, r, pal, flags, painter, widget);
1043         return;
1044     }
1045 
1046     case PE_PanelLineEdit: {
1047         drawKStylePrimitive(WT_LineEdit, LineEdit::Panel, option, r, pal, flags, painter, widget);
1048         return;
1049     }
1050 
1051     case PE_FrameLineEdit: {
1052         drawKStylePrimitive(WT_LineEdit, Generic::Frame, option, r, pal, flags, painter, widget);
1053         return;
1054     }
1055 
1056     case PE_FrameGroupBox: {
1057         if (const QStyleOptionFrame *fOpt =
1058                     qstyleoption_cast<const QStyleOptionFrame *>(option)) {
1059             QStyleOptionFrame fOpt2(*fOpt);
1060 
1061             if (fOpt2.features & QStyleOptionFrame::Flat) {
1062                 drawKStylePrimitive(WT_GroupBox, GroupBox::FlatFrame, option, r, pal, flags, painter, widget);
1063             } else {
1064                 drawKStylePrimitive(WT_GroupBox, Generic::Frame, option, r, pal, flags, painter, widget);
1065             }
1066         }
1067         return;
1068     }
1069 
1070     case PE_FrameStatusBar: {
1071         drawKStylePrimitive(WT_StatusBar, Generic::Frame, option, r, pal, flags, painter, widget);
1072         return;
1073     }
1074 
1075     case PE_FrameDockWidget: {
1076         drawKStylePrimitive(WT_DockWidget, Generic::Frame, option, r, pal, flags, painter, widget);
1077         return;
1078     }
1079 
1080     case PE_IndicatorDockWidgetResizeHandle: {
1081         drawKStylePrimitive(WT_DockWidget, DockWidget::SeparatorHandle, option, r, pal, flags,
1082                             painter, widget);
1083         return;
1084     }
1085 
1086     case PE_FrameWindow: {
1087         drawKStylePrimitive(WT_Window, Generic::Frame, option, r, pal, flags, painter, widget);
1088         return;
1089     }
1090 
1091     case PE_Frame: {
1092         drawKStylePrimitive(WT_Generic, Generic::Frame, option, r, pal, flags, painter, widget);
1093         return;
1094     }
1095 
1096     case PE_IndicatorToolBarHandle: {
1097         if (flags & State_Horizontal)
1098             drawKStylePrimitive(WT_ToolBar, ToolBar::HandleHor,
1099                                 option, r, pal, flags, painter, widget);
1100         else
1101             drawKStylePrimitive(WT_ToolBar, ToolBar::HandleVert,
1102                                 option, r, pal, flags, painter, widget);
1103         return;
1104     }
1105 
1106     case PE_IndicatorToolBarSeparator:
1107         drawKStylePrimitive(WT_ToolBar, ToolBar::Separator, option, r, pal, flags, painter, widget);
1108         return;
1109 
1110     case PE_PanelButtonCommand:
1111         //case PE_PanelButtonBevel: // ### CHECKME
1112         drawKStylePrimitive(WT_PushButton, PushButton::Panel, option, r, pal, flags, painter, widget);
1113         return;
1114     case PE_FrameDefaultButton:
1115         drawKStylePrimitive(WT_PushButton, PushButton::DefaultButtonFrame, option, r, pal, flags, painter, widget);
1116         return;
1117 
1118     case PE_PanelButtonTool:
1119         drawKStylePrimitive(WT_ToolButton, ToolButton::Panel, option, r, pal, flags, painter, widget);
1120         return;
1121 
1122     case PE_IndicatorButtonDropDown:
1123         drawKStylePrimitive(WT_ToolButton, Generic::ArrowDown, option, r, pal, flags, painter, widget);
1124         return;
1125 
1126     case PE_PanelItemViewItem: {
1127 
1128         const QStyleOptionViewItem *opt = qstyleoption_cast<const QStyleOptionViewItem *>(option);
1129         const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget);
1130         bool hover = (option->state & State_MouseOver) && (!view ||
1131                      view->selectionMode() != QAbstractItemView::NoSelection);
1132 
1133         bool hasCustomBackground = opt->backgroundBrush.style() != Qt::NoBrush &&
1134                                    !(option->state & State_Selected);
1135         bool hasSolidBackground = !hasCustomBackground || opt->backgroundBrush.style() == Qt::SolidPattern;
1136 
1137         const qreal rounding = 2.5;
1138 
1139         if (!hover && !(option->state & State_Selected) && !hasCustomBackground &&
1140                 !(opt->features & QStyleOptionViewItem::Alternate)) {
1141             return;
1142         }
1143 
1144         QPalette::ColorGroup cg;
1145         if (option->state & State_Enabled) {
1146             cg = (option->state & State_Active) ? QPalette::Normal : QPalette::Inactive;
1147         } else {
1148             cg = QPalette::Disabled;
1149         }
1150 
1151         QColor color;
1152 
1153         if (hasCustomBackground && hasSolidBackground) {
1154             color = opt->backgroundBrush.color();
1155         } else {
1156             color = option->palette.color(cg, QPalette::Highlight);
1157         }
1158 
1159         if (hover && !hasCustomBackground) {
1160             if (!(option->state & State_Selected)) {
1161                 color.setAlphaF(.20);
1162             } else {
1163                 color = color.lighter(110);
1164             }
1165         }
1166 
1167         if (opt && (opt->features & QStyleOptionViewItem::Alternate)) {
1168             painter->fillRect(option->rect, option->palette.brush(cg, QPalette::AlternateBase));
1169         }
1170 
1171         if (!hover && !(option->state & State_Selected) && !hasCustomBackground) {
1172             return;
1173         }
1174 
1175         quint64 key = quint64(option->rect.height()) << 32 | color.rgba();
1176         SelectionTiles tiles;
1177         SelectionTiles *tilesPtr = d->selectionCache.object(key);
1178         if (tilesPtr) {
1179             // We can't use tilesPtr directly since obj lifetime is different
1180             // if we QCache::insert() vs. use ret value from QCache::object().
1181             tiles = *tilesPtr;
1182         }
1183         if (!tilesPtr && hasSolidBackground) {
1184             QImage image(32 + 16, option->rect.height(), QImage::Format_ARGB32_Premultiplied);
1185             image.fill(0);
1186 
1187             QRect r = image.rect().adjusted(0, 0, -1, -1);
1188 
1189             QPainterPath path1, path2;
1190             path1.addRoundedRect(r, rounding, rounding);
1191             path2.addRoundedRect(r.adjusted(1, 1, -1, -1), rounding - 1, rounding - 1);
1192 
1193             // items with custom background brushes always have their background drawn
1194             // regardless of whether they are hovered or selected or neither so
1195             // the gradient effect needs to be more subtle
1196             int lightenAmount = hasCustomBackground ? 110 : 130;
1197             QLinearGradient gradient(0, 0, 0, r.bottom());
1198             gradient.setColorAt(0, color.lighter(lightenAmount));
1199             gradient.setColorAt(1, color);
1200 
1201             QPainter p(&image);
1202             p.setRenderHint(QPainter::Antialiasing);
1203             p.translate(.5, .5);
1204             p.setPen(QPen(color, 1));
1205             p.setBrush(gradient);
1206             p.drawPath(path1);
1207             p.strokePath(path2, QPen(QColor(255, 255, 255, 64), 1));
1208             p.end();
1209 
1210             QPixmap pixmap = QPixmap::fromImage(image);
1211 
1212             tiles.left   = pixmap.copy(0, 0, 8, image.height());
1213             tiles.center = pixmap.copy(8, 0, 32, image.height());
1214             tiles.right  = pixmap.copy(40, 0, 8, image.height());
1215 
1216             d->selectionCache.insert(key, new SelectionTiles(tiles));
1217         } else if (hasCustomBackground && !hasSolidBackground) {
1218             const QPointF oldBrushOrigin = painter->brushOrigin();
1219             painter->setBrushOrigin(opt->rect.topLeft());
1220             painter->setBrush(opt->backgroundBrush);
1221             painter->setPen(Qt::NoPen);
1222             painter->drawRect(opt->rect);
1223             painter->setBrushOrigin(oldBrushOrigin);
1224             return;
1225         }
1226 
1227         bool roundedLeft  = false;
1228         bool roundedRight = false;
1229         if (opt) {
1230             roundedLeft  = (opt->viewItemPosition == QStyleOptionViewItem::Beginning);
1231             roundedRight = (opt->viewItemPosition == QStyleOptionViewItem::End);
1232             if (opt->viewItemPosition == QStyleOptionViewItem::OnlyOne ||
1233                     opt->viewItemPosition == QStyleOptionViewItem::Invalid ||
1234                     (view && view->selectionBehavior() != QAbstractItemView::SelectRows)) {
1235                 roundedLeft  = true;
1236                 roundedRight = true;
1237             }
1238         }
1239 
1240         QRect r = option->rect;
1241         bool reverseLayout = option->direction == Qt::RightToLeft;
1242 
1243         if (!reverseLayout ? roundedLeft : roundedRight) {
1244             painter->drawPixmap(r.topLeft(), tiles.left);
1245             r.adjust(8, 0, 0, 0);
1246         }
1247         if (!reverseLayout ? roundedRight : roundedLeft) {
1248             painter->drawPixmap(r.right() - 8 + 1, r.top(), tiles.right);
1249             r.adjust(0, 0, -8, 0);
1250         }
1251         if (r.isValid()) {
1252             painter->drawTiledPixmap(r, tiles.center);
1253         }
1254 
1255         return;
1256     }
1257 
1258     default:
1259         break;
1260     }
1261 
1262     QCommonStyle::drawPrimitive(elem, option, painter, widget);
1263 }
1264 
1265 void K4Style::drawControl(ControlElement element, const QStyleOption *option, QPainter *p, const QWidget *widget) const
1266 {
1267     //Extract the stuff we need out of the option
1268     State flags = option->state;
1269     QRect      r     = option->rect;
1270     QPalette   pal   = option->palette;
1271 
1272     switch (element) {
1273     case CE_PushButton: {
1274         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
1275         if (!bOpt) {
1276             return;
1277         }
1278 
1279         //Draw the bevel outside
1280         drawControl(CE_PushButtonBevel, option, p, widget);
1281 
1282         //Now, draw the label...
1283         QRect labelRect = r;
1284 
1285         //Move inside of default indicator margin if need be
1286         if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton)) {
1287             labelRect = insideMargin(labelRect, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
1288         }
1289 
1290         //now get the contents area
1291         labelRect = insideMargin(labelRect, WT_PushButton, PushButton::ContentsMargin, option, widget);
1292 
1293         //### do we do anything for RTL here?
1294 
1295         QStyleOptionButton bOptTmp = *bOpt;
1296         bOptTmp.rect = labelRect;
1297         drawControl(CE_PushButtonLabel, &bOptTmp, p, widget);
1298 
1299         //Finally, renderer the focus indicator if need be
1300         if (flags & State_HasFocus) {
1301             QRect focusRect = insideMargin(r, WT_PushButton, PushButton::FocusMargin, option, widget);
1302 
1303             QStyleOptionFocusRect foOpts;
1304             foOpts.palette         = pal;
1305             foOpts.rect            = focusRect;
1306             foOpts.state           = flags;
1307 
1308             drawKStylePrimitive(WT_PushButton, Generic::FocusIndicator, &foOpts, focusRect, pal, flags, p, widget);
1309         }
1310 
1311         return;
1312     }
1313 
1314     case CE_PushButtonBevel: {
1315         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
1316         if (!bOpt) {
1317             return;
1318         }
1319 
1320         //Check whether we should draw default indicator.
1321         if (bOpt->features & QStyleOptionButton::DefaultButton) {
1322             drawPrimitive(PE_FrameDefaultButton, option, p, widget);
1323         }
1324 
1325         QRect bevelRect = r;
1326         //Exclude the margin if default or auto-default
1327         if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton)) {
1328             bevelRect = insideMargin(r, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
1329         }
1330 
1331         //Now draw the bevel itself.
1332         QStyleOptionButton bOptTmp = *bOpt;
1333         bOptTmp.rect = bevelRect;
1334         drawPrimitive(PE_PanelButtonCommand, &bOptTmp, p, widget);
1335 
1336         return;
1337     }
1338 
1339     case CE_PushButtonLabel: {
1340         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
1341         if (!bOpt) {
1342             return;
1343         }
1344 
1345         //Extract out coordinates for easier manipulation
1346         //(OK, OK, for easier stealing of code from Keramik)
1347         int x, y, w, h;
1348         r.getRect(&x, &y, &w, &h);
1349 
1350         //Are we active? If so, shift contents
1351         bool active = (flags & State_On) || (flags & State_Sunken);
1352         if (active) {
1353             x += widgetLayoutProp(WT_PushButton, PushButton::PressedShiftHorizontal, option, widget);
1354             y += widgetLayoutProp(WT_PushButton, PushButton::PressedShiftVertical, option, widget);
1355         }
1356 
1357         //Layout the stuff.
1358         if (bOpt->features & QStyleOptionButton::HasMenu) {
1359             int indicatorWidth = widgetLayoutProp(WT_PushButton, PushButton::MenuIndicatorSize, option, widget);
1360             int indicatorSpacing = widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget);
1361             w -= indicatorWidth + indicatorSpacing;
1362 
1363             //Draw the arrow...
1364             drawKStylePrimitive(WT_PushButton, Generic::ArrowDown, option,
1365                                 handleRTL(bOpt, QRect(x + w + indicatorSpacing, y, indicatorWidth, h)),
1366                                 pal, flags, p, widget);
1367         }
1368 
1369         // Draw the icon if there is one
1370         if (!bOpt->icon.isNull()) {
1371             IconOption icoOpt;
1372             icoOpt.icon   = bOpt->icon;
1373             icoOpt.size   = bOpt->iconSize;
1374             icoOpt.active = flags & State_HasFocus;
1375 
1376             if (!bOpt->text.isEmpty()) {
1377                 int margin = widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget);
1378                 //Center text + icon w/margin in between..
1379 
1380                 //Calculate length of both.
1381                 int length = bOpt->iconSize.width() + margin
1382                              + p->fontMetrics().size(Qt::TextShowMnemonic, bOpt->text).width();
1383 
1384                 //Calculate offset.
1385                 int offset = (w - length) / 2;
1386 
1387                 //draw icon
1388                 QRect rect = QRect(QPoint(x + offset, y + h / 2 - bOpt->iconSize.height() / 2), bOpt->iconSize);
1389                 drawKStylePrimitive(WT_PushButton, Generic::Icon, option,
1390                                     handleRTL(bOpt, rect),
1391                                     pal, flags, p, widget, &icoOpt);
1392 
1393                 //new bounding rect for the text
1394                 x += offset + bOpt->iconSize.width() + margin;
1395                 w =  length - bOpt->iconSize.width() - margin;
1396             } else {
1397                 //Icon only. Center it. (Thankfully, they killed the icon + pixmap insanity in Qt4. Whee!
1398                 //(no need to do anything for RTL here, it's symmetric)
1399                 drawKStylePrimitive(WT_PushButton, Generic::Icon, option,
1400                                     QRect(x, y, w, h),
1401                                     pal, flags, p, widget, &icoOpt);
1402             }
1403         } else {
1404             //Center the text
1405             int textW = p->fontMetrics().size(Qt::TextShowMnemonic, bOpt->text).width();
1406             x += (w - textW) / 2;
1407             w =  textW;
1408         }
1409 
1410         TextOption lbOpt(bOpt->text);
1411         drawKStylePrimitive(WT_PushButton, Generic::Text, option, handleRTL(bOpt, QRect(x, y, w, h)),
1412                             pal, flags, p, widget, &lbOpt);
1413 
1414         return;
1415     }
1416 
1417     case CE_DockWidgetTitle: {
1418         const QStyleOptionDockWidget *dwOpt = ::qstyleoption_cast<const QStyleOptionDockWidget *>(option);
1419         if (!dwOpt) {
1420             return;
1421         }
1422 
1423         QRect textRect = insideMargin(r, WT_DockWidget, DockWidget::TitleMargin, option, widget);
1424         drawKStylePrimitive(WT_DockWidget, DockWidget::TitlePanel, option, r, pal, flags, p, widget);
1425 
1426         TextOption lbOpt(dwOpt->title);
1427         lbOpt.color = widgetLayoutProp(WT_DockWidget, DockWidget::TitleTextColor,
1428                                        option, widget);
1429         drawKStylePrimitive(WT_DockWidget, Generic::Text, option, textRect, pal, flags, p, widget, &lbOpt);
1430         return;
1431     }
1432 
1433     case CE_ToolBoxTabShape: {
1434         drawKStylePrimitive(WT_ToolBoxTab, ToolBoxTab::Panel, option, r, pal, flags, p, widget);
1435         return;
1436     }
1437     /*
1438             case CE_ToolBoxTabLabel:
1439             {
1440                 drawKStylePrimitive(WT_ToolBoxTab, Generic::Text, option, r, pal, flags, p, widget);
1441                 return;
1442             }
1443     */
1444     case CE_CheckBox: {
1445         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
1446         if (!bOpt) {
1447             return;
1448         }
1449 
1450         //Draw the checkbox
1451         QRect checkBox = subElementRect(SE_CheckBoxIndicator, option, widget);
1452         QStyleOptionButton bOptTmp = *bOpt;
1453         bOptTmp.rect = checkBox;
1454         drawPrimitive(PE_IndicatorCheckBox, &bOptTmp, p, widget);
1455 
1456         // pixmap and text label...
1457         bOptTmp.rect = subElementRect(SE_CheckBoxContents, option, widget);
1458         drawControl(CE_CheckBoxLabel, &bOptTmp, p, widget);
1459 
1460         //Draw the focus rect...
1461         if (flags & State_HasFocus) {
1462             QRect focusRect = subElementRect(SE_CheckBoxFocusRect, option, widget);
1463             drawKStylePrimitive(WT_CheckBox, Generic::FocusIndicator, option, focusRect,
1464                                 pal, flags, p, widget);
1465         }
1466         return;
1467     }
1468 
1469     case CE_CheckBoxLabel: {
1470         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
1471         if (!bOpt) {
1472             return;
1473         }
1474 
1475         int textShift = 0; // shift text in case there is a label pixmap
1476         // draw the pixmap, if there is one
1477         if (!bOpt->icon.isNull()) {
1478             IconOption icoOpt;
1479             icoOpt.icon   = bOpt->icon;
1480             icoOpt.size   = bOpt->iconSize;
1481             icoOpt.active = flags & State_HasFocus;
1482 
1483             QRect iconRect(r.x(), r.y() + (r.height() - bOpt->iconSize.height()) / 2,
1484                            bOpt->iconSize.width(), bOpt->iconSize.height());
1485             drawKStylePrimitive(WT_CheckBox, Generic::Icon, option,
1486                                 handleRTL(bOpt, iconRect),
1487                                 pal, flags, p, widget, &icoOpt);
1488 
1489             textShift = bOpt->iconSize.width() +
1490                         widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget);
1491         }
1492 
1493         if (!bOpt->text.isEmpty()) {
1494             TextOption lbOpt(bOpt->text);
1495             drawKStylePrimitive(WT_CheckBox, Generic::Text, option,
1496                                 handleRTL(bOpt, r.adjusted(textShift, 0, 0, 0)),
1497                                 pal, flags, p, widget, &lbOpt);
1498         }
1499 
1500         return;
1501     }
1502 
1503     case CE_RadioButton: {
1504         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
1505         if (!bOpt) {
1506             return;
1507         }
1508 
1509         //Draw the indicator
1510         QRect indicator = subElementRect(SE_RadioButtonIndicator, option, widget);
1511         QStyleOptionButton bOptTmp = *bOpt;
1512         bOptTmp.rect = indicator;
1513         drawPrimitive(PE_IndicatorRadioButton, &bOptTmp, p, widget);
1514 
1515         // pixmap and text label...
1516         bOptTmp.rect = subElementRect(SE_RadioButtonContents, option, widget);
1517         drawControl(CE_RadioButtonLabel, &bOptTmp, p, widget);
1518 
1519         //Draw the focus rect...
1520         if (flags & State_HasFocus) {
1521             QRect focusRect = subElementRect(SE_RadioButtonFocusRect, option, widget);
1522             drawKStylePrimitive(WT_RadioButton, Generic::FocusIndicator, option, focusRect,
1523                                 pal, flags, p, widget);
1524         }
1525         return;
1526     }
1527 
1528     case CE_RadioButtonLabel: {
1529         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
1530         if (!bOpt) {
1531             return;
1532         }
1533 
1534         int textShift = 0; // shift text in case there is a label pixmap
1535         // draw the pixmap, if there is one
1536         if (!bOpt->icon.isNull()) {
1537             IconOption icoOpt;
1538             icoOpt.icon   = bOpt->icon;
1539             icoOpt.active = flags & State_HasFocus;
1540             icoOpt.size   = bOpt->iconSize;
1541 
1542             QRect iconRect(r.x(), r.y() + (r.height() - bOpt->iconSize.height()) / 2,
1543                            bOpt->iconSize.width(), bOpt->iconSize.height());
1544             drawKStylePrimitive(WT_RadioButton, Generic::Icon, option,
1545                                 handleRTL(bOpt, iconRect),
1546                                 pal, flags, p, widget, &icoOpt);
1547 
1548             textShift = bOpt->iconSize.width() +
1549                         widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget);
1550         }
1551 
1552         TextOption lbOpt(bOpt->text);
1553         drawKStylePrimitive(WT_RadioButton, Generic::Text, option,
1554                             handleRTL(bOpt, r.adjusted(textShift, 0, 0, 0)),
1555                             pal, flags, p, widget, &lbOpt);
1556         return;
1557     }
1558 
1559     //The CE_ProgressBar implementation inside QCommonStyle is acceptible.
1560     //We just implement the subElementRect's it uses
1561 
1562     case CE_ProgressBarGroove: {
1563         drawKStylePrimitive(WT_ProgressBar, ProgressBar::Groove,  option, r,
1564                             pal, flags, p, widget);
1565         return;
1566     }
1567 
1568     case CE_ProgressBarContents: {
1569         const QStyleOptionProgressBar *pbOpt = qstyleoption_cast<const QStyleOptionProgressBar *>(option);
1570         const QStyleOptionProgressBar *pbOpt2 = qstyleoption_cast<const QStyleOptionProgressBar *>(option);
1571         if (!pbOpt) {
1572             return;
1573         }
1574 
1575         //We layout as if LTR, relying on visualRect to fix it up
1576         double progress    = pbOpt->progress - pbOpt->minimum;
1577         int steps          = qMax(pbOpt->maximum  - pbOpt->minimum, 1);
1578         bool busyIndicator = (pbOpt->minimum == 0 && pbOpt->maximum == 0);
1579         bool horizontal    = !pbOpt2 || pbOpt2->orientation == Qt::Horizontal;
1580 
1581         //Do we have to draw anything?
1582         if (!progress && ! busyIndicator) {
1583             return;
1584         }
1585 
1586         //Calculate width fraction
1587         double widthFrac;
1588         if (busyIndicator) {
1589             widthFrac = widgetLayoutProp(WT_ProgressBar, ProgressBar::BusyIndicatorSize, option, widget) / 100.0;
1590         } else {
1591             widthFrac = progress / steps;
1592         }
1593 
1594         //And now the pixel width
1595         int width = qMin(r.width(), (int)(widthFrac * double(r.width())));
1596         int height = qMin(r.height(), (int)(widthFrac * r.height()));
1597 
1598         if (busyIndicator) {
1599             int size = width;
1600             if (!horizontal) {
1601                 size = height;
1602             }
1603             //Clamp to upper width limit
1604             if (size > widgetLayoutProp(WT_ProgressBar, ProgressBar::MaxBusyIndicatorSize, option, widget)) {
1605                 size = widgetLayoutProp(WT_ProgressBar, ProgressBar::MaxBusyIndicatorSize, option, widget);
1606             }
1607 
1608             //A busy indicator with width 0 is kind of useless
1609             if (size < 1) {
1610                 size = 1;
1611             }
1612 
1613             int remSize = (horizontal ? r.width() : r.height()) - size; //The space around which we move around...
1614             if (remSize <= 0) {
1615                 remSize = 1;    //Do something non-crashy when too small...
1616             }
1617 
1618             int pstep =  int(progress) % (2 * remSize);
1619 
1620             if (pstep > remSize) {
1621                 //Bounce about.. We're remWidth + some delta, we want to be remWidth - delta...
1622                 // - ( (remWidth + some delta) - 2* remWidth )  = - (some deleta - remWidth) = remWidth - some delta..
1623                 pstep = -(pstep - 2 * remSize);
1624             }
1625 
1626             QRect indicatorRect;
1627             if (horizontal) {
1628                 indicatorRect = QRect(r.x() + pstep, r.y(), size, r.height());
1629             } else {
1630                 indicatorRect = QRect(r.x(), r.y() + pstep, r.width(), size);
1631             }
1632             drawKStylePrimitive(WT_ProgressBar, ProgressBar::BusyIndicator, option, handleRTL(option, indicatorRect),
1633                                 pal, flags, p, widget);
1634         } else {
1635             QRect indicatorRect;
1636             if (horizontal) {
1637                 indicatorRect = QRect(r.x(), r.y(), width, r.height());
1638             } else {
1639                 indicatorRect = QRect(r.x(), r.bottom() - height + 1, r.width(), height);
1640             }
1641             drawKStylePrimitive(WT_ProgressBar, ProgressBar::Indicator, option, handleRTL(option, indicatorRect),
1642                                 pal, flags, p, widget);
1643         }
1644         return;
1645     }
1646 
1647     case CE_ProgressBarLabel: {
1648         const QStyleOptionProgressBar *pbOpt = qstyleoption_cast<const QStyleOptionProgressBar *>(option);
1649         const QStyleOptionProgressBar *pbOpt2 = qstyleoption_cast<const QStyleOptionProgressBar *>(option);
1650         if (pbOpt) {
1651             TextOption lbOpt(pbOpt->text);
1652             bool horizontal = !pbOpt2 || pbOpt2->orientation == Qt::Horizontal;
1653             bool reverseLayout = option->direction == Qt::RightToLeft;
1654 
1655             p->save();
1656 
1657             // rotate label for vertical layout
1658             if (!horizontal && !reverseLayout) {
1659                 p->translate(r.topRight());
1660                 p->rotate(90.0);
1661             } else if (!horizontal) {
1662                 p->translate(r.bottomLeft());
1663                 p->rotate(-90.0);
1664             }
1665 
1666             if (useSideText(pbOpt)) {
1667                 lbOpt.color = QPalette::ButtonText;
1668 
1669                 //### or other way around?
1670                 if (option->direction == Qt::LeftToRight) {
1671                     lbOpt.hAlign = Qt::AlignRight;
1672                 } else {
1673                     lbOpt.hAlign = Qt::AlignLeft;
1674                 }
1675 
1676                 //Handle side margin.
1677                 int marWidth = widgetLayoutProp(WT_ProgressBar, ProgressBar::SideTextSpace, option, widget);
1678 
1679                 drawKStylePrimitive(WT_ProgressBar, Generic::Text, option,
1680                                     horizontal ? r.adjusted(0, marWidth, 0, -marWidth) : QRect(0, marWidth, r.height(), r.width() - marWidth),
1681                                     pal, flags, p, widget, &lbOpt);
1682             } else {
1683                 if (pbOpt->textAlignment == Qt::AlignLeft) { //TODO: Check BIDI?
1684                     lbOpt.hAlign = Qt::AlignHCenter;
1685                 } else {
1686                     lbOpt.hAlign = pbOpt->textAlignment;
1687                 }
1688 
1689                 //Now, we need to figure out the geometry of the indicator.
1690                 QRect progressRect;
1691                 double progress    = pbOpt->progress - pbOpt->minimum;
1692                 int steps          = qMax(pbOpt->maximum  - pbOpt->minimum, 1);
1693                 bool busyIndicator = (steps <= 1);
1694 
1695                 int width;
1696                 int height;
1697                 if (busyIndicator) {
1698                     //how did this happen? handle as 0%
1699                     width = 0;
1700                     height = 0;
1701                 } else {
1702                     double widthFrac = progress / steps;;
1703                     width = qMin(r.width(), (int)(widthFrac * r.width()));
1704                     height = qMin(r.height(), (int)(widthFrac * r.height()));
1705                 }
1706 
1707                 //If there is any indicator, we do two paths, with different
1708                 //clipping rects, for the two colors.
1709                 if (width || height) {
1710                     if (horizontal) {
1711                         p->setClipRect(handleRTL(option, QRect(r.x(), r.y(), width, r.height())));
1712                     } else if (!reverseLayout) {
1713                         p->setClipRect(QRect(r.height() - height, 0, r.height(), r.width()));
1714                     } else {
1715                         p->setClipRect(QRect(0, 0, height, r.width()));
1716                     }
1717                     lbOpt.color = QPalette::HighlightedText;
1718                     drawKStylePrimitive(WT_ProgressBar, Generic::Text, option,
1719                                         horizontal ? r : QRect(0, 0, r.height(), r.width()),
1720                                         pal, flags, p, widget, &lbOpt);
1721 
1722                     if (horizontal) {
1723                         p->setClipRect(handleRTL(option, QRect(r.x() + width, r.y(), r.width() - width, r.height())));
1724                     } else if (!reverseLayout) {
1725                         p->setClipRect(QRect(0, 0, r.height() - height, r.width()));
1726                     } else {
1727                         p->setClipRect(QRect(height, 0, r.height() - height, r.width()));
1728                     }
1729                     lbOpt.color = QPalette::ButtonText;
1730                     drawKStylePrimitive(WT_ProgressBar, Generic::Text, option,
1731                                         horizontal ? r : QRect(0, 0, r.height(), r.width()),
1732                                         pal, flags, p, widget, &lbOpt);
1733                     p->setClipping(false);
1734                 } else {
1735                     lbOpt.color = QPalette::ButtonText;
1736                     drawKStylePrimitive(WT_ProgressBar, Generic::Text, option,
1737                                         horizontal ? r : QRect(0, 0, r.height(), r.width()),
1738                                         pal, flags, p, widget, &lbOpt);
1739                 }
1740             }
1741             p->restore();
1742         }
1743         return;
1744     }
1745 
1746     case CE_MenuBarItem: {
1747         const QStyleOptionMenuItem *mOpt = ::qstyleoption_cast<const QStyleOptionMenuItem *>(option);
1748         if (!mOpt) {
1749             return;
1750         }
1751 
1752         //Bevel...
1753         drawKStylePrimitive(WT_MenuBarItem, MenuBarItem::Panel, option, r,
1754                             pal, flags, p, widget);
1755 
1756         //Text...
1757         QRect textRect = insideMargin(r, WT_MenuBarItem, MenuBarItem::Margin, option, widget);
1758 
1759         TextOption lbOpt(mOpt->text);
1760         drawKStylePrimitive(WT_MenuBarItem, Generic::Text, option, textRect,
1761                             pal, flags, p, widget, &lbOpt);
1762 
1763         return;
1764     }
1765 
1766     case CE_MenuBarEmptyArea: {
1767         drawKStylePrimitive(WT_MenuBar, MenuBar::EmptyArea,  option, r,
1768                             pal, flags, p, widget);
1769         return;
1770     }
1771 
1772     case CE_MenuEmptyArea:
1773     case CE_MenuVMargin:
1774     case CE_MenuHMargin: {
1775         drawKStylePrimitive(WT_Menu, Menu::Background,  option, r,
1776                             pal, flags, p, widget);
1777         return;
1778     }
1779 
1780     case CE_MenuItem: {
1781 
1782         //First of all,render the background.
1783         drawKStylePrimitive(WT_Menu, Menu::Background, option, r,
1784                             pal, flags, p, widget);
1785 
1786         const QStyleOptionMenuItem *miOpt = ::qstyleoption_cast<const QStyleOptionMenuItem *>(option);
1787         if (!miOpt || miOpt->menuItemType == QStyleOptionMenuItem::EmptyArea) {
1788             return;
1789         }
1790 
1791         //Remove the margin (for everything but the column background)
1792         QRect ir = insideMargin(r, WT_MenuItem, MenuItem::Margin, option, widget);
1793 
1794         //First, figure out the left column width. When CheckAlongsideIcon is disabled it's just
1795         // the icon column width. Otherwise it consists of CheckWidth+CheckSpace+icon column width.
1796         int iconColW = miOpt->maxIconWidth;
1797         iconColW     = qMax(iconColW, widgetLayoutProp(WT_MenuItem, MenuItem::IconWidth, option, widget));
1798         int checkColW = widgetLayoutProp(WT_MenuItem, MenuItem::CheckWidth, option, widget);
1799         int checkSpace = widgetLayoutProp(WT_MenuItem, MenuItem::CheckSpace, option, widget);
1800 
1801         int leftColW = iconColW;
1802         // only use the additional check row if the menu has checkable menuItems.
1803         bool checkAlongsideIcon = (miOpt->menuHasCheckableItems &&
1804                                    widgetLayoutProp(WT_MenuItem, MenuItem::CheckAlongsideIcon, option, widget));
1805         if (checkAlongsideIcon) {
1806             leftColW = checkColW + checkSpace + iconColW;
1807         }
1808 
1809         //And the right arrow column...
1810         int rightColW = widgetLayoutProp(WT_MenuItem, MenuItem::ArrowSpace, option, widget) +
1811                         widgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, option, widget);
1812 
1813         //Render left column background. This is a bit tricky, since we don't use the V margin.
1814         QRect leftColRect(ir.x(), r.y(), leftColW, r.height());
1815         drawKStylePrimitive(WT_MenuItem, MenuItem::CheckColumn, option, handleRTL(option, leftColRect),
1816                             pal, flags, p, widget);
1817 
1818         //Separators: done with the bg, can paint them and bail them out.
1819         if (miOpt->menuItemType == QStyleOptionMenuItem::Separator) {
1820             drawKStylePrimitive(WT_MenuItem, MenuItem::Separator, option, ir, pal, flags, p, widget);
1821             return;
1822         }
1823 
1824         //Now paint the active indicator --- other stuff goes on top of it
1825         bool active = (flags & State_Selected);
1826 
1827         //Active indicator...
1828         if (active) {
1829             drawKStylePrimitive(WT_MenuItem, MenuItem::ItemIndicator, option, handleRTL(option, r), pal, flags, p, widget);
1830         }
1831 
1832         ColorMode textColor = (flags & State_Enabled) ? (widgetLayoutProp(WT_MenuItem, active ?
1833                               MenuItem::ActiveTextColor :
1834                               MenuItem::TextColor, option, widget))
1835                               : (widgetLayoutProp(WT_MenuItem, active ?
1836                                       MenuItem::ActiveDisabledTextColor :
1837                                       MenuItem::DisabledTextColor, option, widget));
1838 
1839         //Readjust the column rectangle back to proper height
1840         leftColRect = QRect(ir.x(), ir.y(), leftColW, ir.height());
1841         // Paint checkbox, etc.
1842         if (!checkAlongsideIcon && !miOpt->icon.isNull()) {
1843             // there is an icon and the item is checked, so paint a CheckIcon
1844             if (miOpt->checked) {
1845                 drawKStylePrimitive(WT_MenuItem, MenuItem::CheckIcon,
1846                                     option, handleRTL(option, leftColRect), pal, flags,
1847                                     p, widget);
1848             }
1849         } else {
1850             // paint a normal check- resp. radiomark.
1851             QRect checkColRect;
1852             if (checkAlongsideIcon) {
1853                 checkColRect = QRect(leftColRect.x(), leftColRect.y(),
1854                                      checkColW, leftColRect.height());
1855             } else {
1856                 checkColRect = leftColRect;
1857             }
1858 
1859             bool checked = miOpt->checked;
1860             if (miOpt->checkType == QStyleOptionMenuItem::NonExclusive) {
1861                 drawKStylePrimitive(WT_MenuItem, checked ? MenuItem::CheckOn : MenuItem::CheckOff,
1862                                     option, handleRTL(option, checkColRect), pal, flags,
1863                                     p, widget);
1864             } else if (miOpt->checkType == QStyleOptionMenuItem::Exclusive) {
1865                 drawKStylePrimitive(WT_MenuItem, checked ? MenuItem::RadioOn : MenuItem::RadioOff,
1866                                     option, handleRTL(option, checkColRect), pal, flags,
1867                                     p, widget);
1868             }
1869         }
1870         // Paint the menu icon.
1871         if (!miOpt->icon.isNull()) {
1872             int iconSize = pixelMetric(PM_SmallIconSize);
1873 
1874             QRect iconColRect;
1875             if (checkAlongsideIcon) {
1876                 iconColRect = QRect(leftColRect.x() + checkColW + checkSpace, leftColRect.y(),
1877                                     leftColRect.width() - (checkColW + checkSpace), leftColRect.height());
1878             } else {
1879                 iconColRect = leftColRect;
1880             }
1881             IconOption icoOpt;
1882             icoOpt.icon   = miOpt->icon;
1883             icoOpt.active = flags & State_Selected;
1884             drawKStylePrimitive(WT_MenuItem, Generic::Icon, option,
1885                                 handleRTL(option, centerRect(iconColRect, iconSize, iconSize)),
1886                                 pal, flags, p, widget, &icoOpt);
1887         }
1888 
1889         //Now include the spacing when calculating the next columns
1890         leftColW += widgetLayoutProp(WT_MenuItem, MenuItem::IconSpace, option, widget);
1891 
1892         //Render the text, including any accel.
1893         QString text = miOpt->text;
1894         QRect   textRect = QRect(ir.x() + leftColW, ir.y(), ir.width() - leftColW - rightColW, ir.height());
1895         QFont   font = miOpt->font;
1896         const QFont oldFont = p->font();
1897 
1898         p->setFont(font);
1899         int tabPos = miOpt->text.indexOf(QLatin1Char('\t'));
1900         if (tabPos != -1) {
1901             text = miOpt->text.left(tabPos);
1902             QString accl = miOpt->text.mid(tabPos + 1);
1903 
1904             //Draw the accel.
1905             TextOption lbOpt(accl);
1906             lbOpt.color  = textColor;
1907             lbOpt.hAlign = Qt::AlignRight;
1908             drawKStylePrimitive(WT_MenuItem, Generic::Text, option, handleRTL(option, textRect),
1909                                 pal, flags, p, widget, &lbOpt);
1910         }
1911 
1912         //Draw the text.
1913         TextOption lbOpt(text);
1914         lbOpt.color = textColor;
1915         drawKStylePrimitive(WT_MenuItem, Generic::Text, option, handleRTL(option, textRect),
1916                             pal, flags, p, widget, &lbOpt);
1917 
1918         p->setFont(oldFont);
1919 
1920         //Render arrow, if need be.
1921         if (miOpt->menuItemType == QStyleOptionMenuItem::SubMenu) {
1922             ColorOption arrowColor;
1923             arrowColor.color = textColor;
1924 
1925             int aw = widgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, option, widget);
1926 
1927             QRect arrowRect(ir.x() + ir.width() - aw, ir.y(), aw, ir.height());
1928             drawKStylePrimitive(WT_MenuItem, option->direction == Qt::LeftToRight ?
1929                                 Generic::ArrowRight : Generic::ArrowLeft,
1930                                 option, handleRTL(option, arrowRect), pal, flags, p, widget, &arrowColor);
1931         }
1932 
1933         return;
1934     }
1935 
1936     case CE_ScrollBarAddLine:
1937     case CE_ScrollBarSubLine: {
1938         const QStyleOptionSlider *slOpt = ::qstyleoption_cast<const QStyleOptionSlider *>(option);
1939         if (!slOpt) {
1940             return;
1941         }
1942 
1943         //Fix up the rectangle to be what we want
1944         r = internalSubControlRect(CC_ScrollBar, slOpt,
1945                                    element == CE_ScrollBarAddLine ? SC_ScrollBarAddLine : SC_ScrollBarSubLine, widget);
1946         const_cast<QStyleOption *>(option)->rect = r;
1947 
1948         bool doubleButton = false;
1949 
1950         //See whether we're a double-button...
1951         if (element == CE_ScrollBarAddLine && widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, option, widget)) {
1952             doubleButton = true;
1953         }
1954         if (element == CE_ScrollBarSubLine && widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, option, widget)) {
1955             doubleButton = true;
1956         }
1957 
1958         if (doubleButton) {
1959             if (flags & State_Horizontal) {
1960                 DoubleButtonOption::ActiveButton ab = DoubleButtonOption::None;
1961 
1962                 //Depending on RTL direction, the one on the left is either up or down.
1963                 bool leftAdds, rightAdds;
1964                 if (slOpt->direction == Qt::LeftToRight) {
1965                     leftAdds  = false;
1966                     rightAdds = true;
1967                 } else {
1968                     leftAdds  = true;
1969                     rightAdds = false;
1970                 }
1971 
1972                 //Determine whether any of the buttons is active
1973                 if (flags & State_Sunken) {
1974                     if (((slOpt->activeSubControls & SC_ScrollBarAddLine) && leftAdds) ||
1975                             ((slOpt->activeSubControls & SC_ScrollBarSubLine) && !leftAdds)) {
1976                         ab = DoubleButtonOption::Left;
1977                     }
1978 
1979                     if (((slOpt->activeSubControls & SC_ScrollBarAddLine) && rightAdds) ||
1980                             ((slOpt->activeSubControls & SC_ScrollBarSubLine) && !rightAdds)) {
1981                         ab = DoubleButtonOption::Right;
1982                     }
1983                 }
1984 
1985                 DoubleButtonOption bOpt(ab);
1986                 drawKStylePrimitive(WT_ScrollBar, ScrollBar::DoubleButtonHor,
1987                                     option, r, pal, flags, p, widget, &bOpt);
1988 
1989                 //Draw the left arrow..
1990                 QRect leftSubButton = QRect(r.x(), r.y(), r.width() / 2, r.height());
1991 
1992                 ColorOption colOpt;
1993                 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
1994                 if (ab == DoubleButtonOption::Left) {
1995                     colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
1996                 }
1997 
1998                 drawKStylePrimitive(WT_ScrollBar, Generic::ArrowLeft, option, leftSubButton, pal,
1999                                     flags, p, widget, &colOpt);
2000 
2001                 //Right half..
2002                 QRect rightSubButton;
2003                 rightSubButton.setBottomRight(r.bottomRight());
2004                 rightSubButton.setLeft(leftSubButton.right() + 1);
2005                 rightSubButton.setTop(r.top());
2006 
2007                 //Chose proper color
2008                 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
2009                 if (ab == DoubleButtonOption::Right) {
2010                     colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
2011                 }
2012 
2013                 drawKStylePrimitive(WT_ScrollBar, Generic::ArrowRight, option, rightSubButton, pal,
2014                                     flags, p, widget, &colOpt);
2015             } else {
2016                 DoubleButtonOption::ActiveButton ab = DoubleButtonOption::None;
2017 
2018                 //Determine whether any of the buttons is active
2019                 //Qt sets both sunken and activeSubControls for active,
2020                 //just activeSubControls for hover.
2021                 if (flags & State_Sunken) {
2022                     if (slOpt->activeSubControls & SC_ScrollBarSubLine) {
2023                         ab = DoubleButtonOption::Top;
2024                     }
2025 
2026                     if (slOpt->activeSubControls & SC_ScrollBarAddLine) {
2027                         ab = DoubleButtonOption::Bottom;
2028                     }
2029                 }
2030 
2031                 //Paint the bevel
2032                 DoubleButtonOption bOpt(ab);
2033                 drawKStylePrimitive(WT_ScrollBar, ScrollBar::DoubleButtonVert,
2034                                     option, r, pal, flags, p, widget, &bOpt);
2035 
2036                 //Paint top button.
2037                 ColorOption colOpt;
2038                 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
2039 
2040                 if (ab == DoubleButtonOption::Top) {
2041                     colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
2042                 }
2043 
2044                 QRect topSubButton = QRect(r.x(), r.y(), r.width(), r.height() / 2);
2045                 drawKStylePrimitive(WT_ScrollBar, Generic::ArrowUp, option, topSubButton, pal,
2046                                     flags, p, widget, &colOpt);
2047 
2048                 //Paint bot button
2049                 QRect botSubButton;
2050                 botSubButton.setBottomRight(r.bottomRight());
2051                 botSubButton.setLeft(r.left());
2052                 botSubButton.setTop(topSubButton.bottom() + 1);
2053 
2054                 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
2055 
2056                 if (ab == DoubleButtonOption::Bottom) {
2057                     colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
2058                 }
2059 
2060                 drawKStylePrimitive(WT_ScrollBar, Generic::ArrowDown, option, botSubButton, pal,
2061                                     flags, p, widget, &colOpt);
2062             }
2063         } else {
2064             // Single button
2065             if (flags & State_Horizontal) {
2066                 drawKStylePrimitive(WT_ScrollBar, ScrollBar::SingleButtonHor,
2067                                     option, r, pal, flags, p, widget);
2068 
2069                 int  primitive;
2070                 bool active   = false;
2071 
2072                 if (element == CE_ScrollBarAddLine) {
2073                     if (slOpt->direction == Qt::LeftToRight) {
2074                         primitive = Generic::ArrowRight;
2075                     } else {
2076                         primitive = Generic::ArrowLeft;
2077                     }
2078 
2079                     if ((slOpt->activeSubControls & SC_ScrollBarAddLine) && (flags & State_Sunken)) {
2080                         active = true;
2081                     }
2082                 } else {
2083                     if (slOpt->direction == Qt::LeftToRight) {
2084                         primitive = Generic::ArrowLeft;
2085                     } else {
2086                         primitive = Generic::ArrowRight;
2087                     }
2088 
2089                     if ((slOpt->activeSubControls & SC_ScrollBarSubLine) && (flags & State_Sunken)) {
2090                         active = true;
2091                     }
2092                 }
2093 
2094                 ColorOption colOpt;
2095                 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
2096                 if (active) {
2097                     colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
2098                 }
2099 
2100                 drawKStylePrimitive(WT_ScrollBar, primitive, option, r, pal,
2101                                     flags, p, widget, &colOpt);
2102             } else {
2103                 drawKStylePrimitive(WT_ScrollBar, ScrollBar::SingleButtonVert,
2104                                     option, r, pal, flags, p, widget);
2105 
2106                 int  primitive;
2107                 bool active   = false;
2108 
2109                 if (element == CE_ScrollBarAddLine) {
2110                     primitive = Generic::ArrowDown;
2111                     if ((slOpt->activeSubControls & SC_ScrollBarAddLine) && (flags & State_Sunken)) {
2112                         active = true;
2113                     }
2114                 } else {
2115                     primitive = Generic::ArrowUp;
2116                     if ((slOpt->activeSubControls & SC_ScrollBarSubLine) && (flags & State_Sunken)) {
2117                         active = true;
2118                     }
2119                 }
2120 
2121                 ColorOption colOpt;
2122                 colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ArrowColor, option, widget);
2123                 if (active) {
2124                     colOpt.color = widgetLayoutProp(WT_ScrollBar, ScrollBar::ActiveArrowColor, option, widget);
2125                 }
2126 
2127                 drawKStylePrimitive(WT_ScrollBar, primitive, option, r, pal,
2128                                     flags, p, widget, &colOpt);
2129             }
2130         }
2131         return;
2132     }
2133 
2134 // TODO: what about CE_ScrollBarFirst, CE_ScrollBarLast...?
2135 //         case CE_ScrollBarFirst:
2136 //         case CE_ScrollBarLast:
2137 
2138     case CE_ScrollBarSlider: {
2139         drawKStylePrimitive(WT_ScrollBar,
2140                             (flags & State_Horizontal) ? ScrollBar::SliderHor  :
2141                             ScrollBar::SliderVert,
2142                             option, r, pal, flags, p, widget);
2143         return;
2144     }
2145 
2146     case CE_ScrollBarAddPage: {
2147         const QStyleOptionSlider *slOpt = ::qstyleoption_cast<const QStyleOptionSlider *>(option);
2148         if (!slOpt) {
2149             return;
2150         }
2151 
2152         if (flags & State_Horizontal)
2153             drawKStylePrimitive(WT_ScrollBar,
2154                                 (slOpt->direction == Qt::LeftToRight) ? ScrollBar::GrooveAreaHorRight :
2155                                 ScrollBar::GrooveAreaHorLeft,
2156                                 option, r, pal, flags, p, widget);
2157         else
2158             drawKStylePrimitive(WT_ScrollBar, ScrollBar::GrooveAreaVertBottom,
2159                                 option, r, pal, flags, p, widget);
2160         return;
2161     }
2162 
2163     case CE_ScrollBarSubPage: {
2164         const QStyleOptionSlider *slOpt = ::qstyleoption_cast<const QStyleOptionSlider *>(option);
2165         if (!slOpt) {
2166             return;
2167         }
2168 
2169         if (flags & State_Horizontal)
2170             drawKStylePrimitive(WT_ScrollBar,
2171                                 (slOpt->direction == Qt::LeftToRight) ? ScrollBar::GrooveAreaHorLeft :
2172                                 ScrollBar::GrooveAreaHorRight,
2173                                 option, r, pal, flags, p, widget);
2174         else
2175             drawKStylePrimitive(WT_ScrollBar, ScrollBar::GrooveAreaVertTop,
2176                                 option, r, pal, flags, p, widget);
2177         return;
2178     }
2179 
2180     //QCS's CE_TabBarTab is perfectly fine, so we just handle the subbits
2181 
2182     case CE_TabBarTabShape: {
2183         const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(option);
2184         if (!tabOpt) {
2185             return;
2186         }
2187 
2188         // TabOverlap handling
2189         int tabOverlap = pixelMetric(PM_TabBarTabOverlap, option, widget);
2190         bool beginning = tabOpt->position == QStyleOptionTab::Beginning;
2191         bool onlyOne = tabOpt->position == QStyleOptionTab::OnlyOneTab;
2192         if (!beginning && !onlyOne) {
2193             switch (tabSide(tabOpt)) {
2194             case North:
2195             case South:
2196                 if (option->direction == Qt::LeftToRight) {
2197                     r.adjust(-tabOverlap, 0, 0, 0);
2198                 } else {
2199                     r.adjust(0, 0, tabOverlap, 0);
2200                 }
2201                 break;
2202             case East:
2203             case West:
2204                 r.adjust(0, -tabOverlap, 0, 0);
2205             default:
2206                 break;
2207             }
2208         }
2209 
2210         int prim;
2211         switch (tabSide(tabOpt)) {
2212         case North:
2213             prim = TabBar::NorthTab; break;
2214         case South:
2215             prim = TabBar::SouthTab; break;
2216         case East:
2217             prim = TabBar::EastTab; break;
2218         default:
2219             prim = TabBar::WestTab; break;
2220         }
2221 
2222         drawKStylePrimitive(WT_TabBar, prim, option, r, pal, flags, p, widget);
2223 
2224         return;
2225     }
2226 
2227     case CE_TabBarTabLabel: {
2228         const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(option);
2229         if (!tabOpt) {
2230             return;
2231         }
2232 
2233         //First, we get our content region.
2234         QRect labelRect = subElementRect(SE_TabBarTabText, option, widget);
2235 
2236         Side tabSd = tabSide(tabOpt);
2237 
2238         //Now, what we do, depends on rotation, LTR vs. RTL, and text/icon combinations.
2239         //First, figure out if we have to deal with icons, and place them if need be.
2240         if (!tabOpt->icon.isNull()) {
2241             QStyleOptionTab tabV3(*tabOpt);
2242             QSize iconSize = tabV3.iconSize;
2243             if (!iconSize.isValid()) {
2244                 int iconExtent = pixelMetric(PM_SmallIconSize);
2245                 iconSize = QSize(iconExtent, iconExtent);
2246             }
2247 
2248             IconOption icoOpt;
2249             icoOpt.icon   = tabOpt->icon;
2250             icoOpt.active = flags & State_Selected;
2251             icoOpt.size = iconSize;
2252 
2253             if (tabOpt->text.isNull()) {
2254                 //Icon only. Easy.
2255                 drawKStylePrimitive(WT_TabBar, Generic::Icon, option, labelRect,
2256                                     pal, flags, p, widget, &icoOpt);
2257                 return;
2258             }
2259 
2260             //OK, we have to stuff both icon and text. So we figure out where to stick the icon.
2261             QRect iconRect;
2262 
2263             if (tabSd == North || tabSd == South) {
2264                 //OK, this is simple affair, we just pick a side for the icon
2265                 //based on layout direction. (Actually, I guess text
2266                 //would be more accurate, but I am -so- not doing BIDI here)
2267                 if (tabOpt->direction == Qt::LeftToRight) {
2268                     //We place icon on the left.
2269                     iconRect = QRect(labelRect.x(), labelRect.y() + (labelRect.height() - iconSize.height() + 1) / 2,
2270                                      iconSize.width(), iconSize.height());
2271 
2272                     //Adjust the text rect.
2273                     labelRect.setLeft(labelRect.x() + iconSize.width() +
2274                                       widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget));
2275                 } else {
2276                     //We place icon on the right
2277                     iconRect = QRect(labelRect.x() + labelRect.width() - iconSize.width(),
2278                                      labelRect.y() + (labelRect.height() - iconSize.height() + 1) / 2, iconSize.width(), iconSize.height());
2279                     //Adjust the text rect
2280                     labelRect.setWidth(labelRect.width() - iconSize.width() -
2281                                        widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget));
2282                 }
2283             } else {
2284                 bool aboveIcon = false;
2285                 if (tabSd == West && tabOpt->direction == Qt::RightToLeft) {
2286                     aboveIcon = true;
2287                 }
2288                 if (tabSd == East && tabOpt->direction == Qt::LeftToRight) {
2289                     aboveIcon = true;
2290                 }
2291 
2292                 if (aboveIcon) {
2293                     iconRect = QRect(labelRect.x() + (labelRect.width() - iconSize.width() + 1) / 2, labelRect.y(),
2294                                      iconSize.width(), iconSize.height());
2295                     labelRect.setTop(labelRect.y() + iconSize.height() +
2296                                      widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget));
2297                 } else {
2298                     iconRect = QRect(labelRect.x() + (labelRect.width() - iconSize.width() + 1) / 2,
2299                                      labelRect.y() + labelRect.height() - iconSize.height(),
2300                                      iconSize.width(), iconSize.height());
2301                     labelRect.setHeight(labelRect.height() - iconSize.height() -
2302                                         widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget));
2303                 }
2304             }
2305 
2306             //Draw the thing
2307             drawKStylePrimitive(WT_TabBar, Generic::Icon, option, iconRect,
2308                                 pal, flags, p, widget, &icoOpt);
2309         } //if have icon.
2310 
2311         //Draw text
2312         if (!tabOpt->text.isNull()) {
2313             TextOption lbOpt(tabOpt->text);
2314             if (widget) {
2315                 lbOpt.color = widget->foregroundRole();
2316             }
2317 
2318             int primitive = Generic::Text; // For horizontal tabs
2319 
2320             if (tabSd == East) {
2321                 primitive = TabBar::EastText;
2322             } else if (tabSd == West) {
2323                 primitive = TabBar::WestText;
2324             }
2325 
2326             drawKStylePrimitive(WT_TabBar, primitive, option, labelRect,
2327                                 pal, flags, p, widget, &lbOpt);
2328         }
2329 
2330         //If need be, draw focus rect
2331         if (tabOpt->state & State_HasFocus) {
2332             QRect focusRect = marginAdjustedTab(tabOpt, TabBar::TabFocusMargin);
2333             drawKStylePrimitive(WT_TabBar, Generic::FocusIndicator, option, focusRect,
2334                                 pal, flags, p, widget);
2335         }
2336         return;
2337     }
2338 
2339     case CE_ToolBar: {
2340         if (flags & State_Horizontal) {
2341             drawKStylePrimitive(WT_ToolBar, ToolBar::PanelHor, option, r, pal, flags, p, widget);
2342         } else {
2343             drawKStylePrimitive(WT_ToolBar, ToolBar::PanelVert, option, r, pal, flags, p, widget);
2344         }
2345 
2346         return;
2347     }
2348 
2349     case CE_HeaderSection: {
2350         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
2351             drawKStylePrimitive(WT_Header, (header->orientation == Qt::Horizontal) ? Header::SectionHor : Header::SectionVert,
2352                                 option, r, pal, flags, p, widget);
2353             return;
2354         }
2355     }
2356 
2357     case CE_HeaderLabel: {
2358         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
2359             QRect textRect = r;
2360             if (!header->icon.isNull()) {
2361                 bool enabled = flags & State_Enabled;
2362                 QPixmap pm = header->icon.pixmap(pixelMetric(PM_SmallIconSize), enabled ? QIcon::Normal : QIcon::Disabled);
2363 
2364                 // TODO: respect header->iconAlignment.
2365                 bool reverseLayout = header->direction == Qt::RightToLeft;
2366                 int iy = r.top() + (r.height() - pm.height()) / 2;
2367                 int ix = reverseLayout ? r.right() - pm.width() : r.left();
2368                 QRect iconRect = QRect(ix, iy, pm.width(), pm.height());
2369 
2370                 IconOption iconOpt;
2371                 iconOpt.icon = pm;
2372                 drawKStylePrimitive(WT_Header, Generic::Icon, option, iconRect, pal, flags, p, widget, &iconOpt);
2373 
2374                 // adjust the rect for the text...
2375                 int spacing = widgetLayoutProp(WT_Header, Header::TextToIconSpace, option, widget);
2376                 if (reverseLayout) {
2377                     textRect.setRight(r.right() - iconRect.width() - spacing);
2378                 } else {
2379                     textRect.setLeft(r.x() + iconRect.width() + spacing);
2380                 }
2381             }
2382 
2383             TextOption lbOpt(header->text);
2384             lbOpt.hAlign = header->textAlignment;
2385             drawKStylePrimitive(WT_Header, Generic::Text, option, textRect, pal, flags, p, widget, &lbOpt);
2386         }
2387         return;
2388     }
2389 
2390     case CE_Splitter: {
2391         if (flags & State_Horizontal) {
2392             drawKStylePrimitive(WT_Splitter, Splitter::HandleHor, option, r, pal, flags, p, widget);
2393         } else {
2394             drawKStylePrimitive(WT_Splitter, Splitter::HandleVert, option, r, pal, flags, p, widget);
2395         }
2396         return;
2397     }
2398 
2399     default:
2400         break;
2401     }
2402 
2403     QCommonStyle::drawControl(element, option, p, widget);
2404 }
2405 
2406 int K4Style::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const
2407 {
2408     switch (hint) {
2409     case SH_ComboBox_ListMouseTracking:
2410         return true;
2411 
2412     case SH_MenuBar_MouseTracking:
2413     case SH_Menu_MouseTracking:
2414         return true;
2415 
2416     case SH_Menu_SubMenuPopupDelay:
2417         return 96; // Motif-like delay...
2418 
2419     case SH_TitleBar_NoBorder:
2420         return widgetLayoutProp(WT_Window, Window::NoTitleFrame, option, widget);
2421 
2422     case SH_GroupBox_TextLabelVerticalAlignment:
2423         if (widgetLayoutProp(WT_GroupBox, GroupBox::TextAlignTop, option, widget)) {
2424             return Qt::AlignTop;
2425         } else {
2426             return Qt::AlignVCenter;
2427         }
2428 
2429     case SH_GroupBox_TextLabelColor: {
2430         ColorMode cm(widgetLayoutProp(WT_GroupBox, GroupBox::TitleTextColor,
2431                                       option, widget));
2432         return cm.color(option ? option->palette : qApp->palette()).rgba();
2433     }
2434 
2435     case SH_DialogButtonLayout:
2436         return QDialogButtonBox::KdeLayout;
2437 
2438     case SH_ScrollBar_MiddleClickAbsolutePosition:
2439         return true;
2440 
2441     // Don't draw the branch as selected in tree views
2442     case SH_ItemView_ShowDecorationSelected:
2443         return false;
2444 
2445     case SH_ItemView_ActivateItemOnSingleClick:
2446         return KSharedConfig::openConfig()->group("KDE").readEntry("SingleClick", true);
2447     case SH_KCustomStyleElement:
2448         if (!widget) {
2449             return 0;
2450         }
2451         return d->styleElements.value(widget->objectName(), 0);
2452 
2453     // per HIG, align the contents in a form layout to the left
2454     case SH_FormLayoutFormAlignment:
2455         return Qt::AlignLeft | Qt::AlignTop;
2456 
2457     // per HIG, align the labels in a form layout to the right
2458     case SH_FormLayoutLabelAlignment:
2459         return Qt::AlignRight;
2460 
2461     case SH_FormLayoutFieldGrowthPolicy:
2462         return QFormLayout::ExpandingFieldsGrow;
2463 
2464     case SH_FormLayoutWrapPolicy:
2465         return QFormLayout::DontWrapRows;
2466 
2467     case SH_MessageBox_TextInteractionFlags:
2468         return true;
2469 
2470     case SH_DialogButtonBox_ButtonsHaveIcons: {
2471         // was KGlobalSettings::showIconsOnPushButtons() :
2472         KConfigGroup g(KSharedConfig::openConfig(), "KDE");
2473         return g.readEntry("ShowIconsOnPushButtons", true);
2474     }
2475     case SH_ItemView_ArrowKeysNavigateIntoChildren:
2476         return true;
2477     case SH_Widget_Animate: {
2478         KConfigGroup g(KSharedConfig::openConfig(), "KDE-Global GUI Settings");
2479         return g.readEntry("GraphicEffectsLevel", 0);
2480     }
2481     default:
2482         break;
2483     };
2484 
2485     return QCommonStyle::styleHint(hint, option, widget, returnData);
2486 }
2487 
2488 int K4Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
2489 {
2490     switch (metric) {
2491     case PM_SmallIconSize:
2492     case PM_ButtonIconSize:
2493         return KIconLoader::global()->currentSize(KIconLoader::Small);
2494     case PM_ToolBarIconSize:
2495         return KIconLoader::global()->currentSize(KIconLoader::Toolbar);
2496     case PM_LargeIconSize:
2497         return KIconLoader::global()->currentSize(KIconLoader::Dialog);
2498     case PM_MessageBoxIconSize:
2499         // TODO return KIconLoader::global()->currentSize(KIconLoader::MessageBox);
2500         return KIconLoader::SizeHuge;
2501 
2502     case PM_DefaultFrameWidth:
2503         if (qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
2504             return widgetLayoutProp(WT_GroupBox, GroupBox::FrameWidth, option, widget);
2505         } else {
2506             return widgetLayoutProp(WT_Generic, Generic::DefaultFrameWidth, option, widget);
2507         }
2508 
2509     case PM_DefaultChildMargin:
2510     case PM_DefaultTopLevelMargin:
2511         return widgetLayoutProp(WT_Generic, Generic::DefaultLayoutMargin, option, widget);
2512 
2513     case PM_LayoutHorizontalSpacing:
2514     case PM_LayoutVerticalSpacing:
2515         // use layoutSpacingImplementation
2516         return -1;
2517 
2518     case PM_DefaultLayoutSpacing:
2519         return widgetLayoutProp(WT_Generic, Generic::DefaultLayoutSpacing, option, widget);
2520 
2521     case PM_LayoutLeftMargin:
2522     case PM_LayoutTopMargin:
2523     case PM_LayoutRightMargin:
2524     case PM_LayoutBottomMargin: {
2525         PixelMetric marginMetric;
2526         if ((option && (option->state & QStyle::State_Window))
2527                 || (widget && widget->isWindow())) {
2528             marginMetric = PM_DefaultTopLevelMargin;
2529         } else {
2530             marginMetric = PM_DefaultChildMargin;
2531         }
2532         return pixelMetric(marginMetric, option, widget);
2533     }
2534 
2535     case PM_ButtonMargin:
2536         return 0; //Better not return anything here since we already
2537     //incorporated this into SE_PushButtonContents
2538     case PM_ButtonDefaultIndicator:
2539         // PushButton::DefaultIndicatorMargin is used throughout KStyle button
2540         // implementation code, so this probably is not necessary.
2541         // return it in case Apps rely on this metric, though.
2542         return widgetLayoutProp(WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
2543     case PM_ButtonShiftHorizontal:
2544         return widgetLayoutProp(WT_PushButton, PushButton::PressedShiftHorizontal, option, widget);
2545     case PM_ButtonShiftVertical:
2546         return widgetLayoutProp(WT_PushButton, PushButton::PressedShiftVertical, option, widget);
2547     case PM_MenuButtonIndicator:
2548         if (qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
2549             return widgetLayoutProp(WT_ToolButton, ToolButton::MenuIndicatorSize, option, widget);
2550         } else {
2551             return widgetLayoutProp(WT_PushButton, PushButton::MenuIndicatorSize, option, widget);
2552         }
2553 
2554     case PM_SplitterWidth:
2555         return widgetLayoutProp(WT_Splitter, Splitter::Width, option, widget);
2556 
2557     case PM_IndicatorWidth:
2558     case PM_IndicatorHeight:
2559         return widgetLayoutProp(WT_CheckBox, CheckBox::Size, option, widget);
2560 
2561     case PM_ExclusiveIndicatorWidth:
2562     case PM_ExclusiveIndicatorHeight:
2563         return widgetLayoutProp(WT_RadioButton, RadioButton::Size, option, widget);
2564 
2565     case PM_DockWidgetFrameWidth:
2566         return widgetLayoutProp(WT_DockWidget, DockWidget::FrameWidth, option, widget);
2567 
2568     case PM_DockWidgetSeparatorExtent:
2569         return widgetLayoutProp(WT_DockWidget, DockWidget::SeparatorExtent, option, widget);
2570 
2571     // handle extent only used somewhere in Qt3support, don't care.
2572     // case PM_DockWidgetHandleExtent:
2573 
2574     case PM_DockWidgetTitleMargin:
2575         return widgetLayoutProp(WT_DockWidget, DockWidget::TitleMargin, option, widget);
2576 
2577     case PM_ProgressBarChunkWidth:
2578         return widgetLayoutProp(WT_ProgressBar, ProgressBar::Precision, option, widget);
2579 
2580     case PM_MenuBarPanelWidth:
2581         return 0; //Simplification: just one primitive is used and it includes the border
2582 
2583     case PM_MenuBarHMargin: {
2584         //Calculate how much extra space we need besides the frame size. We use the left margin
2585         //here, and adjust the total rect by the difference between it and the right margin
2586         int spaceL = widgetLayoutProp(WT_MenuBar, MenuBar::Margin, option, widget) + widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Left, option, widget);
2587 
2588         return spaceL;
2589     }
2590 
2591     case PM_MenuBarVMargin: {
2592         //As above, we return the top one, and fudge the total size for the bottom.
2593         int spaceT = widgetLayoutProp(WT_MenuBar, MenuBar::Margin, option, widget) + widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Top, option, widget);
2594         return spaceT;
2595     }
2596 
2597     case PM_MenuBarItemSpacing:
2598         return widgetLayoutProp(WT_MenuBar, MenuBar::ItemSpacing, option, widget);
2599 
2600     case PM_MenuDesktopFrameWidth:
2601         return 0; //### CHECKME
2602 
2603     case PM_MenuPanelWidth:
2604         return widgetLayoutProp(WT_Menu, Menu::FrameWidth, option, widget);
2605 
2606     /* ### seems to trigger Qt bug. So we loose the margins for now
2607     case PM_MenuHMargin:
2608     {
2609     //Calculate how much extra space we need besides the frame size. We use the left margin
2610     //here, and adjust the total rect by the difference between it and the right margin
2611     int spaceL = widgetLayoutProp(WT_Menu, Menu::Margin, option, widget) + widgetLayoutProp(WT_Menu, Menu::Margin + Left, option, widget) -
2612             widgetLayoutProp(WT_Menu, Menu::FrameWidth, option, widget);
2613 
2614     return spaceL;
2615     }
2616 
2617     case PM_MenuVMargin:
2618     {
2619     //As above, we return the top one, and fudge the total size for the bottom.
2620     int spaceT = widgetLayoutProp(WT_Menu, Menu::Margin, option, widget) + widgetLayoutProp(WT_Menu, Menu::Margin + Top, option, widget) -
2621         widgetLayoutProp(WT_Menu, Menu::FrameWidth, option, widget);
2622     return spaceT;
2623     }     */
2624 
2625     case PM_MenuScrollerHeight:
2626         return widgetLayoutProp(WT_Menu, Menu::ScrollerHeight, option, widget);
2627 
2628     case PM_MenuTearoffHeight:
2629         return widgetLayoutProp(WT_Menu, Menu::TearOffHeight, option, widget);
2630 
2631     case PM_TabBarTabHSpace: {
2632         const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(option);
2633         if (tabOpt) {
2634             //Perhaps we can avoid the extra margin...
2635             if (tabOpt->text.isNull() && !tabOpt->icon.isNull()) {
2636                 return 0;
2637             }
2638             if (tabOpt->icon.isNull() && !tabOpt->text.isNull()) {
2639                 return 0;
2640             }
2641         }
2642 
2643         return widgetLayoutProp(WT_TabBar, TabBar::TabTextToIconSpace, option, widget);
2644     }
2645 
2646     case PM_TabBarTabVSpace:
2647         return 0;
2648 
2649     case PM_TabBarBaseHeight:
2650         return widgetLayoutProp(WT_TabBar, TabBar::BaseHeight, option, widget);
2651 
2652     case PM_TabBarBaseOverlap:
2653         return widgetLayoutProp(WT_TabBar, TabBar::BaseOverlap, option, widget);
2654 
2655     case PM_TabBarTabOverlap:
2656         return widgetLayoutProp(WT_TabBar, TabBar::TabOverlap, option, widget);
2657 
2658     case PM_TabBarScrollButtonWidth:
2659         return widgetLayoutProp(WT_TabBar, TabBar::ScrollButtonWidth, option, widget);
2660 
2661     case PM_TabBarTabShiftVertical:
2662         return 1;
2663 
2664     case PM_TabBarTabShiftHorizontal:
2665         return 0;
2666 
2667     case PM_SliderControlThickness:
2668         return widgetLayoutProp(WT_Slider, Slider::HandleThickness, option, widget);
2669 
2670     case PM_SliderLength:
2671         return widgetLayoutProp(WT_Slider, Slider::HandleLength, option, widget);
2672 
2673     case PM_SliderThickness: {
2674         // not sure what the difference to PM_SliderControlThickness actually is
2675         return widgetLayoutProp(WT_Slider, Slider::HandleThickness, option, widget);
2676     }
2677 
2678     case PM_SpinBoxFrameWidth:
2679         return widgetLayoutProp(WT_SpinBox, SpinBox::FrameWidth, option, widget);
2680 
2681     case PM_ComboBoxFrameWidth:
2682         return widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget);
2683 
2684     case PM_HeaderMarkSize:
2685         return widgetLayoutProp(WT_Header, Header::MarkSize, option, widget);
2686 
2687     case PM_HeaderMargin:
2688         return widgetLayoutProp(WT_Header, Header::TextToIconSpace, option, widget);
2689 
2690     case PM_ToolBarFrameWidth:
2691         return widgetLayoutProp(WT_ToolBar, ToolBar::FrameWidth, option, widget);
2692 
2693     case PM_ToolBarHandleExtent:
2694         return widgetLayoutProp(WT_ToolBar, ToolBar::HandleExtent, option, widget);
2695 
2696     case PM_ToolBarSeparatorExtent:
2697         return widgetLayoutProp(WT_ToolBar, ToolBar::SeparatorExtent, option, widget);
2698 
2699     case PM_ToolBarExtensionExtent:
2700         return widgetLayoutProp(WT_ToolBar, ToolBar::ExtensionExtent, option, widget);
2701 
2702     case PM_ToolBarItemMargin:
2703         return widgetLayoutProp(WT_ToolBar, ToolBar::ItemMargin, option, widget);
2704 
2705     case PM_ToolBarItemSpacing:
2706         return widgetLayoutProp(WT_ToolBar, ToolBar::ItemSpacing, option, widget);
2707 
2708     case PM_ScrollBarExtent:
2709         return widgetLayoutProp(WT_ScrollBar, ScrollBar::BarWidth, option, widget);
2710 
2711     case PM_TitleBarHeight:
2712         return widgetLayoutProp(WT_Window, Window::TitleHeight, option, widget);
2713 
2714     default:
2715         break;
2716     }
2717 
2718     return QCommonStyle::pixelMetric(metric, option, widget);
2719 }
2720 
2721 int K4Style::layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget) const
2722 {
2723     Q_UNUSED(control1); Q_UNUSED(control2); Q_UNUSED(orientation);
2724 
2725     return pixelMetric(PM_DefaultLayoutSpacing, option, widget);
2726 }
2727 
2728 bool K4Style::isVerticalTab(const QStyleOptionTab *tbOpt) const
2729 {
2730     switch (tbOpt->shape) {
2731     case QTabBar::RoundedWest:
2732     case QTabBar::RoundedEast:
2733     case QTabBar::TriangularWest:
2734     case QTabBar::TriangularEast:
2735         return true;
2736     default:
2737         return false;
2738     }
2739 }
2740 
2741 bool K4Style::isReflectedTab(const QStyleOptionTab *tbOpt) const
2742 {
2743     switch (tbOpt->shape) {
2744     case QTabBar::RoundedEast:
2745     case QTabBar::TriangularEast:
2746     case QTabBar::RoundedSouth:
2747     case QTabBar::TriangularSouth:
2748         return true;
2749     default:
2750         return false;
2751     }
2752 }
2753 
2754 K4Style::Side K4Style::tabSide(const QStyleOptionTab *tbOpt) const
2755 {
2756     switch (tbOpt->shape) {
2757     case QTabBar::RoundedEast:
2758     case QTabBar::TriangularEast:
2759         return East;
2760     case QTabBar::RoundedWest:
2761     case QTabBar::TriangularWest:
2762         return West;
2763     case QTabBar::RoundedNorth:
2764     case QTabBar::TriangularNorth:
2765         return North;
2766     default:
2767         return South;
2768     }
2769 }
2770 
2771 QRect K4Style::marginAdjustedTab(const QStyleOptionTab *tabOpt, int property) const
2772 {
2773     QRect r = tabOpt->rect;
2774 
2775     //For region, we first figure out the geometry if it was normal, and adjust.
2776     //this takes some rotating
2777     bool vertical = isVerticalTab(tabOpt);
2778     bool flip     = isReflectedTab(tabOpt);
2779 
2780     QRect idializedGeometry = vertical ? QRect(0, 0, r.height(), r.width())
2781                               : QRect(0, 0, r.width(),  r.height());
2782 
2783     QRect contentArea = insideMargin(idializedGeometry, WT_TabBar, property, tabOpt, nullptr);
2784 
2785     int leftMargin  = contentArea.x();
2786     int rightMargin = idializedGeometry.width() - 1 - contentArea.right();
2787     int topMargin   = contentArea.y();
2788     int botMargin   = idializedGeometry.height() - 1 - contentArea.bottom();
2789 
2790     if (vertical) {
2791         int t       = rightMargin;
2792         rightMargin = topMargin;
2793         topMargin   = leftMargin;
2794         leftMargin  = botMargin;
2795         botMargin   = t;
2796 
2797         if (!flip) {
2798             qSwap(leftMargin, rightMargin);
2799         }
2800     } else if (flip) {
2801         qSwap(topMargin, botMargin);
2802         //For horizontal tabs, we also want to reverse stuff for RTL!
2803         if (tabOpt->direction == Qt::RightToLeft) {
2804             qSwap(leftMargin, rightMargin);
2805         }
2806     }
2807 
2808     QRect geom =
2809         QRect(QPoint(leftMargin, topMargin),
2810               QPoint(r.width()  - 1 - rightMargin,
2811                      r.height() - 1 - botMargin));
2812     geom.translate(r.topLeft());
2813     return geom;
2814 }
2815 
2816 bool K4Style::useSideText(const QStyleOptionProgressBar *pbOpt) const
2817 {
2818     if (widgetLayoutProp(WT_ProgressBar, ProgressBar::SideText) == 0) {
2819         return false;
2820     }
2821 
2822     if (!pbOpt) {
2823         return false;    //Paranoia
2824     }
2825 
2826     if (!pbOpt->textVisible) {
2827         return false;    //Don't allocate side margin if text display is off...
2828     }
2829 
2830     if (pbOpt->textAlignment & Qt::AlignHCenter) {
2831         return false;    //### do we want this? we don't
2832     }
2833     //force indicator to the side outside
2834     //the main otherwise.
2835 
2836     if (pbOpt->minimum == pbOpt->maximum) {
2837         return false;
2838     }
2839 
2840     int widthAlloc = pbOpt->fontMetrics.width(QLatin1String("100%"));
2841 
2842     if (pbOpt->fontMetrics.width(pbOpt->text) > widthAlloc) {
2843         return false;    //Doesn't fit!
2844     }
2845 
2846     return true;
2847 }
2848 
2849 int K4Style::sideTextWidth(const QStyleOptionProgressBar *pbOpt) const
2850 {
2851     return pbOpt->fontMetrics.width(QLatin1String("100%")) +
2852            2 * widgetLayoutProp(WT_ProgressBar, ProgressBar::SideTextSpace);
2853 }
2854 
2855 QRect K4Style::subElementRect(SubElement sr, const QStyleOption *option, const QWidget *widget) const
2856 {
2857     QRect r = option->rect;
2858 
2859     switch (sr) {
2860     case SE_PushButtonContents: {
2861         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
2862         if (!bOpt) {
2863             return r;
2864         }
2865 
2866         if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton)) {
2867             r = insideMargin(r, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
2868         }
2869 
2870         return insideMargin(r, WT_PushButton, PushButton::ContentsMargin, option, widget);
2871     }
2872 
2873     case SE_PushButtonFocusRect: {
2874         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
2875         if (!bOpt) {
2876             return r;
2877         }
2878 
2879         if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton)) {
2880             r = insideMargin(r, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
2881         }
2882 
2883         return insideMargin(r, WT_PushButton, PushButton::FocusMargin, option, widget);
2884     }
2885 
2886     case SE_ToolBoxTabContents: {
2887         return insideMargin(r, WT_ToolBoxTab, ToolBoxTab::Margin, option, widget);
2888     }
2889 
2890     case SE_CheckBoxContents: {
2891         r.setX(r.x() + widgetLayoutProp(WT_CheckBox, CheckBox::Size, option, widget) +
2892                widgetLayoutProp(WT_CheckBox, CheckBox::BoxTextSpace, option, widget));
2893         return handleRTL(option, r);
2894     }
2895 
2896     case SE_RadioButtonContents: {
2897         r.setX(r.x() + widgetLayoutProp(WT_RadioButton, RadioButton::Size, option, widget) +
2898                widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget));
2899         return handleRTL(option, r);
2900     }
2901 
2902     case SE_CheckBoxFocusRect: {
2903         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
2904         if (!bOpt) {
2905             return r;
2906         }
2907 
2908         QRect ret;
2909 
2910         if (bOpt->text.isEmpty()) {
2911             // first convert, so we can deal with logical coords
2912             QRect checkRect =
2913                 handleRTL(option, subElementRect(SE_CheckBoxIndicator, option, widget));
2914             ret = insideMargin(checkRect, WT_CheckBox, CheckBox::NoLabelFocusMargin, option, widget);
2915         } else {
2916             // first convert, so we can deal with logical coords
2917             QRect contentsRect =
2918                 handleRTL(option, subElementRect(SE_CheckBoxContents, option, widget));
2919             ret = insideMargin(contentsRect, WT_CheckBox, CheckBox::FocusMargin, option, widget);
2920         }
2921         // convert back to screen coords
2922         return handleRTL(option, ret);
2923     }
2924 
2925     case SE_RadioButtonFocusRect: {
2926         // first convert it back to logical coords
2927         QRect contentsRect =
2928             handleRTL(option, subElementRect(SE_RadioButtonContents, option, widget));
2929 
2930         // modify the rect and convert back to screen coords
2931         return handleRTL(option,
2932                          insideMargin(contentsRect, WT_RadioButton,
2933                                       RadioButton::FocusMargin, option, widget));
2934     }
2935 
2936     case SE_ProgressBarGroove: {
2937         const QStyleOptionProgressBar *pbOpt = ::qstyleoption_cast<const QStyleOptionProgressBar *>(option);
2938         if (useSideText(pbOpt)) {
2939             r.setWidth(r.width() - sideTextWidth(pbOpt));
2940             return r;
2941         }
2942 
2943         //Centering mode --- could be forced or side... so the groove area is everything
2944         return r;
2945     }
2946 
2947     case SE_ProgressBarContents: {
2948         QRect grooveRect = subElementRect(SE_ProgressBarGroove, option, widget);
2949         return insideMargin(grooveRect, WT_ProgressBar, ProgressBar::GrooveMargin, option, widget);
2950     }
2951 
2952     case SE_ProgressBarLabel: {
2953         const QStyleOptionProgressBar *pbOpt = ::qstyleoption_cast<const QStyleOptionProgressBar *>(option);
2954         if (useSideText(pbOpt)) {
2955             int width = sideTextWidth(pbOpt);
2956             return QRect(r.x() + r.width() - width, r.y(), width, r.height());
2957         }
2958 
2959         //The same as the contents area..
2960         return subElementRect(SE_PushButtonContents, option, widget);
2961     }
2962 
2963     // SE_TabWidgetTabPane implementation in QCommonStyle is perfectly fine.
2964     case SE_TabWidgetTabContents: {
2965         const QStyleOptionTabWidgetFrame *tabOpt = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option);
2966         if (!tabOpt) {
2967             break;
2968         }
2969 
2970         // Don't apply the custom margin when documentMode is enabled.
2971         if (tabOpt->lineWidth == 0) {
2972             break;
2973         }
2974 
2975         // use QCommonStyle's SE_TabWidgetTabPane, and adjust the result
2976         // according to the custom frame width.
2977         QRect pane = QCommonStyle::subElementRect(SE_TabWidgetTabPane, option, widget);
2978         int m   = widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin, option, widget);
2979         int top = m + widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Top,
2980                                        option, widget);
2981         int bot = m + widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Bot,
2982                                        option, widget);
2983         int left = m + widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Left,
2984                                         option, widget);
2985         int right = m + widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Right,
2986                                          option, widget);
2987 
2988         switch (tabOpt->shape) {
2989         case QTabBar::RoundedNorth:
2990         case QTabBar::TriangularNorth:
2991             return pane.adjusted(left, top, -right, -bot);
2992         case QTabBar::RoundedEast:
2993         case QTabBar::TriangularEast:
2994             return pane.adjusted(bot, left, -top, -right);
2995         case QTabBar::RoundedSouth:
2996         case QTabBar::TriangularSouth:
2997             return pane.adjusted(right, bot, -left, -top);
2998         case QTabBar::RoundedWest:
2999         case QTabBar::TriangularWest:
3000             return pane.adjusted(top, right, -bot, -left);
3001         }
3002     }
3003 
3004     case SE_TabBarTabText: {
3005         const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(option);
3006         if (!tabOpt) {
3007             return QRect();
3008         }
3009 
3010         QRect r = marginAdjustedTab(tabOpt, TabBar::TabContentsMargin);
3011         QStyleOptionTab tov3(*tabOpt);
3012 
3013         switch (tov3.shape) {
3014         case QTabBar::RoundedNorth:
3015         case QTabBar::TriangularNorth:
3016         case QTabBar::RoundedSouth:
3017         case QTabBar::TriangularSouth:
3018             if (tov3.direction == Qt::LeftToRight) {
3019                 r.adjust(tov3.leftButtonSize.width(), 0, -tov3.rightButtonSize.width(), 0);
3020             } else {
3021                 r.adjust(tov3.rightButtonSize.width(), 0, -tov3.leftButtonSize.width(), 0);
3022             }
3023             break;
3024         case QTabBar::RoundedEast:
3025         case QTabBar::TriangularEast:
3026             r.adjust(0, tov3.leftButtonSize.width(), 0, -tov3.rightButtonSize.width());
3027             break;
3028         case QTabBar::RoundedWest:
3029         case QTabBar::TriangularWest:
3030             r.adjust(0, tov3.rightButtonSize.width(), 0, -tov3.leftButtonSize.width());
3031             break;
3032         }
3033 
3034         return r;
3035     }
3036 
3037     default:
3038         break;
3039     }
3040 
3041     return QCommonStyle::subElementRect(sr, option, widget);
3042 }
3043 
3044 void  K4Style::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
3045                                   QPainter *p,      const QWidget *w) const
3046 {
3047     //Extract the stuff we need out of the option
3048     State flags = opt->state;
3049     QRect      r     = opt->rect;
3050     QPalette   pal   = opt->palette;
3051 
3052     switch (cc) {
3053     case CC_ScrollBar: {
3054         QStyleOptionComplex *mutableOpt = const_cast<QStyleOptionComplex *>(opt);
3055         if ((mutableOpt->subControls & SC_ScrollBarSubLine) || (mutableOpt->subControls & SC_ScrollBarAddLine)) {
3056             //If we paint one of the buttons, must paint both!
3057             mutableOpt->subControls |= SC_ScrollBarSubPage | SC_ScrollBarAddLine;
3058         }
3059         //Note: we falldown to the base intentionally
3060     }
3061     break;
3062 
3063     case CC_Slider: {
3064         if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
3065             QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, w);
3066             QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, w);
3067             bool hor = slider->orientation == Qt::Horizontal;
3068 
3069             if (slider->subControls & SC_SliderTickmarks) {
3070                 // TODO: make tickmarks customizable with Slider::Tickmark-primitives?
3071                 QStyleOptionSlider tmpSlider = *slider;
3072                 tmpSlider.subControls = SC_SliderTickmarks;
3073                 QCommonStyle::drawComplexControl(cc, &tmpSlider, p, w);
3074             }
3075 
3076             if ((slider->subControls & SC_SliderGroove) && groove.isValid()) {
3077                 drawKStylePrimitive(WT_Slider, hor ? Slider::GrooveHor : Slider::GrooveVert, opt, groove, pal, flags, p, w);
3078             }
3079 
3080             if (slider->subControls & SC_SliderHandle) {
3081                 drawKStylePrimitive(WT_Slider, hor ? Slider::HandleHor : Slider::HandleVert, opt, handle, pal, flags, p, w);
3082 
3083                 if (slider->state & State_HasFocus) {
3084                     QRect focus = subElementRect(SE_SliderFocusRect, slider, w);
3085                     drawKStylePrimitive(WT_Slider, Generic::FocusIndicator, opt, focus, pal, flags, p, w, nullptr);
3086                 }
3087             }
3088         } //option OK
3089         return;
3090     } //CC_Slider
3091 
3092     case CC_SpinBox: {
3093         if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
3094             bool activeSbUp = sb->activeSubControls & SC_SpinBoxUp && (flags & State_Sunken);
3095             bool activeSbDown = sb->activeSubControls & SC_SpinBoxDown && (flags & State_Sunken);
3096 
3097             if (sb->subControls & SC_SpinBoxFrame) {
3098                 drawKStylePrimitive(WT_SpinBox, Generic::Frame, opt, r, pal, flags, p, w);
3099             }
3100 
3101             if (sb->subControls & SC_SpinBoxEditField) {
3102                 QRect editField = subControlRect(CC_SpinBox, opt, SC_SpinBoxEditField, w);
3103                 drawKStylePrimitive(WT_SpinBox, SpinBox::EditField, opt, editField, pal, flags, p, w);
3104             }
3105 
3106             QRect upRect, downRect;
3107             if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown)) {
3108                 upRect   = subControlRect(CC_SpinBox, opt, SC_SpinBoxUp,   w);
3109                 downRect = subControlRect(CC_SpinBox, opt, SC_SpinBoxDown, w);
3110                 QRect buttonAreaRect = upRect | downRect;
3111                 drawKStylePrimitive(WT_SpinBox, SpinBox::ButtonArea, opt, buttonAreaRect, pal, flags, p, w);
3112             }
3113 
3114             if (sb->subControls & SC_SpinBoxUp) {
3115                 // adjust the sunken state flag...
3116                 State upFlags = flags;
3117                 if (activeSbUp) {
3118                     upFlags |= State_Sunken;
3119                 } else {
3120                     upFlags &= ~State_Sunken;
3121                 }
3122 
3123                 drawKStylePrimitive(WT_SpinBox, SpinBox::UpButton, opt, upRect, pal, upFlags, p, w);
3124 
3125                 // draw symbol...
3126                 int primitive;
3127                 if (sb->buttonSymbols == QAbstractSpinBox::PlusMinus) {
3128                     primitive = SpinBox::PlusSymbol;
3129                 } else {
3130                     primitive = Generic::ArrowUp;
3131                 }
3132                 drawKStylePrimitive(WT_SpinBox, primitive, opt, upRect, pal, upFlags, p, w);
3133             }
3134 
3135             if (sb->subControls & SC_SpinBoxDown) {
3136                 // adjust the sunken state flag...
3137                 State downFlags = flags;
3138                 if (activeSbDown) {
3139                     downFlags |= State_Sunken;
3140                 } else {
3141                     downFlags &= ~State_Sunken;
3142                 }
3143 
3144                 drawKStylePrimitive(WT_SpinBox, SpinBox::DownButton, opt, downRect, pal, downFlags, p, w);
3145 
3146                 // draw symbol...
3147                 int primitive;
3148                 if (sb->buttonSymbols == QAbstractSpinBox::PlusMinus) {
3149                     primitive = SpinBox::MinusSymbol;
3150                 } else {
3151                     primitive = Generic::ArrowDown;
3152                 }
3153                 drawKStylePrimitive(WT_SpinBox, primitive, opt, downRect, pal, downFlags, p, w);
3154             }
3155 
3156             return;
3157         } //option OK
3158     } //CC_SpinBox
3159 
3160     case CC_ComboBox: {
3161         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
3162             if (cb->subControls & SC_ComboBoxFrame) {
3163                 drawKStylePrimitive(WT_ComboBox, Generic::Frame, opt, r, pal, flags, p, w);
3164 
3165                 // focus indicator
3166                 if (cb->state & State_HasFocus) {
3167                     QRect editField = subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, w);
3168                     QRect focusRect = insideMargin(editField, WT_ComboBox, ComboBox::FocusMargin, opt, w);
3169                     drawKStylePrimitive(WT_ComboBox, Generic::FocusIndicator, opt, focusRect, pal, flags, p, w, nullptr);
3170                 }
3171             }
3172 
3173             if (cb->subControls & SC_ComboBoxEditField) {
3174                 QRect editField = subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, w);
3175                 drawKStylePrimitive(WT_ComboBox, ComboBox::EditField, opt, editField, pal, flags, p, w);
3176             }
3177 
3178             if (cb->subControls & SC_ComboBoxArrow) {
3179                 QRect buttonRect = subControlRect(CC_ComboBox, opt, SC_ComboBoxArrow, w);
3180                 drawKStylePrimitive(WT_ComboBox, ComboBox::Button, opt, buttonRect, pal, flags, p, w);
3181 
3182                 // draw symbol...
3183                 drawKStylePrimitive(WT_ComboBox, Generic::ArrowDown, opt, buttonRect, pal, flags, p, w);
3184             }
3185 
3186             return;
3187         } //option OK
3188         break;
3189     } //CC_Combo
3190 
3191     case CC_ToolButton: {
3192         if (const QStyleOptionToolButton *tool = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
3193             QRect buttonRect = subControlRect(cc, tool, SC_ToolButton, w);
3194             QRect menuRect = subControlRect(cc, tool, SC_ToolButtonMenu, w);
3195 
3196             // State_AutoRaise: only draw button when State_MouseOver
3197             State bflags = tool->state;
3198             if (bflags & State_AutoRaise) {
3199                 if (!(bflags & State_MouseOver)) {
3200                     bflags &= ~State_Raised;
3201                 }
3202             }
3203             State mflags = bflags;
3204 
3205             QStyleOption tOpt(0);
3206             tOpt.palette = pal;
3207 
3208             if (tool->subControls & SC_ToolButton) {
3209                 if (bflags & (State_Sunken | State_On | State_Raised)) {
3210                     tOpt.rect = buttonRect;
3211                     tOpt.state = bflags;
3212                     drawPrimitive(PE_PanelButtonTool, &tOpt, p, w);
3213                 }
3214             }
3215 
3216             if (tool->subControls & SC_ToolButtonMenu) {
3217                 tOpt.rect = menuRect;
3218                 tOpt.state = mflags;
3219                 drawPrimitive(PE_IndicatorButtonDropDown, &tOpt, p, w);
3220             } else if (tool->features & QStyleOptionToolButton::HasMenu) {
3221                 // This is requesting KDE3-style arrow indicator, per Qt 4.4 behavior. Qt 4.3 prefers to hide
3222                 // the fact of the menu's existence. Whee! Since we don't know how to paint this right,
3223                 // though, we have to have some metrics set for it to look nice.
3224                 int size = widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorSize, opt, w);
3225 
3226                 if (size) {
3227                     int xOff = widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorXOff, opt, w);
3228                     int yOff = widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorYOff, opt, w);
3229 
3230                     QRect r = QRect(buttonRect.right() + xOff, buttonRect.bottom() + yOff, size, size);
3231                     tOpt.rect  = r;
3232                     tOpt.state = bflags;
3233                     drawPrimitive(PE_IndicatorButtonDropDown, &tOpt, p, w);
3234                 }
3235             }
3236 
3237             if (flags & State_HasFocus) {
3238                 QRect focusRect = insideMargin(r, WT_ToolButton, ToolButton::FocusMargin, opt, w);
3239                 tOpt.rect = focusRect;
3240                 tOpt.state = bflags;
3241                 drawKStylePrimitive(WT_ToolButton, Generic::FocusIndicator, &tOpt, focusRect, pal, bflags, p, w);
3242             }
3243 
3244             // CE_ToolButtonLabel expects a readjusted rect, for the button area proper
3245             QStyleOptionToolButton labelOpt = *tool;
3246             labelOpt.rect = buttonRect;
3247             drawControl(CE_ToolButtonLabel, &labelOpt, p, w);
3248 
3249             return;
3250         }
3251         break;
3252     } //CC_ToolButton
3253 
3254     case CC_TitleBar: {
3255         const QStyleOptionTitleBar *tb =
3256             qstyleoption_cast<const QStyleOptionTitleBar *>(opt);
3257         if (!tb) {
3258             break;
3259         }
3260 
3261         // title bar
3262         drawKStylePrimitive(WT_Window, Window::TitlePanel, opt, r, pal, flags, p, w);
3263 
3264         // TODO: different color depending on Active/inactive state
3265         // draw title text
3266         QRect textRect = subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, w);
3267         TextOption textOpt(tb->text);
3268         textOpt.color = widgetLayoutProp(WT_Window, Window::TitleTextColor, opt, w);
3269         drawKStylePrimitive(WT_Window, Generic::Text, opt, textRect,
3270                             pal, flags, p, w, &textOpt);
3271 
3272         TitleButtonOption buttonKOpt;
3273         buttonKOpt.icon = tb->icon;
3274 
3275         if ((tb->subControls & SC_TitleBarSysMenu) &&
3276                 (tb->titleBarFlags & Qt::WindowSystemMenuHint)) {
3277             buttonKOpt.active = (tb->activeSubControls & SC_TitleBarSysMenu)
3278                                 && (tb->state & State_Sunken);
3279             QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, w);
3280             drawKStylePrimitive(WT_Window, Window::ButtonMenu, opt, br, pal, flags, p, w,
3281                                 &buttonKOpt);
3282         }
3283 
3284         if ((tb->subControls & SC_TitleBarMinButton) &&
3285                 (tb->titleBarFlags & Qt::WindowMinimizeButtonHint)) {
3286             buttonKOpt.active = (tb->activeSubControls & SC_TitleBarMinButton)
3287                                 && (tb->state & State_Sunken);
3288             QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarMinButton, w);
3289             drawKStylePrimitive(WT_Window, Window::ButtonMin, opt, br, pal, flags, p, w,
3290                                 &buttonKOpt);
3291         }
3292 
3293         if ((tb->subControls & SC_TitleBarMaxButton) &&
3294                 (tb->titleBarFlags & Qt::WindowMaximizeButtonHint)) {
3295             buttonKOpt.active = (tb->activeSubControls & SC_TitleBarMaxButton)
3296                                 && (tb->state & State_Sunken);
3297             QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarMaxButton, w);
3298             drawKStylePrimitive(WT_Window, Window::ButtonMax, opt, br, pal, flags, p, w,
3299                                 &buttonKOpt);
3300         }
3301 
3302         if ((tb->subControls & SC_TitleBarCloseButton) &&
3303                 (tb->titleBarFlags & Qt::WindowSystemMenuHint)) {
3304 //                 bool hover = (tb->activeSubControls & SC_TitleBarCloseButton)
3305 //                         && (tb->state & State_MouseOver);
3306             buttonKOpt.active = (tb->activeSubControls & SC_TitleBarCloseButton)
3307                                 && (tb->state & State_Sunken);
3308             QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarCloseButton, w);
3309             drawKStylePrimitive(WT_Window, Window::ButtonClose, opt, br, pal, flags, p, w,
3310                                 &buttonKOpt);
3311         }
3312 
3313         if ((tb->subControls & SC_TitleBarNormalButton) &&
3314                 (((tb->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
3315                   (tb->titleBarState & Qt::WindowMinimized)) ||
3316                  ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
3317                   (tb->titleBarState & Qt::WindowMaximized)))) {
3318             buttonKOpt.active = (tb->activeSubControls & SC_TitleBarNormalButton)
3319                                 && (tb->state & State_Sunken);
3320             QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarNormalButton, w);
3321             drawKStylePrimitive(WT_Window, Window::ButtonRestore, opt, br, pal, flags, p, w,
3322                                 &buttonKOpt);
3323         }
3324 
3325         if (tb->subControls & SC_TitleBarShadeButton) {
3326             buttonKOpt.active = (tb->activeSubControls & SC_TitleBarShadeButton)
3327                                 && (tb->state & State_Sunken);
3328             QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarShadeButton, w);
3329             drawKStylePrimitive(WT_Window, Window::ButtonShade, opt, br, pal, flags, p, w,
3330                                 &buttonKOpt);
3331         }
3332 
3333         if (tb->subControls & SC_TitleBarUnshadeButton) {
3334             buttonKOpt.active = (tb->activeSubControls & SC_TitleBarUnshadeButton)
3335                                 && (tb->state & State_Sunken);
3336             QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarUnshadeButton, w);
3337             drawKStylePrimitive(WT_Window, Window::ButtonUnshade, opt, br, pal, flags, p, w,
3338                                 &buttonKOpt);
3339         }
3340 
3341         if ((tb->subControls & SC_TitleBarContextHelpButton)
3342                 && (tb->titleBarFlags & Qt::WindowContextHelpButtonHint)) {
3343             buttonKOpt.active = (tb->activeSubControls & SC_TitleBarContextHelpButton)
3344                                 && (tb->state & State_Sunken);
3345             QRect br = subControlRect(CC_TitleBar, tb, SC_TitleBarContextHelpButton, w);
3346             drawKStylePrimitive(WT_Window, Window::ButtonHelp, opt, br, pal, flags, p, w,
3347                                 &buttonKOpt);
3348         }
3349 
3350         return;
3351     } // CC_TitleBar
3352 
3353     default:
3354         break;
3355     } //switch
3356 
3357     QCommonStyle::drawComplexControl(cc, opt, p, w);
3358 }
3359 
3360 QRect K4Style::internalSubControlRect(ComplexControl control, const QStyleOptionComplex *option,
3361                                       SubControl subControl, const QWidget *widget) const
3362 {
3363     QRect r = option->rect;
3364 
3365     if (control == CC_ScrollBar) {
3366         switch (subControl) {
3367         //The "top" arrow
3368         case SC_ScrollBarSubLine: {
3369             int majorSize;
3370             if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, option, widget)) {
3371                 majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleButtonHeight, option, widget);
3372             } else {
3373                 majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::SingleButtonHeight, option, widget);
3374             }
3375 
3376             if (option->state & State_Horizontal) {
3377                 return handleRTL(option, QRect(r.x(), r.y(), majorSize, r.height()));
3378             } else {
3379                 return handleRTL(option, QRect(r.x(), r.y(), r.width(), majorSize));
3380             }
3381 
3382         }
3383 
3384         //The "bottom" arrow
3385         case SC_ScrollBarAddLine: {
3386             int majorSize;
3387             if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, option, widget)) {
3388                 majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleButtonHeight, option, widget);
3389             } else {
3390                 majorSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::SingleButtonHeight, option, widget);
3391             }
3392 
3393             if (option->state & State_Horizontal) {
3394                 return handleRTL(option, QRect(r.right() - majorSize + 1, r.y(), majorSize, r.height()));
3395             } else {
3396                 return handleRTL(option, QRect(r.x(), r.bottom() - majorSize + 1, r.width(), majorSize));
3397             }
3398         }
3399 
3400         default:
3401             break;
3402         }
3403     }
3404 
3405     return QRect();
3406 }
3407 
3408 QRect K4Style::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
3409                               SubControl subControl, const QWidget *widget) const
3410 {
3411     QRect r = option->rect;
3412 
3413     switch (control) {
3414     case CC_ScrollBar: {
3415         switch (subControl) {
3416         //For both arrows, we return -everything-,
3417         //to get stuff to repaint right. See internalSubControlRect
3418         //for the real thing
3419         case SC_ScrollBarSubLine:
3420         case SC_ScrollBarAddLine:
3421             return r;
3422 
3423         //The main groove area. This is used to compute the others...
3424         case SC_ScrollBarGroove: {
3425             QRect top = handleRTL(option, internalSubControlRect(control, option, SC_ScrollBarSubLine, widget));
3426             QRect bot = handleRTL(option, internalSubControlRect(control, option, SC_ScrollBarAddLine, widget));
3427 
3428             QPoint topLeftCorner, botRightCorner;
3429             if (option->state & State_Horizontal) {
3430                 topLeftCorner  = QPoint(top.right() + 1, top.top());
3431                 botRightCorner = QPoint(bot.left()  - 1, top.bottom());
3432             } else {
3433                 topLeftCorner  = QPoint(top.left(),  top.bottom() + 1);
3434                 botRightCorner = QPoint(top.right(), bot.top()    - 1);
3435             }
3436 
3437             return handleRTL(option, QRect(topLeftCorner, botRightCorner));
3438         }
3439 
3440         case SC_ScrollBarFirst:
3441         case SC_ScrollBarLast:
3442             return QRect();
3443 
3444         case SC_ScrollBarSlider: {
3445             const QStyleOptionSlider *slOpt = ::qstyleoption_cast<const QStyleOptionSlider *>(option);
3446 
3447             //We do handleRTL here to unreflect things if need be
3448             QRect groove = handleRTL(option, subControlRect(control, option, SC_ScrollBarGroove, widget));
3449             Q_ASSERT(slOpt);
3450 
3451             if (slOpt->minimum == slOpt->maximum) {
3452                 return groove;
3453             }
3454 
3455             //Figure out how much room we have..
3456             int space;
3457             if (option->state & State_Horizontal) {
3458                 space = groove.width();
3459             } else {
3460                 space = groove.height();
3461             }
3462 
3463             //Calculate the portion of this space that the slider should take up.
3464             int sliderSize = int(space * float(slOpt->pageStep) /
3465                                  (slOpt->maximum - slOpt->minimum + slOpt->pageStep));
3466 
3467             if (sliderSize < widgetLayoutProp(WT_ScrollBar, ScrollBar::MinimumSliderHeight, option, widget)) {
3468                 sliderSize = widgetLayoutProp(WT_ScrollBar, ScrollBar::MinimumSliderHeight, option, widget);
3469             }
3470 
3471             if (sliderSize > space) {
3472                 sliderSize = space;
3473             }
3474 
3475             //What do we have remaining?
3476             space = space - sliderSize;
3477 
3478             //uhm, yeah, nothing much
3479             if (space <= 0) {
3480                 return groove;
3481             }
3482 
3483             int pos = qRound(float(slOpt->sliderPosition - slOpt->minimum) /
3484                              (slOpt->maximum - slOpt->minimum) * space);
3485             if (option->state & State_Horizontal) {
3486                 return handleRTL(option, QRect(groove.x() + pos, groove.y(), sliderSize, groove.height()));
3487             } else {
3488                 return handleRTL(option, QRect(groove.x(), groove.y() + pos, groove.width(), sliderSize));
3489             }
3490         }
3491 
3492         case SC_ScrollBarSubPage: {
3493             //We do handleRTL here to unreflect things if need be
3494             QRect slider = handleRTL(option, subControlRect(control, option, SC_ScrollBarSlider, widget));
3495             QRect groove = handleRTL(option, subControlRect(control, option, SC_ScrollBarGroove, widget));
3496 
3497             //We're above the slider in the groove.
3498             if (option->state & State_Horizontal) {
3499                 return handleRTL(option, QRect(groove.x(), groove.y(), slider.x() - groove.x(), groove.height()));
3500             } else {
3501                 return handleRTL(option, QRect(groove.x(), groove.y(), groove.width(), slider.y() - groove.y()));
3502             }
3503         }
3504 
3505         case SC_ScrollBarAddPage: {
3506             //We do handleRTL here to unreflect things if need be
3507             QRect slider = handleRTL(option, subControlRect(control, option, SC_ScrollBarSlider, widget));
3508             QRect groove = handleRTL(option, subControlRect(control, option, SC_ScrollBarGroove, widget));
3509 
3510             //We're below the slider in the groove.
3511             if (option->state & State_Horizontal)
3512                 return handleRTL(option,
3513                                  QRect(slider.right() + 1, groove.y(), groove.right() - slider.right(), groove.height()));
3514             else
3515                 return handleRTL(option,
3516                                  QRect(groove.x(), slider.bottom() + 1, groove.width(), groove.bottom() - slider.bottom()));
3517         }
3518 
3519         default:
3520             break;
3521         }
3522     } //CC_ScrollBar
3523 
3524     case CC_SpinBox: {
3525         if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
3526 
3527             int fw = widgetLayoutProp(WT_SpinBox, SpinBox::FrameWidth, option, widget);
3528             int bw = widgetLayoutProp(WT_SpinBox, SpinBox::ButtonWidth, option, widget);
3529             int bm = widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin, option, widget);
3530             int bml = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Left, option, widget);
3531             int bmr = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Right, option, widget);
3532             int bmt = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Top, option, widget);
3533             int bmb = bm + widgetLayoutProp(WT_SpinBox, SpinBox::ButtonMargin + Bot, option, widget);
3534             int bs = widgetLayoutProp(WT_SpinBox, SpinBox::ButtonSpacing, option, widget);
3535             bool symmButtons = widgetLayoutProp(WT_SpinBox, SpinBox::SymmetricButtons, option, widget);
3536             bool supportFrameless = widgetLayoutProp(WT_SpinBox, SpinBox::SupportFrameless, option, widget);
3537 
3538             // SpinBox without a frame, set the corresponding layout values to 0, reduce button width.
3539             if (supportFrameless && !sb->frame) {
3540                 bw = bw - bmr; // reduce button with as the right button margin will be ignored.
3541                 fw = 0;
3542                 bmt = bmb = bmr = 0;
3543             }
3544 
3545             const int buttonsWidth = bw - bml - bmr;
3546             const int buttonsLeft = r.right() - bw + bml + 1;
3547 
3548             // compute the height of each button...
3549             int availableButtonHeight = r.height() - bmt - bmb - bs;
3550             if (symmButtons) {
3551                 // make sure the availableButtonHeight is even by reducing the
3552                 // button spacing by 1 if necessary. Results in both buttons
3553                 // of the same height...
3554                 if (availableButtonHeight % 2 != 0) {
3555                     --bs;
3556 
3557                     // recalculate...
3558                     availableButtonHeight = r.height() - bmt - bmb - bs;
3559                 }
3560             }
3561             int heightUp = availableButtonHeight / 2;
3562             int heightDown = availableButtonHeight - heightUp;
3563 
3564             switch (subControl) {
3565             case SC_SpinBoxUp:
3566                 return handleRTL(option,
3567                                  QRect(buttonsLeft, r.top() + bmt, buttonsWidth, heightUp));
3568             case SC_SpinBoxDown:
3569                 return handleRTL(option,
3570                                  QRect(buttonsLeft, r.bottom() - bmb - heightDown + 1, buttonsWidth, heightDown));
3571             case SC_SpinBoxEditField: {
3572                 QRect labelRect(r.left() + fw, r.top() + fw, r.width() - fw - bw, r.height() - 2 * fw);
3573                 labelRect = insideMargin(labelRect, WT_SpinBox, SpinBox::ContentsMargin, option, widget);
3574                 return handleRTL(option, labelRect);
3575             }
3576             case SC_SpinBoxFrame:
3577                 return (sb->frame || !supportFrameless) ? r : QRect();
3578             default:
3579                 break;
3580             }
3581         } //option ok
3582     } //CC_SpinBox
3583 
3584     case CC_ComboBox: {
3585         if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
3586 
3587             int fw = widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget);
3588             int bw = widgetLayoutProp(WT_ComboBox, ComboBox::ButtonWidth, option, widget);
3589             int bm = widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin, option, widget);
3590             int bml = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Left, option, widget);
3591             int bmr = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Right, option, widget);
3592             int bmt = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Top, option, widget);
3593             int bmb = bm + widgetLayoutProp(WT_ComboBox, ComboBox::ButtonMargin + Bot, option, widget);
3594             bool supportFrameless = widgetLayoutProp(WT_ComboBox, ComboBox::SupportFrameless, option, widget);
3595 
3596             // ComboBox without a frame, set the corresponding layout values to 0, reduce button width.
3597             if (supportFrameless && !cb->frame) {
3598                 bw = bw - bmr; // reduce button with as the right button margin will be ignored.
3599                 fw = 0;
3600                 bmt = bmb = bmr = 0;
3601             }
3602 
3603             switch (subControl) {
3604             case SC_ComboBoxFrame:
3605                 return (cb->frame || !supportFrameless) ? r : QRect();
3606             case SC_ComboBoxArrow:
3607                 return handleRTL(option,
3608                                  QRect(r.right() - bw + bml + 1, r.top() + bmt, bw - bml - bmr, r.height() - bmt - bmb));
3609             case SC_ComboBoxEditField: {
3610                 QRect labelRect(r.left() + fw, r.top() + fw, r.width() - fw - bw, r.height() - 2 * fw);
3611                 labelRect = insideMargin(labelRect, WT_ComboBox, ComboBox::ContentsMargin, option, widget);
3612                 return handleRTL(option, labelRect);
3613             }
3614             case SC_ComboBoxListBoxPopup:
3615                 // TODO: need to add layoutProps to control the popup rect?
3616 //                         return cb->popupRect;
3617                 // popupRect seems to be empty, so use QStyleOption::rect as Qt's styles do
3618                 return r;
3619             default:
3620                 break;
3621             }
3622         } //option ok
3623     } //CC_ComboBox
3624 
3625     case CC_TitleBar: {
3626         const QStyleOptionTitleBar *tbOpt =
3627             qstyleoption_cast<const QStyleOptionTitleBar *>(option);
3628         if (!tbOpt) {
3629             break;
3630         }
3631 
3632         QRect ret = insideMargin(r, WT_Window, Window::TitleMargin, option, widget);
3633 
3634         const int btnHeight = ret.height();
3635         const int btnWidth = widgetLayoutProp(WT_Window, Window::ButtonWidth, option, widget);
3636         const int btnSpace = widgetLayoutProp(WT_Window, Window::ButtonSpace, option, widget);
3637         const int titleSpace = widgetLayoutProp(WT_Window, Window::ButtonToTextSpace, option, widget);
3638 
3639         bool isMinimized = tbOpt->titleBarState & Qt::WindowMinimized;
3640         bool isMaximized = tbOpt->titleBarState & Qt::WindowMaximized;
3641 
3642         // button layout:  menu -title- help,shade,min,max,close
3643 
3644         bool menuCloseBtn = tbOpt->titleBarFlags & Qt::WindowSystemMenuHint;
3645         bool minBtn = !isMinimized &&
3646                       (tbOpt->titleBarFlags & Qt::WindowMinimizeButtonHint);
3647         bool maxBtn = !isMaximized &&
3648                       (tbOpt->titleBarFlags & Qt::WindowMaximizeButtonHint);
3649         bool restoreBtn =
3650             (isMinimized && (tbOpt->titleBarFlags & Qt::WindowMinimizeButtonHint)) ||
3651             (isMaximized && (tbOpt->titleBarFlags & Qt::WindowMaximizeButtonHint));
3652         bool shadeBtn = tbOpt->titleBarFlags & Qt::WindowShadeButtonHint;
3653         bool helpBtn = tbOpt->titleBarFlags & Qt::WindowContextHelpButtonHint;
3654 
3655         int btnOffsetCount = 0; // for button rects; count the position in the button bar
3656 
3657         switch (subControl) {
3658         case SC_TitleBarLabel: {
3659             if (tbOpt->titleBarFlags & Qt::WindowTitleHint) {
3660                 int cLeft = 0; // count buttons in the button bar
3661                 int cRight = 0;
3662 
3663                 if (menuCloseBtn) {
3664                     // menu and close button
3665                     ++cLeft;
3666                     ++cRight;
3667                 }
3668                 if (minBtn) {
3669                     ++cRight;
3670                 }
3671                 if (restoreBtn) {
3672                     ++cRight;
3673                 }
3674                 if (maxBtn) {
3675                     ++cRight;
3676                 }
3677                 if (shadeBtn) {
3678                     ++cRight;
3679                 }
3680                 if (helpBtn) {
3681                     ++cRight;
3682                 }
3683 
3684                 ret.adjust(cLeft * btnWidth + (cLeft - 1)*btnSpace + titleSpace, 0,
3685                            -(titleSpace + cRight * btnWidth + (cRight - 1)*btnSpace), 0);
3686             }
3687             break;
3688         }
3689 
3690         case SC_TitleBarSysMenu: {
3691             if (tbOpt->titleBarFlags & Qt::WindowSystemMenuHint) {
3692                 ret.setRect(ret.left(), ret.top(), btnWidth, btnHeight);
3693             }
3694             break;
3695         }
3696 
3697         case SC_TitleBarContextHelpButton:
3698             if (helpBtn) {
3699                 ++btnOffsetCount;
3700             }
3701         case SC_TitleBarMinButton:
3702             if (minBtn) {
3703                 ++btnOffsetCount;
3704             } else if (subControl == SC_TitleBarMinButton) {
3705                 return QRect();
3706             }
3707         case SC_TitleBarNormalButton:
3708             if (restoreBtn) {
3709                 ++btnOffsetCount;
3710             } else if (subControl == SC_TitleBarNormalButton) {
3711                 return QRect();
3712             }
3713         case SC_TitleBarMaxButton:
3714             if (maxBtn) {
3715                 ++btnOffsetCount;
3716             } else if (subControl == SC_TitleBarMaxButton) {
3717                 return QRect();
3718             }
3719         case SC_TitleBarShadeButton:
3720             if (!isMinimized && shadeBtn) {
3721                 ++btnOffsetCount;
3722             } else if (subControl == SC_TitleBarShadeButton) {
3723                 return QRect();
3724             }
3725         case SC_TitleBarUnshadeButton:
3726             if (isMinimized && shadeBtn) {
3727                 ++btnOffsetCount;
3728             } else if (subControl == SC_TitleBarUnshadeButton) {
3729                 return QRect();
3730             }
3731         case SC_TitleBarCloseButton: {
3732             if (menuCloseBtn) {
3733                 ++btnOffsetCount;
3734             } else if (subControl == SC_TitleBarCloseButton) {
3735                 return QRect();
3736             }
3737             // set the rect for all buttons that fell through:
3738             ret.setRect(ret.right() - btnOffsetCount * btnWidth - (btnOffsetCount - 1)*btnSpace,
3739                         ret.top(), btnWidth, btnHeight);
3740             break;
3741         }
3742 
3743         default:
3744             return QRect();
3745         }
3746 
3747         return visualRect(tbOpt->direction, tbOpt->rect, ret);
3748 
3749     } // CC_TitleBar
3750 
3751     default:
3752         break;
3753     }
3754 
3755     return QCommonStyle::subControlRect(control, option, subControl, widget);
3756 }
3757 
3758 /*
3759  Checks whether the point is before the bound rect for
3760  bound of given orientation
3761 */
3762 static bool preceeds(const QPoint &pt, const QRect &bound,
3763                      const QStyleOption *opt)
3764 {
3765     if (opt->state & QStyle::State_Horizontal) {
3766         //What's earlier depends on RTL or not
3767         if (opt->direction == Qt::LeftToRight) {
3768             return pt.x() < bound.right();
3769         } else {
3770             return pt.x() > bound.x();
3771         }
3772     } else {
3773         return pt.y() < bound.y();
3774     }
3775 }
3776 
3777 static QStyle::SubControl buttonPortion(const QRect &totalRect,
3778                                         const QPoint &pt,
3779                                         const QStyleOption *opt)
3780 {
3781     if (opt->state & QStyle::State_Horizontal) {
3782         //What's earlier depends on RTL or not
3783         if (opt->direction == Qt::LeftToRight) {
3784             return pt.x() < totalRect.center().x() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine;
3785         } else {
3786             return pt.x() > totalRect.center().x() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine;
3787         }
3788     } else {
3789         return pt.y() < totalRect.center().y() ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine;
3790     }
3791 }
3792 
3793 QStyle::SubControl K4Style::hitTestComplexControl(ComplexControl cc, const QStyleOptionComplex *opt,
3794         const QPoint &pt, const QWidget *w) const
3795 {
3796     if (cc == CC_ScrollBar) {
3797         //First, check whether we're inside the groove or not...
3798         QRect groove = subControlRect(CC_ScrollBar, opt, SC_ScrollBarGroove, w);
3799 
3800         if (groove.contains(pt)) {
3801             //Must be either page up/page down, or just click on the slider.
3802             //Grab the slider to compare
3803             QRect slider = subControlRect(CC_ScrollBar, opt, SC_ScrollBarSlider, w);
3804 
3805             if (slider.contains(pt)) {
3806                 return SC_ScrollBarSlider;
3807             } else if (preceeds(pt, slider, opt)) {
3808                 return SC_ScrollBarSubPage;
3809             } else {
3810                 return SC_ScrollBarAddPage;
3811             }
3812         } else {
3813             //This is one of the up/down buttons. First, decide which one it is.
3814             if (preceeds(pt, groove, opt)) {
3815                 //"Upper" button
3816                 if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleTopButton, nullptr, w)) {
3817                     QRect buttonRect = internalSubControlRect(CC_ScrollBar, opt, SC_ScrollBarSubLine, w);
3818                     return buttonPortion(buttonRect, pt, opt);
3819                 } else {
3820                     return SC_ScrollBarSubLine;    //Easy one!
3821                 }
3822             } else {
3823                 //"Bottom" button
3824                 if (widgetLayoutProp(WT_ScrollBar, ScrollBar::DoubleBotButton, nullptr, w)) {
3825                     QRect buttonRect = internalSubControlRect(CC_ScrollBar, opt, SC_ScrollBarAddLine, w);
3826                     return buttonPortion(buttonRect, pt, opt);
3827                 } else {
3828                     return SC_ScrollBarAddLine;    //Easy one!
3829                 }
3830             }
3831         }
3832     }
3833 
3834     return QCommonStyle::hitTestComplexControl(cc, opt, pt, w);
3835 }
3836 
3837 QSize K4Style::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const
3838 {
3839     switch (type) {
3840     case CT_PushButton: {
3841         const QStyleOptionButton *bOpt = qstyleoption_cast<const QStyleOptionButton *>(option);
3842         if (!bOpt) {
3843             return contentsSize;
3844         }
3845 
3846         QSize size = contentsSize;
3847 
3848         if ((bOpt->features & QStyleOptionButton::DefaultButton) || (bOpt->features & QStyleOptionButton::AutoDefaultButton)) {
3849             size = expandDim(size, WT_PushButton, PushButton::DefaultIndicatorMargin, option, widget);
3850         }
3851 
3852         //### TODO: Handle minimum size limits, extra spacing as in current styles ??
3853         size = expandDim(size, WT_PushButton, PushButton::ContentsMargin, option, widget);
3854 
3855         if (bOpt->features & QStyleOptionButton::HasMenu) {
3856             size.setWidth(size.width() + widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget));
3857         }
3858 
3859         if (!bOpt->text.isEmpty() && !bOpt->icon.isNull()) {
3860             // Incorporate the spacing between the icon and text. Qt sticks 4 there,
3861             // but we use PushButton::TextToIconSpace.
3862             size.setWidth(size.width() - 4 + widgetLayoutProp(WT_PushButton, PushButton::TextToIconSpace, option, widget));
3863         }
3864         return size;
3865     }
3866 
3867     case CT_ToolButton: {
3868         // We want to avoid super-skiny buttons, for things like "up" when icons + text
3869         // For this, we would like to make width >= height.
3870         // However, once we get here, QToolButton may have already put in the menu area
3871         // (PM_MenuButtonIndicator) into the width. So we may have to take it out, fix things
3872         // up, and add it back in. So much for class-independent rendering...
3873         QSize size = contentsSize;
3874         int   menuAreaWidth = 0;
3875         if (const QStyleOptionToolButton *tbOpt = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
3876             if (tbOpt->features & QStyleOptionToolButton::MenuButtonPopup) {
3877                 menuAreaWidth = pixelMetric(QStyle::PM_MenuButtonIndicator, option, widget);
3878             } else if (tbOpt->features & QStyleOptionToolButton::HasMenu) {
3879                 size.setWidth(size.width() + widgetLayoutProp(WT_ToolButton, ToolButton::InlineMenuIndicatorSize, tbOpt, widget));
3880             }
3881         }
3882 
3883         size.setWidth(size.width() - menuAreaWidth);
3884         if (size.width() < size.height()) {
3885             size.setWidth(size.height());
3886         }
3887         size.setWidth(size.width() + menuAreaWidth);
3888 
3889         return expandDim(size, WT_ToolButton, ToolButton::ContentsMargin, option, widget);
3890     }
3891 
3892     case CT_CheckBox: {
3893         //Add size for indicator ### handle empty case differently?
3894         int indicator = widgetLayoutProp(WT_CheckBox, CheckBox::Size, option, widget);
3895         int spacer    = widgetLayoutProp(WT_CheckBox, CheckBox::BoxTextSpace, option, widget);
3896 
3897         //Make sure we include space for the focus rect margin
3898         QSize size = expandDim(contentsSize, WT_CheckBox, CheckBox::FocusMargin, option, widget);
3899 
3900         //Make sure we can fit the indicator (### an extra margin around that?)
3901         size.setHeight(qMax(size.height(), indicator));
3902 
3903         //Add space for the indicator and the icon
3904         size.setWidth(size.width() + indicator + spacer);
3905 
3906         return size;
3907     }
3908 
3909     case CT_RadioButton: {
3910         //Add size for indicator
3911         int indicator = widgetLayoutProp(WT_RadioButton, RadioButton::Size, option, widget);
3912         int spacer    = widgetLayoutProp(WT_RadioButton, RadioButton::BoxTextSpace, option, widget);
3913 
3914         //Make sure we include space for the focus rect margin
3915         QSize size = expandDim(contentsSize, WT_RadioButton, RadioButton::FocusMargin, option, widget);
3916 
3917         //Make sure we can fit the indicator (### an extra margin around that?)
3918         size.setHeight(qMax(size.height(), indicator));
3919 
3920         //Add space for the indicator and the icon
3921         size.setWidth(size.width() + indicator + spacer);
3922 
3923         return size;
3924     }
3925 
3926     case CT_ProgressBar: {
3927         QSize size = contentsSize;
3928 
3929         const QStyleOptionProgressBar *pbOpt = ::qstyleoption_cast<const QStyleOptionProgressBar *>(option);
3930         if (useSideText(pbOpt)) {
3931             //Allocate extra room for side text
3932             size.setWidth(size.width() + sideTextWidth(pbOpt));
3933         }
3934 
3935         return size;
3936     }
3937 
3938     case CT_MenuBar: {
3939         int extraW = widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Right, option, widget) -
3940                      widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Left, option, widget);
3941 
3942         int extraH = widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Bot, option, widget) -
3943                      widgetLayoutProp(WT_MenuBar, MenuBar::Margin + Top, option, widget);
3944 
3945         return QSize(contentsSize.width() + extraW, contentsSize.height() + extraH);
3946     }
3947 
3948     case CT_Menu: {
3949         int extraW = widgetLayoutProp(WT_Menu, Menu::Margin + Right, option, widget) -
3950                      widgetLayoutProp(WT_Menu, Menu::Margin + Left, option, widget);
3951 
3952         int extraH = widgetLayoutProp(WT_Menu, Menu::Margin + Bot, option, widget) -
3953                      widgetLayoutProp(WT_Menu, Menu::Margin + Top, option, widget);
3954 
3955         return QSize(contentsSize.width() + extraW, contentsSize.height() + extraH);
3956     }
3957 
3958     case CT_MenuItem: {
3959         const QStyleOptionMenuItem *miOpt = ::qstyleoption_cast<const QStyleOptionMenuItem *>(option);
3960         if (!miOpt) {
3961             return contentsSize;    //Someone is asking for trouble..
3962         }
3963 
3964         //First, we calculate the intrinsic size of the item..
3965         QSize insideSize;
3966 
3967         switch (miOpt->menuItemType) {
3968         case QStyleOptionMenuItem::Normal:
3969         case QStyleOptionMenuItem::DefaultItem: //huh?
3970         case QStyleOptionMenuItem::SubMenu: {
3971             int iconColW = miOpt->maxIconWidth;
3972             iconColW     = qMax(iconColW, widgetLayoutProp(WT_MenuItem, MenuItem::IconWidth, option, widget));
3973 
3974             int leftColW = iconColW;
3975             if (miOpt->menuHasCheckableItems &&
3976                     widgetLayoutProp(WT_MenuItem, MenuItem::CheckAlongsideIcon, option, widget)) {
3977                 leftColW = widgetLayoutProp(WT_MenuItem, MenuItem::CheckWidth, option, widget) +
3978                            widgetLayoutProp(WT_MenuItem, MenuItem::CheckSpace, option, widget) +
3979                            iconColW;
3980             }
3981 
3982             leftColW     += widgetLayoutProp(WT_MenuItem, MenuItem::IconSpace, option, widget);
3983 
3984             int rightColW = widgetLayoutProp(WT_MenuItem, MenuItem::ArrowSpace, option, widget) +
3985                             widgetLayoutProp(WT_MenuItem, MenuItem::ArrowWidth, option, widget);
3986 
3987             QFontMetrics fm(miOpt->font);
3988 
3989             int textW;
3990             int tabPos = miOpt->text.indexOf(QLatin1Char('\t'));
3991             if (tabPos == -1) {
3992                 //No accel..
3993                 textW = contentsSize.width();
3994             } else {
3995                 // The width of the accelerator is not included here since
3996                 // Qt will add that on separately after obtaining the
3997                 // sizeFromContents() for each menu item in the menu to be shown
3998                 // ( see QMenuPrivate::calcActionRects() )
3999                 textW = contentsSize.width() +
4000                         widgetLayoutProp(WT_MenuItem, MenuItem::AccelSpace, option, widget);
4001             }
4002 
4003             int h = qMax(contentsSize.height(), widgetLayoutProp(WT_MenuItem, MenuItem::MinHeight, option, widget));
4004             insideSize = QSize(leftColW + textW + rightColW, h);
4005             break;
4006         }
4007 
4008         case QStyleOptionMenuItem::Separator: {
4009             insideSize = QSize(10, widgetLayoutProp(WT_MenuItem, MenuItem::SeparatorHeight, option, widget));
4010         }
4011         break;
4012 
4013         //Double huh if we get those.
4014         case QStyleOptionMenuItem::Scroller:
4015         case QStyleOptionMenuItem::TearOff:
4016         case QStyleOptionMenuItem::Margin:
4017         case QStyleOptionMenuItem::EmptyArea:
4018             return contentsSize;
4019         }
4020 
4021         //...now apply the outermost margin.
4022         return expandDim(insideSize, WT_MenuItem, MenuItem::Margin, option, widget);
4023     }
4024 
4025     case CT_MenuBarItem:
4026         return expandDim(contentsSize, WT_MenuBarItem, MenuBarItem::Margin, option, widget);
4027 
4028     case CT_TabBarTab: {
4029         //With our PM_TabBarTabHSpace/VSpace, Qt should give us what we want for
4030         //contentsSize, so we just expand that. Qt also takes care of
4031         //the vertical thing.
4032 
4033         bool rotated = false; // indicates whether the tab is rotated by 90 degrees
4034         if (const QStyleOptionTab *tabOpt = qstyleoption_cast<const QStyleOptionTab *>(option)) {
4035             rotated = isVerticalTab(tabOpt);
4036         }
4037 
4038         return expandDim(contentsSize, WT_TabBar, TabBar::TabContentsMargin, option, widget, rotated);
4039     }
4040 
4041     case CT_TabWidget: {
4042         const QStyleOptionTabWidgetFrame *tabOpt = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option);
4043         if (!tabOpt) {
4044             break;
4045         }
4046 
4047         int m = widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin, option, widget);
4048         int vert = 2 * m +
4049                    widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Top, option, widget) +
4050                    widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Bot, option, widget);
4051         int hor = 2 * m +
4052                   widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Left, option, widget) +
4053                   widgetLayoutProp(WT_TabWidget, TabWidget::ContentsMargin + Right, option, widget);
4054 
4055         switch (tabOpt->shape) {
4056         case QTabBar::RoundedNorth:
4057         case QTabBar::TriangularNorth:
4058         case QTabBar::RoundedWest:
4059         case QTabBar::TriangularWest:
4060             return contentsSize + QSize(hor, vert);
4061         case QTabBar::RoundedSouth:
4062         case QTabBar::TriangularSouth:
4063         case QTabBar::RoundedEast:
4064         case QTabBar::TriangularEast:
4065             return contentsSize + QSize(vert, hor);
4066         }
4067     }
4068 
4069     case CT_HeaderSection: {
4070         if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
4071             QSize iconSize = header->icon.isNull() ? QSize(0, 0) : QSize(22, 22);
4072             QSize textSize = header->fontMetrics.size(0, header->text);
4073             int iconSpacing = widgetLayoutProp(WT_Header, Header::TextToIconSpace, option, widget);
4074             int w = iconSize.width() + iconSpacing + textSize.width();
4075             int h = qMax(iconSize.height(), textSize.height());
4076 
4077             return expandDim(QSize(w, h), WT_Header, Header::ContentsMargin, option, widget);
4078         }
4079     }
4080 
4081     case CT_ComboBox: {
4082         // TODO: Figure out what to do with the button margins
4083         QSize size = contentsSize;
4084 
4085         // Add the contents margin
4086         size = expandDim(size, WT_ComboBox, ComboBox::ContentsMargin, option, widget);
4087 
4088         // Add the button width
4089         size.rwidth() += widgetLayoutProp(WT_ComboBox, ComboBox::ButtonWidth, option, widget);
4090 
4091         // Add the frame width
4092         size.rwidth()  += widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget) * 2;
4093         size.rheight() += widgetLayoutProp(WT_ComboBox, ComboBox::FrameWidth, option, widget) * 2;
4094 
4095         return size;
4096     }
4097 
4098     default:
4099         break;
4100     }
4101 
4102     return QCommonStyle::sizeFromContents(type, option, contentsSize, widget);
4103 }
4104 
4105 bool K4Style::eventFilter(QObject *obj, QEvent *ev)
4106 {
4107     if (QCommonStyle::eventFilter(obj, ev)) {
4108         return true;
4109     }
4110 
4111     if (QLabel *lbl = qobject_cast<QLabel *>(obj)) {
4112         QWidget *buddy = lbl->buddy();
4113         if (buddy) {
4114             switch (ev->type()) {
4115             case QEvent::MouseButtonPress: {
4116                 QMouseEvent *mev = dynamic_cast<QMouseEvent *>(ev);
4117                 if (!mev) {
4118                     break;
4119                 }
4120 
4121                 if (lbl->rect().contains(mev->pos())) {
4122                     clickedLabel = obj;
4123                     lbl->repaint();
4124                 }
4125                 break;
4126             }
4127             case QEvent::MouseButtonRelease: {
4128                 QMouseEvent *mev = dynamic_cast<QMouseEvent *>(ev);
4129                 if (!mev) {
4130                     break;
4131                 }
4132 
4133                 if (clickedLabel) {
4134                     clickedLabel = nullptr;
4135                     lbl->update();
4136                 }
4137 
4138                 // set focus to the buddy...
4139                 if (lbl->rect().contains(mev->pos())) {
4140                     buddy->setFocus(Qt::ShortcutFocusReason);
4141                 }
4142                 break;
4143             }
4144             case QEvent::Paint:
4145                 if (obj == clickedLabel && buddy->isEnabled()) {
4146                     // paint focus rect
4147                     QPainter p(lbl);
4148                     QStyleOptionFocusRect foOpts;
4149                     QRect foRect(0, 0, lbl->width(), lbl->height());
4150                     foOpts.palette = lbl->palette();
4151                     foOpts.rect    = foRect;
4152                     drawKStylePrimitive(WT_Generic, Generic::FocusIndicator, &foOpts,
4153                                         foRect, lbl->palette(), State(), &p, lbl);
4154                 }
4155                 break;
4156 
4157             default:
4158                 break;
4159             }
4160         }
4161     }
4162 
4163     return false;
4164 }
4165 
4166 K4Style::ColorMode::ColorMode(QPalette::ColorRole _role):
4167     mode(PaletteEntryMode),
4168     role(_role)
4169 {}
4170 
4171 K4Style::ColorMode::ColorMode(Mode _mode, QPalette::ColorRole _role):
4172     mode(_mode),
4173     role(_role)
4174 {}
4175 
4176 K4Style::ColorMode::operator int() const
4177 {
4178     return int(role) | int(mode);
4179 }
4180 
4181 K4Style::ColorMode::ColorMode(int encoded)
4182 {
4183     mode = (encoded & BWAutoContrastMode) ? BWAutoContrastMode : PaletteEntryMode;
4184     role = QPalette::ColorRole(encoded & (~BWAutoContrastMode));
4185 }
4186 
4187 QColor K4Style::ColorMode::color(const QPalette &palette)
4188 {
4189     QColor palColor = palette.color(role);
4190 
4191     if (mode == BWAutoContrastMode) {
4192         if (qGray(palColor.rgb()) > 128) { //### CHECKME
4193             palColor = Qt::black;
4194         } else {
4195             palColor = Qt::white;
4196         }
4197     }
4198     return palColor;
4199 }
4200 
4201 K4Style::TextOption::TextOption()
4202 {
4203     init();
4204 }
4205 
4206 K4Style::TextOption::TextOption(const QString &_text):
4207     text(_text)
4208 {
4209     init();
4210 }
4211 
4212 void K4Style::TextOption::init()
4213 {
4214     hAlign = Qt::AlignLeft; //NOTE: Check BIDI?
4215 }
4216 
4217 #include "moc_k4style.cpp"