1 /*****************************************************************************
2  *   Copyright 2007 - 2010 Craig Drummond <craig.p.drummond@gmail.com>       *
3  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
4  *                                                                           *
5  *   This program is free software; you can redistribute it and/or modify    *
6  *   it under the terms of the GNU Lesser General Public License as          *
7  *   published by the Free Software Foundation; either version 2.1 of the    *
8  *   License, or (at your option) version 3, or any later version accepted   *
9  *   by the membership of KDE e.V. (or its successor approved by the         *
10  *   membership of KDE e.V.), which shall act as a proxy defined in          *
11  *   Section 6 of version 3 of the license.                                  *
12  *                                                                           *
13  *   This program is distributed in the hope that it will be useful,         *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
16  *   Lesser General Public License for more details.                         *
17  *                                                                           *
18  *   You should have received a copy of the GNU Lesser General Public        *
19  *   License along with this library. If not,                                *
20  *   see <http://www.gnu.org/licenses/>.                                     *
21  *****************************************************************************/
22 
23 #include <qtcurve-utils/qtprops.h>
24 
25 #include "qtcurve_p.h"
26 #include "argbhelper.h"
27 #include "utils.h"
28 #include "shortcuthandler.h"
29 #include "windowmanager.h"
30 #include "blurhelper.h"
31 #include <common/config_file.h>
32 
33 #include "shadowhelper.h"
34 
35 #include <QFormLayout>
36 #include <QProgressBar>
37 #include <QToolButton>
38 #include <QAbstractItemView>
39 #include <QDialog>
40 #include <QSplitter>
41 #include <QMdiSubWindow>
42 #include <QMainWindow>
43 #include <QComboBox>
44 #include <QTreeView>
45 #include <QGroupBox>
46 #include <QListView>
47 #include <QCheckBox>
48 #include <QRadioButton>
49 #include <QTextEdit>
50 #include <QFontMetrics>
51 #include <QDial>
52 #include <QLabel>
53 #include <QStackedLayout>
54 #include <QMenuBar>
55 #include <QMouseEvent>
56 #include <QScrollBar>
57 #include <QWizard>
58 #include <QDialogButtonBox>
59 #include <QPushButton>
60 #include <QHeaderView>
61 #include <QLineEdit>
62 #include <QDir>
63 #include <QSettings>
64 #include <QPixmapCache>
65 #include <QTextStream>
66 #include <QFileDialog>
67 #include <QToolBox>
68 
69 #include <QDebug>
70 
71 #ifdef QTC_QT5_ENABLE_KDE
72 #include <QPrintDialog>
73 #include <KDE/KApplication>
74 #include <KDE/KGlobal>
75 #include <KDE/KGlobalSettings>
76 #include <KDE/KIconLoader>
77 #include <KDE/KIcon>
78 #include <KDE/KTitleWidget>
79 #include <KDE/KTabBar>
80 #include <KDE/KFileDialog>
81 #include <KDE/KAboutApplicationDialog>
82 #endif
83 
84 #include <qtcurve-utils/color.h>
85 
86 namespace QtCurve {
87 
88 void
polish(QApplication * app)89 Style::polish(QApplication *app)
90 {
91     // appName = getFile(app->arguments()[0]);
92 
93     if (appName == "kwin" || appName == "kwin_x11" || appName == "kwin_wayland") {
94         theThemedApp = APP_KWIN;
95     } else if (appName == "systemsettings" || appName == "systemsettings5") {
96         theThemedApp = APP_SYSTEMSETTINGS;
97     } else if ("plasma" == appName || appName.startsWith("plasma-")) {
98         theThemedApp = APP_PLASMA;
99     } else if ("krunner" == appName || "krunner_lock" == appName ||
100                "kscreenlocker" == appName) {
101         theThemedApp = APP_KRUNNER;
102     } else if ("kontact" == appName) {
103         theThemedApp = APP_KONTACT;
104     } else if ("k3b" == appName) {
105         theThemedApp = APP_K3B;
106     } else if("arora" == appName) {
107         theThemedApp = APP_ARORA;
108     } else if("rekonq" == appName) {
109         theThemedApp = APP_REKONQ;
110     } else if("QtCreator" == QCoreApplication::applicationName()) {
111         theThemedApp = APP_QTCREATOR;
112     } else if("kdevelop" == appName || "kdevelop.bin" == appName) {
113         theThemedApp = APP_KDEVELOP;
114     } else if("soffice.bin" == appName) {
115         theThemedApp = APP_OPENOFFICE;
116     } else if("kdmgreet" == appName) {
117         opts.forceAlternateLvCols = false;
118     }
119 
120     qtcInfo("QtCurve: Application name: \"%s\"\n",
121             appName.toLatin1().constData());
122 
123     if (theThemedApp == APP_REKONQ)
124         opts.statusbarHiding=0;
125     if(opts.menubarHiding)
126         m_saveMenuBarStatus=opts.menubarApps.contains("kde") || opts.menubarApps.contains(appName);
127     if(opts.statusbarHiding)
128         m_saveStatusBarStatus=opts.statusbarApps.contains("kde") || opts.statusbarApps.contains(appName);
129 
130     if(!qtcIsFlatBgnd(opts.bgndAppearance) && opts.noBgndGradientApps.contains(appName))
131         opts.bgndAppearance = APPEARANCE_FLAT;
132     if(IMG_NONE!=opts.bgndImage.type && opts.noBgndImageApps.contains(appName))
133         opts.bgndImage.type=IMG_NONE;
134     if(SHADE_NONE!=opts.menuStripe && opts.noMenuStripeApps.contains(appName))
135         opts.menuStripe=SHADE_NONE;
136 
137     if((100!=opts.bgndOpacity || 100!=opts.dlgOpacity) && (opts.noBgndOpacityApps.contains(appName) || appName.endsWith(".kss")))
138         opts.bgndOpacity=opts.dlgOpacity=100;
139     if (100 != opts.menuBgndOpacity &&
140         opts.noMenuBgndOpacityApps.contains(appName))
141         opts.menuBgndOpacity = 100;
142 
143     if (APP_KWIN == theThemedApp) {
144         opts.bgndAppearance = APPEARANCE_FLAT;
145     } else if(APP_OPENOFFICE == theThemedApp) {
146         opts.scrollbarType=SCROLLBAR_WINDOWS;
147         if(APPEARANCE_FADE == opts.menuitemAppearance)
148             opts.menuitemAppearance = APPEARANCE_FLAT;
149         opts.borderMenuitems=opts.etchEntry=false;
150 
151         if(opts.useHighlightForMenu && blendOOMenuHighlight(QApplication::palette(), m_highlightCols[ORIGINAL_SHADE]))
152         {
153             m_ooMenuCols=new QColor [TOTAL_SHADES+1];
154             shadeColors(tint(popupMenuCols()[ORIGINAL_SHADE], m_highlightCols[ORIGINAL_SHADE], 0.5), m_ooMenuCols);
155         }
156         opts.menubarHiding=opts.statusbarHiding=HIDE_NONE;
157         opts.square|=SQUARE_POPUP_MENUS|SQUARE_TOOLTIPS;
158         if(!qtcIsFlatBgnd(opts.menuBgndAppearance) && 0 == opts.lighterPopupMenuBgnd)
159             opts.lighterPopupMenuBgnd=1; // shade so that we dont have 3d-ish borders...
160         opts.menuBgndAppearance = APPEARANCE_FLAT;
161     }
162 
163     ParentStyleClass::polish(app);
164     if (opts.hideShortcutUnderline) {
165         app->installEventFilter(m_shortcutHandler);
166     }
167 }
168 
polish(QPalette & palette)169 void Style::polish(QPalette &palette)
170 {
171     int  contrast(QSettings(QLatin1String("Trolltech")).value("/Qt/KDE/contrast", DEFAULT_CONTRAST).toInt());
172     bool newContrast(false);
173 
174     if(contrast<0 || contrast>10)
175         contrast=DEFAULT_CONTRAST;
176 
177     if (contrast != opts.contrast) {
178         opts.contrast = contrast;
179         newContrast = true;
180     }
181 
182     bool newHighlight(newContrast ||
183                       m_highlightCols[ORIGINAL_SHADE]!=palette.color(QPalette::Active, QPalette::Highlight)),
184         newGray(newContrast ||
185                 m_backgroundCols[ORIGINAL_SHADE]!=palette.color(QPalette::Active, QPalette::Background)),
186         newButton(newContrast ||
187                   m_buttonCols[ORIGINAL_SHADE]!=palette.color(QPalette::Active, QPalette::Button)),
188         newSlider(m_sliderCols && m_highlightCols!=m_sliderCols && SHADE_BLEND_SELECTED == opts.shadeSliders &&
189                   (newButton || newHighlight)),
190         newDefBtn(m_defBtnCols &&
191                   (opts.defBtnIndicator != IND_COLORED ||
192                    opts.shadeSliders != SHADE_BLEND_SELECTED) &&
193                   noneOf(opts.defBtnIndicator, IND_SELECTED, IND_GLOW) &&
194                   (newContrast || newButton || newHighlight)),
195         newComboBtn(m_comboBtnCols &&
196                     noneOf(m_comboBtnCols, m_highlightCols, m_sliderCols) &&
197                     opts.comboBtn == SHADE_BLEND_SELECTED &&
198                     (newButton || newHighlight)),
199         newSortedLv(m_sortedLvColors && ((SHADE_BLEND_SELECTED == opts.sortedLv && m_defBtnCols!=m_sortedLvColors &&
200                                             m_sliderCols!=m_sortedLvColors && m_comboBtnCols!=m_sortedLvColors) ||
201                                            SHADE_DARKEN == opts.sortedLv) &&
202                     (newContrast || (opts.lvButton ? newButton : newGray))),
203         newCheckRadioSelCols(m_checkRadioSelCols && ((SHADE_BLEND_SELECTED == opts.crColor && m_defBtnCols!=m_checkRadioSelCols &&
204                                                        m_sliderCols!=m_checkRadioSelCols && m_comboBtnCols!=m_checkRadioSelCols &&
205                                                        m_sortedLvColors!=m_checkRadioSelCols) ||
206                                                       SHADE_DARKEN == opts.crColor) &&
207                              (newContrast || newButton)),
208         newProgressCols(m_progressCols && SHADE_BLEND_SELECTED == opts.progressColor &&
209                         m_sliderCols!=m_progressCols && m_comboBtnCols!=m_progressCols &&
210                         m_sortedLvColors!=m_progressCols && m_checkRadioSelCols!=m_progressCols && (newContrast || newButton));
211 
212     if (newGray) {
213         shadeColors(palette.color(QPalette::Active, QPalette::Background), m_backgroundCols);
214         if (oneOf(opts.bgndImage.type, IMG_PLAIN_RINGS, IMG_BORDERED_RINGS,
215                   IMG_SQUARE_RINGS) ||
216             oneOf(opts.menuBgndImage.type, IMG_PLAIN_RINGS,
217                   IMG_BORDERED_RINGS, IMG_SQUARE_RINGS)) {
218             qtcCalcRingAlphas(&m_backgroundCols[ORIGINAL_SHADE]);
219             if (m_usePixmapCache) {
220                 QPixmapCache::clear();
221             }
222         }
223     }
224 
225     if (newButton)
226         shadeColors(palette.color(QPalette::Active, QPalette::Button),
227                     m_buttonCols);
228 
229     if (newHighlight)
230         shadeColors(palette.color(QPalette::Active, QPalette::Highlight),
231                     m_highlightCols);
232 
233 // Dont set these here, they will be updated in setDecorationColors()...
234 //     shadeColors(QApplication::palette().color(QPalette::Active, QPalette::Highlight), m_focusCols);
235 //     if(opts.coloredMouseOver)
236 //         shadeColors(QApplication::palette().color(QPalette::Active, QPalette::Highlight), m_mouseOverCols);
237 
238     setMenuColors(palette.color(QPalette::Active, QPalette::Background));
239 
240     if (newSlider) {
241         shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE],
242                              m_buttonCols[ORIGINAL_SHADE]), m_sliderCols);
243     }
244 
245     if (newDefBtn) {
246         if (opts.defBtnIndicator == IND_TINT) {
247             shadeColors(tint(m_buttonCols[ORIGINAL_SHADE],
248                              m_highlightCols[ORIGINAL_SHADE],
249                              DEF_BNT_TINT), m_defBtnCols);
250         } else if (opts.defBtnIndicator != IND_GLOW) {
251             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE],
252                                  m_buttonCols[ORIGINAL_SHADE]), m_defBtnCols);
253         }
254     }
255 
256     if (newComboBtn) {
257         shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE],
258                              m_buttonCols[ORIGINAL_SHADE]), m_comboBtnCols);
259     }
260     if (newSortedLv) {
261         if (opts.sortedLv == SHADE_BLEND_SELECTED) {
262             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE],
263                                  opts.lvButton ? m_buttonCols[ORIGINAL_SHADE] :
264                                  m_backgroundCols[ORIGINAL_SHADE]),
265                         m_sortedLvColors);
266         } else {
267             shadeColors(shade(opts.lvButton ? m_buttonCols[ORIGINAL_SHADE] :
268                               m_backgroundCols[ORIGINAL_SHADE],
269                               LV_HEADER_DARK_FACTOR), m_sortedLvColors);
270         }
271     }
272 
273     if (m_sidebarButtonsCols && opts.shadeSliders != SHADE_BLEND_SELECTED &&
274         opts.defBtnIndicator != IND_COLORED) {
275         shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE],
276                              m_buttonCols[ORIGINAL_SHADE]),
277                     m_sidebarButtonsCols);
278     }
279 
280     switch (opts.shadeCheckRadio) {
281     default:
282         m_checkRadioCol = palette.color(QPalette::Active,
283                                          opts.crButton ? QPalette::ButtonText :
284                                          QPalette::Text);
285         break;
286     case SHADE_BLEND_SELECTED:
287     case SHADE_SELECTED:
288         m_checkRadioCol = palette.color(QPalette::Active, QPalette::Highlight);
289         break;
290     case SHADE_CUSTOM:
291         m_checkRadioCol = opts.customCheckRadioColor;
292     }
293 
294     if (newCheckRadioSelCols) {
295         if (opts.crColor == SHADE_BLEND_SELECTED) {
296             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE],
297                                  m_buttonCols[ORIGINAL_SHADE]),
298                         m_checkRadioSelCols);
299         } else {
300             shadeColors(shade(m_buttonCols[ORIGINAL_SHADE],
301                               LV_HEADER_DARK_FACTOR), m_checkRadioSelCols);
302         }
303     }
304     if (newProgressCols) {
305         shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE],
306                              m_backgroundCols[ORIGINAL_SHADE]),
307                     m_progressCols);
308     }
309     if (theThemedApp == APP_OPENOFFICE && opts.useHighlightForMenu &&
310         (newGray || newHighlight)) {
311         if (blendOOMenuHighlight(palette, m_highlightCols[ORIGINAL_SHADE])) {
312             if (!m_ooMenuCols) {
313                 m_ooMenuCols = new QColor[TOTAL_SHADES + 1];
314             }
315             shadeColors(tint(popupMenuCols()[ORIGINAL_SHADE],
316                              m_highlightCols[ORIGINAL_SHADE], 0.5),
317                         m_ooMenuCols);
318         } else if (m_ooMenuCols) {
319             delete []m_ooMenuCols;
320             m_ooMenuCols = 0L;
321         }
322     }
323 
324     palette.setColor(QPalette::Active, QPalette::Light, m_backgroundCols[0]);
325     palette.setColor(QPalette::Active, QPalette::Dark,
326                      m_backgroundCols[QTC_STD_BORDER]);
327     palette.setColor(QPalette::Inactive, QPalette::Light, m_backgroundCols[0]);
328     palette.setColor(QPalette::Inactive, QPalette::Dark,
329                      m_backgroundCols[QTC_STD_BORDER]);
330     palette.setColor(QPalette::Inactive, QPalette::WindowText,
331                      palette.color(QPalette::Active, QPalette::WindowText));
332     palette.setColor(QPalette::Disabled, QPalette::Light, m_backgroundCols[0]);
333     palette.setColor(QPalette::Disabled, QPalette::Dark,
334                      m_backgroundCols[QTC_STD_BORDER]);
335 
336     palette.setColor(QPalette::Disabled, QPalette::Base,
337                      palette.color(QPalette::Active, QPalette::Background));
338     palette.setColor(QPalette::Disabled, QPalette::Background,
339                      palette.color(QPalette::Active, QPalette::Background));
340 
341     // Fix KDE4's palette...
342     if (palette.color(QPalette::Active, QPalette::Highlight) !=
343         palette.color(QPalette::Inactive, QPalette::Highlight)) {
344         m_inactiveChangeSelectionColor = true;
345     }
346     for (int i = QPalette::WindowText;i < QPalette::NColorRoles;i++) {
347         // if (i != QPalette::Highlight && i != QPalette::HighlightedText)
348         palette.setColor(QPalette::Inactive, (QPalette::ColorRole)i,
349                          palette.color(QPalette::Active,
350                                        (QPalette::ColorRole)i));
351     }
352 
353     // Force this to be re-generated!
354     if (opts.menuStripe == SHADE_BLEND_SELECTED) {
355         opts.customMenuStripeColor = Qt::black;
356     }
357 #ifdef QTC_QT5_ENABLE_KDE
358     // Only set palette here...
359     if (kapp) {
360         setDecorationColors();
361     }
362 #endif
363 }
364 
polish(QWidget * widget)365 void Style::polish(QWidget *widget)
366 {
367     // TODO:
368     //      Reorganize this polish function
369     if (!widget)
370         return;
371 
372     prePolish(widget);
373     QtcQWidgetProps qtcProps(widget);
374     bool enableMouseOver(opts.highlightFactor || opts.coloredMouseOver);
375 
376     if (opts.buttonEffect != EFFECT_NONE && !USE_CUSTOM_ALPHAS(opts) &&
377         isNoEtchWidget(widget)) {
378         qtcProps->noEtch = true;
379     }
380 
381     m_windowManager->registerWidget(widget);
382     m_shadowHelper->registerWidget(widget);
383 
384     // Need to register all widgets to blur helper, in order to have proper
385     // blur_behind region set have proper regions removed for opaque widgets.
386     // Note: that the helper does nothing as long as compositing and ARGB are
387     // not enabled
388     const bool isDialog = qtcIsDialog(widget->window());
389     if ((opts.menuBgndOpacity != 100 &&
390          (qobject_cast<QMenu*>(widget) ||
391           // TODO temporary solution only
392           widget->inherits("QComboBoxPrivateContainer"))) ||
393         (opts.bgndOpacity != 100 && (!widget->window() || !isDialog)) ||
394         (opts.dlgOpacity != 100 && (!widget->window() || isDialog))) {
395         m_blurHelper->registerWidget(widget);
396     }
397 
398     // Sometimes get background errors with QToolBox (e.g. in Bespin config),
399     // and setting WA_StyledBackground seems to fix this,..
400     if (qtcIsCustomBgnd(opts) ||
401         oneOf(opts.groupBox, FRAME_SHADED, FRAME_FADED)) {
402         switch (widget->windowType()) {
403         case Qt::Window:
404         case Qt::Sheet:
405         case Qt::Dialog: {
406             // For non-transparent widgets, only need to set
407             // WA_StyledBackground - and PE_Widget will be called to
408             // render background...
409             widget->setAttribute(Qt::WA_StyledBackground);
410             break;
411         }
412         case Qt::Popup:
413             // we currently don't want that kind of gradient on menus etc
414         case Qt::Drawer:
415         case Qt::Tool:
416             // this we exclude as it is used for dragging of icons etc
417         default:
418             break;
419         }
420         if (qobject_cast<QSlider*>(widget)) {
421             widget->setBackgroundRole(QPalette::NoRole);
422         }
423         if (widget->autoFillBackground() && widget->parentWidget() &&
424             widget->parentWidget()->objectName() == "qt_scrollarea_viewport" &&
425             qtcCheckType<QAbstractScrollArea>(getParent<2>(widget)) &&
426             qtcCheckType<QToolBox>(getParent<3>(widget))) {
427             widget->parentWidget()->setAutoFillBackground(false);
428             widget->setAutoFillBackground(false);
429         }
430     }
431     if (qobject_cast<QMdiSubWindow*>(widget)) {
432         widget->setAttribute(Qt::WA_StyledBackground);
433     }
434     if (opts.menubarHiding && qobject_cast<QMainWindow*>(widget) &&
435         static_cast<QMainWindow*>(widget)->menuWidget()) {
436         widget->installEventFilter(this);
437         if (m_saveMenuBarStatus)
438             static_cast<QMainWindow*>(widget)->menuWidget()
439                 ->installEventFilter(this);
440         if (m_saveMenuBarStatus && qtcMenuBarHidden(appName)) {
441             static_cast<QMainWindow*>(widget)->menuWidget()->setHidden(true);
442             if (BLEND_TITLEBAR || opts.menubarHiding & HIDE_KWIN ||
443                 opts.windowBorder & WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR)
444                 emitMenuSize(static_cast<QMainWindow*>(widget)->menuWidget(), 0);
445         }
446     }
447 
448     if (opts.statusbarHiding && qobject_cast<QMainWindow*>(widget)) {
449         QList<QStatusBar*> sb = getStatusBars(widget);
450 
451         if (sb.count()) {
452             widget->installEventFilter(this);
453             for (QStatusBar *statusBar: const_(sb)) {
454                 if (m_saveStatusBarStatus) {
455                     statusBar->installEventFilter(this);
456                 }
457                 if (m_saveStatusBarStatus && qtcStatusBarHidden(appName)) {
458                     statusBar->setHidden(true);
459                 }
460             }
461             setSbProp(widget);
462             emitStatusBarState(sb.first());
463         }
464     }
465 
466     // Enable hover effects in all itemviews
467     if (QAbstractItemView *itemView = qobject_cast<QAbstractItemView*>(widget))
468     {
469         QWidget *viewport=itemView->viewport();
470         viewport->setAttribute(Qt::WA_Hover);
471 
472         if(opts.forceAlternateLvCols &&
473            viewport->autoFillBackground() && // Dolphins Folders panel
474            //255==viewport->palette().color(itemView->viewport()->backgroundRole()).alpha() && // KFilePlacesView
475            !widget->inherits("KFilePlacesView") &&
476            // Exclude non-editable combo popup...
477            !(opts.gtkComboMenus && widget->inherits("QComboBoxListView") &&
478              qtcCheckType<QComboBox>(getParent<2>(widget)) &&
479              !static_cast<QComboBox*>(getParent<2>(widget))->isEditable()) &&
480            // Exclude KAboutDialog...
481            !qtcCheckKDEType(getParent<5>(widget), KAboutApplicationDialog) &&
482            (qobject_cast<QTreeView*>(widget) ||
483             (qobject_cast<QListView*>(widget) &&
484              ((QListView*)widget)->viewMode() != QListView::IconMode)))
485             itemView->setAlternatingRowColors(true);
486     }
487 
488     if(APP_KONTACT==theThemedApp && qobject_cast<QToolButton *>(widget))
489         ((QToolButton *)widget)->setAutoRaise(true);
490 
491     if(enableMouseOver &&
492        (qobject_cast<QPushButton*>(widget) ||
493         qobject_cast<QAbstractButton*>(widget) ||
494         qobject_cast<QComboBox*>(widget) ||
495         qobject_cast<QAbstractSpinBox*>(widget) ||
496         qobject_cast<QCheckBox*>(widget) ||
497         qobject_cast<QGroupBox*>(widget) ||
498         qobject_cast<QRadioButton*>(widget) ||
499         qobject_cast<QSplitterHandle*>(widget) ||
500         qobject_cast<QSlider*>(widget) ||
501         qobject_cast<QHeaderView*>(widget) ||
502         qobject_cast<QTabBar*>(widget) ||
503         qobject_cast<QAbstractScrollArea*>(widget) ||
504         qobject_cast<QTextEdit*>(widget) ||
505         qobject_cast<QLineEdit*>(widget) ||
506         qobject_cast<QDial*>(widget) ||
507         // qobject_cast<QDockWidget*>(widget) ||
508         widget->inherits("QWorkspaceTitleBar") ||
509         widget->inherits("QDockSeparator") ||
510         widget->inherits("QDockWidgetSeparator")))
511         widget->setAttribute(Qt::WA_Hover, true);
512 
513     if (qobject_cast<QSplitterHandle*>(widget)) {
514         widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
515     } else if (qobject_cast<QScrollBar*>(widget)) {
516         if(enableMouseOver)
517             widget->setAttribute(Qt::WA_Hover, true);
518         widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
519         if (!opts.gtkScrollViews) {
520             widget->installEventFilter(this);
521         }
522     } else if (qobject_cast<QAbstractScrollArea*>(widget) &&
523                widget->inherits("KFilePlacesView")) {
524         if (qtcIsCustomBgnd(opts))
525             polishScrollArea(static_cast<QAbstractScrollArea*>(widget), true);
526         widget->installEventFilter(this);
527     } else if (qobject_cast<QProgressBar*>(widget)) {
528         if (widget->palette().color(QPalette::Inactive,
529                                     QPalette::HighlightedText) !=
530             widget->palette().color(QPalette::Active,
531                                     QPalette::HighlightedText)) {
532             QPalette pal(widget->palette());
533             pal.setColor(QPalette::Inactive, QPalette::HighlightedText,
534                          pal.color(QPalette::Active,
535                                    QPalette::HighlightedText));
536             widget->setPalette(pal);
537         }
538 
539         if (opts.boldProgress)
540             setBold(widget);
541         widget->installEventFilter(this);
542     } else if (qobject_cast<QMenuBar*>(widget)) {
543         if (BLEND_TITLEBAR || opts.menubarHiding & HIDE_KWIN ||
544             opts.windowBorder &
545             WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR) {
546             emitMenuSize(widget, PREVIEW_MDI == m_isPreview ||
547                          !widget->isVisible() ? 0 : widget->rect().height());
548         }
549         if (qtcIsCustomBgnd(opts))
550             widget->setBackgroundRole(QPalette::NoRole);
551 
552         widget->setAttribute(Qt::WA_Hover, true);
553 
554         // if(opts.shadeMenubarOnlyWhenActive && SHADE_NONE!=opts.shadeMenubars)
555         widget->installEventFilter(this);
556 
557         setMenuTextColors(widget, true);
558     } else if(qobject_cast<QLabel*>(widget)) {
559         widget->installEventFilter(this);
560         if (opts.windowDrag == WM_DRAG_ALL &&
561             ((QLabel*)widget)->textInteractionFlags()
562             .testFlag(Qt::TextSelectableByMouse) &&
563             qtcCheckType<QFrame>(widget->parentWidget()) &&
564             qtcCheckKDEType(getParent<2>(widget), KTitleWidget))
565             ((QLabel*)widget)->setTextInteractionFlags(
566                 ((QLabel*)widget)->textInteractionFlags() &
567                 ~Qt::TextSelectableByMouse);
568     } else if (qobject_cast<QAbstractScrollArea*>(widget)) {
569         if (qtcIsCustomBgnd(opts))
570             polishScrollArea(static_cast<QAbstractScrollArea *>(widget));
571         if (!opts.gtkScrollViews && (((QFrame*)widget)->frameWidth() > 0)) {
572             widget->installEventFilter(this);
573         }
574         if (APP_KONTACT == theThemedApp && widget->parentWidget()) {
575             QWidget *frame = scrollViewFrame(widget->parentWidget());
576 
577             if (frame) {
578                 frame->installEventFilter(this);
579                 m_sViewContainers[frame].insert(widget);
580                 connect(qtcSlot(widget, destroyed),
581                         qtcSlot(this, widgetDestroyed));
582                 connect(qtcSlot(frame, destroyed),
583                         qtcSlot(this, widgetDestroyed));
584             }
585         }
586     } else if (qobject_cast<QDialog*>(widget) &&
587                widget->inherits("QPrintPropertiesDialog") &&
588                widget->parentWidget() && widget->parentWidget()->window() &&
589                widget->window() && widget->window()->windowTitle().isEmpty() &&
590                !widget->parentWidget()->window()->windowTitle().isEmpty()) {
591         widget->window()->setWindowTitle(widget->parentWidget()->window()
592                                          ->windowTitle());
593     } else if (widget->inherits("QWhatsThat")) {
594         QPalette pal(widget->palette());
595         QColor   shadow(pal.shadow().color());
596 
597         shadow.setAlpha(32);
598         pal.setColor(QPalette::Shadow, shadow);
599         widget->setPalette(pal);
600         widget->setMask(QRegion(widget->rect().adjusted(0, 0, -6, -6))+QRegion(widget->rect().adjusted(6, 6, 0, 0)));
601     } else if (qobject_cast<QDockWidget*>(widget) &&
602                qtcCheckType<QSplitter>(widget->parentWidget()) &&
603                qtcCheckType(getParent<2>(widget), "KFileWidget"))
604         ((QDockWidget*)widget)->setTitleBarWidget(new QtCurveDockWidgetTitleBar(widget));
605 
606     if (widget->inherits("QTipLabel") && !qtcIsFlat(opts.tooltipAppearance)) {
607         widget->setBackgroundRole(QPalette::NoRole);
608         // TODO: turn this into addAlphaChannel
609         widget->setAttribute(Qt::WA_TranslucentBackground);
610     }
611 
612     if (!widget->isWindow())
613         if (QFrame *frame = qobject_cast<QFrame*>(widget)) {
614             // kill ugly frames...
615             if (QFrame::Box == frame->frameShape() ||
616                 QFrame::Panel == frame->frameShape() ||
617                 QFrame::WinPanel == frame->frameShape()) {
618                 frame->setFrameShape(QFrame::StyledPanel);
619             }
620             //else if (QFrame::HLine==frame->frameShape() || QFrame::VLine==frame->frameShape())
621             widget->installEventFilter(this);
622 
623             if (qtcCheckKDEType(widget->parent(), KTitleWidget)) {
624                 if (qtcIsCustomBgnd(opts)) {
625                     frame->setAutoFillBackground(false);
626                 } else {
627                     frame->setBackgroundRole(QPalette::Window);
628                 }
629                 QLayout *layout(frame->layout());
630                 if (layout) {
631                     layout->setMargin(0);
632                 }
633             }
634 
635             QComboBox *p = nullptr;
636             if (opts.gtkComboMenus &&
637                 (p = qtcObjCast<QComboBox>(getParent<2>(widget))) &&
638                 !p->isEditable()) {
639                 QPalette pal(widget->palette());
640                 QColor   col(popupMenuCols()[ORIGINAL_SHADE]);
641 
642                 if (!qtcIsFlatBgnd(opts.menuBgndAppearance) ||
643                    100 != opts.menuBgndOpacity ||
644                     !(opts.square & SQUARE_POPUP_MENUS))
645                     col.setAlphaF(0);
646 
647                 pal.setBrush(QPalette::Active, QPalette::Base, col);
648                 pal.setBrush(QPalette::Active, QPalette::Window, col);
649                 widget->setPalette(pal);
650                 if(opts.shadePopupMenu)
651                     setMenuTextColors(widget, false);
652             }
653         }
654 
655     if (qobject_cast<QMenu*>(widget)) {
656         if (opts.lighterPopupMenuBgnd || opts.shadePopupMenu) {
657             QPalette pal(widget->palette());
658             pal.setBrush(QPalette::Active, QPalette::Window,
659                          popupMenuCols()[ORIGINAL_SHADE]);
660             widget->setPalette(pal);
661             if (opts.shadePopupMenu) {
662                 setMenuTextColors(widget, false);
663             }
664         }
665         if (opts.menuBgndOpacity != 100 ||
666             !(opts.square & SQUARE_POPUP_MENUS)) {
667             widget->setAttribute(Qt::WA_NoSystemBackground);
668             addAlphaChannel(widget);
669         }
670     }
671 
672     if ((!qtcIsFlatBgnd(opts.menuBgndAppearance) ||
673          opts.menuBgndOpacity != 100 ||
674          !(opts.square & SQUARE_POPUP_MENUS)) &&
675         widget->inherits("QComboBoxPrivateContainer")) {
676         widget->installEventFilter(this);
677         widget->setAttribute(Qt::WA_NoSystemBackground);
678         addAlphaChannel(widget);
679     }
680 
681     bool parentIsToolbar(false);
682 
683     // Using dark menubars - konqueror's combo box texts get messed up. Seems
684     // to be when a plain QWidget has widget->setBackgroundRole(QPalette::Window);
685     // and widget->setAutoFillBackground(false); set (below). These only happen
686     // if 'parentIsToolbar' - so dont bather detecting this if the widget
687     // is a plain QWidget
688     //
689     // QWidget QComboBoxListView QComboBoxPrivateContainer SearchBarCombo KToolBar KonqMainWindow
690     // QWidget KCompletionBox KLineEdit SearchBarCombo KToolBar KonqMainWindow
691     if(strcmp(widget->metaObject()->className(), "QWidget"))
692     {
693         QWidget *wid=widget ? widget->parentWidget() : 0L;
694 
695         while(wid && !parentIsToolbar) {
696             parentIsToolbar=qobject_cast<QToolBar*>(wid);
697             wid=wid->parentWidget();
698         }
699     }
700 
701     if (APP_QTCREATOR == theThemedApp &&
702         qobject_cast<QMainWindow*>(widget) &&
703         static_cast<QMainWindow*>(widget)->menuWidget()) {
704         // As of 2.8.1, QtCreator still uses it's own style by default.
705         // Have no idea what the **** they are thinking.
706         static_cast<QMainWindow*>(widget)->menuWidget()->setStyle(this);
707     }
708 
709     if (APP_QTCREATOR == theThemedApp && qobject_cast<QDialog*>(widget) &&
710         qtcCheckKDEType(widget, QFileDialog)) {
711 
712         QToolBar *tb = getToolBarChild(widget);
713         if (tb) {
714             int size = pixelMetric(PM_ToolBarIconSize);
715             tb->setIconSize(QSize(size, size));
716             tb->setMinimumSize(QSize(size + 14, size + 14));
717             setStyleRecursive(tb, this, size + 4);
718         }
719     }
720 
721     if(parentIsToolbar && (qobject_cast<QComboBox *>(widget) ||
722                            qobject_cast<QLineEdit *>(widget)))
723         widget->setFont(QApplication::font());
724 
725     if (qobject_cast<QMenuBar*>(widget) || qobject_cast<QToolBar*>(widget) ||
726         parentIsToolbar)
727         widget->setBackgroundRole(QPalette::Window);
728 
729     if (!qtcIsFlat(opts.toolbarAppearance) && parentIsToolbar) {
730         widget->setAutoFillBackground(false);
731     }
732 
733     if (theThemedApp == APP_SYSTEMSETTINGS &&
734         qobject_cast<QTabWidget*>(getParent<2>(widget)) &&
735         qobject_cast<QFrame*>(widget) &&
736         ((QFrame*)widget)->frameShape() != QFrame::NoFrame &&
737         qobject_cast<QFrame*>(widget->parentWidget())) {
738         ((QFrame*)widget)->setFrameShape(QFrame::NoFrame);
739     }
740 
741     if (QLayout *layout = widget->layout()) {
742         // explicitly check public layout classes,
743         // QMainWindowLayout doesn't work here
744         if (qobject_cast<QBoxLayout*>(layout) ||
745             qobject_cast<QFormLayout*>(layout) ||
746             qobject_cast<QGridLayout*>(layout) ||
747             qobject_cast<QStackedLayout*>(layout)) {
748             polishLayout(layout);
749         }
750     }
751 
752     if ((theThemedApp == APP_K3B &&
753          widget->inherits("K3b::ThemedHeader") &&
754          qobject_cast<QFrame*>(widget)) ||
755         widget->inherits("KColorPatch")) {
756         ((QFrame*)widget)->setLineWidth(0);
757         ((QFrame*)widget)->setFrameShape(QFrame::NoFrame);
758     }
759 
760     if (theThemedApp == APP_KDEVELOP && !opts.stdSidebarButtons &&
761         widget->inherits("Sublime::IdealButtonBarWidget") && widget->layout()) {
762         widget->layout()->setSpacing(0);
763         widget->layout()->setMargin(0);
764     }
765 
766     QWidget *window=widget->window();
767 
768     if ((100 != opts.bgndOpacity && qtcIsWindow(window)) ||
769         (100 != opts.dlgOpacity && qtcIsDialog(window))) {
770         widget->installEventFilter(this);
771         if (widget->inherits("KFilePlacesView")) {
772             widget->setAutoFillBackground(false);
773             widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
774         }
775     }
776 
777 #ifdef QTC_QT5_ENABLE_KDE
778     // Make file selection button in QPrintDialog appear more KUrlRequester like...
779     if (qtcCheckType<QPrintDialog>(getParent<3>(widget)) &&
780         qobject_cast<QToolButton*>(widget) &&
781         qobject_cast<QGroupBox*>(widget->parentWidget()) &&
782         static_cast<QToolButton*>(widget)->text() == QLatin1String("...")) {
783         static_cast<QToolButton*>(widget)->setIcon(QIcon::fromTheme(QStringLiteral("document-open")));
784         static_cast<QToolButton*>(widget)->setAutoRaise(false);
785     }
786 #endif
787 }
788 
789 void
unpolish(QApplication * app)790 Style::unpolish(QApplication *app)
791 {
792     if (opts.hideShortcutUnderline)
793         app->removeEventFilter(m_shortcutHandler);
794     ParentStyleClass::unpolish(app);
795 }
796 
unpolish(QWidget * widget)797 void Style::unpolish(QWidget *widget)
798 {
799     if (!widget)
800         return;
801     widget->removeEventFilter(this);
802     m_windowManager->unregisterWidget(widget);
803     m_shadowHelper->unregisterWidget(widget);
804     m_blurHelper->unregisterWidget(widget);
805 
806     // Sometimes get background errors with QToolBox (e.g. in Bespin config),
807     // and setting WA_StyledBackground seems to fix this,..
808     if (qtcIsCustomBgnd(opts) || opts.groupBox == FRAME_SHADED ||
809         opts.groupBox == FRAME_FADED) {
810         switch (widget->windowType()) {
811         case Qt::Window:
812         case Qt::Sheet:
813         case Qt::Dialog:
814             widget->setAttribute(Qt::WA_StyledBackground, false);
815             break;
816         case Qt::Popup:
817             // we currently don't want that kind of gradient on menus etc
818         case Qt::Drawer:
819         case Qt::Tool:
820             // this we exclude as it is used for dragging of icons etc
821         default:
822             break;
823         }
824 
825         if (qobject_cast<QSlider*>(widget)) {
826             widget->setBackgroundRole(QPalette::Window);
827         }
828     }
829 
830     if (qobject_cast<QMdiSubWindow*>(widget))
831         widget->setAttribute(Qt::WA_StyledBackground, false);
832 
833     if (opts.menubarHiding && qobject_cast<QMainWindow*>(widget) &&
834         static_cast<QMainWindow*>(widget)->menuWidget()) {
835         if (m_saveMenuBarStatus) {
836             static_cast<QMainWindow*>(widget)->menuWidget()
837                 ->removeEventFilter(this);
838         }
839     }
840 
841     if (opts.statusbarHiding && qobject_cast<QMainWindow*>(widget)) {
842         if (m_saveStatusBarStatus) {
843             for (QStatusBar *statusBar: getStatusBars(widget)) {
844                 statusBar->removeEventFilter(this);
845             }
846         }
847     }
848 
849     if(qobject_cast<QPushButton*>(widget) ||
850        qobject_cast<QComboBox*>(widget) ||
851        qobject_cast<QAbstractSpinBox*>(widget) ||
852        qobject_cast<QCheckBox*>(widget) ||
853        qobject_cast<QGroupBox*>(widget) ||
854        qobject_cast<QRadioButton*>(widget) ||
855        qobject_cast<QSplitterHandle*>(widget) ||
856        qobject_cast<QSlider*>(widget) ||
857        qobject_cast<QHeaderView*>(widget) ||
858        qobject_cast<QTabBar*>(widget) ||
859        qobject_cast<QAbstractScrollArea*>(widget) ||
860        qobject_cast<QTextEdit*>(widget) ||
861        qobject_cast<QLineEdit*>(widget) ||
862        qobject_cast<QDial*>(widget) ||
863        // qobject_cast<QDockWidget *>(widget) ||
864        widget->inherits("QWorkspaceTitleBar") ||
865        widget->inherits("QDockSeparator") ||
866        widget->inherits("QDockWidgetSeparator"))
867         widget->setAttribute(Qt::WA_Hover, false);
868     if (qobject_cast<QScrollBar*>(widget)) {
869         widget->setAttribute(Qt::WA_Hover, false);
870         if (opts.round != ROUND_NONE && !opts.flatSbarButtons)
871             widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
872     } else if (qobject_cast<QProgressBar*>(widget)) {
873         if(opts.boldProgress)
874             unSetBold(widget);
875         m_progressBars.remove((QProgressBar *)widget);
876     } else if (qobject_cast<QMenuBar*>(widget)) {
877         widget->setAttribute(Qt::WA_Hover, false);
878 
879         if(qtcIsCustomBgnd(opts))
880             widget->setBackgroundRole(QPalette::Background);
881 
882         if(SHADE_WINDOW_BORDER==opts.shadeMenubars || opts.customMenuTextColor || SHADE_BLEND_SELECTED==opts.shadeMenubars ||
883            SHADE_SELECTED==opts.shadeMenubars || (SHADE_CUSTOM==opts.shadeMenubars &&TOO_DARK(m_menubarCols[ORIGINAL_SHADE])))
884             widget->setPalette(QApplication::palette());
885     } else if (/*!opts.gtkScrollViews && */
886         qobject_cast<QAbstractScrollArea*>(widget)) {
887         if (APP_KONTACT==theThemedApp && widget->parentWidget()) {
888             QWidget *frame = scrollViewFrame(widget->parentWidget());
889             if (frame) {
890                 if (m_sViewContainers.contains(frame)) {
891                     m_sViewContainers[frame].remove(widget);
892                     if (0 == m_sViewContainers[frame].count()) {
893                         frame->removeEventFilter(this);
894                         m_sViewContainers.remove(frame);
895                         disconnect(frame, &QWidget::destroyed,
896                                    this, &Style::widgetDestroyed);
897                     }
898                 }
899             }
900         }
901     } else if (qobject_cast<QDockWidget *>(widget) &&
902                ((QDockWidget*)widget)->titleBarWidget() &&
903                qobject_cast<QtCurveDockWidgetTitleBar*>(
904                    ((QDockWidget*)widget)->titleBarWidget()) &&
905                qtcCheckType<QSplitter>(widget->parentWidget()) &&
906                getParent<3>(widget) &&
907                qtcCheckType(getParent<2>(widget), "KFileWidget")) {
908         delete ((QDockWidget *)widget)->titleBarWidget();
909         ((QDockWidget*)widget)->setTitleBarWidget(0L);
910     } else if (opts.boldProgress && "CE_CapacityBar"==widget->objectName()) {
911         unSetBold(widget);
912     }
913 
914     if (widget->inherits("QTipLabel") && !qtcIsFlat(opts.tooltipAppearance)) {
915         widget->setAttribute(Qt::WA_NoSystemBackground, false);
916         widget->clearMask();
917     }
918 
919     if (!widget->isWindow())
920         if (QFrame *frame = qobject_cast<QFrame *>(widget)) {
921             if (qtcCheckKDEType(widget->parent(), KTitleWidget)) {
922                 if(qtcIsCustomBgnd(opts)) {
923                     frame->setAutoFillBackground(true);
924                 } else {
925                     frame->setBackgroundRole(QPalette::Base);
926                 }
927                 QLayout *layout(frame->layout());
928 
929                 if(layout) {
930                     layout->setMargin(6);
931                 }
932             }
933 
934             QComboBox *p = nullptr;
935             if (opts.gtkComboMenus &&
936                 (p = qtcObjCast<QComboBox>(getParent<2>(widget))) &&
937                 !p->isEditable()) {
938                 widget->setPalette(QApplication::palette());
939             }
940         }
941 
942     if (qobject_cast<QMenu*>(widget)) {
943         // TODO remove these
944         widget->setAttribute(Qt::WA_NoSystemBackground, false);
945         widget->clearMask();
946 
947         if (opts.lighterPopupMenuBgnd || opts.shadePopupMenu) {
948             widget->setPalette(QApplication::palette());
949         }
950     }
951 
952     if((!qtcIsFlatBgnd(opts.menuBgndAppearance) || 100!=opts.menuBgndOpacity || !(opts.square&SQUARE_POPUP_MENUS)) &&
953        widget->inherits("QComboBoxPrivateContainer")) {
954         widget->setAttribute(Qt::WA_NoSystemBackground, false);
955         widget->clearMask();
956     }
957 
958     if (widget && (qobject_cast<QMenuBar*>(widget) ||
959                    qobject_cast<QToolBar*>(widget) ||
960                    qobject_cast<QToolBar*>(widget->parent()))) {
961         widget->setBackgroundRole(QPalette::Button);
962     }
963 }
964 
eventFilter(QObject * object,QEvent * event)965 bool Style::eventFilter(QObject *object, QEvent *event)
966 {
967     if (qobject_cast<QMenuBar*>(object) &&
968         dynamic_cast<QMouseEvent*>(event)) {
969         if (updateMenuBarEvent((QMouseEvent*)event, (QMenuBar*)object)) {
970             return true;
971         }
972     }
973 
974     if (event->type() == QEvent::Show &&
975         qobject_cast<QAbstractScrollArea*>(object) &&
976         object->inherits("KFilePlacesView")) {
977         QWidget *view = ((QAbstractScrollArea*)object)->viewport();
978         QPalette palette = view->palette();
979         QColor color = ((QWidget*)object)->palette().background().color();
980 
981         if (qtcIsCustomBgnd(opts))
982             color.setAlphaF(0.0);
983 
984         palette.setColor(view->backgroundRole(), color);
985         view->setPalette(palette);
986         object->removeEventFilter(this);
987     }
988 
989     bool isSViewCont = (APP_KONTACT == theThemedApp &&
990                         m_sViewContainers.contains((QWidget*)object));
991     if ((!opts.gtkScrollViews &&
992          qobject_cast<QAbstractScrollArea*>(object)) || isSViewCont) {
993         QPoint pos;
994         switch (event->type()) {
995         case QEvent::MouseMove:
996         case QEvent::MouseButtonPress:
997         case QEvent::MouseButtonRelease:
998             pos = ((QMouseEvent*)event)->pos();
999             break;
1000         case QEvent::Wheel:
1001             pos=((QWheelEvent*)event)->pos();
1002         default:
1003             break;
1004         }
1005 
1006         if (!pos.isNull()) {
1007             QAbstractScrollArea *area = 0L;
1008             QPoint mapped(pos);
1009 
1010             if (isSViewCont) {
1011                 QSet<QWidget*>::ConstIterator it =
1012                     m_sViewContainers[(QWidget*)object].begin();
1013                 QSet<QWidget*>::ConstIterator end =
1014                     m_sViewContainers[(QWidget*)object].end();
1015 
1016                 for (;it != end && !area;++it) {
1017                     if ((*it)->isVisible()) {
1018                         mapped = (*it)->mapFrom((QWidget*)object, pos);
1019                         if ((*it)->rect().adjusted(0, 0, 4, 4).contains(mapped)) {
1020                             area = (QAbstractScrollArea*)(*it);
1021                         }
1022                     }
1023                 }
1024             } else {
1025                 area = (QAbstractScrollArea*)object;
1026             }
1027 
1028             if (area) {
1029                 QScrollBar *sbars[2] = {
1030                     area->verticalScrollBar(),
1031                     area->horizontalScrollBar()
1032                 };
1033 
1034                 for (int i = 0;i < 2;++i) {
1035                     if (sbars[i]) {
1036                         QRect r(i ? 0 : area->rect().right()-3,
1037                                 i ? area->rect().bottom()-3 : 0,
1038                                 sbars[i]->rect().width(),
1039                                 sbars[i]->rect().height());
1040 
1041                         if (r.contains(pos) ||
1042                             (sbars[i] == m_sViewSBar &&
1043                              (QEvent::MouseMove == event->type() ||
1044                               QEvent::MouseButtonRelease == event->type()))) {
1045                             if (QEvent::Wheel != event->type()) {
1046                                 struct HackEvent : public QMouseEvent {
1047                                     void set(const QPoint &mapped, bool vert)
1048                                         {
1049                                             l = QPointF(vert ? 0 : mapped.x(),
1050                                                         vert ? mapped.y() : 0);
1051                                             s = QPointF(s.x() + (vert ? 0 : -3),
1052                                                         s.y() + (vert ? -3 : 0));
1053                                         }
1054                                 };
1055                                 ((HackEvent*)event)->set(mapped, 0 == i);
1056                             }
1057                             sbars[i]->event(event);
1058                             if (QEvent::MouseButtonPress == event->type()) {
1059                                 m_sViewSBar = sbars[i];
1060                             } else if (QEvent::MouseButtonRelease ==
1061                                        event->type()) {
1062                                 m_sViewSBar = 0L;
1063                             }
1064                             return true;
1065                         }
1066                     }
1067                 }
1068             }
1069         }
1070     }
1071 
1072     switch((int)(event->type())) {
1073     case QEvent::Timer:
1074     case QEvent::Move:
1075         return false; // just for performance - they can occur really often
1076     case QEvent::Resize:
1077         if(!(opts.square & SQUARE_POPUP_MENUS) &&
1078            object->inherits("QComboBoxPrivateContainer")) {
1079             QWidget *widget = static_cast<QWidget*>(object);
1080             if (Utils::hasAlphaChannel(widget)) {
1081                 widget->clearMask();
1082             } else {
1083                 widget->setMask(windowMask(widget->rect(),
1084                                            opts.round > ROUND_SLIGHT));
1085             }
1086             return false;
1087         } else if ((BLEND_TITLEBAR ||
1088                  opts.windowBorder &
1089                  WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR ||
1090                  opts.menubarHiding & HIDE_KWIN) &&
1091                 qobject_cast<QMenuBar*>(object)) {
1092             QResizeEvent *re = static_cast<QResizeEvent*>(event);
1093 
1094             if (re->size().height() != re->oldSize().height()) {
1095                 emitMenuSize((QMenuBar*)object,
1096                              PREVIEW_MDI == m_isPreview ||
1097                              !((QMenuBar*)object)->isVisible() ? 0 :
1098                              re->size().height());
1099             }
1100         }
1101         break;
1102     case QEvent::ShortcutOverride:
1103         if ((opts.menubarHiding || opts.statusbarHiding) &&
1104             qobject_cast<QMainWindow*>(object)) {
1105             QMainWindow *window = static_cast<QMainWindow*>(object);
1106 
1107             if (window->isVisible()) {
1108                 if (opts.menubarHiding & HIDE_KEYBOARD &&
1109                     window->menuWidget()) {
1110                     QKeyEvent *k = static_cast<QKeyEvent*>(event);
1111 
1112                     if (k->modifiers() & Qt::ControlModifier &&
1113                         k->modifiers() & Qt::AltModifier &&
1114                         Qt::Key_M == k->key()) {
1115                         toggleMenuBar(window);
1116                     }
1117                 }
1118                 if (opts.statusbarHiding & HIDE_KEYBOARD) {
1119                     QKeyEvent *k = static_cast<QKeyEvent*>(event);
1120 
1121                     if(k->modifiers()&Qt::ControlModifier && k->modifiers()&Qt::AltModifier && Qt::Key_S==k->key())
1122                         toggleStatusBar(window);
1123                 }
1124             }
1125         }
1126         break;
1127     case QEvent::ShowToParent:
1128         if (qobject_cast<QMenuBar *>(object)) {
1129             if(opts.menubarHiding && m_saveMenuBarStatus && qtcMenuBarHidden(appName))
1130                 static_cast<QMenuBar *>(object)->setHidden(true);
1131 #ifdef Q_OS_MACOS
1132                 if (opts.nonnativeMenubarApps.contains(appName)) {
1133                     QMenuBar *mnb = static_cast<QMenuBar*>(object);
1134                     if (mnb->isNativeMenuBar()) {
1135                         mnb->setNativeMenuBar(false);
1136                         mnb->setHidden(false);
1137                         mnb->setVisible(true);
1138                         if (!opts.currentNonnativeMenubarApps.contains(appName)) {
1139                             opts.currentNonnativeMenubarApps << appName;
1140                         }
1141                     }
1142                 } else if ((QGuiApplication::platformName() == QLatin1String("cocoa"))
1143                         && opts.currentNonnativeMenubarApps.contains(appName)) {
1144                     // only force the native menubar on applications that were forced
1145                     // to use something else before!
1146                     static_cast<QMenuBar*>(object)->setNativeMenuBar(true);
1147                     opts.currentNonnativeMenubarApps.remove(appName);
1148                 }
1149 #endif
1150         }
1151         if(opts.statusbarHiding && m_saveStatusBarStatus && qobject_cast<QStatusBar *>(object) &&
1152            qtcStatusBarHidden(appName))
1153             static_cast<QStatusBar *>(object)->setHidden(true);
1154         break;
1155     case QEvent::PaletteChange: {
1156         QWidget *widget = qtcToWidget(object);
1157 
1158         if (widget && widget->isWindow() &&
1159             (qtcIsDialog(widget) || qtcIsWindow(widget))) {
1160             setBgndProp(widget, opts.bgndAppearance,
1161                         IMG_NONE != opts.bgndImage.type);
1162         }
1163         break;
1164     }
1165     case QEvent::Paint: {
1166         if ((!qtcIsFlatBgnd(opts.menuBgndAppearance) ||
1167              opts.menuBgndImage.type != IMG_NONE ||
1168              opts.menuBgndOpacity != 100 ||
1169              !(opts.square & SQUARE_POPUP_MENUS)) &&
1170             object->inherits("QComboBoxPrivateContainer")) {
1171             QWidget *widget = qtcToWidget(object);
1172             QPainter p(widget);
1173             QRect r(widget->rect());
1174             double radius = opts.round >= ROUND_FULL ? 5.0 : 2.5;
1175             QStyleOption opt;
1176             opt.init(widget);
1177             const QColor *use(popupMenuCols(&opt));
1178 
1179             p.setClipRegion(static_cast<QPaintEvent*>(event)->region());
1180             if (!opts.popupBorder) {
1181                 p.setRenderHint(QPainter::Antialiasing, true);
1182                 p.setPen(use[ORIGINAL_SHADE]);
1183                 p.drawPath(buildPath(r, WIDGET_OTHER, ROUNDED_ALL, radius));
1184                 QPAINTER_RENDERHINT_AA_MAYBE_OFF(&p);
1185             }
1186             if (!(opts.square&SQUARE_POPUP_MENUS))
1187                 p.setClipRegion(windowMask(r, opts.round>ROUND_SLIGHT),
1188                                 Qt::IntersectClip);
1189 
1190             // In case the gradient uses alpha, we need to fill with the background colour - this makes it consistent with Gtk.
1191             if(100==opts.menuBgndOpacity)
1192                 p.fillRect(r, opt.palette.brush(QPalette::Background));
1193             drawBackground(&p, widget, BGND_MENU);
1194             if (opts.popupBorder) {
1195                 EGradientBorder border=qtcGetGradient(opts.menuBgndAppearance, &opts)->border;
1196 
1197                 p.setClipping(false);
1198                 p.setPen(use[QTC_STD_BORDER]);
1199                 // For now dont round combos - getting weird effects with shadow/clipping in Gtk2 style :-(
1200                 if(opts.square&SQUARE_POPUP_MENUS) // || isCombo)
1201                     drawRect(&p, r);
1202                 else
1203                 {
1204                     p.setRenderHint(QPainter::Antialiasing, true);
1205                     p.drawPath(buildPath(r, WIDGET_OTHER, ROUNDED_ALL, radius));
1206                 }
1207 
1208                 if(qtcUseBorder(border) && APPEARANCE_FLAT!=opts.menuBgndAppearance)
1209                 {
1210                     QRect ri(r.adjusted(1, 1, -1, -1));
1211 
1212                     p.setPen(use[0]);
1213                     if(GB_LIGHT==border)
1214                     {
1215                         if(opts.square&SQUARE_POPUP_MENUS) // || isCombo)
1216                             drawRect(&p, ri);
1217                         else
1218                             p.drawPath(buildPath(ri, WIDGET_OTHER, ROUNDED_ALL, radius-1.0));
1219                     }
1220                     else if(opts.square&SQUARE_POPUP_MENUS) // || isCombo)
1221                     {
1222                         if(GB_3D!=border)
1223                         {
1224                             p.drawLine(ri.x(), ri.y(), ri.x()+ri.width()-1,  ri.y());
1225                             p.drawLine(ri.x(), ri.y(), ri.x(), ri.y()+ri.height()-1);
1226                         }
1227                         p.setPen(use[FRAME_DARK_SHADOW]);
1228                         p.drawLine(ri.x(), ri.y()+ri.height()-1, ri.x()+ri.width()-1,  ri.y()+ri.height()-1);
1229                         p.drawLine(ri.x()+ri.width()-1, ri.y(), ri.x()+ri.width()-1,  ri.y()+ri.height()-1);
1230                     }
1231                     else
1232                     {
1233                         QPainterPath tl,
1234                             br;
1235 
1236                         buildSplitPath(ri, ROUNDED_ALL, radius-1.0, tl, br);
1237                         if(GB_3D!=border)
1238                             p.drawPath(tl);
1239                         p.setPen(use[FRAME_DARK_SHADOW]);
1240                         p.drawPath(br);
1241                     }
1242                 }
1243             }
1244         } else if (m_clickedLabel == object &&
1245                    qobject_cast<QLabel*>(object) &&
1246                    ((QLabel*)object)->buddy() &&
1247                    ((QLabel*)object)->buddy()->isEnabled()) {
1248             // paint focus rect
1249             QLabel                *lbl = (QLabel *)object;
1250             QPainter              painter(lbl);
1251             QStyleOptionFocusRect opts;
1252 
1253             opts.palette = lbl->palette();
1254             opts.rect    = QRect(0, 0, lbl->width(), lbl->height());
1255             drawPrimitive(PE_FrameFocusRect, &opts, &painter, lbl);
1256         } else {
1257             QFrame *frame = qobject_cast<QFrame*>(object);
1258 
1259             if (frame)
1260             {
1261                 if(QFrame::HLine==frame->frameShape() || QFrame::VLine==frame->frameShape())
1262                 {
1263                     QPainter painter(frame);
1264                     QRect    r(QFrame::HLine==frame->frameShape()
1265                                ? QRect(frame->rect().x(), frame->rect().y()+ (frame->rect().height()/2), frame->rect().width(), 1)
1266                                : QRect(frame->rect().x()+(frame->rect().width()/2),  frame->rect().y(), 1, frame->rect().height()));
1267 
1268                     drawFadedLine(&painter, r, backgroundColors(frame->palette().window().color())[QTC_STD_BORDER], true, true,
1269                                   QFrame::HLine==frame->frameShape());
1270                     return true;
1271                 }
1272                 else
1273                     return false;
1274             }
1275         }
1276         break;
1277     }
1278     case QEvent::MouseButtonPress:
1279         if(dynamic_cast<QMouseEvent*>(event) && qobject_cast<QLabel*>(object) && ((QLabel *)object)->buddy())
1280         {
1281             QLabel      *lbl = (QLabel *)object;
1282             QMouseEvent *mev = (QMouseEvent *)event;
1283 
1284             if (lbl->rect().contains(mev->pos()))
1285             {
1286                 m_clickedLabel=lbl;
1287                 lbl->repaint();
1288             }
1289         }
1290         break;
1291     case QEvent::MouseButtonRelease:
1292         if(dynamic_cast<QMouseEvent*>(event) && qobject_cast<QLabel*>(object) && ((QLabel *)object)->buddy())
1293         {
1294             QLabel      *lbl = (QLabel *)object;
1295             QMouseEvent *mev = (QMouseEvent *)event;
1296 
1297             if(m_clickedLabel)
1298             {
1299                 m_clickedLabel=0;
1300                 lbl->update();
1301             }
1302 
1303             // set focus to the buddy...
1304             if (lbl->rect().contains(mev->pos()))
1305                 ((QLabel *)object)->buddy()->setFocus(Qt::ShortcutFocusReason);
1306         }
1307         break;
1308     case QEvent::StyleChange:
1309     case QEvent::Show:
1310     {
1311         QProgressBar *bar = qobject_cast<QProgressBar *>(object);
1312 
1313         if(bar)
1314         {
1315             m_progressBars.insert(bar);
1316             if (1==m_progressBars.size())
1317             {
1318                 m_timer.start();
1319                 m_progressBarAnimateTimer = startTimer(1000 / constProgressBarFps);
1320             }
1321         } else if (!(opts.square & SQUARE_POPUP_MENUS) &&
1322                    object->inherits("QComboBoxPrivateContainer")) {
1323             QWidget *widget = static_cast<QWidget*>(object);
1324             if (Utils::hasAlphaChannel(widget)) {
1325                 widget->clearMask();
1326             } else {
1327                 widget->setMask(windowMask(widget->rect(),
1328                                            opts.round > ROUND_SLIGHT));
1329             }
1330             return false;
1331         } else if ((BLEND_TITLEBAR ||
1332                   opts.windowBorder &
1333                   WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR ||
1334                   opts.menubarHiding & HIDE_KWIN) &&
1335                  qobject_cast<QMenuBar*>(object)) {
1336             QMenuBar *mb=(QMenuBar*)object;
1337             emitMenuSize((QMenuBar*)mb, PREVIEW_MDI==m_isPreview ||
1338                          !((QMenuBar *)mb)->isVisible() ? 0 :
1339                          mb->size().height(), true);
1340         } else if (QEvent::Show==event->type()) {
1341             QWidget *widget = qtcToWidget(object);
1342 
1343             if(widget && widget->isWindow() &&
1344                (qtcIsWindow(widget) || qtcIsDialog(widget))) {
1345                 setBgndProp(widget, opts.bgndAppearance,
1346                             IMG_NONE != opts.bgndImage.type);
1347                 int opacity = (qtcIsDialog(widget) ? opts.dlgOpacity :
1348                                opts.bgndOpacity);
1349                 setOpacityProp(widget, (unsigned short)opacity);
1350             }
1351         }
1352         break;
1353     }
1354     case QEvent::Destroy:
1355     case QEvent::Hide: {
1356         if ((BLEND_TITLEBAR ||
1357              opts.windowBorder &
1358              WINDOW_BORDER_USE_MENUBAR_COLOR_FOR_TITLEBAR ||
1359              opts.menubarHiding & HIDE_KWIN) &&
1360            qobject_cast<QMenuBar*>(object)) {
1361             QMenuBar *mb = (QMenuBar*)object;
1362             emitMenuSize((QMenuBar*)mb, 0);
1363         }
1364         // if(m_hoverWidget && object==m_hoverWidget) {
1365         //     // m_pos.setX(-1);
1366         //     // m_pos.setY(-1);
1367         //     m_hoverWidget=0L;
1368         // }
1369 
1370         // The Destroy event is sent from ~QWidget, which happens after ~QProgressBar - therefore, we can't cast to a QProgressBar.
1371         // So we have to check on object.
1372         if (object && !m_progressBars.isEmpty()) {
1373             m_progressBars.remove(reinterpret_cast<QProgressBar*>(object));
1374             if (m_progressBars.isEmpty() && m_progressBarAnimateTimer) {
1375                 killTimer(m_progressBarAnimateTimer);
1376                 m_progressBarAnimateTimer = 0;
1377             }
1378         }
1379         break;
1380     }
1381     case QEvent::Enter:
1382         break;
1383     case QEvent::Leave:
1384         // if(m_hoverWidget && object==m_hoverWidget)
1385         // {
1386         //     // m_pos.setX(-1);
1387         //     // m_pos.setY(-1);
1388         //     m_hoverWidget=0L;
1389         //     ((QWidget *)object)->repaint();
1390         // }
1391         break;
1392     case QEvent::MouseMove:  // Only occurs for widgets with mouse tracking enabled
1393         break;
1394     case QEvent::FocusIn:
1395     case QEvent::FocusOut:
1396         break;
1397     case QEvent::WindowActivate:
1398         if(opts.shadeMenubarOnlyWhenActive && SHADE_NONE!=opts.shadeMenubars && qobject_cast<QMenuBar *>(object))
1399         {
1400             m_active=true;
1401             ((QWidget *)object)->repaint();
1402             return false;
1403         }
1404         break;
1405     case QEvent::WindowDeactivate:
1406         if(opts.shadeMenubarOnlyWhenActive && SHADE_NONE!=opts.shadeMenubars && qobject_cast<QMenuBar *>(object))
1407         {
1408             m_active=false;
1409             ((QWidget *)object)->repaint();
1410             return false;
1411         }
1412         break;
1413     default:
1414         break;
1415     }
1416 
1417     return ParentStyleClass::eventFilter(object, event);
1418 }
1419 
timerEvent(QTimerEvent * event)1420 void Style::timerEvent(QTimerEvent *event)
1421 {
1422     if (event->timerId() == m_progressBarAnimateTimer) {
1423         m_animateStep = m_timer.elapsed() / (1000 / constProgressBarFps);
1424         for (QProgressBar *bar: const_(m_progressBars)) {
1425             if ((opts.animatedProgress && 0 == m_animateStep % 2 &&
1426                  bar->value() != bar->minimum() &&
1427                  bar->value() != bar->maximum()) ||
1428                 (0 == bar->minimum() && 0 == bar->maximum())) {
1429                 bar->update();
1430             }
1431         }
1432     }
1433 
1434     event->ignore();
1435 }
1436 
1437 int
pixelMetric(PixelMetric metric,const QStyleOption * option,const QWidget * widget) const1438 Style::pixelMetric(PixelMetric metric, const QStyleOption *option,
1439                    const QWidget *widget) const
1440 {
1441     prePolish(widget);
1442     switch((unsigned)metric) {
1443     case PM_ToolTipLabelFrameWidth:
1444         if (opts.round != ROUND_NONE && !(opts.square & SQUARE_TOOLTIPS))
1445             return 3;
1446         return ParentStyleClass::pixelMetric(metric, option, widget);
1447     case PM_MdiSubWindowFrameWidth:
1448         return 3;
1449     case PM_DockWidgetTitleMargin:
1450         if (!(opts.dwtSettings & DWT_TEXT_ALIGN_AS_PER_TITLEBAR) ||
1451             opts.titlebarAlignment == ALIGN_LEFT)
1452             return 4;
1453         return 0;
1454     case PM_DockWidgetTitleBarButtonMargin:
1455         return 4;
1456     case PM_DockWidgetFrameWidth:
1457         return 2;
1458     case PM_ToolBarExtensionExtent:
1459         return 15;
1460 #ifndef QTC_QT5_ENABLE_KDE
1461     case PM_SmallIconSize:
1462         return 16;
1463     case PM_ToolBarIconSize:
1464         return 22;
1465     case PM_IconViewIconSize:
1466     case PM_LargeIconSize:
1467         return 32;
1468 #else
1469     case PM_TabCloseIndicatorWidth:
1470     case PM_TabCloseIndicatorHeight:
1471     case PM_SmallIconSize:
1472     case PM_ButtonIconSize:
1473         return KIconLoader::global()->currentSize(KIconLoader::Small);
1474     case PM_ToolBarIconSize:
1475         return KIconLoader::global()->currentSize(KIconLoader::Toolbar);
1476     case PM_IconViewIconSize:
1477     case PM_LargeIconSize:
1478         return KIconLoader::global()->currentSize(KIconLoader::Dialog);
1479     case PM_MessageBoxIconSize:
1480         // TODO return KIconLoader::global()->currentSize(KIconLoader::MessageBox);
1481         return KIconLoader::SizeHuge;
1482 #endif
1483     case PM_SubMenuOverlap:
1484         return -2;
1485     case PM_ScrollView_ScrollBarSpacing:
1486         return opts.etchEntry ? 2 : 3;
1487     case PM_MenuPanelWidth:
1488         return (opts.popupBorder ?
1489                 pixelMetric(PM_DefaultFrameWidth, option, widget) : 0);
1490     case PM_SizeGripSize:
1491         return SIZE_GRIP_SIZE;
1492     case PM_TabBarScrollButtonWidth:
1493         return 18;
1494     case PM_HeaderMargin:
1495         return 3;
1496     case PM_DefaultChildMargin:
1497         return isOOWidget(widget) ? 2 : 6;
1498     case PM_DefaultTopLevelMargin:
1499         return 9;
1500     case PM_LayoutHorizontalSpacing:
1501     case PM_LayoutVerticalSpacing:
1502         return -1; // use layoutSpacing
1503     case PM_DefaultLayoutSpacing:
1504         return 6;
1505     case PM_LayoutLeftMargin:
1506     case PM_LayoutTopMargin:
1507     case PM_LayoutRightMargin:
1508     case PM_LayoutBottomMargin:
1509         return pixelMetric((option && (option->state & State_Window)) ||
1510                            (widget && widget->isWindow()) ?
1511                            PM_DefaultTopLevelMargin : PM_DefaultChildMargin,
1512                            option, widget);
1513     case PM_MenuBarItemSpacing:
1514         return 0;
1515     case PM_ToolBarItemMargin:
1516         return 0;
1517     case PM_ToolBarItemSpacing:
1518         return opts.tbarBtns == TBTN_JOINED ? 0 : 1;
1519     case PM_ToolBarFrameWidth:
1520         // Remove because, in KDE4 at least, if have two locked toolbars
1521         // together then the last/first items are too close
1522         return /* opts.toolbarBorders == TB_NONE ? 0 : */1;
1523     case PM_FocusFrameVMargin:
1524     case PM_FocusFrameHMargin:
1525         return 2;
1526     case PM_MenuBarVMargin:
1527     case PM_MenuBarHMargin:
1528         // Bangarang (media player) has a 4 pixel high menubar at the top -
1529         // when it doesn't actually have a menubar! Seems to be because of
1530         // the return 2 below (which was previously always returned unless
1531         // XBar support and size was 0). So, if we are askes for these metrics
1532         // for a widet whose size<6, then return 0.
1533         return widget && widget->size().height() < 6 ? 0 : 2;
1534     case PM_MenuHMargin:
1535     case PM_MenuVMargin:
1536         return 0;
1537     case PM_MenuButtonIndicator:
1538         return ((opts.buttonEffect != EFFECT_NONE ? 10 : 9) +
1539                 (!widget || qobject_cast<const QToolButton*>(widget) ? 6 : 0));
1540     case PM_ButtonMargin:
1541         return (opts.buttonEffect != EFFECT_NONE ? (opts.thin & THIN_BUTTONS) ?
1542                 4 : 6 : (opts.thin & THIN_BUTTONS) ? 2 : 4) + MAX_ROUND_BTN_PAD;
1543     case PM_TabBarTabShiftVertical:
1544         return 2;
1545     case PM_TabBarTabShiftHorizontal:
1546         return 0;
1547     case PM_ButtonShiftHorizontal:
1548         // return Qt::RightToLeft==QApplication::layoutDirection() ? -1 : 1;
1549     case PM_ButtonShiftVertical:
1550         return (theThemedApp == APP_KDEVELOP && !opts.stdSidebarButtons &&
1551                 widget && isMultiTabBarTab(getButton(widget, 0L)) ? 0 : 1);
1552     case PM_ButtonDefaultIndicator:
1553         return 0;
1554     case PM_DefaultFrameWidth:
1555         if (opts.gtkComboMenus &&
1556             qtcCheckType(widget,"QComboBoxPrivateContainer")) {
1557             return (opts.gtkComboMenus ?
1558                     (opts.borderMenuitems ||
1559                      !(opts.square & SQUARE_POPUP_MENUS) ? 2 : 1) : 0);
1560         }
1561         if ((!opts.gtkScrollViews || (opts.square & SQUARE_SCROLLVIEW)) &&
1562             isKateView(widget))
1563             return (opts.square&SQUARE_SCROLLVIEW) ? 1 : 0;
1564 
1565         if ((opts.square & SQUARE_SCROLLVIEW) && widget && !opts.etchEntry &&
1566             (qobject_cast<const QAbstractScrollArea*>(widget) ||
1567              isKontactPreviewPane(widget)))
1568             return ((opts.gtkScrollViews || opts.thinSbarGroove ||
1569                      !opts.borderSbarGroove) && (!opts.highlightScrollViews) ?
1570                     1 : 2);
1571 
1572         if  (!qtcDrawMenuBorder(opts) && !opts.borderMenuitems &&
1573              opts.square & SQUARE_POPUP_MENUS &&
1574              qobject_cast<const QMenu*>(widget))
1575             return 1;
1576 
1577         if (opts.buttonEffect != EFFECT_NONE && opts.etchEntry &&
1578             (!widget || // !isFormWidget(widget) &&
1579             qobject_cast<const QLineEdit*>(widget) ||
1580              qobject_cast<const QAbstractScrollArea*>(widget)
1581              /*|| isKontactPreviewPane(widget)*/)) {
1582             return 3;
1583         } else {
1584             return 2;
1585         }
1586     case PM_SpinBoxFrameWidth:
1587         return opts.buttonEffect != EFFECT_NONE && opts.etchEntry ? 3 : 2;
1588     case PM_IndicatorWidth:
1589     case PM_IndicatorHeight:
1590     case PM_ExclusiveIndicatorWidth:
1591     case PM_ExclusiveIndicatorHeight:
1592         // TODO??
1593         // case PM_CheckListControllerSize:
1594         // case PM_CheckListButtonSize:
1595         return opts.buttonEffect != EFFECT_NONE ? opts.crSize+2 : opts.crSize;
1596     case PM_TabBarTabOverlap:
1597         return TAB_MO_GLOW==opts.tabMouseOver ? 0 : 1;
1598     case PM_ProgressBarChunkWidth:
1599         return 4;
1600     // case PM_DockWindowHandleExtent:
1601     //     return 10;
1602     case PM_DockWidgetSeparatorExtent:
1603     case PM_SplitterWidth:
1604         return LINE_1DOT==opts.splitters ? 7 : 6;
1605     case PM_ToolBarHandleExtent:
1606         return LINE_1DOT==opts.handles ? 7 : 8;
1607     case PM_ScrollBarSliderMin:
1608         // Leave a minimum of 21 pixels (which is the size used by Oxygen)
1609         // See https://github.com/QtCurve/qtcurve-qt4/issues/7
1610         // and https://bugs.kde.org/show_bug.cgi?id=317690
1611         return qtcMax(opts.sliderWidth, 20) + 1;
1612     case PM_SliderThickness: {
1613         int glowSize = (opts.buttonEffect != EFFECT_NONE &&
1614                         opts.coloredMouseOver == MO_GLOW ? 2 : 0);
1615         if (opts.sliderStyle == SLIDER_CIRCULAR) {
1616             return CIRCULAR_SLIDER_SIZE + 6 + glowSize;
1617         } else if (opts.sliderStyle == SLIDER_TRIANGULAR) {
1618             return 19 + glowSize;
1619         } else {
1620             return (SLIDER_SIZE + glowSize +
1621                     (oneOf(opts.sliderStyle, SLIDER_PLAIN_ROTATED,
1622                            SLIDER_ROUND_ROTATED) ? 11 : 6));
1623         }
1624     }
1625     case PM_SliderControlThickness: {
1626         int glowSize = (opts.buttonEffect != EFFECT_NONE &&
1627                         opts.coloredMouseOver == MO_GLOW ? 2 : 0);
1628         if (opts.sliderStyle == SLIDER_CIRCULAR) {
1629             return CIRCULAR_SLIDER_SIZE + glowSize;
1630         } else if (opts.sliderStyle == SLIDER_TRIANGULAR) {
1631             return 11 + glowSize;
1632         } else {
1633             return (SLIDER_SIZE + glowSize +
1634                     (oneOf(opts.sliderStyle, SLIDER_PLAIN_ROTATED,
1635                            SLIDER_ROUND_ROTATED) ? 6 : -2));
1636         }
1637     }
1638     case PM_SliderTickmarkOffset:
1639         return opts.sliderStyle == SLIDER_TRIANGULAR ? 5 : 4;
1640     case PM_SliderSpaceAvailable:
1641         if (auto slider = styleOptCast<QStyleOptionSlider>(option)) {
1642             int size = pixelMetric(PM_SliderControlThickness, slider, widget);
1643 
1644             if (slider->tickPosition & QSlider::TicksBelow)
1645                 ++size;
1646             if (slider->tickPosition & QSlider::TicksAbove)
1647                 ++size;
1648             return size;
1649         }
1650         return ParentStyleClass::pixelMetric(metric, option, widget);
1651     case PM_SliderLength: {
1652         int glowSize = (opts.buttonEffect != EFFECT_NONE &&
1653                         opts.coloredMouseOver == MO_GLOW ? 2 : 0);
1654         if (opts.sliderStyle == SLIDER_CIRCULAR) {
1655             return CIRCULAR_SLIDER_SIZE + glowSize;
1656         } else if (opts.sliderStyle == SLIDER_TRIANGULAR) {
1657             return 11 + glowSize;
1658         } else {
1659             return (SLIDER_SIZE + glowSize +
1660                     (oneOf(opts.sliderStyle, SLIDER_PLAIN_ROTATED,
1661                            SLIDER_ROUND_ROTATED) ? -2 : 6));
1662         }
1663     }
1664     case PM_ScrollBarExtent:
1665         return opts.sliderWidth;
1666     case PM_MaximumDragDistance:
1667         return -1;
1668     case PM_TabBarTabHSpace:
1669         return 14;
1670     case PM_TabBarTabVSpace:
1671         return opts.highlightTab ? 10 : 8;
1672     case PM_TitleBarHeight:
1673         return qMax(widget ? widget->fontMetrics().lineSpacing() :
1674                     option ? option->fontMetrics.lineSpacing() : 0, 24);
1675     case PM_MenuBarPanelWidth:
1676         return 0;
1677     case QtC_Round:
1678         return (int)((opts.square & SQUARE_WINDOWS && opts.round>ROUND_SLIGHT) ?
1679                      ROUND_SLIGHT : opts.round);
1680     case QtC_WindowBorder:
1681         return opts.windowBorder;
1682     case QtC_CustomBgnd:
1683         return qtcIsCustomBgnd(opts);
1684     case QtC_TitleAlignment:
1685         switch (opts.titlebarAlignment) {
1686         default:
1687         case ALIGN_LEFT:
1688             return Qt::AlignLeft;
1689         case ALIGN_CENTER:
1690             return Qt::AlignHCenter | Qt::AlignVCenter;
1691         case ALIGN_FULL_CENTER:
1692             return Qt::AlignHCenter;
1693         case ALIGN_RIGHT:
1694             return Qt::AlignRight;
1695         }
1696     case QtC_TitleBarButtons:
1697         return opts.titlebarButtons;
1698     case QtC_TitleBarIcon:
1699         return opts.titlebarIcon;
1700     case QtC_TitleBarIconColor:
1701         return titlebarIconColor(option).rgb();
1702     case QtC_TitleBarEffect:
1703         return opts.titlebarEffect;
1704     case QtC_BlendMenuAndTitleBar:
1705         return BLEND_TITLEBAR;
1706     case QtC_ShadeMenubarOnlyWhenActive:
1707         return opts.shadeMenubarOnlyWhenActive;
1708     case QtC_ToggleButtons:
1709         return ((opts.menubarHiding & HIDE_KWIN   ? 0x1 : 0) +
1710                 (opts.statusbarHiding & HIDE_KWIN ? 0x2 : 0));
1711     case QtC_MenubarColor:
1712         return m_menubarCols[ORIGINAL_SHADE].rgb();
1713     case QtC_TitleBarApp:
1714         return (!option || option->state & State_Active ?
1715                 opts.titlebarAppearance : opts.inactiveTitlebarAppearance);
1716         // The following was a somewhat hackyish fix for konqueror's show close
1717         // button on tab setting...... its hackish in the way that I'm assuming
1718         // when KTabBar is positioning the close button and it asks for these
1719         // options, it only passes in a QStyleOption  not a QStyleOptionTab
1720         // Now that KTabBar is deprecated and (KF5) code should use QTabBar instead
1721         // it isn't certain these hacks ought to be preserved.
1722     case PM_TabBarBaseHeight:
1723         if (qtcCheckKDEType(widget, QTabBar) &&
1724             !styleOptCast<QStyleOptionTab>(option)) {
1725             return 10;
1726         }
1727         return ParentStyleClass::pixelMetric(metric, option, widget);
1728     case PM_TabBarBaseOverlap:
1729         if (qtcCheckKDEType(widget, QTabBar) &&
1730             !styleOptCast<QStyleOptionTab>(option)) {
1731             return 0;
1732         }
1733         // Fall through!
1734     default:
1735         return ParentStyleClass::pixelMetric(metric, option, widget);
1736     }
1737 }
1738 
1739 int
styleHint(StyleHint hint,const QStyleOption * option,const QWidget * widget,QStyleHintReturn * returnData) const1740 Style::styleHint(StyleHint hint, const QStyleOption *option,
1741                  const QWidget *widget, QStyleHintReturn *returnData) const
1742 {
1743     prePolish(widget);
1744     switch (hint) {
1745     case SH_ToolTip_Mask:
1746     case SH_Menu_Mask:
1747         if ((SH_ToolTip_Mask == hint && (opts.square & SQUARE_TOOLTIPS)) ||
1748             (SH_Menu_Mask == hint && (opts.square & SQUARE_POPUP_MENUS))) {
1749             return ParentStyleClass::styleHint(hint, option, widget, returnData);
1750         } else {
1751             if (!Utils::hasAlphaChannel(widget) &&
1752                 (!widget || widget->isWindow())) {
1753                 if (auto mask =
1754                     styleOptCast<QStyleHintReturnMask>(returnData)) {
1755                     mask->region = windowMask(option->rect,
1756                                               opts.round > ROUND_SLIGHT);
1757                 }
1758             }
1759             return true;
1760         }
1761     case SH_ComboBox_ListMouseTracking:
1762     case SH_PrintDialog_RightAlignButtons:
1763     case SH_ItemView_ArrowKeysNavigateIntoChildren:
1764     case SH_ToolBox_SelectedPageTitleBold:
1765     case SH_ScrollBar_MiddleClickAbsolutePosition:
1766     case SH_SpinControls_DisableOnBounds:
1767     case SH_Slider_SnapToValue:
1768     case SH_FontDialog_SelectAssociatedText:
1769     case SH_Menu_MouseTracking:
1770         return true;
1771     case SH_UnderlineShortcut:
1772         return ((widget && opts.hideShortcutUnderline) ?
1773                 m_shortcutHandler->showShortcut(widget) : true);
1774     case SH_GroupBox_TextLabelVerticalAlignment:
1775         if (auto frame = styleOptCast<QStyleOptionGroupBox>(option)) {
1776             if (frame->features & QStyleOptionFrame::Flat) {
1777                 return Qt::AlignVCenter;
1778             }
1779         }
1780         if (opts.gbLabel & GB_LBL_INSIDE) {
1781             return Qt::AlignBottom;
1782         } else if (opts.gbLabel & GB_LBL_OUTSIDE) {
1783             return Qt::AlignTop;
1784         } else {
1785             return Qt::AlignVCenter;
1786         }
1787     case SH_MessageBox_CenterButtons:
1788     case SH_ProgressDialog_CenterCancelButton:
1789     case SH_DitherDisabledText:
1790     case SH_EtchDisabledText:
1791     case SH_Menu_AllowActiveAndDisabled:
1792     case SH_ItemView_ShowDecorationSelected:
1793         // Controls whether the highlighting of listview/treeview
1794         // items highlights whole line.
1795     case SH_MenuBar_AltKeyNavigation:
1796         return false;
1797     case SH_ItemView_ChangeHighlightOnFocus:
1798         // gray out selected items when losing focus.
1799         return false;
1800     case SH_WizardStyle:
1801         return QWizard::ClassicStyle;
1802     case SH_RubberBand_Mask: {
1803         auto opt = styleOptCast<QStyleOptionRubberBand>(option);
1804         if (!opt) {
1805             return true;
1806         }
1807         if (auto mask = styleOptCast<QStyleHintReturnMask>(returnData)) {
1808             mask->region = option->rect;
1809             mask->region -= option->rect.adjusted(1,1,-1,-1);
1810         }
1811         return true;
1812     }
1813     case SH_Menu_SubMenuPopupDelay:
1814         return opts.menuDelay;
1815 #if QT_VERSION >= QT_VERSION_CHECK(5,5,0)
1816     case SH_Menu_SloppySubMenus:
1817         return opts.menuCloseDelay > 0;
1818     case SH_Menu_SubMenuSloppyCloseTimeout:
1819         return opts.menuCloseDelay;
1820 #endif
1821     case SH_ToolButton_PopupDelay:
1822         return 250;
1823     case SH_ComboBox_PopupFrameStyle:
1824         return opts.popupBorder || !(opts.square&SQUARE_POPUP_MENUS) ? QFrame::StyledPanel|QFrame::Plain : QFrame::NoFrame;
1825     case SH_TabBar_Alignment:
1826         return Qt::AlignLeft;
1827     case SH_Header_ArrowAlignment:
1828         return Qt::AlignLeft;
1829     case SH_WindowFrame_Mask:
1830         if (auto mask = styleOptCast<QStyleHintReturnMask>(returnData)) {
1831             const QRect &r = option->rect;
1832             switch ((opts.square & SQUARE_WINDOWS &&
1833                      opts.round > ROUND_SLIGHT) ? ROUND_SLIGHT : opts.round) {
1834             case ROUND_NONE:
1835                 mask->region = r;
1836                 break;
1837             case ROUND_SLIGHT:
1838                 mask->region = QRegion(r.x() + 1, r.y(),
1839                                        r.width() - 2, r.height());
1840                 mask->region += QRegion(r.x() + 0, r.y() + 1,
1841                                         1, r.height() - 2);
1842                 mask->region += QRegion(r.x() + r.width() - 1, r.y() + 1,
1843                                         1, r.height() - 2);
1844                 break;
1845             default: // ROUND_FULL
1846                 mask->region = QRegion(r.x() + 5, r.y(),
1847                                        r.width() - 10, r.height());
1848                 mask->region += QRegion(r.x() + 0, r.y() + 5,
1849                                         1, r.height() - 5);
1850                 mask->region += QRegion(r.x() + 1, r.y() + 3,
1851                                         1, r.height() - 2);
1852                 mask->region += QRegion(r.x() + 2, r.y() + 2,
1853                                         1, r.height() - 1);
1854                 mask->region += QRegion(r.x() + 3, r.y() + 1,
1855                                         2, r.height());
1856                 mask->region += QRegion(r.x() + r.width() - 1, r.y() + 5,
1857                                         1, r.height() - 5);
1858                 mask->region += QRegion(r.x() + r.width() - 2, r.y() + 3,
1859                                         1, r.height() - 2);
1860                 mask->region += QRegion(r.x() + r.width() - 3, r.y() + 2,
1861                                         1, r.height() - 1);
1862                 mask->region += QRegion(r.x() + r.width() - 5, r.y() + 1,
1863                                         2, r.height() - 0);
1864             }
1865         }
1866         return 1;
1867     case SH_TitleBar_NoBorder:
1868     case SH_TitleBar_AutoRaise:
1869         return 1;
1870     case SH_MainWindow_SpaceBelowMenuBar:
1871         return 0;
1872     case SH_DialogButtonLayout:
1873         if (opts.gtkButtonOrder)
1874             return QDialogButtonBox::GnomeLayout;
1875         return QDialogButtonBox::KdeLayout;
1876     case SH_MessageBox_TextInteractionFlags:
1877         return Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse;
1878     case SH_LineEdit_PasswordCharacter:
1879         if (opts.passwordChar) {
1880             int chars[4] = {opts.passwordChar, 0x25CF, 0x2022, 0};
1881             const QFontMetrics &fm(option ? option->fontMetrics :
1882                                    (widget ? widget->fontMetrics() :
1883                                     QFontMetrics(QFont())));
1884             for (int i = 0;chars[i];i++) {
1885                 if (fm.inFont(QChar(chars[i]))) {
1886                     return chars[i];
1887                 }
1888             }
1889             return '*';
1890         } else {
1891             return '\0';
1892         }
1893     case SH_MenuBar_MouseTracking:
1894         // Always return 1, as setting to 0 dissables the effect when
1895         // a menu is shown.
1896         return 1; // opts.menubarMouseOver ? 1 : 0;
1897     case SH_ScrollView_FrameOnlyAroundContents:
1898         return (widget && widget->isWindow() ? false :
1899                 opts.gtkScrollViews &&
1900                 !qtcCheckType(widget, "QComboBoxListView"));
1901     case SH_ComboBox_Popup:
1902         if (opts.gtkComboMenus) {
1903             if (auto cmb = styleOptCast<QStyleOptionComboBox>(option)) {
1904                 return !cmb->editable;
1905             }
1906         }
1907         return 0;
1908     case SH_FormLayoutFormAlignment:
1909         // KDE4 HIG, align the contents in a form layout to the left
1910         return Qt::AlignLeft | Qt::AlignTop;
1911     case SH_FormLayoutLabelAlignment:
1912         // KDE4  HIG, align the labels in a form layout to the right
1913         return Qt::AlignRight;
1914     case SH_FormLayoutFieldGrowthPolicy:
1915         return QFormLayout::ExpandingFieldsGrow;
1916     case SH_FormLayoutWrapPolicy:
1917         return QFormLayout::DontWrapRows;
1918 #ifdef QTC_QT5_ENABLE_KDE
1919     case SH_DialogButtonBox_ButtonsHaveIcons:{
1920         KConfigGroup cg(m_kdeGlobals, "KDE");
1921         return cg.readEntry("ShowIconsOnPushButtons", false);
1922     }
1923     case SH_ItemView_ActivateItemOnSingleClick:{
1924         KConfigGroup cg(m_kdeGlobals, "KDE");
1925         return cg.readEntry("SingleClick", false);
1926     }
1927 #endif
1928     case SH_Widget_Animate:
1929         return false;
1930     case SH_Menu_SupportsSections:
1931         return true;
1932     default:
1933 #ifdef QTC_QT5_ENABLE_KDE
1934         // Tell the calling app that we can handle certain custom widgets...
1935         if (hint >= SH_CustomBase && widget) {
1936             if (widget->objectName() == "CE_CapacityBar") {
1937                 if (opts.boldProgress) {
1938                     setBold(const_cast<QWidget*>(widget));
1939                 }
1940                 return CE_QtC_KCapacityBar;
1941             }
1942         }
1943 #endif
1944         return ParentStyleClass::styleHint(hint, option, widget, returnData);
1945     }
1946 }
1947 
standardPalette() const1948 QPalette Style::standardPalette() const
1949 {
1950     return ParentStyleClass::standardPalette();
1951 }
1952 
initFontTickData(Options & opts,QFont font,const QWidget * widget=0)1953 static bool initFontTickData(Options &opts, QFont font, const QWidget *widget=0)
1954 {
1955     if (opts.onlyTicksInMenu && opts.fontTickWidth <= 0) {
1956         opts.tickFont = font;
1957 #ifndef Q_OS_MACOS
1958         opts.tickFont.setBold(true);
1959 #else
1960         opts.tickFont.setFamily(QStringLiteral("Apple Symbols"));
1961         opts.tickFont.setBold(false);
1962 #endif
1963         // adjust the size so the tickmark looks just about right
1964         opts.tickFont.setPointSizeF(opts.tickFont.pointSizeF() * 1.3);
1965         opts.fontTickWidth = QFontMetrics(opts.tickFont).width(opts.menuTick);
1966         // qDebug() << widget << "font->tickFont:" << font.toString() << opts.tickFont.toString() << "tickMark:" << opts.menuTick
1967         //    << "width=" << opts.fontTickWidth << "/" << QFontMetrics(opts.tickFont).boundingRect(opts.menuTick).width();
1968         return true;
1969     }
1970     return false;
1971 }
1972 
menuTickCompensation(const Options & opts,int refWidth,int & dx)1973 static bool menuTickCompensation(const Options &opts, int refWidth, int &dx)
1974 {
1975     if (opts.onlyTicksInMenu && opts.fontTickWidth > refWidth) {
1976         dx = opts.fontTickWidth - refWidth;
1977         return true;
1978     }
1979     return false;
1980 }
1981 
1982 void
drawPrimitive(PrimitiveElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const1983 Style::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
1984                      QPainter *painter, const QWidget *widget) const
1985 {
1986     prePolish(widget);
1987     bool (Style::*drawFunc)(PrimitiveElement, const QStyleOption*,
1988                             QPainter*, const QWidget*) const = nullptr;
1989     switch ((unsigned)element) {
1990     case PE_IndicatorTabClose:
1991         drawFunc = &Style::drawPrimitiveIndicatorTabClose;
1992         break;
1993     case PE_Widget:
1994         drawFunc = &Style::drawPrimitiveWidget;
1995         break;
1996     case PE_PanelScrollAreaCorner:
1997         drawFunc = &Style::drawPrimitivePanelScrollAreaCorner;
1998         break;
1999     case PE_IndicatorBranch:
2000         drawFunc = &Style::drawPrimitiveIndicatorBranch;
2001         break;
2002     case PE_IndicatorViewItemCheck:
2003         drawFunc = &Style::drawPrimitiveIndicatorViewItemCheck;
2004         break;
2005     case PE_IndicatorHeaderArrow:
2006         drawFunc = &Style::drawPrimitiveIndicatorHeaderArrow;
2007         break;
2008     case PE_IndicatorArrowUp:
2009     case PE_IndicatorArrowDown:
2010     case PE_IndicatorArrowLeft:
2011     case PE_IndicatorArrowRight:
2012         drawFunc = &Style::drawPrimitiveIndicatorArrow;
2013         break;
2014     case PE_IndicatorSpinMinus:
2015     case PE_IndicatorSpinPlus:
2016     case PE_IndicatorSpinUp:
2017     case PE_IndicatorSpinDown:
2018         drawFunc = &Style::drawPrimitiveIndicatorSpin;
2019         break;
2020     case PE_IndicatorToolBarSeparator:
2021         drawFunc = &Style::drawPrimitiveIndicatorToolBarSeparator;
2022         break;
2023     case PE_FrameGroupBox:
2024         drawFunc = &Style::drawPrimitiveFrameGroupBox;
2025         break;
2026     case PE_Frame:
2027         drawFunc = &Style::drawPrimitiveFrame;
2028         break;
2029     case PE_PanelMenuBar:
2030         drawFunc = &Style::drawPrimitivePanelMenuBar;
2031         break;
2032     case PE_FrameTabBarBase:
2033         drawFunc = &Style::drawPrimitiveFrameTabBarBase;
2034         break;
2035     case PE_FrameStatusBar:
2036     case PE_FrameMenu:
2037         if (widget) {
2038             initFontTickData(opts, widget->font(), widget);
2039         }
2040         drawFunc = &Style::drawPrimitiveFrameStatusBarOrMenu;
2041         break;
2042     case PE_FrameDockWidget:
2043         drawFunc = &Style::drawPrimitiveFrameDockWidget;
2044         break;
2045     case PE_FrameButtonTool:
2046     case PE_PanelButtonTool:
2047     case PE_IndicatorButtonDropDown:
2048         drawFunc = &Style::drawPrimitiveButtonTool;
2049         break;
2050     case PE_IndicatorDockWidgetResizeHandle:
2051         drawFunc = &Style::drawPrimitiveIndicatorDockWidgetResizeHandle;
2052         break;
2053     case PE_PanelLineEdit:
2054         drawFunc = &Style::drawPrimitivePanelLineEdit;
2055         break;
2056     case PE_FrameLineEdit:
2057         drawFunc = &Style::drawPrimitiveFrameLineEdit;
2058         break;
2059     case PE_IndicatorMenuCheckMark:
2060     case PE_IndicatorCheckBox:
2061         drawFunc = &Style::drawPrimitiveIndicatorCheckBox;
2062         break;
2063     case PE_IndicatorRadioButton:
2064         drawFunc = &Style::drawPrimitiveIndicatorRadioButton;
2065         break;
2066     case PE_IndicatorToolBarHandle:
2067         drawFunc = &Style::drawPrimitiveIndicatorToolBarHandle;
2068         break;
2069     case PE_FrameFocusRect:
2070         drawFunc = &Style::drawPrimitiveFrameFocusRect;
2071         break;
2072     case PE_FrameButtonBevel:
2073     case PE_PanelButtonBevel:
2074     case PE_PanelButtonCommand:
2075         drawFunc = &Style::drawPrimitiveButton;
2076         break;
2077     case PE_FrameDefaultButton:
2078         drawFunc = &Style::drawPrimitiveNone;
2079         break;
2080     case PE_FrameWindow:
2081         drawFunc = &Style::drawPrimitiveFrameWindow;
2082         break;
2083     case PE_FrameTabWidget:
2084         drawFunc = &Style::drawPrimitiveFrameTabWidget;
2085         break;
2086     case PE_PanelItemViewItem:
2087         drawFunc = &Style::drawPrimitivePanelItemViewItem;
2088         break;
2089     case QtC_PE_DrawBackground:
2090         drawFunc = &Style::drawPrimitiveQtcBackground;
2091         break;
2092     case PE_PanelTipLabel:
2093         drawFunc = &Style::drawPrimitivePanelTipLabel;
2094         break;
2095     case PE_PanelMenu:
2096         if (widget) {
2097             initFontTickData(opts, widget->font(), widget);
2098         }
2099         drawFunc = &Style::drawPrimitivePanelMenu;
2100         break;
2101     default:
2102         break;
2103     }
2104     painter->save();
2105     if (!drawFunc ||
2106         qtcUnlikely(!(this->*drawFunc)(element, option, painter, widget))) {
2107         ParentStyleClass::drawPrimitive(element, option, painter, widget);
2108     }
2109     painter->restore();
2110 }
2111 
2112 void
drawControl(ControlElement element,const QStyleOption * option,QPainter * painter,const QWidget * widget) const2113 Style::drawControl(ControlElement element, const QStyleOption *option,
2114                    QPainter *painter, const QWidget *widget) const
2115 {
2116     prePolish(widget);
2117     QRect r = option->rect;
2118     const State &state = option->state;
2119     const QPalette &palette = option->palette;
2120     bool reverse = option->direction == Qt::RightToLeft;
2121 
2122     switch ((unsigned)element) {
2123     case CE_QtC_SetOptions:
2124         if (auto preview = styleOptCast<PreviewOption>(option)) {
2125             if (!painter && widget &&
2126                 widget->objectName() == QLatin1String("QtCurveConfigDialog")) {
2127                 Style *that = (Style*)this;
2128                 opts = preview->opts;
2129                 qtcCheckConfig(&opts);
2130                 that->init(true);
2131             }
2132         }
2133         break;
2134     case CE_QtC_Preview:
2135         if (auto preview = styleOptCast<PreviewOption>(option)) {
2136             if (widget &&
2137                 widget->objectName() ==
2138                 QLatin1String("QtCurveConfigDialog-GradientPreview")) {
2139                 Options old = opts;
2140                 const QColor *use(buttonColors(option));
2141                 opts = preview->opts;
2142 
2143                 drawLightBevelReal(painter, r, option, widget, ROUNDED_ALL,
2144                                    getFill(option, use, false, false), use,
2145                                    true, WIDGET_STD_BUTTON, false, opts.round,
2146                                    false);
2147                 opts = old;
2148             }
2149         }
2150         break;
2151     case CE_QtC_KCapacityBar:
2152         if (auto bar = styleOptCast<QStyleOptionProgressBar>(option)) {
2153             QStyleOptionProgressBar mod = *bar;
2154 
2155             if (mod.rect.height() > 16 &&
2156                 (qtcCheckType<QStatusBar>(widget->parentWidget()) ||
2157                  qtcCheckType(widget->parentWidget(), "DolphinStatusBar"))) {
2158                 int m = (mod.rect.height() - 16) / 2;
2159                 mod.rect.adjust(0, m, 0, -m);
2160             }
2161             drawControl(CE_ProgressBarGroove, &mod, painter, widget);
2162             if (opts.buttonEffect != EFFECT_NONE && opts.borderProgress)
2163                 mod.rect.adjust(1, 1, -1, -1);
2164             drawControl(CE_ProgressBarContents, &mod, painter, widget);
2165             drawControl(CE_ProgressBarLabel, &mod, painter, widget);
2166         }
2167         break;
2168     case CE_ToolBoxTabShape: {
2169         auto tb = styleOptCast<QStyleOptionToolBox>(option);
2170         if (!(tb && widget))
2171             break;
2172         const QColor *use =
2173             backgroundColors(widget->palette().color(QPalette::Window));
2174         QPainterPath path;
2175         int y = r.height() * 15 / 100;
2176 
2177         painter->save();
2178         if (reverse) {
2179             path.moveTo(r.left() + 52, r.top());
2180             path.cubicTo(QPointF(r.left() + 50 - 8, r.top()),
2181                          QPointF(r.left() + 50 - 10, r.top() + y),
2182                          QPointF(r.left() + 50 - 10, r.top() + y));
2183             path.lineTo(r.left() + 18 + 9, r.bottom() - y);
2184             path.cubicTo(QPointF(r.left() + 18 + 9, r.bottom() - y),
2185                          QPointF(r.left() + 19 + 6, r.bottom() - 1 - 0.3),
2186                          QPointF(r.left() + 19, r.bottom() - 1 - 0.3));
2187         } else {
2188             path.moveTo(r.right() - 52, r.top());
2189             path.cubicTo(QPointF(r.right() - 50 + 8, r.top()),
2190                          QPointF(r.right() - 50 + 10, r.top() + y),
2191                          QPointF(r.right() - 50 + 10, r.top() + y));
2192             path.lineTo(r.right() - 18 - 9, r.bottom() - y);
2193             path.cubicTo(QPointF(r.right() - 18 - 9, r.bottom() - y),
2194                          QPointF(r.right() - 19 - 6, r.bottom() - 1 - 0.3),
2195                          QPointF(r.right() - 19, r.bottom() - 1 - 0.3));
2196         }
2197 
2198         painter->setRenderHint(QPainter::Antialiasing, true);
2199         painter->translate(0, 1);
2200         painter->setPen(use[0]);
2201         painter->drawPath(path);
2202         painter->translate(0, -1);
2203         painter->setPen(use[4]);
2204         painter->drawPath(path);
2205         QPAINTER_RENDERHINT_AA_MAYBE_OFF(painter);
2206         if (reverse) {
2207             painter->drawLine(r.left() + 50 - 1, r.top(), r.right(), r.top());
2208             painter->drawLine(r.left() + 20, r.bottom() - 2,
2209                               r.left(), r.bottom() - 2);
2210             painter->setPen(use[0]);
2211             painter->drawLine(r.left() + 50, r.top() + 1,
2212                               r.right(), r.top() + 1);
2213             painter->drawLine(r.left() + 20, r.bottom() - 1,
2214                               r.left(), r.bottom() - 1);
2215         } else {
2216             painter->drawLine(r.left(), r.top(), r.right() - 50 + 1, r.top());
2217             painter->drawLine(r.right() - 20, r.bottom() - 2,
2218                               r.right(), r.bottom() - 2);
2219             painter->setPen(use[0]);
2220             painter->drawLine(r.left(), r.top() + 1,
2221                               r.right() - 50, r.top() + 1);
2222             painter->drawLine(r.right() - 20, r.bottom() - 1,
2223                               r.right(), r.bottom() - 1);
2224         }
2225         painter->restore();
2226         break;
2227     }
2228     case CE_MenuScroller: {
2229         const QColor *use = popupMenuCols();
2230         painter->fillRect(r, use[ORIGINAL_SHADE]);
2231         painter->setPen(use[QTC_STD_BORDER]);
2232         drawRect(painter, r);
2233         drawPrimitive(((state & State_DownArrow) ? PE_IndicatorArrowDown :
2234                        PE_IndicatorArrowUp), option, painter, widget);
2235         break;
2236     }
2237     case CE_RubberBand: {
2238         // Rubber band used in such things as iconview.
2239         if (r.width() > 0 && r.height() > 0) {
2240             painter->save();
2241             QColor c(m_highlightCols[ORIGINAL_SHADE]);
2242 
2243             painter->setClipRegion(r);
2244             painter->setPen(c);
2245             c.setAlpha(50);
2246             painter->setBrush(c);
2247             drawRect(painter, r);
2248             painter->restore();
2249         }
2250         break;
2251     }
2252     case CE_Splitter: {
2253         const QColor *use = buttonColors(option);
2254         const QColor *border = borderColors(option, use);
2255         // In Amarok nightly (2.2) State_Horizontal doesn't
2256         // seem to always be set...
2257         bool horiz = (state & State_Horizontal ||
2258                       (r.height() > 6 && r.height() > r.width()));
2259 
2260         painter->save();
2261         if (/*qtcIsFlatBgnd(opts.bgndAppearance) || */
2262             state & State_MouseOver && state & State_Enabled) {
2263             QColor color(palette.color(QPalette::Active, QPalette::Window));
2264 
2265             if (state & State_MouseOver && state & State_Enabled &&
2266                 opts.splitterHighlight) {
2267                 if (ROUND_NONE != opts.round) {
2268                     painter->save();
2269                     painter->setRenderHint(QPainter::Antialiasing, true);
2270                     double radius =
2271                         qtcGetRadius(&opts, r.width(), r.height(),
2272                                      WIDGET_OTHER, RADIUS_SELECTION);
2273 
2274                     drawBevelGradient(shade(palette.background().color(),
2275                                             TO_FACTOR(opts.splitterHighlight)),
2276                                       painter, r,
2277                                       buildPath(QRectF(r), WIDGET_OTHER,
2278                                                 ROUNDED_ALL, radius),
2279                                       !(state & State_Horizontal), false,
2280                                       opts.selectionAppearance,
2281                                       WIDGET_SELECTION, false);
2282                     painter->restore();
2283                 } else {
2284                     drawBevelGradient(shade(palette.background().color(),
2285                                             TO_FACTOR(opts.splitterHighlight)),
2286                                       painter, r, !(state & State_Horizontal),
2287                                       false, opts.selectionAppearance,
2288                                       WIDGET_SELECTION);
2289                 }
2290             } else {
2291                 painter->fillRect(r, color);
2292             }
2293         }
2294 
2295         switch (opts.splitters) {
2296         case LINE_NONE:
2297             break;
2298         case LINE_1DOT:
2299             painter->drawPixmap(r.x() + ((r.width() - 5) / 2),
2300                                 r.y() + ((r.height() - 5) / 2),
2301                                 *getPixmap(border[QTC_STD_BORDER],
2302                                            PIX_DOT, 1.0));
2303             break;
2304         default:
2305         case LINE_DOTS:
2306             drawDots(painter, r, horiz, NUM_SPLITTER_DASHES, 1, border, 0, 5);
2307             break;
2308         case LINE_FLAT:
2309         case LINE_SUNKEN:
2310         case LINE_DASHES:
2311             drawLines(painter, r, horiz, NUM_SPLITTER_DASHES, 3,
2312                       border, 0, 3, opts.splitters);
2313         }
2314         painter->restore();
2315         break;
2316     }
2317     case CE_SizeGrip: {
2318         QPolygon triangle(3);
2319         Qt::Corner corner;
2320         int size = SIZE_GRIP_SIZE - 2;
2321 
2322         if (auto sgrp = styleOptCast<QStyleOptionSizeGrip>(option)) {
2323             corner = sgrp->corner;
2324         } else if (option->direction == Qt::RightToLeft) {
2325             corner = Qt::BottomLeftCorner;
2326         } else {
2327             corner = Qt::BottomRightCorner;
2328         }
2329 
2330         switch (corner) {
2331         case Qt::BottomLeftCorner:
2332             triangle.putPoints(0, 3, 0, 0, size, size, 0, size);
2333             triangle.translate(r.x(), r.y() + (r.height() -
2334                                                (SIZE_GRIP_SIZE - 1)));
2335             break;
2336         case Qt::BottomRightCorner:
2337             triangle.putPoints(0, 3, size, 0, size, size, 0, size);
2338             triangle.translate(r.x() + (r.width() - (SIZE_GRIP_SIZE - 1)),
2339                                r.y() + (r.height() - (SIZE_GRIP_SIZE - 1)));
2340             break;
2341         case Qt::TopRightCorner:
2342             triangle.putPoints(0, 3, 0, 0, size, 0, size, size);
2343             triangle.translate(r.x() + (r.width() - (SIZE_GRIP_SIZE - 1)),
2344                                r.y());
2345             break;
2346         case Qt::TopLeftCorner:
2347             triangle.putPoints(0, 3, 0, 0, size, 0, 0, size);
2348             triangle.translate(r.x(), r.y());
2349         }
2350         painter->save();
2351         painter->setPen(m_backgroundCols[2]);
2352         painter->setBrush(m_backgroundCols[2]);
2353         painter->drawPolygon(triangle);
2354         painter->restore();
2355         break;
2356     }
2357     case CE_ToolBar:
2358         if (auto toolbar = styleOptCast<QStyleOptionToolBar>(option)) {
2359             if (!widget || !widget->parent() ||
2360                 qobject_cast<QMainWindow*>(widget->parent())) {
2361                 painter->save();
2362                 drawMenuOrToolBarBackground(
2363                     widget, painter, r, option, false,
2364                     oneOf(toolbar->toolBarArea, Qt::NoToolBarArea,
2365                           Qt::BottomToolBarArea, Qt::TopToolBarArea));
2366                 if (opts.toolbarBorders != TB_NONE) {
2367                     const QColor *use = backgroundColors(option);
2368                     bool dark = oneOf(opts.toolbarBorders,
2369                                       TB_DARK, TB_DARK_ALL);
2370 
2371                     if (oneOf(opts.toolbarBorders, TB_DARK_ALL, TB_LIGHT_ALL)) {
2372                         painter->setPen(use[0]);
2373                         painter->drawLine(r.x(), r.y(),
2374                                           r.x() + r.width() - 1, r.y());
2375                         painter->drawLine(r.x(), r.y(),
2376                                           r.x(), r.y() + r.height() - 1);
2377                         painter->setPen(use[dark ? 3 : 4]);
2378                         painter->drawLine(r.x(), r.y() + r.height() - 1,
2379                                           r.x() + r.width() - 1,
2380                                           r.y() + r.height() - 1);
2381                         painter->drawLine(r.x() + r.width() - 1, r.y(),
2382                                           r.x() + r.width() - 1,
2383                                           r.y() + r.height() - 1);
2384                     } else {
2385                         bool paintH = true;
2386                         bool paintV = true;
2387 
2388                         switch (toolbar->toolBarArea) {
2389                         case Qt::BottomToolBarArea:
2390                         case Qt::TopToolBarArea:
2391                             paintV = false;
2392                             break;
2393                         case Qt::RightToolBarArea:
2394                         case Qt::LeftToolBarArea:
2395                             paintH = false;
2396                         default:
2397                             break;
2398                         }
2399 
2400                         painter->setPen(use[0]);
2401                         if (paintH) {
2402                             painter->drawLine(r.x(), r.y(),
2403                                               r.x() + r.width() - 1, r.y());
2404                         }
2405                         if (paintV) {
2406                             painter->drawLine(r.x(), r.y(), r.x(),
2407                                               r.y() + r.height()-1);
2408                         }
2409                         painter->setPen(use[dark ? 3 : 4]);
2410                         if (paintH) {
2411                             painter->drawLine(r.x(), r.y() + r.height() - 1,
2412                                               r.x() + r.width() - 1,
2413                                               r.y() + r.height() - 1);
2414                         }
2415                         if (paintV) {
2416                             painter->drawLine(r.x() + r.width() - 1,
2417                                               r.y(), r.x() + r.width() - 1,
2418                                               r.y() + r.height() - 1);
2419                         }
2420                     }
2421                 }
2422                 painter->restore();
2423             }
2424         }
2425         break;
2426     case CE_DockWidgetTitle:
2427         if (auto dwOpt = styleOptCast<QStyleOptionDockWidget>(option)) {
2428             bool verticalTitleBar = dwOpt->verticalTitleBar;
2429             bool isKOffice = qtcCheckType(widget, "KoDockWidgetTitleBar");
2430             QRect fillRect = r;
2431 
2432             // This fixes the look of KOffice's dock widget titlebars...
2433             if (isKOffice)
2434                 fillRect.adjust(-r.x(), -r.y(), 0, 0);
2435 
2436             if (!qtcIsFlat(opts.dwtAppearance)) {
2437                 painter->save();
2438 
2439                 QColor col((opts.dwtSettings & DWT_COLOR_AS_PER_TITLEBAR) ?
2440                            getMdiColors(option,
2441                                         state&State_Active)[ORIGINAL_SHADE] :
2442                            palette.background().color());
2443                 if (opts.round < ROUND_FULL) {
2444                     drawBevelGradient(col, painter, fillRect, !verticalTitleBar,
2445                                       false, opts.dwtAppearance,
2446                                       WIDGET_DOCK_WIDGET_TITLE);
2447                 } else {
2448                     double radius = qtcGetRadius(&opts, fillRect.width(),
2449                                                  fillRect.height(),
2450                                                  WIDGET_OTHER, RADIUS_EXTERNAL);
2451                     int round = ROUNDED_ALL;
2452 
2453                     if (opts.dwtSettings & DWT_ROUND_TOP_ONLY) {
2454                         round = verticalTitleBar ? ROUNDED_LEFT : ROUNDED_TOP;
2455                     }
2456                     painter->setRenderHint(QPainter::Antialiasing, true);
2457                     drawBevelGradient(col, painter, fillRect,
2458                                       buildPath(QRectF(fillRect), WIDGET_OTHER,
2459                                                 round, radius),
2460                                       !verticalTitleBar, false,
2461                                       opts.dwtAppearance,
2462                                       WIDGET_DOCK_WIDGET_TITLE, false);
2463                 }
2464                 painter->restore();
2465             }
2466             if (!dwOpt->title.isEmpty()) {
2467                 QRect titleRect(subElementRect(SE_DockWidgetTitleBarText,
2468                                                option, widget));
2469 
2470                 if (verticalTitleBar) {
2471                     QRect rVert(r);
2472                     QSize s(rVert.size());
2473 
2474                     s.transpose();
2475                     rVert.setSize(s);
2476 
2477                     titleRect = QRect(rVert.left() + r.bottom() -
2478                                       titleRect.bottom(),
2479                                       rVert.top() + titleRect.left() - r.left(),
2480                                       titleRect.height(), titleRect.width());
2481 
2482                     painter->translate(rVert.left(),
2483                                        rVert.top() + rVert.width());
2484                     painter->rotate(-90);
2485                     painter->translate(-rVert.left(), -rVert.top());
2486                 }
2487 #ifdef QTC_QT5_ENABLE_KDE
2488                 if (opts.dwtSettings & DWT_FONT_AS_PER_TITLEBAR) {
2489                     painter->setFont(KGlobalSettings::windowTitleFont());
2490                 }
2491 #endif
2492                 QFontMetrics fm(painter->fontMetrics());
2493                 QString title(fm.elidedText(dwOpt->title, Qt::ElideRight,
2494                                             titleRect.width(),
2495                                             QPalette::WindowText));
2496                 painter->save();
2497                 getMdiColors(option, state & State_Active);
2498 
2499                 QColor textColor((opts.dwtSettings &
2500                                   DWT_COLOR_AS_PER_TITLEBAR) ?
2501                                  state&State_Active ? m_activeMdiTextColor :
2502                                  m_mdiTextColor :
2503                                  palette.color(QPalette::WindowText));
2504                 QColor shadow(WINDOW_SHADOW_COLOR(opts.titlebarEffect));
2505                 int textOpt(Qt::AlignVCenter); // TODO: dwtPosAsPerTitleBar ?
2506 
2507                 if (opts.dwtSettings & DWT_TEXT_ALIGN_AS_PER_TITLEBAR) {
2508                     switch (opts.titlebarAlignment) {
2509                     case ALIGN_FULL_CENTER:
2510                         if (!verticalTitleBar && !reverse) {
2511                             QFontMetrics fm(painter->fontMetrics());
2512                             int width = fm.boundingRect(title).width();
2513 
2514                             if (((fillRect.width() + width) / 2) <=
2515                                 titleRect.width() + (isKOffice ? r.x() : 0)) {
2516                                 titleRect = fillRect;
2517                                 textOpt |= Qt::AlignHCenter;
2518                             } else {
2519                                 textOpt |= Qt::AlignRight;
2520                             }
2521                             break;
2522                         }
2523                     case ALIGN_CENTER:
2524                         textOpt |= Qt::AlignHCenter;
2525                         break;
2526                     case ALIGN_RIGHT:
2527                         textOpt |= Qt::AlignRight;
2528                         break;
2529                     default:
2530                     case ALIGN_LEFT:
2531                         textOpt|=Qt::AlignLeft;
2532                     }
2533                 } else {
2534                     textOpt |= Qt::AlignLeft;
2535                 }
2536 
2537                 if (!styleHint(SH_UnderlineShortcut, dwOpt, widget)) {
2538                     textOpt |= Qt::TextHideMnemonic;
2539                 } else {
2540                     textOpt |= Qt::TextShowMnemonic;
2541                 }
2542 
2543                 if ((opts.dwtSettings & DWT_EFFECT_AS_PER_TITLEBAR) &&
2544                     EFFECT_NONE != opts.titlebarEffect) {
2545                     shadow.setAlphaF(
2546                         WINDOW_TEXT_SHADOW_ALPHA(opts.titlebarEffect));
2547                     painter->setPen(shadow);
2548                     painter->drawText(titleRect.adjusted(1, 1, 1, 1),
2549                                       textOpt, title);
2550 
2551                     if (!(state & State_Active) &&
2552                         DARK_WINDOW_TEXT(textColor)) {
2553                         textColor.setAlpha((textColor.alpha() * 180) >> 8);
2554                     }
2555                 }
2556                 painter->setPen(textColor);
2557                 painter->drawText(titleRect, textOpt, title);
2558                 painter->restore();
2559             }
2560         }
2561         break;
2562     case CE_HeaderEmptyArea: {
2563         auto ho = styleOptCast<QStyleOptionHeader>(option);
2564         bool horiz = (ho ? ho->orientation == Qt::Horizontal :
2565                       state & State_Horizontal);
2566         QStyleOption opt(*option);
2567         const QColor *use = (opts.lvButton ? buttonColors(option) :
2568                              backgroundColors(option));
2569 
2570         opt.state &= ~State_MouseOver;
2571         painter->save();
2572 
2573         drawBevelGradient(getFill(&opt, use), painter, r, horiz, false,
2574                           opts.lvAppearance, WIDGET_LISTVIEW_HEADER);
2575 
2576         painter->setRenderHint(QPainter::Antialiasing, true);
2577         if(opts.lvAppearance == APPEARANCE_RAISED) {
2578             painter->setPen(use[4]);
2579             if (horiz) {
2580                 drawAaLine(painter, r.x(), r.y() + r.height() - 2,
2581                            r.x() + r.width() - 1, r.y() + r.height() - 2);
2582             } else {
2583                 drawAaLine(painter, r.x() + r.width() - 2, r.y(),
2584                            r.x() + r.width() - 2, r.y() + r.height() - 1);
2585             }
2586         }
2587 
2588         painter->setPen(use[QTC_STD_BORDER]);
2589         if (horiz) {
2590             drawAaLine(painter, r.x(), r.y() + r.height() - 1,
2591                        r.x() + r.width() - 1, r.y() + r.height() - 1);
2592         } else if (reverse) {
2593             drawAaLine(painter, r.x(), r.y(), r.x(), r.y() + r.height() - 1);
2594         } else {
2595             drawAaLine(painter, r.x() + r.width() - 1, r.y(),
2596                        r.x() + r.width() - 1, r.y() + r.height() - 1);
2597         }
2598         QPAINTER_RENDERHINT_AA_MAYBE_OFF(painter);
2599         painter->restore();
2600         break;
2601     }
2602     case CE_HeaderSection:
2603         if (auto ho = styleOptCast<QStyleOptionHeader>(option)) {
2604             const QColor *use = (state & State_Enabled && m_sortedLvColors &&
2605                                  QStyleOptionHeader::None != ho->sortIndicator ?
2606                                  m_sortedLvColors : opts.lvButton ?
2607                                  buttonColors(option) :
2608                                  backgroundColors(option));
2609             painter->save();
2610             if (state & (State_Raised | State_Sunken)) {
2611                 bool sunken = (state & (/*State_Down |*/ /*State_On | */
2612                                    State_Sunken));
2613                 QStyleOption opt(*option);
2614                 opt.state &= ~State_On;
2615 
2616                 if (ho->section == -1 && !(state & State_Enabled) && widget &&
2617                     widget->isEnabled()) {
2618                     opt.state |= State_Enabled;
2619                 }
2620                 drawBevelGradient(getFill(&opt, use), painter, r,
2621                                   ho->orientation == Qt::Horizontal, sunken,
2622                                   opts.lvAppearance, WIDGET_LISTVIEW_HEADER);
2623                 painter->setRenderHint(QPainter::Antialiasing, true);
2624                 if(opts.lvAppearance == APPEARANCE_RAISED) {
2625                     painter->setPen(use[4]);
2626                     if (ho->orientation == Qt::Horizontal) {
2627                         drawAaLine(painter, r.x(), r.y() + r.height() - 2,
2628                                    r.x() + r.width() - 1,
2629                                    r.y() + r.height() - 2);
2630                     } else {
2631                         drawAaLine(painter, r.x() + r.width() - 2, r.y(),
2632                                    r.x() + r.width() - 2,
2633                                    r.y() + r.height() - 1);
2634                     }
2635                 }
2636 
2637                 if (ho->orientation == Qt::Horizontal) {
2638                     painter->setPen(use[QTC_STD_BORDER]);
2639                     drawAaLine(painter, r.x(), r.y() + r.height() - 1,
2640                                r.x() + r.width() - 1, r.y() + r.height() - 1);
2641                     if (opts.coloredMouseOver && state & State_MouseOver &&
2642                         state & State_Enabled) {
2643                         drawHighlight(painter, QRect(r.x(),
2644                                                      r.y() + r.height() - 2,
2645                                                      r.width(), 2), true, true);
2646                     }
2647 
2648                     if (noneOf(ho->position, QStyleOptionHeader::End,
2649                                QStyleOptionHeader::OnlyOneSection)) {
2650                         // Draw header separator
2651                         int sep_x = reverse ? r.x() : r.x() + r.width() - 2;
2652                         drawFadedLine(painter, QRect(sep_x, r.y() + 5, 1,
2653                                                      r.height() - 10),
2654                                       use[QTC_STD_BORDER], true, true, false);
2655                         drawFadedLine(painter, QRect(sep_x + 1, r.y() + 5, 1,
2656                                                      r.height() - 10),
2657                                       use[0], true, true, false);
2658                     }
2659                 } else {
2660                     painter->setPen(use[QTC_STD_BORDER]);
2661                     if (reverse) {
2662                         drawAaLine(painter, r.x(), r.y(), r.x(),
2663                                    r.y() + r.height() - 1);
2664                     } else {
2665                         drawAaLine(painter, r.x() + r.width() - 1,
2666                                    r.y(), r.x() + r.width() - 1,
2667                                    r.y() + r.height() - 1);
2668                     }
2669 
2670                     if (noneOf(ho->position, QStyleOptionHeader::End,
2671                                QStyleOptionHeader::OnlyOneSection)) {
2672                         // Draw header separator
2673                         drawFadedLine(painter, QRect(r.x() + 5,
2674                                                      r.y() + r.height() - 2,
2675                                                      r.width() - 10, 1),
2676                                       use[QTC_STD_BORDER], true, true, true);
2677                         drawFadedLine(painter, QRect(r.x() + 5,
2678                                                      r.y() + r.height() - 1,
2679                                                      r.width() - 10, 1),
2680                                       use[0], true, true, true);
2681                     }
2682                     if (opts.coloredMouseOver && state & State_MouseOver &&
2683                         state & State_Enabled) {
2684                         drawHighlight(painter, QRect(r.x(),
2685                                                      r.y() + r.height() - 3,
2686                                                      r.width(), 2), true, true);
2687                     }
2688                 }
2689                 QPAINTER_RENDERHINT_AA_MAYBE_OFF(painter);
2690             } else if (!qtcIsFlat(opts.lvAppearance) && !reverse &&
2691                        ((State_Enabled | State_Active) == state ||
2692                         State_Enabled == state)) {
2693                 QPolygon top;
2694                 const QColor &col = getFill(option, use);
2695 
2696                 top.setPoints(3, r.x(), r.y(), r.x() + r.width(), r.y(),
2697                               r.x() + r.width(), r.y() + r.height());
2698                 painter->setClipRegion(QRegion(top));
2699                 drawBevelGradient(col, painter, r, true, false,
2700                                   opts.lvAppearance, WIDGET_LISTVIEW_HEADER);
2701                 painter->setClipRegion(QRegion(r).xored(QRegion(top)));
2702                 drawBevelGradient(col, painter, r, false, false,
2703                                   opts.lvAppearance, WIDGET_LISTVIEW_HEADER);
2704             } else {
2705                 painter->fillRect(r, getFill(option, use));
2706             }
2707             painter->restore();
2708         }
2709         break;
2710     case CE_HeaderLabel:
2711         if (auto header = styleOptCast<QStyleOptionHeader>(option)) {
2712             if (!header->icon.isNull()) {
2713                 QPixmap pixmap(getIconPixmap(header->icon,
2714                                              pixelMetric(PM_SmallIconSize),
2715                                              header->state));
2716                 int pixw = pixmap.width();
2717                 QRect aligned(alignedRect(header->direction,
2718                                           QFlag(header->iconAlignment),
2719                                           pixmap.size(), r));
2720                 QRect inter(aligned.intersected(r));
2721 
2722                 painter->drawPixmap(inter.x(), inter.y(), pixmap,
2723                                     inter.x() - aligned.x(),
2724                                     inter.y() - aligned.y(), inter.width(),
2725                                     inter.height());
2726 
2727                 if (Qt::LeftToRight == header->direction) {
2728                     r.setLeft(r.left() + pixw + 2);
2729                 } else {
2730                     r.setRight(r.right() - pixw - 2);
2731                 }
2732             }
2733             drawItemTextWithRole(painter, r, header->textAlignment, palette,
2734                                  state & State_Enabled, header->text,
2735                                  QPalette::ButtonText);
2736         }
2737         break;
2738     case CE_ProgressBarGroove: {
2739         bool doEtch = opts.buttonEffect != EFFECT_NONE && opts.borderProgress;
2740         bool horiz = true;
2741         QColor col;
2742 
2743         if (auto bar = styleOptCast<QStyleOptionProgressBar>(option)) {
2744             horiz = bar->orientation == Qt::Horizontal;
2745         }
2746 
2747         painter->save();
2748 
2749         if (doEtch) {
2750             r.adjust(1, 1, -1, -1);
2751         }
2752 
2753         switch (opts.progressGrooveColor) {
2754         default:
2755         case ECOLOR_BASE:
2756             col = palette.base().color();
2757             break;
2758         case ECOLOR_BACKGROUND:
2759             col = palette.background().color();
2760             break;
2761         case ECOLOR_DARK:
2762             col = m_backgroundCols[2];
2763         }
2764 
2765         drawBevelGradient(col, painter, r, opts.borderProgress ?
2766                           buildPath(r, WIDGET_PBAR_TROUGH, ROUNDED_ALL,
2767                                     qtcGetRadius(&opts, r.width(), r.height(),
2768                                                  WIDGET_PBAR_TROUGH,
2769                                                  RADIUS_EXTERNAL)) :
2770                           QPainterPath(), horiz, false,
2771                           opts.progressGrooveAppearance, WIDGET_PBAR_TROUGH);
2772 
2773         if (doEtch) {
2774             drawEtch(painter, r.adjusted(-1, -1, 1, 1), widget,
2775                      WIDGET_PBAR_TROUGH);
2776         } else if (!opts.borderProgress) {
2777             painter->setPen(m_backgroundCols[QTC_STD_BORDER]);
2778             if (horiz) {
2779                 painter->drawLine(r.topLeft(), r.topRight());
2780                 painter->drawLine(r.bottomLeft(), r.bottomRight());
2781             } else {
2782                 painter->drawLine(r.topLeft(), r.bottomLeft());
2783                 painter->drawLine(r.topRight(), r.bottomRight());
2784             }
2785         }
2786 
2787         if (opts.borderProgress)
2788             drawBorder(painter, r, option, ROUNDED_ALL,
2789                        backgroundColors(option), WIDGET_PBAR_TROUGH,
2790                        qtcIsFlat(opts.progressGrooveAppearance) &&
2791                        ECOLOR_DARK != opts.progressGrooveColor ?
2792                        BORDER_SUNKEN : BORDER_FLAT);
2793         painter->restore();
2794         break;
2795     }
2796     case CE_ProgressBarContents:
2797         if (auto bar = styleOptCast<QStyleOptionProgressBar>(option)) {
2798             bool vertical(false);
2799             bool inverted(false);
2800             bool indeterminate = bar->minimum == 0 && bar->maximum == 0;
2801 
2802             // Get extra style options if version 2
2803             if (auto bar = styleOptCast<QStyleOptionProgressBar>(option)) {
2804                 vertical = bar->orientation == Qt::Vertical;
2805                 inverted = bar->invertedAppearance;
2806             }
2807 
2808             if (!indeterminate && bar->progress == -1)
2809                 break;
2810 
2811             bool reverse = ((!vertical && (bar->direction == Qt::RightToLeft)) ||
2812                             vertical);
2813 
2814             if (inverted)
2815                 reverse = !reverse;
2816 
2817             painter->save();
2818 
2819             if (indeterminate) {
2820                 //Busy indicator
2821                 int chunkSize = PROGRESS_CHUNK_WIDTH * 3.4;
2822                 int measure = vertical ? r.height() : r.width();
2823 
2824                 if (chunkSize > measure / 2)
2825                     chunkSize = measure / 2;
2826 
2827                 int step = m_animateStep % ((measure - chunkSize) * 2);
2828                 QStyleOption opt(*option);
2829 
2830                 if (step > (measure - chunkSize))
2831                     step = 2 * (measure - chunkSize) - step;
2832 
2833                 opt.state |= State_Raised | State_Horizontal;
2834                 drawProgress(painter, vertical ? QRect(r.x(), r.y() + step,
2835                                                        r.width(), chunkSize) :
2836                              QRect(r.x() + step, r.y(), chunkSize, r.height()),
2837                              option, vertical);
2838             } else if (r.isValid() && bar->progress > 0) {
2839                 // workaround for bug in QProgressBar
2840                 qint64 progress = qMax(bar->progress, bar->minimum);
2841                 double pg = ((progress - bar->minimum) /
2842                              qtcMax(1.0, double(bar->maximum - bar->minimum)));
2843 
2844                 if (vertical) {
2845                     int height = qtcMin(r.height(), pg * r.height());
2846 
2847                     if (inverted) {
2848                         drawProgress(painter, QRect(r.x(), r.y(), r.width(),
2849                                                     height), option, true);
2850                     } else {
2851                         drawProgress(painter,
2852                                      QRect(r.x(), r.y() + (r.height() - height),
2853                                            r.width(), height), option, true);
2854                     }
2855                 } else {
2856                     int width = qtcMin(r.width(), pg * r.width());
2857 
2858                     if (reverse || inverted) {
2859                         drawProgress(painter, QRect(r.x() + r.width() - width,
2860                                                     r.y(), width, r.height()),
2861                                      option, false, true);
2862                     } else {
2863                         drawProgress(painter, QRect(r.x(), r.y(), width,
2864                                                     r.height()), option);
2865                     }
2866                 }
2867             }
2868             painter->restore();
2869         }
2870         break;
2871     case CE_ProgressBarLabel:
2872         if (auto bar = styleOptCast<QStyleOptionProgressBar>(option)) {
2873             // The busy indicator doesn't draw a label
2874             if (bar->minimum == 0 && bar->maximum == 0)
2875                 return;
2876 
2877             bool vertical = false;
2878             bool inverted = false;
2879             bool bottomToTop = false;
2880 
2881             // Get extra style options if version 2
2882             if (auto bar = styleOptCast<QStyleOptionProgressBar>(option)) {
2883                 vertical = bar->orientation == Qt::Vertical;
2884                 inverted = bar->invertedAppearance;
2885                 bottomToTop = bar->bottomToTop;
2886             }
2887 
2888             painter->save();
2889             painter->setRenderHint(QPainter::Antialiasing, true);
2890 
2891             if (vertical) {
2892                 // flip width and height
2893                 r = QRect(r.left(), r.top(), r.height(), r.width());
2894 
2895                 QTransform m;
2896                 if (bottomToTop) {
2897                     m.translate(0.0, r.width());
2898                     m.rotate(-90);
2899                 } else {
2900                     m.translate(r.height(), 0.0);
2901                     m.rotate(90);
2902                 }
2903                 painter->setTransform(m);
2904             }
2905 
2906             int progressIndicatorPos =
2907                 ((bar->progress - bar->minimum) /
2908                  qMax(1.0, double(bar->maximum - bar->minimum)) * r.width());
2909             bool flip((!vertical &&
2910                        (((bar->direction == Qt::RightToLeft) && !inverted) ||
2911                         ((Qt::LeftToRight==bar->direction) && inverted))) ||
2912                       (vertical && ((!inverted && !bottomToTop) ||
2913                                     (inverted && bottomToTop))));
2914             QRect leftRect;
2915             QRegion rightRect(r);
2916             QPalette::ColorGroup cg =
2917                 (state & State_Enabled || state == State_None ?
2918                  QPalette::Active : QPalette::Current);
2919 
2920             if (flip) {
2921                 int indicatorPos = r.width() - progressIndicatorPos;
2922 
2923                 if (indicatorPos >= 0 && indicatorPos <= r.width()) {
2924                     painter->setPen(palette.brush(cg, QPalette::Base).color());
2925                     leftRect = QRect(r.left(), r.top(), indicatorPos, r.height());
2926                     // rightRect = QRect(r.left() + indicatorPos, r.top(),
2927                     //                   r.width() - indicatorPos, r.height());
2928                 } else if (indicatorPos > r.width()) {
2929                     painter->setPen(palette.brush(cg, QPalette::Text).color());
2930                 } else {
2931                     painter->setPen(
2932                         palette.brush(cg, QPalette::HighlightedText).color());
2933                 }
2934             } else {
2935                 if (progressIndicatorPos >= 0 &&
2936                     progressIndicatorPos <= r.width()) {
2937                     leftRect = QRect(r.left(), r.top(), progressIndicatorPos,
2938                                      r.height());
2939                     // rightRect = QRect(r.left() + progressIndicatorPos, r.top(),
2940                     //                   r.width() - progressIndicatorPos,
2941                     //                   r.height());
2942                 } else if (progressIndicatorPos > r.width()) {
2943                     painter->setPen(
2944                         palette.brush(cg, QPalette::HighlightedText).color());
2945                 } else {
2946                     painter->setPen(palette.brush(cg, QPalette::Text).color());
2947                 }
2948             }
2949 
2950             QString text = bar->fontMetrics.elidedText(bar->text,
2951                                                        Qt::ElideRight,
2952                                                        r.width());
2953             rightRect = rightRect.subtracted(leftRect);
2954             painter->setClipRegion(rightRect);
2955             painter->drawText(r, text,
2956                               QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter |
2957                                           Qt::AlignVCenter));
2958             if (!leftRect.isNull()) {
2959                 painter->setPen(
2960                     palette.brush(cg, flip ? QPalette::Text :
2961                                   QPalette::HighlightedText).color());
2962                 painter->setClipRect(leftRect);
2963                 painter->drawText(
2964                     r, text, QTextOption(Qt::AlignAbsolute | Qt::AlignHCenter |
2965                                          Qt::AlignVCenter));
2966             }
2967             painter->restore();
2968         }
2969         break;
2970     case CE_MenuBarItem:
2971         if (auto mbi = styleOptCast<QStyleOptionMenuItem>(option)) {
2972             bool down = state & (State_On | State_Sunken);
2973             bool active = (state & State_Enabled &&
2974                            (down || (state & State_Selected &&
2975                                      opts.menubarMouseOver)));
2976             uint alignment = (Qt::AlignCenter | Qt::TextShowMnemonic |
2977                               Qt::TextDontClip | Qt::TextSingleLine);
2978             QPixmap pix = getIconPixmap(mbi->icon,
2979                                         pixelMetric(PM_SmallIconSize),
2980                                         mbi->state);
2981             if (!styleHint(SH_UnderlineShortcut, mbi, widget))
2982                 alignment |= Qt::TextHideMnemonic;
2983 
2984             painter->save();
2985             drawMenuOrToolBarBackground(widget, painter, mbi->menuRect, option);
2986             if (active)
2987                 drawMenuItem(painter, !opts.roundMbTopOnly &&
2988                              !(opts.square & SQUARE_POPUP_MENUS) ?
2989                              r.adjusted(1, 1, -1, -1) : r, option, MENU_BAR,
2990                              (down || theThemedApp == APP_OPENOFFICE) &&
2991                              opts.roundMbTopOnly ? ROUNDED_TOP : ROUNDED_ALL,
2992                              opts.useHighlightForMenu &&
2993                              (opts.colorMenubarMouseOver || down ||
2994                               theThemedApp == APP_OPENOFFICE) ?
2995                              (m_ooMenuCols ? m_ooMenuCols :
2996                               m_highlightCols) : m_backgroundCols);
2997             if (!pix.isNull()) {
2998                 drawItemPixmap(painter, mbi->rect, alignment, pix);
2999             } else {
3000                 const QColor &col =
3001                     (state & State_Enabled ?
3002                      ((opts.colorMenubarMouseOver && active) ||
3003                       (!opts.colorMenubarMouseOver && down)) ?
3004                      opts.customMenuTextColor ?
3005                      opts.customMenuSelTextColor :
3006                      opts.useHighlightForMenu ?
3007                      palette.highlightedText().color() :
3008                      palette.foreground().color() :
3009                      palette.foreground().color() :
3010                      palette.foreground().color());
3011 
3012                 painter->setPen(col);
3013                 painter->drawText(r, alignment, mbi->text);
3014             }
3015             painter->restore();
3016         }
3017         break;
3018     case CE_MenuItem:
3019         if (auto menuItem = styleOptCast<QStyleOptionMenuItem>(option)) {
3020             // TODO check qtquick
3021             bool comboMenu(qobject_cast<const QComboBox*>(widget)),
3022                 reverse(Qt::RightToLeft==menuItem->direction),
3023                 isOO(isOOWidget(widget));
3024             int checkcol(qMax(menuItem->maxIconWidth, 20)),
3025                 stripeWidth(qMax(checkcol, constMenuPixmapWidth)-2);
3026             const QColor *use = popupMenuCols(option);
3027 
3028             QRect rx(r);
3029 
3030             if (isOO) {
3031                 if (opts.borderMenuitems) {
3032                     r.adjust(2, 0, -2, 0);
3033                 } else if (opts.menuitemAppearance == APPEARANCE_FADE) {
3034                     r.adjust(1, 0, -1, 0);
3035                 }
3036             }
3037 
3038             painter->save();
3039 
3040             if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
3041                 bool isMenu = !widget || qobject_cast<const QMenu*>(widget);
3042                 bool doStripe = isMenu && opts.menuStripe && !comboMenu;
3043 
3044                 if (doStripe)
3045                     drawBevelGradient(menuStripeCol(), painter,
3046                                       QRect(reverse ? r.right() - stripeWidth :
3047                                             r.x(), r.y(), stripeWidth,
3048                                             r.height()), false, false,
3049                                       opts.menuStripeAppearance, WIDGET_OTHER);
3050 
3051                 if (!menuItem->text.isEmpty()) {
3052                     int textAlignment;
3053                     QFont font(menuItem->font);
3054                     QRect textRect;
3055                     if (opts.buttonStyleMenuSections) {
3056                         QStyleOption opt;
3057                         opt.rect = r.adjusted(2, 2, -3, -2);
3058                         opt.state = State_Raised | State_Enabled | State_Horizontal;
3059                         drawLightBevel(painter, opt.rect, &opt, widget, ROUNDED_ALL,
3060                                        getFill(&opt, use), use, true,
3061                                        WIDGET_NO_ETCH_BTN);
3062 
3063                         font.setBold(true);
3064                         painter->setFont(font);
3065                         textAlignment = Qt::AlignHCenter | Qt::AlignVCenter;
3066                         textRect = r;
3067                     } else {
3068                         font.setBold(true);
3069                         font.setUnderline(true);
3070 #ifdef Q_OS_MACOS
3071                         if (QGuiApplication::platformName() == QLatin1String("cocoa")) {
3072                             font.setLetterSpacing(QFont::PercentageSpacing, 95);
3073                         }
3074 #endif
3075                         painter->setFont(font);
3076                         QRect miRect(menuItem->rect.left() + 5 +
3077                                      (!reverse && doStripe ? stripeWidth : 0),
3078                                      menuItem->rect.center().y() - painter->fontMetrics().ascent() / 2 - 5,
3079                                      menuItem->rect.width() -
3080                                      (9 + (doStripe ? stripeWidth : 0)), 1);
3081                         QColor lineCol = use[MENU_SEP_SHADE];
3082                         if (miRect.y() >= rx.height() / 2) {
3083                             drawFadedLine(painter, miRect, lineCol, reverse,
3084                                       !reverse, true);
3085                         }
3086                         textAlignment = Qt::AlignLeft | Qt::AlignBottom;
3087                         textRect = r.adjusted(5, 5, -5, -5);
3088                     }
3089                     drawItemTextWithRole(painter, textRect,
3090                                          textAlignment,
3091                                          palette, state & State_Enabled,
3092                                          menuItem->text, QPalette::Text);
3093                 } else {
3094                     QRect miRect(menuItem->rect.left() + 3 +
3095                                  (!reverse && doStripe ? stripeWidth : 0),
3096                                  menuItem->rect.center().y(),
3097                                  menuItem->rect.width() -
3098                                  (7 + (doStripe ? stripeWidth : 0)), 1);
3099                     drawFadedLine(painter, miRect, use[MENU_SEP_SHADE], true,
3100                                   true, true);
3101                 }
3102 
3103                 if (isOO) {
3104                     painter->setPen(use[QTC_STD_BORDER]);
3105                     painter->drawLine(rx.topLeft(), rx.bottomLeft());
3106                     painter->drawLine(rx.topRight(), rx.bottomRight());
3107                 }
3108                 painter->restore();
3109                 break;
3110             }
3111 
3112             bool selected = state & State_Selected;
3113             bool checkable =
3114                 menuItem->checkType != QStyleOptionMenuItem::NotCheckable;
3115             bool checked = menuItem->checked;
3116             bool enabled = state & State_Enabled;
3117 
3118             // check if the font tick is wider than the current margin
3119             // and adjust if necessary
3120             initFontTickData(opts, menuItem->font, widget);
3121             int dx = 0;
3122             if (menuTickCompensation(opts, checkcol, dx)) {
3123                 r.adjust(-dx, 0, dx, 0);
3124                 checkcol += dx;
3125             }
3126             if (opts.menuStripe && !comboMenu)
3127                 drawBevelGradient(menuStripeCol(), painter,
3128                                   QRect(reverse ? r.right()-stripeWidth : r.x(),
3129                                         r.y(), stripeWidth, r.height()),
3130                                   false, false, opts.menuStripeAppearance,
3131                                   WIDGET_OTHER);
3132 
3133             if (selected && enabled) {
3134                 drawMenuItem(painter, r, option,
3135                              /*comboMenu ? MENU_COMBO : */MENU_POPUP,
3136                              ROUNDED_ALL,
3137                              opts.useHighlightForMenu ?
3138                              (m_ooMenuCols ? m_ooMenuCols :
3139                               m_highlightCols) : use);
3140             }
3141 
3142             if (comboMenu) {
3143                 if (menuItem->icon.isNull()) {
3144                     checkcol = 0;
3145                 } else {
3146                     checkcol = menuItem->maxIconWidth;
3147                 }
3148             } else {
3149                 // Check
3150                 QRect checkRect(r.left() + 3, r.center().y() - 6,
3151                                 opts.crSize, opts.crSize);
3152                 checkRect = visualRect(menuItem->direction, menuItem->rect,
3153                                        checkRect);
3154                 if (checkable) {
3155                     if (!opts.onlyTicksInMenu && (menuItem->checkType &
3156                          QStyleOptionMenuItem::Exclusive) &&
3157                         menuItem->icon.isNull()) {
3158                         QStyleOptionButton button;
3159                         button.rect = checkRect;
3160                         button.state = menuItem->state|STATE_MENU;
3161                         if (checked)
3162                             button.state |= State_On;
3163                         button.palette = palette;
3164                         drawPrimitive(PE_IndicatorRadioButton, &button,
3165                                       painter, widget);
3166                     } else {
3167                         if (menuItem->icon.isNull() || !opts.menuIcons) {
3168                             QStyleOptionButton button;
3169                             button.rect = checkRect;
3170                             button.state = menuItem->state|STATE_MENU;
3171                             if (checked)
3172                                 button.state |= State_On;
3173                             button.palette = palette;
3174                             drawPrimitive(PE_IndicatorMenuCheckMark, &button,
3175                                           painter, widget);
3176                         } else if (checked) {
3177                             int iconSize = qMax(menuItem->maxIconWidth, 20);
3178                             QRect sunkenRect(r.left() + 1,
3179                                              r.top() + (r.height() -
3180                                                         iconSize) / 2,
3181                                              iconSize, iconSize);
3182                             QStyleOption opt(*option);
3183 
3184                             sunkenRect = visualRect(menuItem->direction,
3185                                                     menuItem->rect, sunkenRect);
3186                             opt.state = menuItem->state;
3187                             opt.state |= State_Raised | State_Horizontal | State_On;
3188                             drawLightBevel(painter, sunkenRect, &opt, widget,
3189                                            ROUNDED_ALL,
3190                                            getFill(&opt, m_buttonCols),
3191                                            m_buttonCols);
3192                         }
3193                     }
3194                 }
3195             }
3196 
3197             // Text and icon, ripped from windows style
3198             bool dis = !(state & State_Enabled);
3199             bool act = state & State_Selected;
3200 
3201             if (opts.menuIcons && !menuItem->icon.isNull()) {
3202                 QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
3203                 if (act && !dis)
3204                     mode = QIcon::Active;
3205                 QIcon::State state = checked ? QIcon::On : QIcon::Off;
3206 
3207                 int size = pixelMetric(PM_SmallIconSize, option, widget);
3208                 QRect iconRect(menuItem->rect.x(),
3209                                menuItem->rect.y(), checkcol,
3210                                menuItem->rect.height());
3211                 iconRect = centerRect(iconRect, size, size);
3212                 iconRect = visualRect(option->direction, menuItem->rect, iconRect);
3213 
3214                 QPixmap pixmap(getIconPixmap(menuItem->icon, iconRect.size(), mode, state));
3215                 painter->setPen(palette.text().color());
3216                 if (checkable && checked)
3217                     iconRect.adjust(1, 1, 1, 1);
3218                 painter->drawPixmap(iconRect.topLeft(), pixmap);
3219             }
3220 
3221             painter->setPen(dis ? palette.text().color() :
3222                             selected && opts.useHighlightForMenu &&
3223                             !m_ooMenuCols ? palette.highlightedText().color() :
3224                             palette.foreground().color());
3225 
3226             int x;
3227             int y;
3228             int w;
3229             int h;
3230             int tab = menuItem->tabWidth;
3231             menuItem->rect.getRect(&x, &y, &w, &h);
3232             int xm = windowsItemFrame + checkcol + windowsItemHMargin - 2;
3233             int xpos = menuItem->rect.x() + xm;
3234             QRect textRect(xpos, y + windowsItemVMargin,
3235                            opts.menuIcons ?
3236                            (w - xm - windowsRightBorder - tab + 1) :
3237                            (w - ((xm*2) + tab)), h - 2 * windowsItemVMargin);
3238             QRect vTextRect = visualRect(option->direction, menuItem->rect,
3239                                          textRect);
3240             QString s = menuItem->text;
3241 
3242             if (!s.isEmpty()) {
3243                 // draw text
3244                 int t(s.indexOf(QLatin1Char('\t'))),
3245                     textFlags(Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine);
3246 
3247                 if (!styleHint(SH_UnderlineShortcut, menuItem, widget))
3248                     textFlags |= Qt::TextHideMnemonic;
3249                 textFlags |= Qt::AlignLeft;
3250 
3251                 if (t >= 0)
3252                 {
3253                     QRect vShortcutRect(visualRect(option->direction, menuItem->rect,
3254                                                    QRect(textRect.topRight(), QPoint(menuItem->rect.right(), textRect.bottom()))));
3255                     vShortcutRect.adjust(dx, 0, dx, 0);
3256                     painter->drawText(vShortcutRect, textFlags, s.mid(t + 1));
3257                     s = s.left(t);
3258                 }
3259 
3260                 QFont font(menuItem->font);
3261 
3262                 if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem)
3263                     font.setBold(true);
3264 
3265                 painter->setFont(font);
3266                 painter->drawText(vTextRect, textFlags, s.left(t));
3267             }
3268 
3269             // Arrow
3270             if (QStyleOptionMenuItem::SubMenu==menuItem->menuItemType) // draw sub menu arrow
3271             {
3272                 int              dim((menuItem->rect.height() - 4) / 2),
3273                     xpos(menuItem->rect.left() + menuItem->rect.width() - 3 - dim);
3274                 PrimitiveElement arrow(Qt::RightToLeft==option->direction ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight);
3275                 QRect            vSubMenuRect(visualRect(option->direction, menuItem->rect,
3276                                                          QRect(xpos, menuItem->rect.top() + menuItem->rect.height() / 2 - dim / 2, dim, dim)));
3277 
3278                 drawArrow(painter, vSubMenuRect, arrow,
3279                           opts.useHighlightForMenu && state&State_Enabled && state&State_Selected && !m_ooMenuCols
3280                           ? palette.highlightedText().color()
3281                           : palette.text().color());
3282             }
3283 
3284             if(isOO)
3285             {
3286                 painter->setPen(use[QTC_STD_BORDER]);
3287                 painter->drawLine(rx.topLeft(), rx.bottomLeft());
3288                 painter->drawLine(rx.topRight(), rx.bottomRight());
3289             }
3290             painter->restore();
3291         }
3292         break;
3293     case CE_MenuHMargin:
3294     case CE_MenuVMargin:
3295     case CE_MenuEmptyArea:
3296         break;
3297     case CE_PushButton:
3298         if (auto btn = styleOptCast<QStyleOptionButton>(option)) {
3299             // For OO.o 3.2 need to fill widget background!
3300             if(isOOWidget(widget))
3301                 painter->fillRect(r, palette.brush(QPalette::Window));
3302             drawControl(CE_PushButtonBevel, btn, painter, widget);
3303 
3304             QStyleOptionButton subopt(*btn);
3305             if (!btn->icon.isNull()
3306                 && !(styleHint(SH_DialogButtonBox_ButtonsHaveIcons, btn, widget) || btn->text.isEmpty())) {
3307                 // remove the icon from our local QStyleOptionButton copy
3308                 subopt.icon = QIcon();
3309             }
3310 
3311             subopt.rect = subElementRect(SE_PushButtonContents, &subopt, widget);
3312             drawControl(CE_PushButtonLabel, &subopt, painter, widget);
3313 
3314             if (state & State_HasFocus &&
3315                 !(state & State_MouseOver && opts.coloredMouseOver != MO_NONE &&
3316                   oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED))) {
3317                 QStyleOptionFocusRect fropt;
3318                 fropt.QStyleOption::operator=(*btn);
3319                 fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget);
3320                 drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
3321             }
3322         }
3323         break;
3324     case CE_PushButtonBevel:
3325         if (auto btn = styleOptCast<QStyleOptionButton>(option)) {
3326             int dbi(pixelMetric(PM_ButtonDefaultIndicator, btn, widget));
3327 
3328             if (btn->features & QStyleOptionButton::DefaultButton)
3329                 drawPrimitive(PE_FrameDefaultButton, option, painter, widget);
3330             if (btn->features & QStyleOptionButton::AutoDefaultButton)
3331                 r.setCoords(r.left() + dbi, r.top() + dbi, r.right() - dbi, r.bottom() - dbi);
3332             if (!(btn->features & (QStyleOptionButton::Flat |
3333                                    QStyleOptionButton::CommandLinkButton)) ||
3334                 state&(State_Sunken | State_On | State_MouseOver)) {
3335                 QStyleOptionButton tmpBtn(*btn);
3336 
3337                 tmpBtn.rect = r;
3338                 drawPrimitive(PE_PanelButtonCommand, &tmpBtn, painter, widget);
3339             }
3340             if (btn->features & QStyleOptionButton::HasMenu)
3341             {
3342                 int   mbi(pixelMetric(PM_MenuButtonIndicator, btn, widget));
3343                 QRect ar(Qt::LeftToRight==btn->direction
3344                          ? btn->rect.right() - (mbi+6)
3345                          : btn->rect.x() + 6,
3346                          ((btn->rect.height() - mbi)/2),
3347                          mbi, mbi);
3348 
3349                 if(option->state &(State_On | State_Sunken))
3350                     ar.adjust(1, 1, 1, 1);
3351 
3352                 drawArrow(painter, ar, PE_IndicatorArrowDown,
3353                           MOArrow(state, palette, QPalette::ButtonText));
3354             }
3355         }
3356         break;
3357     case CE_PushButtonLabel:
3358         if (auto button = styleOptCast<QStyleOptionButton>(option)) {
3359             uint tf(Qt::AlignVCenter | Qt::TextShowMnemonic);
3360 
3361             if (!styleHint(SH_UnderlineShortcut, button, widget))
3362                 tf |= Qt::TextHideMnemonic;
3363 
3364             if (!button->icon.isNull() &&
3365                 (styleHint(SH_DialogButtonBox_ButtonsHaveIcons, button, widget) ||
3366                  button->text.isEmpty())) {
3367                 QIcon::Mode mode(button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled);
3368 
3369                 if (QIcon::Normal == mode && button->state & State_HasFocus)
3370                     mode = QIcon::Active;
3371 
3372                 QIcon::State state((button->state & State_On) || (button->state & State_Sunken) ?
3373                                    QIcon::On : QIcon::Off);
3374 
3375                 QSize iconSize = button->iconSize;
3376                 int width = iconSize.width();
3377                 int height = iconSize.height();
3378                 int iconSpacing = 4; //### 4 is currently hardcoded in QPushButton::sizeHint()
3379 
3380                 // Center both icon and text
3381                 int xoffset = width;
3382                 if (!button->text.isEmpty())
3383                     xoffset += (button->fontMetrics.boundingRect(r, tf, button->text).width() +
3384                                 iconSpacing);
3385                 QRect iconRect(r.x() + (r.width() - xoffset) / 2,
3386                                r.y() + (r.height() - height) / 2, width, height);
3387 
3388                 tf |= Qt::AlignLeft; // left align, we adjust the text-rect instead
3389 
3390                 if (button->direction == Qt::RightToLeft)
3391                     r.setRight(iconRect.left() - iconSpacing);
3392                 else
3393                     r.setLeft(iconRect.right() + iconSpacing);
3394 
3395                 if (button->state & (State_On|State_Sunken))
3396                     iconRect.translate(pixelMetric(PM_ButtonShiftHorizontal, option, widget),
3397                                        pixelMetric(PM_ButtonShiftVertical, option, widget));
3398                 iconRect = visualRect(option->direction, button->rect, iconRect);
3399 
3400                 QPixmap pixmap(getIconPixmap(button->icon, iconRect.size(), mode, state));
3401                 painter->drawPixmap(iconRect, pixmap);
3402             } else {
3403                 tf |= Qt::AlignHCenter;
3404             }
3405 
3406             if (button->state & (State_On|State_Sunken))
3407                 r.translate(pixelMetric(PM_ButtonShiftHorizontal, option, widget),
3408                             pixelMetric(PM_ButtonShiftVertical, option, widget));
3409 
3410             // The following is mainly for DejaVu Sans 11...
3411             if(button->fontMetrics.height()==19 && r.height()==(23+((opts.thin&THIN_BUTTONS) ? 0 : 2)))
3412                 r.translate(0, 1);
3413 
3414             if (button->features & QStyleOptionButton::HasMenu) {
3415                 int mbi(pixelMetric(PM_MenuButtonIndicator, button, widget));
3416 
3417                 if (Qt::LeftToRight == button->direction) {
3418                     r = r.adjusted(0, 0, -mbi, 0);
3419                 } else {
3420                     r = r.adjusted(mbi, 0, 0, 0);
3421                 }
3422             }
3423 
3424             int num(opts.embolden && button->features&QStyleOptionButton::DefaultButton ? 2 : 1);
3425 
3426             for(int i=0; i<num; ++i)
3427                 drawItemTextWithRole(painter, r.adjusted(i, 0, i, 0), tf, palette, (button->state&State_Enabled),
3428                                      button->text, QPalette::ButtonText);
3429         }
3430         break;
3431     case CE_ComboBoxLabel:
3432         if (auto comboBox = styleOptCast<QStyleOptionComboBox>(option)) {
3433             QRect editRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget);
3434             bool  sunken=!comboBox->editable && (state&(State_On|State_Sunken));
3435             int   shiftH=sunken ? pixelMetric(PM_ButtonShiftHorizontal, option, widget) : 0,
3436                 shiftV=sunken ? pixelMetric(PM_ButtonShiftVertical, option, widget) : 0;
3437 
3438             painter->save();
3439 
3440             if (!comboBox->currentIcon.isNull())
3441             {
3442                 QPixmap pixmap = getIconPixmap(comboBox->currentIcon, comboBox->iconSize, state);
3443                 QRect   iconRect(editRect);
3444 
3445                 iconRect.setWidth(comboBox->iconSize.width() + 5);
3446                 if(!comboBox->editable)
3447                     iconRect = alignedRect(QApplication::layoutDirection(), Qt::AlignLeft|Qt::AlignVCenter,
3448                                            iconRect.size(), editRect);
3449                 if (comboBox->editable)
3450                 {
3451                     int adjust=opts.etchEntry ? 2 : 1;
3452 
3453                     if(opts.square&SQUARE_ENTRY || opts.round<ROUND_FULL)
3454                         painter->fillRect(iconRect.adjusted(adjust-1, adjust, -(adjust-1), -adjust), palette.brush(QPalette::Base));
3455                     else
3456                     {
3457                         painter->fillRect(iconRect.adjusted(1, adjust, -1, -adjust), palette.brush(QPalette::Base));
3458                         painter->fillRect(iconRect.adjusted(0, adjust+1, 0, -(adjust+1)), palette.brush(QPalette::Base));
3459                     }
3460                 }
3461 
3462                 if (sunken)
3463                     iconRect.translate(shiftH, shiftV);
3464 
3465                 drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
3466 
3467                 if (reverse)
3468                     editRect.translate(-4 - comboBox->iconSize.width(), 0);
3469                 else
3470                     editRect.translate(comboBox->iconSize.width() + 4, 0);
3471             }
3472 
3473             if (!comboBox->currentText.isEmpty() && !comboBox->editable)
3474             {
3475                 if (sunken)
3476                     editRect.translate(shiftH, shiftV);
3477 
3478                 int margin=comboBox->frame && widget && widget->rect().height()<(opts.buttonEffect != EFFECT_NONE ? 22 : 20)  ? 4 : 0;
3479                 editRect.adjust(1, -margin, -1, margin);
3480                 painter->setClipRect(editRect);
3481                 drawItemTextWithRole(painter, editRect, Qt::AlignLeft|Qt::AlignVCenter, palette,
3482                                      state&State_Enabled, comboBox->currentText, QPalette::ButtonText);
3483             }
3484             painter->restore();
3485         }
3486         break;
3487     case CE_MenuBarEmptyArea:
3488     {
3489         painter->save();
3490 
3491         drawMenuOrToolBarBackground(widget, painter, r, option);
3492         if (TB_NONE!=opts.toolbarBorders && widget && widget->parentWidget() &&
3493             (qobject_cast<const QMainWindow *>(widget->parentWidget())))
3494         {
3495             const QColor *use=menuColors(option, m_active);
3496             bool         dark(TB_DARK==opts.toolbarBorders || TB_DARK_ALL==opts.toolbarBorders);
3497 
3498             if(TB_DARK_ALL==opts.toolbarBorders || TB_LIGHT_ALL==opts.toolbarBorders)
3499             {
3500                 painter->setPen(use[0]);
3501                 painter->drawLine(r.x(), r.y(), r.x()+r.width()-1, r.y());
3502                 painter->drawLine(r.x(), r.y(), r.x(), r.y()+r.width()-1);
3503                 painter->setPen(use[dark ? 3 : 4]);
3504                 painter->drawLine(r.x(), r.y()+r.height()-1, r.x()+r.width()-1, r.y()+r.height()-1);
3505                 painter->drawLine(r.x()+r.width()-1, r.y(), r.x()+r.width()-1, r.y()+r.height()-1);
3506             }
3507             else
3508             {
3509                 painter->setPen(use[dark ? 3 : 4]);
3510                 painter->drawLine(r.x(), r.y()+r.height()-1, r.x()+r.width()-1, r.y()+r.height()-1);
3511             }
3512         }
3513         painter->restore();
3514     }
3515     break;
3516     case CE_TabBarTabLabel:
3517         if (auto _tab = styleOptCast<QStyleOptionTab>(option)) {
3518             QStyleOptionTab tab(*_tab);
3519             bool verticalTabs(QTabBar::RoundedEast == tab.shape ||
3520                               QTabBar::RoundedWest == tab.shape ||
3521                               QTabBar::TriangularEast == tab.shape ||
3522                               QTabBar::TriangularWest == tab.shape);
3523             bool toolbarTab = (!opts.toolbarTabs &&
3524                                widget && widget->parentWidget() &&
3525                                qobject_cast<QToolBar*>(widget->parentWidget()));
3526 
3527             if (verticalTabs) {
3528                 painter->save();
3529                 int newX, newY, newRot;
3530                 if (QTabBar::RoundedEast == tab.shape ||
3531                     QTabBar::TriangularEast == tab.shape) {
3532                     newX = r.width();
3533                     newY = r.y();
3534                     newRot = 90;
3535                 } else {
3536                     newX = 0;
3537                     newY = r.y() + r.height();
3538                     newRot = -90;
3539                 }
3540                 r.setRect(0, 0, r.height(), r.width());
3541 
3542                 QTransform m;
3543                 m.translate(newX, newY);
3544                 m.rotate(newRot);
3545                 painter->setTransform(m, true);
3546             }
3547 
3548             int alignment(Qt::AlignVCenter | Qt::TextShowMnemonic |
3549                           (opts.centerTabText ? Qt::AlignHCenter : Qt::AlignLeft));
3550 
3551             if (!styleHint(SH_UnderlineShortcut, option, widget))
3552                 alignment |= Qt::TextHideMnemonic;
3553 
3554             if(toolbarTab)
3555                 tab.state &= ~State_Selected;
3556             r = subElementRect(SE_TabBarTabText, &tab, widget);
3557             if (!tab.icon.isNull()) {
3558                 QSize iconSize(tab.iconSize);
3559                 if (!iconSize.isValid()) {
3560                     int iconExtent(pixelMetric(PM_SmallIconSize));
3561                     iconSize = QSize(iconExtent, iconExtent);
3562                 }
3563 
3564                 QPixmap tabIcon(getIconPixmap(tab.icon, iconSize,
3565                                               state & State_Enabled));
3566                 QSize tabIconSize = tab.icon.actualSize(iconSize,
3567                                                         tab.state & State_Enabled
3568                                                         ? QIcon::Normal
3569                                                         : QIcon::Disabled);
3570 
3571                 int offset = 4,
3572                     left = option->rect.left();
3573                 if (tab.leftButtonSize.isNull() || tab.leftButtonSize.width()<=0) {
3574                     offset += 2;
3575                 } else {
3576                     left += tab.leftButtonSize.width() + 2;
3577                 }
3578                 QRect iconRect = QRect(left + offset,
3579                                        r.center().y() - tabIcon.height() / 2,
3580                                        tabIconSize.width(),
3581                                        tabIconSize.height());
3582                 if (!verticalTabs)
3583                     iconRect = visualRect(option->direction, option->rect,
3584                                           iconRect);
3585                 painter->drawPixmap(iconRect.x(), iconRect.y(), tabIcon);
3586             }
3587 
3588             if(!_tab->text.isEmpty()) {
3589                 drawItemTextWithRole(painter, r, alignment, _tab->palette,
3590                                      _tab->state & State_Enabled, _tab->text,
3591                                      !opts.stdSidebarButtons && toolbarTab &&
3592                                      state&State_Selected ?
3593                                      QPalette::HighlightedText :
3594                                      QPalette::WindowText);
3595             }
3596 
3597             if (verticalTabs)
3598                 painter->restore();
3599 
3600             if (tab.state & State_HasFocus) {
3601                 const int constOffset = 1 + pixelMetric(PM_DefaultFrameWidth);
3602 
3603                 int x1 = tab.rect.left();
3604                 int x2 = tab.rect.right() - 1;
3605                 QStyleOptionFocusRect fropt;
3606                 fropt.QStyleOption::operator=(*_tab);
3607                 fropt.rect.setRect(x1 + 1 + constOffset,
3608                                    tab.rect.y() + constOffset,
3609                                    x2 - x1 - 2 * constOffset,
3610                                    tab.rect.height() - 2 * constOffset);
3611 
3612                 fropt.state|=State_Horizontal;
3613                 if(FOCUS_LINE != opts.focus) {
3614                     if(QTabBar::RoundedNorth == tab.shape ||
3615                        QTabBar::TriangularNorth == tab.shape) {
3616                         fropt.rect.adjust(0, 1, 0, 0);
3617                     }
3618                 } else if(TAB_MO_BOTTOM == opts.tabMouseOver &&
3619                           FOCUS_LINE==opts.focus)
3620                     switch(tab.shape) {
3621                     case QTabBar::RoundedNorth:
3622                     case QTabBar::TriangularNorth:
3623                         fropt.rect.adjust(0, 0, 0, 1);
3624                         break;
3625                     case QTabBar::RoundedEast:
3626                     case QTabBar::TriangularEast:
3627                         fropt.rect.adjust(-2, 0, -(fropt.rect.width()+1), 0);
3628                         fropt.state&=~State_Horizontal;
3629                         break;
3630                     case QTabBar::RoundedSouth:
3631                     case QTabBar::TriangularSouth:
3632                         fropt.rect.adjust(0, 0, 0, 1);
3633                         break;
3634                     case QTabBar::RoundedWest:
3635                     case QTabBar::TriangularWest:
3636                         fropt.rect.adjust(0, 0, 2, 0);
3637                         fropt.state&=~State_Horizontal;
3638                     default:
3639                         break;
3640                     }
3641 
3642                 drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
3643             }
3644         }
3645         break;
3646     case CE_TabBarTabShape:
3647         if(!opts.toolbarTabs && widget && widget->parentWidget() && qobject_cast<QToolBar *>(widget->parentWidget()))
3648         {
3649             QStyleOption opt(*option);
3650             if(state&State_Selected)
3651                 opt.state|=State_On;
3652             if(opts.stdSidebarButtons)
3653             {
3654                 if(state&(State_Selected|State_MouseOver))
3655                 {
3656                     opt.state|=STATE_TBAR_BUTTON;
3657                     drawPrimitive(PE_PanelButtonTool, &opt, painter, widget);
3658                 }
3659             }
3660             else
3661                 drawSideBarButton(painter, r, &opt, widget);
3662         }
3663         else if (auto tab = styleOptCast<QStyleOptionTab>(option)) {
3664             bool onlyTab(widget && widget->parentWidget() ?
3665                          qobject_cast<const QTabWidget*>(widget->parentWidget()) ?
3666                          false : true : false),
3667                 selected(state&State_Selected),
3668                 horiz(QTabBar::RoundedNorth==tab->shape || QTabBar::RoundedSouth==tab->shape);
3669             QRect        r2(r);
3670             bool         rtlHorTabs(Qt::RightToLeft==tab->direction && horiz),
3671                 oneTab(QStyleOptionTab::OnlyOneTab==tab->position),
3672                 leftCornerWidget(tab->cornerWidgets&QStyleOptionTab::LeftCornerWidget),
3673                 rightCornerWidget(tab->cornerWidgets&QStyleOptionTab::RightCornerWidget),
3674                 firstTab((tab->position == (Qt::LeftToRight==tab->direction || !horiz ?
3675                                             QStyleOptionTab::Beginning : QStyleOptionTab::End)) || oneTab),
3676                 lastTab((tab->position == (Qt::LeftToRight==tab->direction  || !horiz ?
3677                                            QStyleOptionTab::End : QStyleOptionTab::Beginning)) || oneTab);
3678             int          tabBarAlignment(styleHint(SH_TabBar_Alignment, tab, widget)),
3679                 tabOverlap(oneTab ? 0 : pixelMetric(PM_TabBarTabOverlap, option, widget)),
3680                 moOffset(opts.round == ROUND_NONE || TAB_MO_TOP!=opts.tabMouseOver ? 1 : opts.round),
3681                 highlightOffset(opts.highlightTab && opts.round>ROUND_SLIGHT ? 2 : 1),
3682                 highlightBorder(opts.round>ROUND_FULL ? 4 : 3),
3683                 sizeAdjust(!selected && TAB_MO_GLOW==opts.tabMouseOver ? 1 : 0);
3684             bool leftAligned((!rtlHorTabs && Qt::AlignLeft==tabBarAlignment) ||
3685                              (rtlHorTabs && Qt::AlignRight==tabBarAlignment)),
3686                 rightAligned((!rtlHorTabs && Qt::AlignRight==tabBarAlignment) ||
3687                              (rtlHorTabs && Qt::AlignLeft==tabBarAlignment)),
3688                 docMode(tab->documentMode),
3689                 docFixLeft(!leftCornerWidget && leftAligned && firstTab && (docMode || onlyTab)),
3690                 fixLeft(!onlyTab && !leftCornerWidget && leftAligned && firstTab && !docMode),
3691                 fixRight(!onlyTab && !rightCornerWidget && rightAligned && lastTab && !docMode),
3692                 mouseOver(state&State_Enabled && state&State_MouseOver),
3693                 glowMo(!selected && mouseOver && opts.coloredMouseOver &&
3694                        TAB_MO_GLOW==opts.tabMouseOver),
3695                 thin(opts.thin&THIN_FRAMES),
3696                 drawOuterGlow(glowMo && !thin);
3697             const QColor *use(backgroundColors(option));
3698             QColor       fill(getTabFill(selected, mouseOver, use));
3699             double       radius=qtcGetRadius(&opts, r.width(), r.height(), WIDGET_TAB_TOP, RADIUS_EXTERNAL);
3700             EBorder      borderProfile(selected || opts.borderInactiveTab
3701                                        ? opts.borderTab
3702                                        ? BORDER_LIGHT
3703                                        : BORDER_RAISED
3704                                        : BORDER_FLAT);
3705 
3706             painter->save();
3707 
3708             if(!selected && (100!=opts.bgndOpacity || 100!=opts.dlgOpacity))
3709             {
3710                 QWidget *top=widget ? widget->window() : 0L;
3711                 bool isDialog = top && qtcIsDialog(top);
3712 
3713                 // Note: opacity is divided by 150 to make dark
3714                 // inactive tabs more translucent
3715                 if (isDialog && 100 != opts.dlgOpacity) {
3716                     fill.setAlphaF(opts.dlgOpacity / 150.0);
3717                 } else if (!isDialog && 100 != opts.bgndOpacity) {
3718                     fill.setAlphaF(opts.bgndOpacity / 150.0);
3719                 }
3720             }
3721 
3722             switch(tab->shape) {
3723             case QTabBar::RoundedNorth:
3724             case QTabBar::TriangularNorth:
3725             {
3726                 int round=selected || oneTab || TAB_MO_GLOW==opts.tabMouseOver || opts.roundAllTabs
3727                     ? ROUNDED_TOP
3728                     : firstTab
3729                     ? ROUNDED_TOPLEFT
3730                     : lastTab
3731                     ? ROUNDED_TOPRIGHT
3732                     : ROUNDED_NONE;
3733                 if(!selected)
3734                     r.adjust(0, 2, 0, -2);
3735 
3736                 if(!firstTab)
3737                     r.adjust(-tabOverlap, 0, 0, 0);
3738                 painter->setClipPath(buildPath(r.adjusted(0, 0, 0, 4), WIDGET_TAB_TOP, round, radius));
3739                 fillTab(painter, r.adjusted(1+sizeAdjust, 1, -(1+sizeAdjust), 0), option, fill, true, WIDGET_TAB_TOP, (docMode || onlyTab));
3740                 // This clipping (for selected) helps with plasma's tabs and nvidia
3741                 if(selected || thin)
3742                     painter->setClipRect(r2.adjusted(-1, 0, 1, -1));
3743                 else
3744                     painter->setClipping(false);
3745                 drawBorder(painter, r.adjusted(sizeAdjust, 0, -sizeAdjust, 4), option, round, glowMo ? m_mouseOverCols : 0L,
3746                            WIDGET_TAB_TOP, borderProfile, false);
3747                 if(drawOuterGlow)
3748                     drawGlow(painter, r.adjusted(0, -1, 0, 5), WIDGET_TAB_TOP);
3749 
3750                 if(selected || thin)
3751                     painter->setClipping(false);
3752 
3753                 if(selected)
3754                 {
3755                     if(!thin)
3756                     {
3757                         painter->setPen(use[0]);
3758 
3759                         // The point drawn below is because of the clipping above...
3760                         if(fixLeft)
3761                             painter->drawPoint(r2.x()+1, r2.y()+r2.height()-1);
3762                         else
3763                             painter->drawLine(r2.left()-1, r2.bottom(), r2.left(), r2.bottom());
3764                         if(!fixRight)
3765                             painter->drawLine(r2.right()-1, r2.bottom(), r2.right(), r2.bottom());
3766                     }
3767 
3768                     if(docFixLeft)
3769                     {
3770                         QColor col(use[QTC_STD_BORDER]);
3771                         col.setAlphaF(0.5);
3772                         painter->setPen(col);
3773                         painter->drawPoint(r2.x(), r2.y()+r2.height()-1);
3774                     }
3775                 }
3776                 else
3777                 {
3778                     int l(fixLeft ? r2.left()+(opts.round>ROUND_SLIGHT && !(opts.square&SQUARE_TAB_FRAME) ? 2 : 1) : r2.left()-1),
3779                         r(fixRight ? r2.right()-2 : r2.right()+1);
3780                     painter->setPen(use[QTC_STD_BORDER]);
3781                     painter->drawLine(l, r2.bottom()-1, r, r2.bottom()-1);
3782                     if(!thin)
3783                     {
3784                         painter->setPen(use[0]);
3785                         painter->drawLine(l, r2.bottom(), r, r2.bottom());
3786                     }
3787                 }
3788 
3789                 if(selected)
3790                 {
3791                     if(opts.highlightTab)
3792                     {
3793                         QColor col(m_highlightCols[0]);
3794                         painter->setRenderHint(QPainter::Antialiasing, true);
3795                         painter->setPen(col);
3796                         drawAaLine(painter, r.left()+highlightOffset, r.top()+1, r.right()-highlightOffset, r.top()+1);
3797                         col.setAlphaF(0.5);
3798                         painter->setPen(col);
3799                         drawAaLine(painter, r.left()+1, r.top()+2, r.right()-1, r.top()+2);
3800                         QPAINTER_RENDERHINT_AA_MAYBE_OFF(painter);
3801                         painter->setClipRect(QRect(r.x(), r.y(), r.width(), highlightBorder));
3802                         drawBorder(painter, r, option, ROUNDED_ALL, m_highlightCols, WIDGET_TAB_TOP, BORDER_FLAT, false, 3);
3803                     }
3804 
3805                     if(opts.colorSelTab)
3806                         colorTab(painter, r.adjusted(1+sizeAdjust, 1, -(1+sizeAdjust), 0), true, WIDGET_TAB_TOP, round);
3807                 }
3808                 else if(mouseOver && opts.coloredMouseOver && TAB_MO_GLOW!=opts.tabMouseOver)
3809                     drawHighlight(painter, QRect(r.x()+(firstTab ? moOffset : 1),
3810                                                  r.y()+(TAB_MO_TOP==opts.tabMouseOver ? 0 : r.height()-1),
3811                                                  r.width()-(firstTab || lastTab ? moOffset : 1), 2),
3812                                   true, TAB_MO_TOP==opts.tabMouseOver);
3813                 break;
3814             }
3815             case QTabBar::RoundedSouth:
3816             case QTabBar::TriangularSouth:
3817             {
3818                 int round=selected || oneTab || TAB_MO_GLOW==opts.tabMouseOver || opts.roundAllTabs
3819                     ? ROUNDED_BOTTOM
3820                     : firstTab
3821                     ? ROUNDED_BOTTOMLEFT
3822                     : lastTab
3823                     ? ROUNDED_BOTTOMRIGHT
3824                     : ROUNDED_NONE;
3825                 if(!selected)
3826                     r.adjust(0, 2, 0, -2);
3827                 if(!firstTab)
3828                     r.adjust(-tabOverlap, 0, 0, 0);
3829 
3830                 painter->setClipPath(buildPath(r.adjusted(0, -4, 0, 0), WIDGET_TAB_BOT, round, radius));
3831                 fillTab(painter, r.adjusted(1+sizeAdjust, 0, -(1+sizeAdjust), -1), option, fill, true, WIDGET_TAB_BOT, (docMode || onlyTab));
3832                 if(thin)
3833                     painter->setClipRect(r2.adjusted(0, 1, 0, 0));
3834                 else
3835                     painter->setClipping(false);
3836                 drawBorder(painter, r.adjusted(sizeAdjust, -4, -sizeAdjust, 0), option, round, glowMo ? m_mouseOverCols : 0L,
3837                            WIDGET_TAB_BOT, borderProfile, false);
3838                 if(thin)
3839                     painter->setClipping(false);
3840                 if(drawOuterGlow)
3841                     drawGlow(painter, r.adjusted(0, -5, 0, 1), WIDGET_TAB_BOT);
3842 
3843                 if(selected)
3844                 {
3845                     if(!thin)
3846                     {
3847                         painter->setPen(use[opts.borderTab ? 0 : FRAME_DARK_SHADOW]);
3848                         if(!fixLeft)
3849                             painter->drawPoint(r2.left()-(TAB_MO_GLOW==opts.tabMouseOver ? 0 : 1), r2.top());
3850                         if(!fixRight)
3851                             painter->drawLine(r2.right()-(TAB_MO_GLOW==opts.tabMouseOver ? 0 : 1), r2.top(), r2.right(), r2.top());
3852                     }
3853                     if(docFixLeft)
3854                     {
3855                         QColor col(use[QTC_STD_BORDER]);
3856                         col.setAlphaF(0.5);
3857                         painter->setPen(col);
3858                         painter->drawPoint(r2.x(), r2.y());
3859                     }
3860                 }
3861                 else
3862                 {
3863                     int l(fixLeft ? r2.left()+(opts.round>ROUND_SLIGHT && !(opts.square&SQUARE_TAB_FRAME)? 2 : 1) : r2.left()-1),
3864                         r(fixRight ? r2.right()-2 : r2.right());
3865                     painter->setPen(use[QTC_STD_BORDER]);
3866                     painter->drawLine(l, r2.top()+1, r, r2.top()+1);
3867                     if(!thin)
3868                     {
3869                         painter->setPen(use[opts.borderTab ? 0 : FRAME_DARK_SHADOW]);
3870                         painter->drawLine(l, r2.top(), r, r2.top());
3871                     }
3872                 }
3873 
3874                 if(selected)
3875                 {
3876                     if(opts.highlightTab)
3877                     {
3878                         QColor col(m_highlightCols[0]);
3879                         painter->setRenderHint(QPainter::Antialiasing, true);
3880                         painter->setPen(col);
3881                         drawAaLine(painter, r.left()+highlightOffset, r.bottom()-1, r.right()-highlightOffset, r.bottom()-1);
3882                         col.setAlphaF(0.5);
3883                         painter->setPen(col);
3884                         drawAaLine(painter, r.left()+1, r.bottom()-2, r.right()-1, r.bottom()-2);
3885                         QPAINTER_RENDERHINT_AA_MAYBE_OFF(painter);
3886                         painter->setClipRect(QRect(r.x(), r.y()+r.height()-highlightBorder, r.width(), r.y()+r.height()-1));
3887                         drawBorder(painter, r, option, ROUNDED_ALL, m_highlightCols, WIDGET_TAB_BOT, BORDER_FLAT, false, 3);
3888                     }
3889 
3890                     if(opts.colorSelTab)
3891                         colorTab(painter, r.adjusted(1+sizeAdjust, 0, -(1+sizeAdjust), -1), true, WIDGET_TAB_BOT, round);
3892                 }
3893                 else if(mouseOver && opts.coloredMouseOver && TAB_MO_GLOW!=opts.tabMouseOver)
3894                     drawHighlight(painter, QRect(r.x()+(firstTab ? moOffset : 1),
3895                                                  r.y()+(TAB_MO_TOP==opts.tabMouseOver ? r.height()-2 : -1),
3896                                                  r.width()-(firstTab || lastTab ? moOffset : 1), 2),
3897                                   true, TAB_MO_TOP!=opts.tabMouseOver);
3898                 break;
3899             }
3900             case QTabBar::RoundedWest:
3901             case QTabBar::TriangularWest:
3902             {
3903                 int round=selected || oneTab || TAB_MO_GLOW==opts.tabMouseOver || opts.roundAllTabs
3904                     ? ROUNDED_LEFT
3905                     : firstTab
3906                     ? ROUNDED_TOPLEFT
3907                     : lastTab
3908                     ? ROUNDED_BOTTOMLEFT
3909                     : ROUNDED_NONE;
3910                 if(!selected)
3911                     r.adjust(2, 0, -2, 0);
3912 
3913                 if(!firstTab)
3914                     r.adjust(0, -tabOverlap, 0, 0);
3915                 painter->setClipPath(buildPath(r.adjusted(0, 0, 4, 0), WIDGET_TAB_TOP, round, radius));
3916                 fillTab(painter, r.adjusted(1, sizeAdjust, 0, -(1+sizeAdjust)), option, fill, false, WIDGET_TAB_TOP, (docMode || onlyTab));
3917                 if(thin)
3918                     painter->setClipRect(r2.adjusted(0, 0, -1, 0));
3919                 else
3920                     painter->setClipping(false);
3921                 drawBorder(painter, r.adjusted(0, sizeAdjust, 4, -sizeAdjust), option, round, glowMo ? m_mouseOverCols : 0L,
3922                            WIDGET_TAB_TOP, borderProfile, false);
3923                 if(thin)
3924                     painter->setClipping(false);
3925                 if(drawOuterGlow)
3926                     drawGlow(painter, r.adjusted(-1, 0, 5, 0), WIDGET_TAB_TOP);
3927 
3928                 if(selected)
3929                 {
3930                     if(!thin)
3931                     {
3932                         painter->setPen(use[0]);
3933                         if(!firstTab)
3934                             painter->drawPoint(r2.right(), r2.top()-(TAB_MO_GLOW==opts.tabMouseOver ? 0 : 1));
3935                         painter->drawLine(r2.right(), r2.bottom()-1, r2.right(), r2.bottom());
3936                     }
3937                 }
3938                 else
3939                 {
3940                     int t(firstTab ? r2.top()+(opts.round>ROUND_SLIGHT && !(opts.square&SQUARE_TAB_FRAME)? 2 : 1) : r2.top()-1),
3941                         b(/*lastTab ? r2.bottom()-2 : */ r2.bottom()+1);
3942 
3943                     painter->setPen(use[QTC_STD_BORDER]);
3944                     painter->drawLine(r2.right()-1, t, r2.right()-1, b);
3945                     if(!thin)
3946                     {
3947                         painter->setPen(use[0]);
3948                         painter->drawLine(r2.right(), t, r2.right(), b);
3949                     }
3950                 }
3951 
3952                 if(selected)
3953                 {
3954                     if(opts.highlightTab)
3955                     {
3956                         QColor col(m_highlightCols[0]);
3957                         painter->setRenderHint(QPainter::Antialiasing, true);
3958                         painter->setPen(col);
3959                         drawAaLine(painter, r.left()+1, r.top()+highlightOffset, r.left()+1, r.bottom()-highlightOffset);
3960                         col.setAlphaF(0.5);
3961                         painter->setPen(col);
3962                         drawAaLine(painter, r.left()+2, r.top()+1, r.left()+2, r.bottom()-1);
3963                         QPAINTER_RENDERHINT_AA_MAYBE_OFF(painter);
3964                         painter->setClipRect(QRect(r.x(), r.y(), highlightBorder, r.height()));
3965                         drawBorder(painter, r, option, ROUNDED_ALL, m_highlightCols, WIDGET_TAB_TOP, BORDER_FLAT, false, 3);
3966                     }
3967 
3968                     if(opts.colorSelTab)
3969                         colorTab(painter, r.adjusted(1, sizeAdjust, 0, -(1+sizeAdjust)), false, WIDGET_TAB_TOP, round);
3970                 }
3971                 else if(mouseOver && opts.coloredMouseOver && TAB_MO_GLOW!=opts.tabMouseOver)
3972                     drawHighlight(painter, QRect(r.x()+(TAB_MO_TOP==opts.tabMouseOver ? 0 : r.width()-1),
3973                                                  r.y()+(firstTab ? moOffset : 1),
3974                                                  2, r.height()-(firstTab || lastTab ? moOffset : 1)),
3975                                   false, TAB_MO_TOP==opts.tabMouseOver);
3976                 break;
3977             }
3978             case QTabBar::RoundedEast:
3979             case QTabBar::TriangularEast:
3980             {
3981                 int round=selected || oneTab || TAB_MO_GLOW==opts.tabMouseOver || opts.roundAllTabs
3982                     ? ROUNDED_RIGHT
3983                     : firstTab
3984                     ? ROUNDED_TOPRIGHT
3985                     : lastTab
3986                     ? ROUNDED_BOTTOMRIGHT
3987                     : ROUNDED_NONE;
3988                 if(!selected)
3989                     r.adjust(2, 0, -2, 0);
3990 
3991                 if(!firstTab)
3992                     r.adjust(0, -tabOverlap, 0, 0);
3993                 painter->setClipPath(buildPath(r.adjusted(-4, 0, 0, 0), WIDGET_TAB_BOT, round, radius));
3994                 fillTab(painter, r.adjusted(0, sizeAdjust, -1, -(1+sizeAdjust)), option, fill, false, WIDGET_TAB_BOT, (docMode || onlyTab));
3995                 if(thin)
3996                     painter->setClipRect(r2.adjusted(1, 0, 0, 0));
3997                 else
3998                     painter->setClipping(false);
3999                 drawBorder(painter, r.adjusted(-4, sizeAdjust, 0, -sizeAdjust), option, round, glowMo ? m_mouseOverCols : 0L,
4000                            WIDGET_TAB_BOT, borderProfile, false);
4001                 if(thin)
4002                     painter->setClipping(false);
4003                 if(drawOuterGlow)
4004                     drawGlow(painter, r.adjusted(-5, 0, 1, 0), WIDGET_TAB_BOT);
4005 
4006                 if(selected)
4007                 {
4008                     if(!thin)
4009                     {
4010                         painter->setPen(use[opts.borderTab ? 0 : FRAME_DARK_SHADOW]);
4011                         if(!firstTab)
4012                             painter->drawPoint(r2.left(), r2.top()-(TAB_MO_GLOW==opts.tabMouseOver ? 0 : 1));
4013                         painter->drawLine(r2.left(), r2.bottom()-(TAB_MO_GLOW==opts.tabMouseOver ? 0 : 1), r2.left(), r2.bottom());
4014                     }
4015                 }
4016                 else
4017                 {
4018                     int t(firstTab ? r2.top()+(opts.round>ROUND_SLIGHT && !(opts.square&SQUARE_TAB_FRAME)? 2 : 1) : r2.top()-1),
4019                         b(/*lastTab ? r2.bottom()-2 : */ r2.bottom()+1);
4020 
4021                     painter->setPen(use[QTC_STD_BORDER]);
4022                     painter->drawLine(r2.left()+1, t, r2.left()+1, b);
4023                     if(!thin)
4024                     {
4025                         painter->setPen(use[opts.borderTab ? 0 : FRAME_DARK_SHADOW]);
4026                         painter->drawLine(r2.left(), t, r2.left(), b);
4027                     }
4028                 }
4029 
4030                 if(selected)
4031                 {
4032                     if(opts.highlightTab)
4033                     {
4034                         QColor col(m_highlightCols[0]);
4035                         painter->setRenderHint(QPainter::Antialiasing, true);
4036                         painter->setPen(col);
4037                         drawAaLine(painter, r.right()-1, r.top()+highlightOffset, r.right()-1, r.bottom()-highlightOffset);
4038                         col.setAlphaF(0.5);
4039                         painter->setPen(col);
4040                         drawAaLine(painter, r.right()-2, r.top()+1, r.right()-2, r.bottom()-1);
4041                         QPAINTER_RENDERHINT_AA_MAYBE_OFF(painter);
4042                         painter->setClipRect(QRect(r.x()+r.width()-highlightBorder, r.y(), r.x()+r.width()-1, r.height()));
4043                         drawBorder(painter, r, option, ROUNDED_ALL, m_highlightCols, WIDGET_TAB_TOP, BORDER_FLAT, false, 3);
4044                     }
4045 
4046                     if(opts.colorSelTab)
4047                         colorTab(painter, r.adjusted(0, sizeAdjust, -1, -(1+sizeAdjust)), false, WIDGET_TAB_BOT, round);
4048                 }
4049                 else if(mouseOver && opts.coloredMouseOver && TAB_MO_GLOW!=opts.tabMouseOver)
4050                     drawHighlight(painter, QRect(r.x()+(TAB_MO_TOP==opts.tabMouseOver ? r.width()-2 : -1),
4051                                                  r.y()+(firstTab ? moOffset : 1),
4052                                                  2, r.height()-(firstTab || lastTab ? moOffset : 1)),
4053                                   false, TAB_MO_TOP!=opts.tabMouseOver);
4054                 break;
4055             }
4056             }
4057             painter->restore();
4058         }
4059         break;
4060     case CE_ScrollBarAddLine:
4061     case CE_ScrollBarSubLine:
4062     {
4063         QRect            br(r),
4064             ar(r);
4065         const QColor     *use(state&State_Enabled ? m_buttonCols : m_backgroundCols); // buttonColors(option));
4066         bool             reverse(option && Qt::RightToLeft==option->direction);
4067         PrimitiveElement pe=state&State_Horizontal
4068             ? CE_ScrollBarAddLine==element ? (reverse ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight)
4069             : (reverse ? PE_IndicatorArrowRight : PE_IndicatorArrowLeft)
4070             : CE_ScrollBarAddLine==element ? PE_IndicatorArrowDown : PE_IndicatorArrowUp;
4071         int              round=PE_IndicatorArrowRight==pe ? ROUNDED_RIGHT :
4072             PE_IndicatorArrowLeft==pe ? ROUNDED_LEFT :
4073             PE_IndicatorArrowDown==pe ? ROUNDED_BOTTOM :
4074             PE_IndicatorArrowUp==pe ? ROUNDED_TOP : ROUNDED_NONE;
4075 
4076         switch(opts.scrollbarType)
4077         {
4078         default:
4079         case SCROLLBAR_WINDOWS:
4080             break;
4081         case SCROLLBAR_KDE:
4082         case SCROLLBAR_PLATINUM:
4083             if(!reverse && PE_IndicatorArrowLeft==pe && r.x()>3)
4084             {
4085                 round=ROUNDED_NONE;
4086                 br.adjust(0, 0, 1, 0);
4087                 if(opts.flatSbarButtons || !opts.vArrows)
4088                     ar.adjust(1, 0, 1, 0);
4089             }
4090             else if(reverse && PE_IndicatorArrowRight==pe && r.x()>3)
4091             {
4092                 if(SCROLLBAR_PLATINUM==opts.scrollbarType)
4093                 {
4094                     round=ROUNDED_NONE;
4095                     br.adjust(-1, 0, 0, 0);
4096                     if(opts.flatSbarButtons || !opts.vArrows)
4097                         ar.adjust(-1, 0, -1, 0);
4098                 }
4099                 else
4100                 {
4101                     if(r.x()<pixelMetric(PM_ScrollBarExtent, option, widget)+2)
4102                         round=ROUNDED_NONE;
4103                     br.adjust(0, 0, 1, 0);
4104                     if(opts.flatSbarButtons || !opts.vArrows)
4105                         ar.adjust(1, 0, 1, 0);
4106                 }
4107             }
4108             else if(PE_IndicatorArrowUp==pe && r.y()>3)
4109             {
4110                 round=ROUNDED_NONE;
4111                 br.adjust(0, 0, 0, 1);
4112                 if(opts.flatSbarButtons || !opts.vArrows)
4113                     ar.adjust(0, 1, 0, 1);
4114             }
4115             break;
4116         case SCROLLBAR_NEXT:
4117             if(!reverse && PE_IndicatorArrowRight==pe)
4118             {
4119                 round=ROUNDED_NONE;
4120                 br.adjust(-1, 0, 0, 0);
4121                 if(opts.flatSbarButtons || !opts.vArrows)
4122                     ar.adjust(-1, 0, 0, -1);
4123             }
4124             else if(reverse && PE_IndicatorArrowLeft==pe)
4125             {
4126                 round=ROUNDED_NONE;
4127                 br.adjust(0, 0, 1, 0);
4128                 if(opts.flatSbarButtons || !opts.vArrows)
4129                     ar.adjust(-1, 0, 0, 1);
4130             }
4131             else if(PE_IndicatorArrowDown==pe)
4132             {
4133                 round=ROUNDED_NONE;
4134                 br.adjust(0, -1, 0, 0);
4135                 if(opts.flatSbarButtons || !opts.vArrows)
4136                     ar.adjust(0, -1, 0, -1);
4137             }
4138             break;
4139         }
4140 
4141         painter->save();
4142         if(opts.flatSbarButtons && !qtcIsFlat(opts.sbarBgndAppearance) /*&& SCROLLBAR_NONE!=opts.scrollbarType*/)
4143             drawBevelGradientReal(palette.brush(QPalette::Background).color(), painter, r, state&State_Horizontal, false,
4144                                   opts.sbarBgndAppearance, WIDGET_SB_BGND);
4145 
4146         QStyleOption opt(*option);
4147 
4148         opt.state|=State_Raised;
4149 
4150         if (auto slider = styleOptCast<QStyleOptionSlider>(option)) {
4151             if((CE_ScrollBarSubLine==element && slider->sliderValue==slider->minimum) ||
4152                (CE_ScrollBarAddLine==element && slider->sliderValue==slider->maximum))
4153                 opt.state&=~(State_MouseOver|State_Sunken|State_On);
4154 
4155             if(slider->minimum==slider->maximum && opt.state&State_Enabled)
4156                 opt.state^=State_Enabled;
4157         }
4158 
4159         if(opts.flatSbarButtons)
4160             opt.state&=~(State_Sunken|State_On);
4161         else
4162             drawLightBevel(painter, br, &opt, widget, round, getFill(&opt, use), use, true, WIDGET_SB_BUTTON);
4163 
4164         opt.rect = ar;
4165 
4166         if(!(opt.state&State_Enabled))
4167             opt.palette.setCurrentColorGroup(QPalette::Disabled);
4168 
4169         if(opt.palette.text().color()!=opt.palette.buttonText().color()) // The following fixes gwenviews scrollbars...
4170             opt.palette.setColor(QPalette::Text, opt.palette.buttonText().color());
4171 
4172         drawPrimitive(pe, &opt, painter, widget);
4173         painter->restore();
4174         break;
4175     }
4176     case CE_ScrollBarSubPage:
4177     case CE_ScrollBarAddPage:
4178     {
4179         const QColor *use(m_backgroundCols); // backgroundColors(option));
4180         int          borderAdjust(0);
4181 
4182         painter->save();
4183 #ifndef SIMPLE_SCROLLBARS
4184         if (opts.round != ROUND_NONE && (SCROLLBAR_NONE==opts.scrollbarType || opts.flatSbarButtons))
4185             painter->fillRect(r, palette.background().color());
4186 #endif
4187 
4188         switch(opts.scrollbarType)
4189         {
4190         case SCROLLBAR_KDE:
4191         case SCROLLBAR_WINDOWS:
4192             borderAdjust=1;
4193             break;
4194         case SCROLLBAR_PLATINUM:
4195             if(CE_ScrollBarAddPage==element)
4196                 borderAdjust=1;
4197             break;
4198         case SCROLLBAR_NEXT:
4199             if(CE_ScrollBarSubPage==element)
4200                 borderAdjust=1;
4201         default:
4202             break;
4203         }
4204 
4205         if(state&State_Horizontal)
4206         {
4207             if(qtcIsFlat(opts.appearance))
4208                 painter->fillRect(r.x(), r.y()+1, r.width(), r.height()-2, use[2]);
4209             else
4210                 drawBevelGradient(use[2], painter, QRect(r.x(), r.y()+1, r.width(), r.height()-2),
4211                                   true, false, opts.grooveAppearance, WIDGET_TROUGH);
4212 
4213 #ifndef SIMPLE_SCROLLBARS
4214             if (opts.round != ROUND_NONE && (SCROLLBAR_NONE==opts.scrollbarType || opts.flatSbarButtons))
4215             {
4216                 if(CE_ScrollBarAddPage==element)
4217                     drawBorder(painter, r.adjusted(-5, 0, 0, 0), option, ROUNDED_RIGHT, use, WIDGET_TROUGH);
4218                 else
4219                     drawBorder(painter, r.adjusted(0, 0, 5, 0), option, ROUNDED_LEFT, use, WIDGET_TROUGH);
4220             }
4221             else
4222 #endif
4223                 if(CE_ScrollBarAddPage==element)
4224                     drawBorder(painter, r.adjusted(-5, 0, borderAdjust, 0), option, ROUNDED_NONE, use, WIDGET_TROUGH);
4225                 else
4226                     drawBorder(painter, r.adjusted(-borderAdjust, 0, 5, 0), option, ROUNDED_NONE, use, WIDGET_TROUGH);
4227         }
4228         else
4229         {
4230             if(qtcIsFlat(opts.appearance))
4231                 painter->fillRect(r.x()+1, r.y(), r.width()-2, r.height(), use[2]);
4232             else
4233                 drawBevelGradient(use[2], painter, QRect(r.x()+1, r.y(), r.width()-2, r.height()),
4234                                   false, false, opts.grooveAppearance, WIDGET_TROUGH);
4235 
4236 #ifndef SIMPLE_SCROLLBARS
4237             if (opts.round != ROUND_NONE && (SCROLLBAR_NONE==opts.scrollbarType || opts.flatSbarButtons))
4238             {
4239                 if(CE_ScrollBarAddPage==element)
4240                     drawBorder(painter, r.adjusted(0, -5, 0, 0), option, ROUNDED_BOTTOM, use, WIDGET_TROUGH);
4241                 else
4242                     drawBorder(painter, r.adjusted(0, 0, 0, 5), option, ROUNDED_TOP, use, WIDGET_TROUGH);
4243             }
4244             else
4245 #endif
4246                 if(CE_ScrollBarAddPage==element)
4247                     drawBorder(painter, r.adjusted(0, -5, 0, borderAdjust), option, ROUNDED_NONE, use, WIDGET_TROUGH);
4248                 else
4249                     drawBorder(painter, r.adjusted(0, -borderAdjust, 0, 5), option, ROUNDED_NONE, use, WIDGET_TROUGH);
4250         }
4251         painter->restore();
4252         break;
4253     }
4254     case CE_ScrollBarSlider:
4255         painter->save();
4256         drawSbSliderHandle(painter, r, option);
4257         painter->restore();
4258         break;
4259 #ifdef FIX_DISABLED_ICONS
4260         // Taken from QStyle - only required so that we can corectly set the disabled icon!!!
4261     case CE_ToolButtonLabel:
4262         if (auto tb = styleOptCast<QStyleOptionToolButton>(option)) {
4263             int shiftX = 0;
4264             int shiftY = 0;
4265             if (state & (State_Sunken | State_On)) {
4266                 shiftX = pixelMetric(PM_ButtonShiftHorizontal, tb, widget);
4267                 shiftY = pixelMetric(PM_ButtonShiftVertical, tb, widget);
4268             }
4269 
4270             // Arrow type always overrules and is always shown
4271             bool hasArrow = tb->features & QStyleOptionToolButton::Arrow;
4272 
4273             if (((!hasArrow && tb->icon.isNull()) && !tb->text.isEmpty()) ||
4274                 tb->toolButtonStyle == Qt::ToolButtonTextOnly) {
4275                 int alignment = Qt::AlignCenter|Qt::TextShowMnemonic;
4276 
4277                 if (!styleHint(SH_UnderlineShortcut, option, widget))
4278                     alignment |= Qt::TextHideMnemonic;
4279 
4280                 r.translate(shiftX, shiftY);
4281 
4282                 drawItemTextWithRole(painter, r, alignment, palette, state&State_Enabled,
4283                                      tb->text, QPalette::ButtonText);
4284             } else {
4285                 QPixmap pm;
4286                 QSize   iconSize = tb->iconSize;
4287                 QRect   pr = r;
4288 
4289                 if (!tb->icon.isNull()) {
4290                     QIcon::State state = tb->state & State_On ? QIcon::On : QIcon::Off;
4291                     QIcon::Mode mode;
4292                     if (!(tb->state & State_Enabled)) {
4293                         mode = QIcon::Disabled;
4294                     } else if ((state & State_MouseOver) && (state & State_AutoRaise)) {
4295                         mode = QIcon::Active;
4296                     } else {
4297                         mode = QIcon::Normal;
4298                     }
4299 
4300                     if (!iconSize.isValid()) {
4301                         int iconExtent = pixelMetric(PM_ToolBarIconSize);
4302                         iconSize = QSize(iconExtent, iconExtent);
4303                     }
4304 
4305                     if (iconSize.width() > tb->rect.size().width())
4306                         iconSize = QSize(tb->rect.size().width(), tb->rect.size().width());
4307                     if (iconSize.height() > tb->rect.size().height())
4308                         iconSize = QSize(tb->rect.size().height(), tb->rect.size().height());
4309 
4310                     pm = getIconPixmap(tb->icon, iconSize, mode, state);
4311                 }
4312 
4313                 if (Qt::ToolButtonIconOnly!=tb->toolButtonStyle)
4314                 {
4315                     QRect tr = r;
4316                     int   alignment = Qt::TextShowMnemonic;
4317 
4318                     painter->setFont(tb->font);
4319                     if (!styleHint(SH_UnderlineShortcut, option, widget))
4320                         alignment |= Qt::TextHideMnemonic;
4321 
4322                     if (Qt::ToolButtonTextUnderIcon==tb->toolButtonStyle)
4323                     {
4324                         pr.setHeight(iconSize.height() + 6);
4325 
4326                         tr.adjust(0, pr.bottom()-3, 0, 0); // -3);
4327                         pr.translate(shiftX, shiftY);
4328                         if (hasArrow)
4329                             drawTbArrow(this, tb, pr, painter, widget);
4330                         else
4331                             drawItemPixmap(painter, pr, Qt::AlignCenter, pm);
4332                         alignment |= Qt::AlignCenter;
4333                     }
4334                     else
4335                     {
4336                         pr.setWidth(iconSize.width() + 8);
4337                         tr.adjust(pr.right(), 0, 0, 0);
4338                         pr.translate(shiftX, shiftY);
4339                         if (hasArrow)
4340                             drawTbArrow(this, tb, pr, painter, widget);
4341                         else
4342                             drawItemPixmap(painter, QStyle::visualRect(option->direction, r, pr), Qt::AlignCenter, pm);
4343                         alignment |= Qt::AlignLeft | Qt::AlignVCenter;
4344                     }
4345                     tr.translate(shiftX, shiftY);
4346                     drawItemTextWithRole(painter, QStyle::visualRect(option->direction, r, tr), alignment, palette,
4347                                          state & State_Enabled, tb->text, QPalette::ButtonText);
4348                 }
4349                 else
4350                 {
4351                     pr.translate(shiftX, shiftY);
4352 
4353                     if (hasArrow)
4354                         drawTbArrow(this, tb, pr, painter, widget);
4355                     else
4356                     {
4357                         if (!(tb->subControls&SC_ToolButtonMenu) && tb->features&QStyleOptionToolButton::HasMenu &&
4358                             pr.width()>pm.width() && ((pr.width()-pm.width())>LARGE_ARR_WIDTH))
4359                             pr.adjust(-LARGE_ARR_WIDTH, 0, 0, 0);
4360                         drawItemPixmap(painter, pr, Qt::AlignCenter, pm);
4361                     }
4362                 }
4363             }
4364         }
4365         break;
4366     case CE_RadioButtonLabel:
4367     case CE_CheckBoxLabel:
4368         if (auto btn = styleOptCast<QStyleOptionButton>(option)) {
4369             uint    alignment = visualAlignment(btn->direction, Qt::AlignLeft | Qt::AlignVCenter);
4370             QPixmap pix;
4371             QRect   textRect = r;
4372 
4373             if (!styleHint(SH_UnderlineShortcut, btn, widget))
4374                 alignment |= Qt::TextHideMnemonic;
4375 
4376             if (!btn->icon.isNull())
4377             {
4378                 pix = getIconPixmap(btn->icon, btn->iconSize, btn->state);
4379                 drawItemPixmap(painter, r, alignment, pix);
4380                 if (reverse)
4381                     textRect.setRight(textRect.right() - btn->iconSize.width() - 4);
4382                 else
4383                     textRect.setLeft(textRect.left() + btn->iconSize.width() + 4);
4384             }
4385             if (!btn->text.isEmpty())
4386                 drawItemTextWithRole(painter, textRect, alignment | Qt::TextShowMnemonic,
4387                                      palette, state&State_Enabled, btn->text, QPalette::WindowText);
4388         }
4389         break;
4390     case CE_ToolBoxTabLabel:
4391         if (auto tb = styleOptCast<QStyleOptionToolBox>(option)) {
4392             bool    enabled = state & State_Enabled,
4393                 selected = state & State_Selected;
4394             QPixmap pm = getIconPixmap(tb->icon, pixelMetric(QStyle::PM_SmallIconSize, tb, widget) ,state);
4395             QRect   cr = subElementRect(QStyle::SE_ToolBoxTabContents, tb, widget);
4396             QRect   tr, ir;
4397             int     ih = 0;
4398 
4399             if (pm.isNull())
4400             {
4401                 tr = cr;
4402                 tr.adjust(4, 0, -8, 0);
4403             }
4404             else
4405             {
4406                 int iw = pm.width() + 4;
4407                 ih = pm.height();
4408                 ir = QRect(cr.left() + 4, cr.top(), iw + 2, ih);
4409                 tr = QRect(ir.right(), cr.top(), cr.width() - ir.right() - 4, cr.height());
4410             }
4411 
4412             if (selected && styleHint(QStyle::SH_ToolBox_SelectedPageTitleBold, tb, widget))
4413             {
4414                 QFont f(painter->font());
4415                 f.setBold(true);
4416                 painter->setFont(f);
4417             }
4418 
4419             QString txt = tb->fontMetrics.elidedText(tb->text, Qt::ElideRight, tr.width());
4420 
4421             if (ih)
4422                 painter->drawPixmap(ir.left(), (tb->rect.height() - ih) / 2, pm);
4423 
4424             int alignment = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic;
4425             if (!styleHint(QStyle::SH_UnderlineShortcut, tb, widget))
4426                 alignment |= Qt::TextHideMnemonic;
4427             drawItemTextWithRole(painter, tr, alignment, tb->palette, enabled, txt, QPalette::ButtonText);
4428 
4429             if (!txt.isEmpty() && state&State_HasFocus)
4430             {
4431                 QStyleOptionFocusRect opt;
4432                 opt.rect = tr;
4433                 opt.palette = palette;
4434                 opt.state = QStyle::State_None;
4435                 drawPrimitive(PE_FrameFocusRect, &opt, painter, widget);
4436             }
4437         }
4438         break;
4439 #endif
4440     case CE_RadioButton:
4441     case CE_CheckBox:
4442         if (opts.crHighlight && (r.width()>opts.crSize*2))
4443             if (auto button = styleOptCast<QStyleOptionButton>(option)) {
4444                 QStyleOptionButton copy(*button);
4445 
4446                 copy.rect.adjust(2, 0, -2, 0);
4447 
4448                 if(button->state&State_MouseOver && button->state&State_Enabled)
4449                 {
4450                     QRect highlightRect(subElementRect(CE_RadioButton==element ? SE_RadioButtonFocusRect : SE_CheckBoxFocusRect,
4451                                                        option, widget));
4452 
4453                     if(Qt::RightToLeft==button->direction)
4454                         highlightRect.setRight(r.right());
4455                     else
4456                         highlightRect.setX(r.x());
4457                     highlightRect.setWidth(highlightRect.width()+1);
4458 
4459                     if(ROUND_NONE!=opts.round)
4460                     {
4461                         painter->save();
4462                         painter->setRenderHint(QPainter::Antialiasing, true);
4463                         double   radius(qtcGetRadius(&opts, highlightRect.width(), highlightRect.height(),
4464                                                      WIDGET_OTHER, RADIUS_SELECTION));
4465 
4466                         drawBevelGradient(shade(palette.background().color(), TO_FACTOR(opts.crHighlight)),
4467                                           painter, highlightRect,
4468                                           buildPath(QRectF(highlightRect), WIDGET_OTHER, ROUNDED_ALL, radius), true,
4469                                           false, opts.selectionAppearance, WIDGET_SELECTION, false);
4470                         painter->restore();
4471                     }
4472                     else
4473                         drawBevelGradient(shade(palette.background().color(), TO_FACTOR(opts.crHighlight)), painter,
4474                                           highlightRect, true, false, opts.selectionAppearance, WIDGET_SELECTION);
4475                 }
4476                 ParentStyleClass::drawControl(element, &copy, painter, widget);
4477                 break;
4478             }
4479         // Fall through!
4480     default:
4481         ParentStyleClass::drawControl(element, option, painter, widget);
4482     }
4483 }
4484 
drawComplexControl(ComplexControl control,const QStyleOptionComplex * option,QPainter * painter,const QWidget * widget) const4485 void Style::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
4486 {
4487     prePolish(widget);
4488     QRect               r(option->rect);
4489     const State &state(option->state);
4490     const QPalette      &palette(option->palette);
4491     bool                reverse(Qt::RightToLeft==option->direction);
4492 
4493     switch (control)
4494     {
4495     case CC_Dial:
4496         if (auto slider = styleOptCast<QStyleOptionSlider>(option)) {
4497             r.adjust(1, 1, -1, -1);
4498 
4499             QStyleOptionComplex opt(*option);
4500             bool                mo(state&State_Enabled && state&State_MouseOver);
4501             QRect               outer(r);
4502             int                 sliderWidth = /*qMin(2*r.width()/5, */CIRCULAR_SLIDER_SIZE/*)*/;
4503 #ifdef DIAL_DOT_ON_RING
4504             int                 halfWidth=sliderWidth/2;
4505 #endif
4506 
4507             opt.state|=State_Horizontal;
4508 
4509             // Outer circle...
4510             if (outer.width() > outer.height())
4511             {
4512                 outer.setLeft(outer.x()+(outer.width()-outer.height())/2);
4513                 outer.setWidth(outer.height());
4514             }
4515             else
4516             {
4517                 outer.setTop(outer.y()+(outer.height()-outer.width())/2);
4518                 outer.setHeight(outer.width());
4519             }
4520 
4521             opt.state&=~State_MouseOver;
4522 #ifdef DIAL_DOT_ON_RING
4523             opt.rect=outer.adjusted(halfWidth, halfWidth, -halfWidth, -halfWidth);
4524 #else
4525             opt.rect=outer;
4526 #endif
4527             drawLightBevel(painter, opt.rect, &opt, widget, ROUNDED_ALL,
4528                            getFill(&opt, m_backgroundCols), m_backgroundCols,
4529                            true, WIDGET_DIAL);
4530 
4531             // Inner 'dot'
4532             if(mo)
4533                 opt.state|=State_MouseOver;
4534 
4535             // angle calculation from qcommonstyle.cpp (c) Trolltech 1992-2007, ASA.
4536             qreal               angle(0);
4537             if(slider->maximum == slider->minimum)
4538                 angle = M_PI / 2;
4539             else
4540             {
4541                 const qreal fraction(qreal(slider->sliderValue - slider->minimum)/
4542                                      qreal(slider->maximum - slider->minimum));
4543                 if(slider->dialWrapping)
4544                     angle = 1.5*M_PI - fraction*2*M_PI;
4545                 else
4546                     angle = (M_PI*8 - fraction*10*M_PI)/6;
4547             }
4548 
4549             QPoint center = outer.center();
4550 #ifdef DIAL_DOT_ON_RING
4551             const qreal radius=0.5*(outer.width() - sliderWidth);
4552 #else
4553             const qreal radius=0.5*(outer.width() - 2*sliderWidth);
4554 #endif
4555             center += QPoint(radius*cos(angle), -radius*sin(angle));
4556 
4557             opt.rect=QRect(outer.x(), outer.y(), sliderWidth, sliderWidth);
4558             opt.rect.moveCenter(center);
4559 
4560             const QColor *use(buttonColors(option));
4561 
4562             drawLightBevel(painter, opt.rect, &opt, widget, ROUNDED_ALL,
4563                            getFill(&opt, use), use, true, WIDGET_RADIO_BUTTON);
4564 
4565             // Draw value...
4566 #ifdef DIAL_DOT_ON_RING
4567             drawItemTextWithRole(painter, outer.adjusted(sliderWidth, sliderWidth, -sliderWidth, -sliderWidth),
4568                                  Qt::AlignCenter, palette, state&State_Enabled,
4569                                  QString::number(slider->sliderValue), QPalette::ButtonText);
4570 #else
4571             int adjust=2*sliderWidth;
4572             drawItemTextWithRole(painter, outer.adjusted(adjust, adjust, -adjust, -adjust),
4573                                  Qt::AlignCenter, palette, state&State_Enabled,
4574                                  QString::number(slider->sliderValue), QPalette::ButtonText);
4575 #endif
4576 
4577             if(state&State_HasFocus)
4578             {
4579                 QStyleOptionFocusRect fr;
4580                 fr.rect = outer.adjusted(-1, -1, 1, 1);
4581                 drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
4582             }
4583         }
4584         break;
4585     case CC_ToolButton:
4586         // For OO.o 3.2 need to fill widget background!
4587         if(isOOWidget(widget))
4588             painter->fillRect(r, palette.brush(QPalette::Window));
4589         if (auto toolbutton = styleOptCast<QStyleOptionToolButton>(option)) {
4590             int widthAdjust(0),
4591                 heightAdjust(0);
4592 
4593             if (widget) {
4594                 if ((opts.dwtSettings & DWT_BUTTONS_AS_PER_TITLEBAR) &&
4595                     (widget->inherits("QDockWidgetTitleButton") ||
4596                      qtcCheckType(getParent(widget),
4597                                   "KoDockWidgetTitleBar"))) {
4598                     ETitleBarButtons btn = TITLEBAR_CLOSE;
4599                     Icon icon = ICN_CLOSE;
4600 
4601                     if (constDwtFloat == widget->objectName()) {
4602                         btn = TITLEBAR_MAX;
4603                         icon = ICN_RESTORE;
4604                     } else if (constDwtClose != widget->objectName() &&
4605                                qtcCheckType(getParent(widget),
4606                                             "KoDockWidgetTitleBar") &&
4607                                qtcCheckType<QDockWidget>(
4608                                    getParent<2>(widget))) {
4609                         QDockWidget *dw = (QDockWidget*)getParent<2>(widget);
4610                         QWidget *koDw = widget->parentWidget();
4611                         int fw = dw->isFloating()
4612                             ? pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, dw)
4613                             : 0;
4614                         QRect geom(widget->geometry());
4615                         QStyleOptionDockWidget dwOpt;
4616                         dwOpt.initFrom(dw);
4617                         dwOpt.rect = QRect(QPoint(fw, fw),
4618                                            QSize(koDw->geometry().width() -
4619                                                  (fw * 2),
4620                                                  koDw->geometry().height() -
4621                                                  (fw * 2)));
4622                         dwOpt.title = dw->windowTitle();
4623                         dwOpt.closable = (dw->features() &
4624                                           QDockWidget::DockWidgetClosable) == QDockWidget::DockWidgetClosable;
4625                         dwOpt.floatable = (dw->features() &
4626                                            QDockWidget::DockWidgetFloatable) ==
4627                             QDockWidget::DockWidgetFloatable;
4628 
4629                         if(dwOpt.closable && subElementRect(QStyle::SE_DockWidgetCloseButton, &dwOpt,
4630                                                             widget->parentWidget()->parentWidget())==geom)
4631                             btn=TITLEBAR_CLOSE, icon=ICN_CLOSE;
4632                         else if(dwOpt.floatable && subElementRect(QStyle::SE_DockWidgetFloatButton, &dwOpt,
4633                                                                   widget->parentWidget()->parentWidget())==geom)
4634                             btn=TITLEBAR_MAX, icon=ICN_RESTORE;
4635                         else
4636                             btn=TITLEBAR_SHADE, icon=dw && dw->widget() && dw->widget()->isVisible()
4637                                 ? ICN_SHADE
4638                                 : ICN_UNSHADE;
4639                     }
4640 
4641                     QColor        shadow(WINDOW_SHADOW_COLOR(opts.titlebarEffect));
4642                     const QColor *bgndCols((opts.dwtSettings&DWT_COLOR_AS_PER_TITLEBAR)
4643                                            ? getMdiColors(option, state&State_Active)
4644                                            : buttonColors(option)),
4645                         *btnCols((opts.dwtSettings&DWT_COLOR_AS_PER_TITLEBAR)
4646                                  ? opts.titlebarButtons&TITLEBAR_BUTTON_STD_COLOR
4647                                  ? buttonColors(option)
4648                                  : getMdiColors(option, state&State_Active)
4649                                  : bgndCols);
4650 
4651                     drawDwtControl(painter, state, r.adjusted(-1, -1, 1, 1), btn,
4652                                    icon, option->palette.color(QPalette::WindowText), btnCols,
4653                                    bgndCols);
4654                     break;
4655                 }
4656                 if(qobject_cast<QTabBar *>(widget->parentWidget()))
4657                 {
4658                     QStyleOptionToolButton btn(*toolbutton);
4659 
4660                     if(Qt::LeftArrow==toolbutton->arrowType || Qt::RightArrow==toolbutton->arrowType)
4661                         btn.rect.adjust(0, 4, 0, -4);
4662                     else
4663                         btn.rect.adjust(4, 0, -4, 0);
4664                     if(!(btn.state&State_Enabled))
4665                         btn.state&=~State_MouseOver;
4666                     drawPrimitive(PE_PanelButtonTool, &btn, painter, widget);
4667                     if(opts.vArrows)
4668                         switch(toolbutton->arrowType)
4669                         {
4670                         case Qt::LeftArrow:
4671                             btn.rect.adjust(-1, 0, -1, 0);
4672                             break;
4673                         case Qt::RightArrow:
4674                             btn.rect.adjust(1, 0, 1, 0);
4675                             break;
4676                         case Qt::UpArrow:
4677                             btn.rect.adjust(0, -1, 0, -1);
4678                             break;
4679                         case Qt::DownArrow:
4680                             btn.rect.adjust(0, 1, 0, 1);
4681                         default:
4682                             break;
4683                         }
4684                     drawTbArrow(this, &btn, btn.rect, painter, widget);
4685                     break;
4686                 }
4687 
4688                 const QToolButton *btn = qobject_cast<const QToolButton *>(widget);
4689 
4690                 if(btn && btn->isDown() && Qt::ToolButtonTextBesideIcon==btn->toolButtonStyle() &&
4691                    widget->parentWidget() && qobject_cast<QMenu*>(widget->parentWidget()))
4692                 {
4693                     painter->save();
4694                     if(opts.menuStripe)
4695                     {
4696                         int stripeWidth(qMax(20, constMenuPixmapWidth));
4697 
4698                         drawBevelGradient(menuStripeCol(),
4699                                           painter, QRect(reverse ? r.right()-stripeWidth : r.x(), r.y(),
4700                                                          stripeWidth, r.height()), false,
4701                                           false, opts.menuStripeAppearance, WIDGET_OTHER);
4702                     }
4703 
4704 #if 0
4705                     // For some reason the MenuTitle has a larger border on the left, so adjust the width by 1 pixel to make this look nicer.
4706                     //drawBorder(painter, r.adjusted(2, 2, -3, -2), option, ROUNDED_ALL, 0L, WIDGET_OTHER, BORDER_SUNKEN);
4707                     QStyleOptionToolButton opt(*toolbutton);
4708                     opt.rect = r.adjusted(2, 2, -3, -2);
4709                     opt.state=State_Raised|State_Enabled|State_Horizontal;
4710                     drawLightBevel(painter, opt.rect, &opt, widget, ROUNDED_ALL,
4711                                    getFill(&opt, m_backgroundCols), m_backgroundCols, true, WIDGET_NO_ETCH_BTN);
4712 #else
4713                     if(!opts.menuStripe)
4714                         drawFadedLine(painter, QRect(r.x()+3, r.y()+r.height()-1, r.width()-7, 1),
4715                                       popupMenuCols(option)[MENU_SEP_SHADE], true, true, true);
4716 #endif
4717                     QFont font(toolbutton->font);
4718 
4719                     font.setBold(true);
4720                     painter->setFont(font);
4721                     drawItemTextWithRole(painter, r, Qt::AlignHCenter | Qt::AlignVCenter,
4722                                          palette, state&State_Enabled, toolbutton->text, QPalette::Text);
4723                     painter->restore();
4724                     break;
4725                 }
4726 
4727                 // Amarok's toolbars (the one just above the collection list)
4728                 // are much thinner then normal, and QToolBarExtension does not
4729                 // seem to take this into account - so adjust the size here...
4730                 QWidget *parent = getParent(widget);
4731                 if (widget->inherits("QToolBarExtension") && parent) {
4732                     if (r.height() > parent->rect().height()) {
4733                         heightAdjust = (r.height() -
4734                                         parent->rect().height()) + 2;
4735                     }
4736                     if (r.width() > parent->rect().width()) {
4737                         widthAdjust = (r.width() -
4738                                        parent->rect().width()) + 2;
4739                     }
4740                 }
4741             }
4742             QRect button(subControlRect(control, toolbutton, SC_ToolButton, widget)),
4743                 menuarea(subControlRect(control, toolbutton, SC_ToolButtonMenu, widget));
4744             State bflags(toolbutton->state);
4745             bool  etched(opts.buttonEffect != EFFECT_NONE),
4746                 raised=widget && (TBTN_RAISED==opts.tbarBtns || TBTN_JOINED==opts.tbarBtns),
4747                 horizTBar(true);
4748             int   round=ROUNDED_ALL,
4749                 leftAdjust(0), topAdjust(0), rightAdjust(0), bottomAdjust(0);
4750 
4751             if(raised)
4752             {
4753                 const QToolBar *toolbar=getToolBar(widget);
4754 
4755                 if(toolbar)
4756                 {
4757                     if(TBTN_JOINED==opts.tbarBtns)
4758                     {
4759                         horizTBar=Qt::Horizontal==toolbar->orientation();
4760                         adjustToolbarButtons(widget, toolbar, leftAdjust, topAdjust, rightAdjust, bottomAdjust, round);
4761                     }
4762                 }
4763                 else
4764                     raised=false;
4765             }
4766 
4767             if (!(bflags&State_Enabled))
4768                 bflags &= ~(State_MouseOver/* | State_Raised*/);
4769 
4770             if(bflags&State_MouseOver)
4771                 bflags |= State_Raised;
4772             else if(!raised && (bflags&State_AutoRaise))
4773                 bflags &= ~State_Raised;
4774 
4775             if(state&State_AutoRaise || toolbutton->subControls&SC_ToolButtonMenu)
4776                 bflags|=STATE_TBAR_BUTTON;
4777 
4778             State mflags(bflags);
4779 
4780             if (!isOOWidget(widget)) {
4781                 if (state&State_Sunken &&
4782                     !(toolbutton->activeSubControls & SC_ToolButton)) {
4783                     bflags &= ~State_Sunken;
4784                 }
4785             }
4786 
4787             bool         drawMenu=TBTN_JOINED==opts.tbarBtns
4788                 ? mflags & (State_Sunken | State_On)
4789                 : raised || (mflags & (State_Sunken | State_On | State_Raised)),
4790                 drawnBevel=false;
4791             QStyleOption tool(0);
4792             tool.palette = toolbutton->palette;
4793 
4794             if ( raised ||
4795                  (toolbutton->subControls&SC_ToolButton && (bflags & (State_Sunken | State_On | State_Raised))) ||
4796                  (toolbutton->subControls&SC_ToolButtonMenu && drawMenu))
4797             {
4798                 const QColor *use(buttonColors(toolbutton));
4799 
4800                 tool.rect = (toolbutton->subControls&SC_ToolButtonMenu ? button.united(menuarea) : button)
4801                     .adjusted(leftAdjust, topAdjust, rightAdjust, bottomAdjust);
4802                 tool.state = bflags|State_Horizontal;
4803 
4804                 if(raised && TBTN_JOINED==opts.tbarBtns && !horizTBar)
4805                     tool.state &= ~State_Horizontal;
4806 
4807                 tool.rect.adjust(0, 0, -widthAdjust, -heightAdjust);
4808                 if(!(bflags&State_Sunken) && (mflags&State_Sunken))
4809                     tool.state &= ~State_MouseOver;
4810                 drawnBevel=true;
4811                 drawLightBevel(painter, tool.rect, &tool, widget, round, getFill(&tool, use), use, true, WIDGET_TOOLBAR_BUTTON);
4812 
4813                 if(raised && TBTN_JOINED==opts.tbarBtns)
4814                 {
4815                     const int constSpace=4;
4816 
4817                     QRect br(tool.rect.adjusted(-leftAdjust, -topAdjust, -rightAdjust, -bottomAdjust));
4818 
4819                     if(leftAdjust)
4820                         drawFadedLine(painter, QRect(br.x(), br.y()+constSpace, 1, br.height()-(constSpace*2)), use[0], true, true, false);
4821                     if(topAdjust)
4822                         drawFadedLine(painter, QRect(br.x()+constSpace, br.y(), br.width()-(constSpace*2), 1), use[0], true, true, true);
4823                     if(rightAdjust)
4824                         drawFadedLine(painter, QRect(br.x()+br.width()-1, br.y()+constSpace, 1, br.height()-(constSpace*2)),
4825                                       use[QTC_STD_BORDER], true, true, false);
4826                     if(bottomAdjust)
4827                         drawFadedLine(painter, QRect(br.x()+constSpace, br.y()+br.height()-1, br.width()-(constSpace*2), 1),
4828                                       use[QTC_STD_BORDER], true, true, true);
4829                 }
4830             }
4831 
4832             if (toolbutton->subControls&SC_ToolButtonMenu)
4833             {
4834                 if(etched)
4835                 {
4836                     if(reverse)
4837                         menuarea.adjust(1, 1, 0, -1);
4838                     else
4839                         menuarea.adjust(0, 1, -1, -1);
4840                 }
4841 
4842                 tool.state = mflags|State_Horizontal;
4843 
4844                 if(drawMenu)
4845                 {
4846                     const QColor *use(buttonColors(option));
4847                     int          mRound=reverse ? ROUNDED_LEFT : ROUNDED_RIGHT;
4848 
4849                     if(mflags&State_Sunken)
4850                         tool.state&=~State_MouseOver;
4851 
4852                     if(raised && TBTN_JOINED==opts.tbarBtns)
4853                     {
4854                         if(!horizTBar)
4855                             tool.state &= ~State_Horizontal;
4856                         painter->save();
4857                         painter->setClipRect(menuarea, Qt::IntersectClip);
4858                         if((reverse && leftAdjust) || (!reverse && rightAdjust))
4859                             mRound=ROUNDED_NONE;
4860                         if(reverse)
4861                             tool.rect.adjust(1, 0, 0, 0);
4862                         else
4863                             tool.rect.adjust(0, 0, -1, 0);
4864                     }
4865                     else
4866                         tool.rect = menuarea;
4867 
4868                     drawLightBevel(painter, tool.rect, &tool, widget, mRound, getFill(&tool, use), use, true,
4869                                    MO_GLOW==opts.coloredMouseOver ? WIDGET_MENU_BUTTON : WIDGET_NO_ETCH_BTN);
4870                     if(raised && TBTN_JOINED==opts.tbarBtns)
4871                         painter->restore();
4872                 }
4873 
4874                 tool.rect = menuarea;
4875 
4876                 if(mflags&State_Sunken)
4877                     tool.rect.adjust(1, 1, 1, 1);
4878                 drawArrow(painter, tool.rect, PE_IndicatorArrowDown,
4879                           MOArrow(state, palette,
4880                                   toolbutton->activeSubControls &
4881                                   SC_ToolButtonMenu,
4882                                   QPalette::ButtonText));
4883             }
4884 
4885             if ((opts.focus != FOCUS_GLOW || !drawnBevel) &&
4886                 toolbutton->state & State_HasFocus) {
4887                 QStyleOptionFocusRect fr;
4888                 fr.QStyleOption::operator=(*toolbutton);
4889 
4890                 if (oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)) {
4891                     if (etched) {
4892                         fr.rect.adjust(1, 1, -1, -1);
4893                     }
4894                 } else {
4895                     if (opts.focus == FOCUS_GLOW) {
4896                         fr.rect.adjust(1, 1, -1, -1);
4897                     } else if (etched) {
4898                         fr.rect.adjust(4, 4, -4, -4);
4899                     } else {
4900                         fr.rect.adjust(3, 3, -3, -3);
4901                     }
4902                     if (toolbutton->features &
4903                         QStyleOptionToolButton::MenuButtonPopup) {
4904                         fr.rect.adjust(
4905                             0, 0, -(pixelMetric(QStyle::PM_MenuButtonIndicator,
4906                                                 toolbutton, widget)-1), 0);
4907                     }
4908                 }
4909                 if (!(state & State_MouseOver &&
4910                       oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED) &&
4911                       opts.coloredMouseOver != MO_NONE)) {
4912                     drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
4913                 }
4914             }
4915             QStyleOptionToolButton label = *toolbutton;
4916             int fw = pixelMetric(PM_DefaultFrameWidth, option, widget);
4917             label.rect = button.adjusted(fw, fw, -(fw+widthAdjust), -(fw+heightAdjust));
4918             label.state = bflags;
4919             drawControl(CE_ToolButtonLabel, &label, painter, widget);
4920 
4921             if (!(toolbutton->subControls&SC_ToolButtonMenu) &&
4922                 (toolbutton->features&QStyleOptionToolButton::HasMenu))
4923             {
4924                 QRect arrow(r.right()-(LARGE_ARR_WIDTH+(etched ? 3 : 2)),
4925                             r.bottom()-(LARGE_ARR_HEIGHT+(etched ? 4 : 3)),
4926                             LARGE_ARR_WIDTH, LARGE_ARR_HEIGHT);
4927 
4928                 if(bflags&State_Sunken)
4929                     arrow.adjust(1, 1, 1, 1);
4930 
4931                 drawArrow(painter, arrow, PE_IndicatorArrowDown,
4932                           MOArrow(state, palette, QPalette::ButtonText));
4933             }
4934         }
4935         break;
4936     case CC_GroupBox:
4937         if (auto groupBox = styleOptCast<QStyleOptionGroupBox>(option)) {
4938             // Draw frame
4939             QRect textRect = /*proxy()->*/subControlRect(CC_GroupBox, option, SC_GroupBoxLabel, widget);
4940             QRect checkBoxRect = /*proxy()->*/subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget);
4941             if (groupBox->subControls & QStyle::SC_GroupBoxFrame)
4942             {
4943                 QStyleOptionFrame frame;
4944                 frame.QStyleOption::operator=(*groupBox);
4945                 frame.features = groupBox->features;
4946                 frame.lineWidth = groupBox->lineWidth;
4947                 frame.midLineWidth = groupBox->midLineWidth;
4948                 frame.rect = /*proxy()->*/subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
4949 
4950                 if((groupBox->features & QStyleOptionFrame::Flat) || !(opts.gbLabel&(GB_LBL_INSIDE|GB_LBL_OUTSIDE)))
4951                 {
4952                     painter->save();
4953                     QRegion region(r);
4954                     if (!groupBox->text.isEmpty())
4955                         region -= QRect(groupBox->subControls&QStyle::SC_GroupBoxCheckBox
4956                                         ? checkBoxRect.united(textRect).adjusted(reverse ? 0 : -2, 0, reverse ? 2 : 0, 0)
4957                                         : textRect);
4958                     painter->setClipRegion(region);
4959                 }
4960                 /*proxy()->*/drawPrimitive(PE_FrameGroupBox, &frame, painter, widget);
4961                 if((groupBox->features&QStyleOptionFrame::Flat) || !(opts.gbLabel&(GB_LBL_INSIDE|GB_LBL_OUTSIDE)))
4962                     painter->restore();
4963             }
4964 
4965             // Draw title
4966             if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty())
4967             {
4968                 QColor textColor = groupBox->textColor;
4969                 if (textColor.isValid())
4970                     painter->setPen(textColor);
4971                 int alignment = int(groupBox->textAlignment);
4972                 if (!/*proxy()->*/styleHint(QStyle::SH_UnderlineShortcut, option, widget))
4973                     alignment |= Qt::TextHideMnemonic;
4974 
4975                 if(opts.gbLabel&GB_LBL_BOLD)
4976                 {
4977                     QFont font(painter->font());
4978 
4979                     font.setBold(true);
4980                     painter->save();
4981                     painter->setFont(font);
4982                 }
4983                 /*proxy()->*/drawItemText(painter, textRect,  Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
4984                                           palette, state & State_Enabled, groupBox->text,
4985                                           textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
4986 
4987                 if(opts.gbLabel&GB_LBL_BOLD)
4988                     painter->restore();
4989 
4990                 if (state & State_HasFocus)
4991                 {
4992                     QStyleOptionFocusRect fropt;
4993                     fropt.QStyleOption::operator=(*groupBox);
4994                     fropt.rect = textRect;
4995                     /*proxy()->*/drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
4996                 }
4997             }
4998 
4999             // Draw checkbox
5000             if (groupBox->subControls & SC_GroupBoxCheckBox)
5001             {
5002                 QStyleOptionButton box;
5003                 box.QStyleOption::operator=(*groupBox);
5004                 box.rect = checkBoxRect;
5005                 /*proxy()->*/drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
5006             }
5007         }
5008         break;
5009     case CC_SpinBox:
5010         if (auto spinBox = styleOptCast<QStyleOptionSpinBox>(option)) {
5011             QRect frame(subControlRect(CC_SpinBox, option, SC_SpinBoxFrame, widget)),
5012                 up(subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget)),
5013                 down(subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget)),
5014                 all(frame.united(up).united(down));
5015             bool  doFrame(spinBox->frame && frame.isValid()),
5016                 sunken(state&State_Sunken),
5017                 enabled(state&State_Enabled),
5018                 mouseOver(state&State_MouseOver),
5019                 upIsActive(SC_SpinBoxUp==spinBox->activeSubControls),
5020                 downIsActive(SC_SpinBoxDown==spinBox->activeSubControls),
5021                 doEtch(opts.buttonEffect != EFFECT_NONE && opts.etchEntry),
5022                 isOO(isOOWidget(widget)),
5023                 oldUnify=opts.unifySpin; // See Krita note below...
5024 
5025             if(!doFrame && isOO && !opts.unifySpin)
5026             {
5027                 doFrame=true;
5028                 frame=all;
5029             }
5030 
5031             if(isOO)
5032                 painter->fillRect(r, palette.brush(QPalette::Window));
5033 
5034             if(up.isValid())
5035             {
5036                 if(reverse)
5037                     frame.adjust(up.width(), 0, 0, 0);
5038                 else
5039                     frame.adjust(0, 0, -up.width(), 0);
5040             }
5041 
5042             if(doEtch)
5043             {
5044                 drawEtch(painter, all, widget, WIDGET_SPIN, false,
5045                          opts.square&SQUARE_ENTRY
5046                          ? opts.unifySpin
5047                          ? ROUNDED_NONE
5048                          : reverse
5049                          ? ROUNDED_LEFT
5050                          : ROUNDED_RIGHT
5051                          : ROUNDED_ALL);
5052                 down.adjust(reverse ? 1 : 0, 0, reverse ? 0 : -1, -1);
5053                 up.adjust(reverse ? 1 : 0, 1, reverse ? 0 : -1, 0);
5054                 frame.adjust(reverse ? 0 : 1, 1, reverse ? -1 : 0, -1);
5055                 all.adjust(1, 1, -1, -1);
5056             }
5057 
5058             // Krita/KOffice uses a progressbar with spin buttons at the end
5059             // ...when drawn, the frame part is not set - so in this case dont draw the background behind the buttons!
5060             if(!isOO && !doFrame)
5061                 opts.unifySpin=true; // So, set this to true to fake the above scenario!
5062             else
5063                 if(opts.unifySpin)
5064                     drawEntryField(painter, all, widget, option, ROUNDED_ALL, true, false);
5065                 else
5066                 {
5067                     if(opts.unifySpinBtns)
5068                     {
5069                         QRect btns=up.united(down);
5070                         const QColor *use(buttonColors(option));
5071                         QStyleOption opt(*option);
5072 
5073                         opt.state&=~(State_Sunken|State_MouseOver);
5074                         opt.state|=State_Horizontal;
5075 
5076                         drawLightBevel(painter, btns, &opt, widget, reverse ?  ROUNDED_LEFT : ROUNDED_RIGHT,
5077                                        getFill(&opt, use), use, true, WIDGET_SPIN);
5078 
5079                         if(state&State_MouseOver && state&State_Enabled && !(state&State_Sunken))
5080                         {
5081                             opt.state|=State_MouseOver;
5082                             painter->save();
5083                             painter->setClipRect(upIsActive ? up : down);
5084                             drawLightBevel(painter, btns, &opt, widget, reverse ?  ROUNDED_LEFT : ROUNDED_RIGHT,
5085                                            getFill(&opt, use), use, true, WIDGET_SPIN);
5086                             painter->restore();
5087                         }
5088                         drawFadedLine(painter, down.adjusted(2, 0, -2, 0), use[BORDER_VAL(state&State_Enabled)], true, true, true);
5089                     }
5090                 }
5091 
5092             if(up.isValid())
5093             {
5094                 QStyleOption opt(*option);
5095 
5096                 up.setHeight(up.height()+1);
5097                 opt.rect=up;
5098                 opt.direction=option->direction;
5099                 opt.state=(enabled && (spinBox->stepEnabled&QAbstractSpinBox::StepUpEnabled ||
5100                                        (QAbstractSpinBox::StepNone==spinBox->stepEnabled && isOO))
5101                            ? State_Enabled : State_None)|
5102                     (upIsActive && sunken ? State_Sunken : State_Raised)|
5103                     (upIsActive && !sunken && mouseOver ? State_MouseOver : State_None)|State_Horizontal;
5104 
5105                 drawPrimitive(QAbstractSpinBox::PlusMinus==spinBox->buttonSymbols ? PE_IndicatorSpinPlus : PE_IndicatorSpinUp,
5106                               &opt, painter, widget);
5107             }
5108 
5109             if(down.isValid())
5110             {
5111                 QStyleOption opt(*option);
5112 
5113                 opt.rect=down;
5114                 opt.state=(enabled && (spinBox->stepEnabled&QAbstractSpinBox::StepDownEnabled ||
5115                                        (QAbstractSpinBox::StepNone==spinBox->stepEnabled && isOO))
5116                            ? State_Enabled : State_None)|
5117                     (downIsActive && sunken ? State_Sunken : State_Raised)|
5118                     (downIsActive && !sunken && mouseOver ? State_MouseOver : State_None)|State_Horizontal;
5119                 opt.direction=option->direction;
5120 
5121                 drawPrimitive(QAbstractSpinBox::PlusMinus==spinBox->buttonSymbols ? PE_IndicatorSpinMinus : PE_IndicatorSpinDown,
5122                               &opt, painter, widget);
5123             }
5124             if(doFrame && !opts.unifySpin)
5125             {
5126                 if(reverse)
5127                     frame.setX(frame.x()-1);
5128                 else
5129                     frame.setWidth(frame.width()+1);
5130                 drawEntryField(painter, frame, widget, option, reverse ? ROUNDED_RIGHT : ROUNDED_LEFT, true, false);
5131             }
5132             opts.unifySpin=oldUnify;
5133         }
5134         break;
5135     case CC_Slider:
5136         if (auto slider = styleOptCast<QStyleOptionSlider>(option)) {
5137             QRect groove(subControlRect(CC_Slider, option,
5138                                         SC_SliderGroove, widget));
5139             QRect handle(subControlRect(CC_Slider, option,
5140                                         SC_SliderHandle, widget));
5141             // QRect ticks(subControlRect(CC_Slider, option,
5142             //                            SC_SliderTickmarks, widget));
5143             bool  horizontal(slider->orientation == Qt::Horizontal),
5144                 ticksAbove(slider->tickPosition & QSlider::TicksAbove),
5145                 ticksBelow(slider->tickPosition & QSlider::TicksBelow);
5146 
5147             //The clickable region is 5 px wider than the visible groove for improved usability
5148 //                 if (groove.isValid())
5149 //                     groove = horizontal ? groove.adjusted(0, 5, 0, -5) : groove.adjusted(5, 0, -5, 0);
5150 
5151             if ((option->subControls&SC_SliderGroove) && groove.isValid())
5152                 drawSliderGroove(painter, groove, handle, slider, widget);
5153 
5154             if ((option->subControls&SC_SliderHandle) && handle.isValid())
5155             {
5156                 QStyleOptionSlider s(*slider);
5157                 if(!(s.activeSubControls & QStyle::SC_SliderHandle))
5158                 {
5159                     s.state &= ~QStyle::State_MouseOver;
5160                     s.state &= ~QStyle::State_Sunken;
5161                 }
5162 
5163                 drawSliderHandle(painter, handle, &s);
5164 
5165                 if (state&State_HasFocus && FOCUS_GLOW!=opts.focus)
5166                 {
5167                     QStyleOptionFocusRect fropt;
5168                     fropt.QStyleOption::operator=(*slider);
5169                     fropt.rect = slider->rect;
5170 
5171                     if(horizontal)
5172                         fropt.rect.adjust(0, 0, 0, -1);
5173                     else
5174                         fropt.rect.adjust(0, 0, -1, 0);
5175 
5176                     drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
5177                 }
5178             }
5179 
5180             if (option->subControls&SC_SliderTickmarks)
5181             {
5182                 QPen oldPen = painter->pen();
5183                 painter->setPen(backgroundColors(option)[QTC_STD_BORDER]);
5184                 int tickSize(pixelMetric(PM_SliderTickmarkOffset, option, widget)),
5185                     available(pixelMetric(PM_SliderSpaceAvailable, slider, widget)),
5186                     interval(slider->tickInterval);
5187                 if (interval <= 0)
5188                 {
5189                     interval = slider->singleStep;
5190                     if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
5191                                                         available)
5192                         - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
5193                                                           0, available) < 3)
5194                         interval = slider->pageStep;
5195                 }
5196                 if (interval <= 0)
5197                     interval = 1;
5198 
5199                 int sliderLength(slider->maximum - slider->minimum + 1),
5200                     nticks(sliderLength / interval); // add one to get the end tickmark
5201                 if (sliderLength % interval > 0)
5202                     nticks++; // round up the number of tick marks
5203 
5204                 int v(slider->minimum),
5205                     len(pixelMetric(PM_SliderLength, slider, widget));
5206 
5207                 while (v <= slider->maximum + 1)
5208                 {
5209                     if (v == slider->maximum + 1 && interval == 1)
5210                         break;
5211 
5212                     int pos(sliderPositionFromValue(slider->minimum, slider->maximum,
5213                                                     qMin(v, slider->maximum), (horizontal
5214                                                                                ? slider->rect.width()
5215                                                                                : slider->rect.height()) - len,
5216                                                     slider->upsideDown) + len / 2);
5217 
5218                     int extra(2); // - ((v == slider->minimum || v == slider->maximum) ? 1 : 0);
5219 
5220                     if (horizontal)
5221                     {
5222                         if (ticksAbove)
5223                             painter->drawLine(QLine(pos, slider->rect.top() + extra,
5224                                                     pos, slider->rect.top() + tickSize));
5225                         if (ticksBelow)
5226                             painter->drawLine(QLine(pos, slider->rect.bottom() - extra,
5227                                                     pos, slider->rect.bottom() - tickSize));
5228                     }
5229                     else
5230                     {
5231                         if (ticksAbove)
5232                             painter->drawLine(QLine(slider->rect.left() + extra, pos,
5233                                                     slider->rect.left() + tickSize, pos));
5234                         if (ticksBelow)
5235                             painter->drawLine(QLine(slider->rect.right() - extra, pos,
5236                                                     slider->rect.right() - tickSize, pos));
5237                     }
5238 
5239                     // in the case where maximum is max int
5240                     int nextInterval = v + interval;
5241                     if (nextInterval < v)
5242                         break;
5243                     v = nextInterval;
5244                 }
5245                 painter->setPen(oldPen);
5246             }
5247         }
5248         break;
5249     case CC_TitleBar:
5250         if (auto titleBar = styleOptCast<QStyleOptionTitleBar>(option)) {
5251             painter->save();
5252 
5253             EAppearance  app=qtcWidgetApp(WIDGET_MDI_WINDOW_TITLE, &opts, option->state&State_Active);
5254             bool         active(state&State_Active),
5255                 kwin(theThemedApp==APP_KWIN || titleBar->titleBarState&QtC_StateKWin);
5256             const QColor *bgndCols(APPEARANCE_NONE==app
5257                                    ? kwin ? backgroundColors(option) : backgroundColors(palette.color(QPalette::Active, QPalette::Window))
5258                                    : kwin ? buttonColors(option) : getMdiColors(titleBar, active)),
5259                 *btnCols(kwin || opts.titlebarButtons&TITLEBAR_BUTTON_STD_COLOR
5260                          ? buttonColors(option)
5261                          : getMdiColors(titleBar, active)),
5262                 *titleCols(APPEARANCE_NONE==app
5263                            ? bgndCols
5264                            : kwin || !(opts.titlebarButtons&TITLEBAR_BUTTON_STD_COLOR)
5265                            ? btnCols : getMdiColors(titleBar, active));
5266             QColor       textColor(theThemedApp==APP_KWIN
5267                                    ? option->palette.color(QPalette::WindowText)
5268                                    : active
5269                                    ? m_activeMdiTextColor
5270                                    : m_mdiTextColor),
5271                 iconColor(textColor),
5272                 shadow(WINDOW_SHADOW_COLOR(opts.titlebarEffect));
5273             QStyleOption opt(*option);
5274             QRect        tr(r),
5275                 menuRect(subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget));
5276             ERound       round=(opts.square&SQUARE_WINDOWS && opts.round>ROUND_SLIGHT) ? ROUND_SLIGHT : opts.round;
5277             QColor       borderCol(kwin && option->version==(TBAR_BORDER_VERSION_HACK+2)
5278                                    ? palette.color(QPalette::Active, QPalette::Shadow)
5279                                    : titleCols[kwin && option->version==TBAR_BORDER_VERSION_HACK ? 0 : QTC_STD_BORDER]);
5280 
5281             if(!kwin && widget && BLEND_TITLEBAR && qobject_cast<const QMdiSubWindow *>(widget))
5282             {
5283                 const QWidget *w=nullptr;
5284                 if(qobject_cast<const QMainWindow *>(widget))
5285                     w=widget;
5286                 else if (static_cast<const QMdiSubWindow *>(widget)->widget())
5287                     w=qobject_cast<const QMainWindow *>(static_cast<const QMdiSubWindow *>(widget)->widget());
5288                 if(w)
5289                 {
5290                     const QMenuBar *menuBar=static_cast<const QMainWindow *>(w)->menuBar();
5291 
5292                     if(menuBar)
5293                         tr.adjust(0, 0, 0, menuBar->rect().height());
5294                 }
5295             }
5296 
5297             opt.state=State_Horizontal|State_Enabled|State_Raised|(active ? State_Active : State_None);
5298 
5299 #ifndef QTC_QT5_ENABLE_KDE
5300             QPainterPath path;
5301 #else
5302             QPainterPath path(round < ROUND_SLIGHT ? QPainterPath() :
5303                               buildPath(QRectF(state&QtC_StateKWinNoBorder ?
5304                                                tr : tr.adjusted(1, 1, -1, 0)),
5305                                         WIDGET_MDI_WINDOW_TITLE,
5306                                         state & QtC_StateKWin &&
5307                                         state & QtC_StateKWinTabDrag ?
5308                                         ROUNDED_ALL : ROUNDED_TOP,
5309                                         (round > ROUND_SLIGHT /*&& kwin*/ ?
5310                                          6.0 : 2.0)));
5311 #endif
5312             if (!kwin && !qtcIsCustomBgnd(opts))
5313                 painter->fillRect(tr, borderCol);
5314 
5315             painter->setRenderHint(QPainter::Antialiasing, true);
5316 
5317             if(kwin && (state&QtC_StateKWinFillBgnd))
5318                 drawBevelGradient(titleCols[ORIGINAL_SHADE], painter, tr, path, true, false, APPEARANCE_FLAT, WIDGET_MDI_WINDOW, false);
5319             if((!kwin && !m_isPreview) ||
5320                (APPEARANCE_NONE!=app && (!qtcIsFlat(app) || (titleCols[ORIGINAL_SHADE]!=QApplication::palette().background().color()))))
5321                 drawBevelGradient(titleCols[ORIGINAL_SHADE], painter, tr, path, true, false, app, WIDGET_MDI_WINDOW, false);
5322 
5323             if(!(state&QtC_StateKWinNoBorder))
5324             {
5325                 QColor light(titleCols[0]),
5326                     dark(borderCol);
5327                 bool   addLight=opts.windowBorder&WINDOW_BORDER_ADD_LIGHT_BORDER && (!kwin || qtcGetWindowBorderSize(false).sides>1);
5328 
5329                 if(kwin)
5330                 {
5331                     light.setAlphaF(1.0);
5332                     dark.setAlphaF(1.0);
5333                 }
5334 
5335                 if(addLight)
5336                 {
5337                     painter->setPen(light);
5338                     painter->save();
5339                     painter->setClipRect(r.adjusted(0, 0, -1, -1));
5340                     painter->drawPath(buildPath(r.adjusted(1, 1, 0, 1), WIDGET_MDI_WINDOW_TITLE, ROUNDED_TOP,
5341                                                 round<ROUND_SLIGHT
5342                                                 ? 0
5343                                                 : round>ROUND_SLIGHT /*&& kwin*/
5344                                                 ? 5.0
5345                                                 : 1.0));
5346                     painter->restore();
5347                 }
5348 
5349                 painter->setPen(dark);
5350                 painter->drawPath(buildPath(r, WIDGET_MDI_WINDOW_TITLE, ROUNDED_TOP,
5351                                             round<ROUND_SLIGHT
5352                                             ? 0
5353                                             : round>ROUND_SLIGHT /*&& kwin*/
5354                                             ? 6.0
5355                                             : 2.0));
5356 
5357                 QPAINTER_RENDERHINT_AA_MAYBE_OFF(painter);
5358 
5359                 if(addLight)
5360                 {
5361                     painter->setPen(light);
5362                     painter->drawPoint(r.x()+1, r.y()+r.height()-1);
5363                 }
5364 
5365                 if (round > ROUND_SLIGHT && opts.round >= ROUND_FULL) {
5366                     if (!(state & QtC_StateKWinCompositing)) {
5367                         painter->setPen(dark);
5368 
5369                         painter->drawLine(r.x()+1, r.y()+4, r.x()+1, r.y()+3);
5370                         painter->drawPoint(r.x()+2, r.y()+2);
5371                         painter->drawLine(r.x()+3, r.y()+1, r.x()+4, r.y()+1);
5372                         painter->drawLine(r.x()+r.width()-2, r.y()+4, r.x()+r.width()-2, r.y()+3);
5373                         painter->drawPoint(r.x()+r.width()-3, r.y()+2);
5374                         painter->drawLine(r.x()+r.width()-4, r.y()+1, r.x()+r.width()-5, r.y()+1);
5375                     }
5376 
5377                     if(addLight &&
5378                        (APPEARANCE_SHINY_GLASS!=(active ? opts.titlebarAppearance : opts.inactiveTitlebarAppearance)))
5379                     {
5380                         painter->setPen(light);
5381                         painter->drawLine(r.x()+2, r.y()+4, r.x()+2, r.y()+3);
5382                         painter->drawLine(r.x()+3, r.y()+2, r.x()+4, r.y()+2);
5383                         painter->drawLine(r.x()+r.width()-4, r.y()+2, r.x()+r.width()-5, r.y()+2);
5384                     }
5385                 }
5386 
5387                 if(opts.windowBorder&WINDOW_BORDER_BLEND_TITLEBAR && (!kwin || !(state&QtC_StateKWinNoBorder)))
5388                 {
5389                     static const int constFadeLen=8;
5390                     QPoint          start(0, r.y()+r.height()-(1+constFadeLen)),
5391                         end(start.x(), start.y()+constFadeLen);
5392                     QLinearGradient grad(start, end);
5393 
5394                     grad.setColorAt(0, dark);
5395                     grad.setColorAt(1, m_backgroundCols[QTC_STD_BORDER]);
5396                     painter->setPen(QPen(QBrush(grad), QPENWIDTH1));
5397                     painter->drawLine(r.x(), start.y(), r.x(), end.y());
5398                     painter->drawLine(r.x()+r.width()-1, start.y(), r.x()+r.width()-1, end.y());
5399 
5400                     if(addLight)
5401                     {
5402                         grad.setColorAt(0, light);
5403                         grad.setColorAt(1, m_backgroundCols[0]);
5404                         painter->setPen(QPen(QBrush(grad), QPENWIDTH1));
5405                         painter->drawLine(r.x()+1, start.y(), r.x()+1, end.y());
5406                     }
5407                 }
5408             }
5409             else
5410                 QPAINTER_RENDERHINT_AA_MAYBE_OFF(painter);
5411 
5412             if(kwin)
5413             {
5414                 painter->restore();
5415                 break;
5416             }
5417 
5418             int   adjust(0);
5419             QRect captionRect(subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget));
5420 
5421             if(opts.titlebarButtons&TITLEBAR_BUTTON_SUNKEN_BACKGROUND && captionRect!=r)
5422             {
5423                 bool menuIcon=TITLEBAR_ICON_MENU_BUTTON==opts.titlebarIcon,
5424                     menuLeft=menuRect.isValid() && !titleBar->icon.isNull() && menuRect.left()<(r.left()+constWindowMargin+4);
5425                 int  height=r.height()-(1+(2*constWindowMargin));
5426 
5427                 adjust=1;
5428                 if(captionRect.left()>(r.left()+constWindowMargin))
5429                 {
5430                     int width=captionRect.left()-(r.left()+(2*constWindowMargin));
5431 
5432                     if(!(menuIcon && menuLeft) || width>(height+4))
5433                         drawSunkenBevel(painter, QRect(r.left()+constWindowMargin+1, r.top()+constWindowMargin+1, width, height), titleCols[ORIGINAL_SHADE]);
5434                 }
5435                 if(captionRect.right()<(r.right()-constWindowMargin))
5436                 {
5437                     int width=r.right()-(captionRect.right()+(2*constWindowMargin));
5438 
5439                     if(!(menuIcon && !menuLeft) || width>(height+4))
5440                         drawSunkenBevel(painter, QRect(captionRect.right()+constWindowMargin, r.top()+constWindowMargin+1, width, height), titleCols[ORIGINAL_SHADE]);
5441                 }
5442             }
5443 
5444             bool    showIcon=TITLEBAR_ICON_NEXT_TO_TITLE==opts.titlebarIcon && !titleBar->icon.isNull();
5445             int     iconSize=showIcon ? pixelMetric(QStyle::PM_SmallIconSize) : 0,
5446                 iconX=r.x();
5447             QPixmap pixmap;
5448 
5449             if(showIcon)
5450                 pixmap=getIconPixmap(titleBar->icon, iconSize, titleBar->state);
5451 
5452             if(!titleBar->text.isEmpty())
5453             {
5454                 static const int constPad=4;
5455 
5456                 Qt::Alignment alignment((Qt::Alignment)pixelMetric((QStyle::PixelMetric)QtC_TitleAlignment, 0L, 0L));
5457                 bool          alignFull(Qt::AlignHCenter==alignment),
5458                     iconRight((!reverse && alignment&Qt::AlignRight) || (reverse && alignment&Qt::AlignLeft));
5459                 QRect         textRect(alignFull
5460                                        ? QRect(r.x(), captionRect.y(), r.width(), captionRect.height())
5461                                        : captionRect);
5462 
5463 #ifndef QTC_QT5_ENABLE_KDE
5464                 QFont         font(painter->font());
5465                 font.setBold(true);
5466                 painter->setFont(font);
5467 #else
5468                 painter->setFont(KGlobalSettings::windowTitleFont());
5469 #endif
5470 
5471                 QFontMetrics fm(painter->fontMetrics());
5472                 QString str(fm.elidedText(titleBar->text, Qt::ElideRight, textRect.width(), QPalette::WindowText));
5473 
5474                 int           textWidth=alignFull || (showIcon && alignment&Qt::AlignHCenter)
5475                     ? fm.boundingRect(str).width()+(showIcon ? iconSize+constPad : 0) : 0;
5476 
5477                 if(alignFull &&
5478                    ( (captionRect.left()>((textRect.width()-textWidth)>>1)) ||
5479                      (captionRect.right()<((textRect.width()+textWidth)>>1)) ) )
5480                 {
5481                     alignment=Qt::AlignVCenter|Qt::AlignRight;
5482                     textRect=captionRect;
5483                 }
5484 
5485                 if(alignment&Qt::AlignLeft && constWindowMargin==textRect.x())
5486                     textRect.adjust(showIcon ? 4 : 6, 0, 0, 0);
5487 
5488                 if(showIcon)
5489                 {
5490                     if(alignment&Qt::AlignHCenter)
5491                     {
5492                         if(reverse)
5493                         {
5494                             iconX=((textRect.width()-textWidth)/2.0)+0.5+textWidth+iconSize;
5495                             textRect.setX(textRect.x()-(iconSize+constPad));
5496                         }
5497                         else
5498                         {
5499                             iconX=((textRect.width()-textWidth)/2.0)+0.5;
5500                             textRect.setX(iconX+iconSize+constPad);
5501                             alignment=Qt::AlignVCenter|Qt::AlignLeft;
5502                         }
5503                     }
5504                     else if((!reverse && alignment&Qt::AlignLeft) || (reverse && alignment&Qt::AlignRight))
5505                     {
5506                         iconX=textRect.x();
5507                         textRect.setX(textRect.x()+(iconSize+constPad));
5508                     }
5509                     else if((!reverse && alignment&Qt::AlignRight) || (reverse && alignment&Qt::AlignLeft))
5510                     {
5511                         if(iconRight)
5512                         {
5513                             iconX=textRect.x()+textRect.width()-iconSize;
5514                             textRect.setWidth(textRect.width()-(iconSize+constPad));
5515                         }
5516                         else
5517                         {
5518                             iconX=textRect.x()+textRect.width()-textWidth;
5519                             if(iconX<textRect.x())
5520                                 iconX=textRect.x();
5521                         }
5522                     }
5523                 }
5524 
5525                 QTextOption textOpt(alignment|Qt::AlignVCenter);
5526                 textOpt.setWrapMode(QTextOption::NoWrap);
5527 
5528                 if(EFFECT_NONE!=opts.titlebarEffect)
5529                 {
5530                     shadow.setAlphaF(WINDOW_TEXT_SHADOW_ALPHA(opts.titlebarEffect));
5531                     //painter->setPen(shadow);
5532                     painter->setPen(blendColors(WINDOW_SHADOW_COLOR(opts.titlebarEffect), titleCols[ORIGINAL_SHADE],
5533                                                 WINDOW_TEXT_SHADOW_ALPHA(opts.titlebarEffect)));
5534                     painter->drawText(EFFECT_SHADOW==opts.titlebarEffect
5535                                       ? textRect.adjusted(1, 1, 1, 1)
5536                                       : textRect.adjusted(0, 1, 0, 1),
5537                                       str, textOpt);
5538 
5539                     if (!active && DARK_WINDOW_TEXT(textColor))
5540                     {
5541                         //textColor.setAlpha((textColor.alpha() * 180) >> 8);
5542                         textColor=blendColors(textColor, titleCols[ORIGINAL_SHADE], ((255 * 180) >> 8)/256.0);
5543                     }
5544                 }
5545                 painter->setPen(textColor);
5546                 painter->drawText(textRect, str, textOpt);
5547             }
5548 
5549             if(showIcon && iconX>=0)
5550                 painter->drawPixmap(iconX, r.y()+((r.height()-iconSize)/2)+1, pixmap);
5551 
5552             if ((titleBar->subControls&SC_TitleBarMinButton) && (titleBar->titleBarFlags&Qt::WindowMinimizeButtonHint) &&
5553                 !(titleBar->titleBarState&Qt::WindowMinimized))
5554                 drawMdiControl(painter, titleBar, SC_TitleBarMinButton, widget, TITLEBAR_MIN, iconColor, btnCols, bgndCols,
5555                                adjust, active);
5556 
5557             if ((titleBar->subControls&SC_TitleBarMaxButton) && (titleBar->titleBarFlags&Qt::WindowMaximizeButtonHint) &&
5558                 !(titleBar->titleBarState&Qt::WindowMaximized))
5559                 drawMdiControl(painter, titleBar, SC_TitleBarMaxButton, widget, TITLEBAR_MAX, iconColor, btnCols, bgndCols,
5560                                adjust, active);
5561 
5562             if ((titleBar->subControls&SC_TitleBarCloseButton) && (titleBar->titleBarFlags&Qt::WindowSystemMenuHint))
5563                 drawMdiControl(painter, titleBar, SC_TitleBarCloseButton, widget, TITLEBAR_CLOSE, iconColor, btnCols, bgndCols,
5564                                adjust, active);
5565 
5566             if ((titleBar->subControls&SC_TitleBarNormalButton) &&
5567                 (((titleBar->titleBarFlags&Qt::WindowMinimizeButtonHint) &&
5568                   (titleBar->titleBarState&Qt::WindowMinimized)) ||
5569                  ((titleBar->titleBarFlags&Qt::WindowMaximizeButtonHint) &&
5570                   (titleBar->titleBarState&Qt::WindowMaximized))))
5571                 drawMdiControl(painter, titleBar, SC_TitleBarNormalButton, widget, TITLEBAR_MAX, iconColor, btnCols, bgndCols,
5572                                adjust, active);
5573 
5574             if (titleBar->subControls&SC_TitleBarContextHelpButton && (titleBar->titleBarFlags&Qt::WindowContextHelpButtonHint))
5575                 drawMdiControl(painter, titleBar, SC_TitleBarContextHelpButton, widget, TITLEBAR_HELP, iconColor, btnCols, bgndCols,
5576                                adjust, active);
5577 
5578             if (titleBar->subControls&SC_TitleBarShadeButton && (titleBar->titleBarFlags&Qt::WindowShadeButtonHint))
5579                 drawMdiControl(painter, titleBar, SC_TitleBarShadeButton, widget, TITLEBAR_SHADE, iconColor, btnCols, bgndCols,
5580                                adjust, active);
5581 
5582             if (titleBar->subControls&SC_TitleBarUnshadeButton && (titleBar->titleBarFlags&Qt::WindowShadeButtonHint))
5583                 drawMdiControl(painter, titleBar, SC_TitleBarUnshadeButton, widget, TITLEBAR_SHADE, iconColor, btnCols, bgndCols,
5584                                adjust, active);
5585 
5586             if ((titleBar->subControls&SC_TitleBarSysMenu) && (titleBar->titleBarFlags&Qt::WindowSystemMenuHint))
5587             {
5588                 if(TITLEBAR_ICON_MENU_BUTTON==opts.titlebarIcon)
5589                 {
5590                     bool hover((titleBar->activeSubControls&SC_TitleBarSysMenu) && (titleBar->state&State_MouseOver));
5591 
5592                     if(active || hover || !(opts.titlebarButtons&TITLEBAR_BUTTOM_HIDE_ON_INACTIVE_WINDOW))
5593                     {
5594                         if (menuRect.isValid())
5595                         {
5596                             bool sunken((titleBar->activeSubControls&SC_TitleBarSysMenu) && (titleBar->state&State_Sunken));
5597                             int  offset(sunken ? 1 : 0);
5598 
5599 //                                 if(!(opts.titlebarButtons&TITLEBAR_BUTTON_ROUND))
5600 //                                     drawMdiButton(painter, menuRect, hover, sunken,
5601 //                                                   coloredMdiButtons(state&State_Active, hover)
5602 //                                                     ? m_titleBarButtonsCols[TITLEBAR_MENU] : btnCols);
5603 
5604                             if (!titleBar->icon.isNull())
5605                                 titleBar->icon.paint(painter, menuRect.adjusted(offset, offset, offset, offset));
5606                             else
5607                             {
5608                                 QStyleOption tool(0);
5609 
5610                                 tool.palette = palette;
5611                                 tool.rect = menuRect;
5612                                 painter->save();
5613                                 drawItemPixmap(painter, menuRect.adjusted(offset, offset, offset, offset), Qt::AlignCenter,
5614                                                standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16));
5615                                 painter->restore();
5616                             }
5617                         }
5618                     }
5619                 }
5620                 else
5621                     drawMdiControl(painter, titleBar, SC_TitleBarSysMenu, widget, TITLEBAR_MENU, iconColor, btnCols, bgndCols,
5622                                    adjust, active);
5623 
5624                 if(active && opts.windowBorder&WINDOW_BORDER_SEPARATOR)
5625                 {
5626                     QColor        color(active ? m_activeMdiTextColor : m_mdiTextColor);
5627                     Qt::Alignment align(pixelMetric((QStyle::PixelMetric)QtC_TitleAlignment, 0L, 0L));
5628                     QRect         lr(r.x(), captionRect.y(), r.width(), captionRect.height());
5629 
5630                     lr.adjust(16, lr.height()-2, -16, 0);
5631                     color.setAlphaF(0.5);
5632                     drawFadedLine(painter, lr, color, align&(Qt::AlignHCenter|Qt::AlignRight),
5633                                   align&(Qt::AlignHCenter|Qt::AlignLeft), true);
5634                 }
5635             }
5636 
5637             painter->restore();
5638         }
5639         break;
5640     case CC_ScrollBar:
5641         if (auto scrollbar = styleOptCast<QStyleOptionSlider>(option)) {
5642             bool useThreeButtonScrollBar(SCROLLBAR_KDE==opts.scrollbarType),
5643                 horiz(Qt::Horizontal==scrollbar->orientation),
5644                 maxed(scrollbar->minimum == scrollbar->maximum),
5645                 atMin(maxed || scrollbar->sliderValue==scrollbar->minimum),
5646                 atMax(maxed || scrollbar->sliderValue==scrollbar->maximum)/*,
5647                                                                             inStack(0!=opts.tabBgnd && inStackWidget(widget))*/;
5648             QRect subline(subControlRect(control, option,
5649                                          SC_ScrollBarSubLine, widget));
5650             QRect addline(subControlRect(control, option,
5651                                          SC_ScrollBarAddLine, widget));
5652             QRect subpage(subControlRect(control, option,
5653                                          SC_ScrollBarSubPage, widget));
5654             QRect addpage(subControlRect(control, option,
5655                                          SC_ScrollBarAddPage, widget));
5656             QRect slider(subControlRect(control, option,
5657                                         SC_ScrollBarSlider, widget));
5658             QRect first(subControlRect(control, option,
5659                                        SC_ScrollBarFirst, widget));
5660             QRect last(subControlRect(control, option,
5661                                       SC_ScrollBarLast, widget));
5662             QRect subline2(addline);
5663             // QRect sbRect(scrollbar->rect);
5664             QStyleOptionSlider opt(*scrollbar);
5665 
5666             // For OO.o 3.2 need to fill widget background!
5667             if(isOOWidget(widget))
5668                 painter->fillRect(r, palette.brush(QPalette::Window));
5669 
5670             if(reverse && horiz)
5671             {
5672                 bool tmp(atMin);
5673 
5674                 atMin=atMax;
5675                 atMax=tmp;
5676             }
5677 
5678             if (useThreeButtonScrollBar)
5679             {
5680                 int sbextent(pixelMetric(PM_ScrollBarExtent, scrollbar, widget));
5681 
5682                 if(horiz && reverse)
5683                     subline2=QRect((r.x()+r.width()-1)-sbextent, r.y(), sbextent, sbextent);
5684                 else if (horiz)
5685                     subline2.translate(-addline.width(), 0);
5686                 else
5687                     subline2.translate(0, -addline.height());
5688 
5689                 if (horiz)
5690                     subline.setWidth(sbextent);
5691                 else
5692                     subline.setHeight(sbextent);
5693             }
5694 
5695             // Draw trough...
5696             bool  noButtons(opts.round != ROUND_NONE &&
5697                             (opts.scrollbarType == SCROLLBAR_NONE ||
5698                              opts.flatSbarButtons));
5699             QRect s2(subpage), a2(addpage);
5700 
5701 #ifndef SIMPLE_SCROLLBARS
5702             if(noButtons)
5703             {
5704                 // Increase clipping to allow trough to "bleed" into slider corners...
5705                 a2.adjust(-3, -3, 3, 3);
5706                 s2.adjust(-3, -3, 3, 3);
5707             }
5708 #endif
5709 
5710             painter->save();
5711 
5712             if ((opts.thinSbarGroove || opts.flatSbarButtons) &&
5713                 qtcCheckType(getParent<2>(widget), "QComboBoxListView")) {
5714                 painter->fillRect(r, palette.brush(QPalette::Base));
5715             } else if (opts.thinSbarGroove && theThemedApp == APP_ARORA &&
5716                        qtcCheckType(widget, "WebView")) {
5717                 painter->fillRect(r, m_backgroundCols[ORIGINAL_SHADE]);
5718             }
5719             if (!opts.gtkScrollViews ||
5720                 (opts.flatSbarButtons && !qtcIsFlat(opts.sbarBgndAppearance)))
5721                 drawBevelGradientReal(palette.brush(QPalette::Background).color(), painter, r, horiz, false,
5722                                       opts.sbarBgndAppearance, WIDGET_SB_BGND);
5723 
5724             if(noButtons || opts.flatSbarButtons)
5725             {
5726                 int mod=THIN_SBAR_MOD;
5727                 // Draw complete groove here, as we want to round both ends...
5728                 opt.rect=subpage.united(addpage);
5729                 opt.state=scrollbar->state;
5730                 opt.state&=~(State_MouseOver|State_Sunken|State_On);
5731 
5732                 if(opts.thinSbarGroove && slider.isValid())
5733                 {
5734                     painter->save();
5735                     painter->setClipRegion(QRegion(opt.rect).subtracted(slider.adjusted(1, 1, -1, -1)));
5736                 }
5737                 drawLightBevel(painter, opts.thinSbarGroove
5738                                ? horiz
5739                                ? opt.rect.adjusted(0, mod, 0, -mod)
5740                                : opt.rect.adjusted(mod, 0, -mod, 0)
5741                                : opt.rect, &opt, widget,
5742 #ifndef SIMPLE_SCROLLBARS
5743                                !(opts.square&SQUARE_SB_SLIDER) && (SCROLLBAR_NONE==opts.scrollbarType || opts.flatSbarButtons)
5744                                ? ROUNDED_ALL :
5745 #endif
5746                                ROUNDED_NONE,
5747                                m_backgroundCols[2], m_backgroundCols, true,
5748                                opts.thinSbarGroove ? WIDGET_SLIDER_TROUGH : WIDGET_TROUGH);
5749                 if(opts.thinSbarGroove && slider.isValid())
5750                     painter->restore();
5751             }
5752             else
5753             {
5754                 if((option->subControls&SC_ScrollBarSubPage) && subpage.isValid())
5755                 {
5756                     opt.state=scrollbar->state;
5757                     opt.rect = subpage;
5758 //                         if (!(scrollbar->activeSubControls&SC_ScrollBarSubPage))
5759                     opt.state &= ~(State_Sunken|State_MouseOver|State_On);
5760                     drawControl(CE_ScrollBarSubPage, &opt, painter, widget);
5761                 }
5762 
5763                 if((option->subControls&SC_ScrollBarAddPage) && addpage.isValid())
5764                 {
5765                     opt.state=scrollbar->state;
5766                     opt.rect = addpage;
5767 //                         if (!(scrollbar->activeSubControls&SC_ScrollBarAddPage))
5768                     opt.state &= ~(State_Sunken|State_MouseOver|State_On);
5769                     drawControl(CE_ScrollBarAddPage, &opt, painter, widget);
5770                 }
5771             }
5772 
5773             if((option->subControls&SC_ScrollBarSubLine) && subline.isValid())
5774             {
5775                 opt.rect=subline;
5776                 opt.state=scrollbar->state/*|(inStack ? NO_BGND_BUTTON : State_None)*/;
5777                 if(maxed || atMin)
5778                     opt.state&=~State_Enabled;
5779                 if (!(scrollbar->activeSubControls&SC_ScrollBarSubLine) ||
5780                     (useThreeButtonScrollBar && m_sbWidget && m_sbWidget==widget))
5781                     opt.state &= ~(State_Sunken | State_MouseOver);
5782 
5783                 drawControl(CE_ScrollBarSubLine, &opt, painter, widget);
5784 
5785                 if (useThreeButtonScrollBar && subline2.isValid())
5786                 {
5787                     opt.rect=subline2;
5788                     opt.state=scrollbar->state/*|(inStack ? NO_BGND_BUTTON : State_None)*/;
5789                     if(maxed || atMin)
5790                         opt.state&=~State_Enabled;
5791                     if ((!(scrollbar->activeSubControls&SC_ScrollBarSubLine)) || (m_sbWidget && m_sbWidget!=widget))
5792                         opt.state &= ~(State_Sunken | State_MouseOver);
5793 
5794                     drawControl(CE_ScrollBarSubLine, &opt, painter, widget);
5795                 }
5796             }
5797 
5798             if((option->subControls&SC_ScrollBarAddLine) && addline.isValid())
5799             {
5800                 opt.rect=addline;
5801                 opt.state=scrollbar->state/*|(inStack ? NO_BGND_BUTTON : State_None)*/;
5802                 if(maxed || atMax)
5803                     opt.state&=~State_Enabled;
5804                 if (!(scrollbar->activeSubControls&SC_ScrollBarAddLine))
5805                     opt.state &= ~(State_Sunken | State_MouseOver);
5806                 drawControl(CE_ScrollBarAddLine, &opt, painter, widget);
5807             }
5808 
5809             if((option->subControls&SC_ScrollBarFirst) && first.isValid())
5810             {
5811                 opt.rect=first;
5812                 opt.state=scrollbar->state;
5813                 if (!(scrollbar->activeSubControls&SC_ScrollBarFirst))
5814                     opt.state &= ~(State_Sunken | State_MouseOver);
5815                 drawControl(CE_ScrollBarFirst, &opt, painter, widget);
5816             }
5817 
5818             if((option->subControls&SC_ScrollBarLast) && last.isValid())
5819             {
5820                 opt.rect=last;
5821                 opt.state=scrollbar->state;
5822                 if (!(scrollbar->activeSubControls&SC_ScrollBarLast))
5823                     opt.state &= ~(State_Sunken | State_MouseOver);
5824                 drawControl(CE_ScrollBarLast, &opt, painter, widget);
5825             }
5826 
5827             if(((option->subControls&SC_ScrollBarSlider) || noButtons) && slider.isValid())
5828             {
5829                 // If "SC_ScrollBarSlider" wasn't specified, then we only want to draw the portion
5830                 // of the slider that overlaps with the trough. So, once again set the clipping
5831                 // region...
5832 
5833                 // NO! Seeems to mess things up with Arora, su just dsiable all clipping when drawing
5834                 // the slider...
5835                 painter->setClipping(false);
5836 #ifdef INCREASE_SB_SLIDER
5837                 if(!opts.flatSbarButtons)
5838                 {
5839                     if(atMax)
5840                         switch(opts.scrollbarType)
5841                         {
5842                         case SCROLLBAR_KDE:
5843                         case SCROLLBAR_WINDOWS:
5844                         case SCROLLBAR_PLATINUM:
5845                             if(horiz)
5846                                 slider.adjust(0, 0, 1, 0);
5847                             else
5848                                 slider.adjust(0, 0, 0, 1);
5849                         default:
5850                             break;
5851                         }
5852                     if(atMin)
5853                         switch(opts.scrollbarType)
5854                         {
5855                         case SCROLLBAR_KDE:
5856                         case SCROLLBAR_WINDOWS:
5857                         case SCROLLBAR_NEXT:
5858                             if(horiz)
5859                                 slider.adjust(-1, 0, 0, 0);
5860                             else
5861                                 slider.adjust(0, -1, 0, 0);
5862                         default:
5863                             break;
5864                         }
5865                 }
5866 #endif
5867                 opt.rect=slider;
5868                 opt.state=scrollbar->state;
5869                 if (!(scrollbar->activeSubControls&SC_ScrollBarSlider))
5870                     opt.state &= ~(State_Sunken | State_MouseOver);
5871                 drawControl(CE_ScrollBarSlider, &opt, painter, widget);
5872 
5873                 // ### perhaps this should not be able to accept focus if maxedOut?
5874                 if(state&State_HasFocus)
5875                 {
5876                     opt.state=scrollbar->state;
5877                     opt.rect=QRect(slider.x()+2, slider.y()+2, slider.width()-5, slider.height()-5);
5878                     drawPrimitive(PE_FrameFocusRect, &opt, painter, widget);
5879                 }
5880             }
5881             painter->restore();
5882         }
5883         break;
5884     case CC_ComboBox:
5885         if (auto comboBox = styleOptCast<QStyleOptionComboBox>(option)) {
5886             painter->save();
5887 
5888             QRect frame(subControlRect(CC_ComboBox, option,
5889                                        SC_ComboBoxFrame, widget));
5890             QRect arrow(subControlRect(CC_ComboBox, option,
5891                                        SC_ComboBoxArrow, widget));
5892             QRect field(subControlRect(CC_ComboBox, option,
5893                                        SC_ComboBoxEditField, widget));
5894             const QColor *use = buttonColors(option);
5895             bool sunken = state & State_On;
5896             bool glowOverFocus =
5897                 (state & State_MouseOver &&
5898                  oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED) &&
5899                  opts.coloredMouseOver == MO_GLOW &&
5900                  opts.buttonEffect != EFFECT_NONE && !sunken &&
5901                  !comboBox->editable && state & State_Enabled &&
5902                  state & State_HasFocus);
5903             bool doEffect = (opts.buttonEffect != EFFECT_NONE &&
5904                              (!comboBox->editable || opts.etchEntry));
5905             bool isOO = isOOWidget(widget);
5906             bool isOO31 = isOO;
5907 
5908             if (isOO) {
5909                 // This (hopefull) checks is we're OO.o 3.2 -
5910                 // in which case no adjustment is required...
5911                 const QImage *img = getImage(painter);
5912 
5913                 isOO31 = !img || img->rect() != r;
5914 
5915                 if (isOO31) {
5916                     frame.adjust(0, 0, 0, -2);
5917                     arrow.adjust(0, 0, 0, -2);
5918                     field.adjust(0, 0, 0, -2);
5919                 } else {
5920                     arrow.adjust(1, 0, 0, 0);
5921                 }
5922             }
5923 
5924             // painter->fillRect(r, Qt::transparent);
5925             if (doEffect) {
5926                 bool glowFocus(state&State_HasFocus && state&State_Enabled && USE_GLOW_FOCUS(state&State_MouseOver));
5927 
5928                 if (!glowOverFocus && !(opts.thin & THIN_FRAMES) && !sunken &&
5929                     opts.coloredMouseOver == MO_GLOW &&
5930                     (((oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED) ||
5931                        glowFocus) && state & State_HasFocus) ||
5932                      state & State_MouseOver) &&
5933                     state & State_Enabled && !comboBox->editable) {
5934                     drawGlow(painter, r,
5935                              oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED) &&
5936                              state & State_HasFocus ? WIDGET_DEF_BUTTON :
5937                              WIDGET_COMBO, glowFocus ? m_focusCols : 0L);
5938                 } else {
5939                     drawEtch(painter, r, widget, WIDGET_COMBO,
5940                              !comboBox->editable &&
5941                              opts.buttonEffect == EFFECT_SHADOW && !sunken,
5942                              comboBox->editable && opts.square & SQUARE_ENTRY ?
5943                              opts.unifyCombo ? ROUNDED_NONE : reverse ?
5944                              ROUNDED_LEFT : ROUNDED_RIGHT : ROUNDED_ALL);
5945                 }
5946                 frame.adjust(1, 1, -1, -1);
5947             }
5948 
5949             if(/*comboBox->frame &&*/ frame.isValid() && (!comboBox->editable || !opts.unifyCombo))
5950             {
5951                 const QColor *cols=m_comboBtnCols && comboBox->editable && state&State_Enabled ? m_comboBtnCols : use;
5952 
5953                 QStyleOption frameOpt(*option);
5954 
5955                 if (comboBox->editable && !(comboBox->activeSubControls&SC_ComboBoxArrow))
5956                     frameOpt.state &= ~(State_Sunken | State_MouseOver);
5957 
5958                 if(!sunken)
5959                     frameOpt.state|=State_Raised;
5960 
5961                 //if(opts.coloredMouseOver && frameOpt.state&State_MouseOver && comboBox->editable && !sunken)
5962                 //    frame.adjust(reverse ? 0 : 1, 0, reverse ? 1 : 0, 0);
5963 
5964                 drawLightBevel(painter, frame, &frameOpt, widget,
5965                                comboBox->editable ? (reverse ? ROUNDED_LEFT : ROUNDED_RIGHT) : ROUNDED_ALL,
5966                                getFill(&frameOpt, cols, false,
5967                                        (SHADE_DARKEN==opts.comboBtn || (SHADE_NONE!=opts.comboBtn &&
5968                                                                         !(state&State_Enabled))) &&
5969                                        comboBox->editable),
5970                                cols, true, comboBox->editable ? WIDGET_COMBO_BUTTON : WIDGET_COMBO);
5971             }
5972 
5973             if(/*controls&SC_ComboBoxEditField &&*/ field.isValid())
5974             {
5975                 if(comboBox->editable)
5976                 {
5977                     if(opts.unifyCombo)
5978                     {
5979                         field=r;
5980                         if(doEffect)
5981                             field.adjust(1, 1, -1, -1);
5982                         if(isOO31)
5983                             field.adjust(0, 0, 0, -2);
5984                     }
5985                     else if(doEffect)
5986                         field.adjust(reverse ? -4 : -3, -1, reverse ? 3 : 4, 1);
5987                     else
5988                         field.adjust(reverse ? -4 : -2, -1, reverse ? 2 : 4, 1);
5989                     drawEntryField(painter, field, widget, option, opts.unifyCombo ? ROUNDED_ALL : reverse ? ROUNDED_RIGHT : ROUNDED_LEFT,
5990                                    true, false);
5991                 }
5992                 else if(opts.comboSplitter && !(SHADE_DARKEN==opts.comboBtn || m_comboBtnCols))
5993                 {
5994                     drawFadedLine(painter, QRect(reverse ? arrow.right()+1 : arrow.x()-1, arrow.top()+2,
5995                                                  1, arrow.height()-4),
5996                                   use[BORDER_VAL(state&State_Enabled)], true, true, false);
5997                     if(!sunken)
5998                         drawFadedLine(painter, QRect(reverse ? arrow.right()+2 : arrow.x(), arrow.top()+2,
5999                                                      1, arrow.height()-4),
6000                                       use[0], true, true, false);
6001                 }
6002             }
6003 
6004             if(/*controls&SC_ComboBoxArrow && */arrow.isValid())
6005             {
6006                 bool mouseOver=comboBox->editable && !(comboBox->activeSubControls&SC_ComboBoxArrow)
6007                     ? false : (state&State_MouseOver ? true : false);
6008 
6009                 if(!comboBox->editable && (SHADE_DARKEN==opts.comboBtn || m_comboBtnCols))
6010                 {
6011                     if(!comboBox->editable && isOO && !isOO31)
6012                         arrow.adjust(reverse ? 0 : 1, 0, reverse ? -1 : 0, 0);
6013 
6014                     QStyleOption frameOpt(*option);
6015                     QRect        btn(arrow.x(), frame.y(), arrow.width()+1, frame.height());
6016                     const QColor *cols=SHADE_DARKEN==opts.comboBtn || !(state&State_Enabled) ? use : m_comboBtnCols;
6017                     if(!sunken)
6018                         frameOpt.state|=State_Raised;
6019                     painter->save();
6020                     painter->setClipRect(btn, Qt::IntersectClip);
6021                     drawLightBevel(painter, opts.comboSplitter
6022                                    ? btn.adjusted(reverse ? -2 : 0, 0, reverse ? 2 : 1, 0)
6023                                    : btn.adjusted(reverse ? -3 : -2, 0, reverse ? 2 : 1, 0),
6024                                    &frameOpt, widget, reverse ? ROUNDED_LEFT : ROUNDED_RIGHT,
6025                                    getFill(&frameOpt, cols, false,
6026                                            SHADE_DARKEN==opts.comboBtn || (SHADE_NONE!=opts.comboBtn &&
6027                                                                            !(state&State_Enabled))),
6028                                    cols, true, WIDGET_COMBO);
6029                     painter->restore();
6030                 }
6031 
6032                 if(sunken && (!comboBox->editable || !opts.unifyCombo))
6033                     arrow.adjust(1, 1, 1, 1);
6034 
6035                 const QColor &arrowColor = MOArrow(state, palette, mouseOver,
6036                                                    QPalette::ButtonText);
6037                 if(comboBox->editable || !(opts.gtkComboMenus && opts.doubleGtkComboArrow))
6038                     drawArrow(painter, arrow, PE_IndicatorArrowDown, arrowColor, false);
6039                 else
6040                 {
6041                     int middle=arrow.y()+(arrow.height()>>1),
6042                         gap=(opts.vArrows ? 2 : 1);
6043 
6044                     QRect ar=QRect(arrow.x(), middle-(LARGE_ARR_HEIGHT+gap), arrow.width(), LARGE_ARR_HEIGHT);
6045                     drawArrow(painter, ar, PE_IndicatorArrowUp, arrowColor, false);
6046                     ar=QRect(arrow.x(), middle+gap, arrow.width(), LARGE_ARR_HEIGHT);
6047                     drawArrow(painter, ar, PE_IndicatorArrowDown, arrowColor, false);
6048                 }
6049             }
6050 
6051             if(state&State_Enabled && state&State_HasFocus &&
6052                /*state&State_KeyboardFocusChange &&*/ !comboBox->editable && FOCUS_GLOW!=opts.focus)
6053             {
6054                 QStyleOptionFocusRect focus;
6055                 bool listViewCombo = (comboBox->frame && widget &&
6056                                       widget->rect().height() <
6057                                       (opts.buttonEffect != EFFECT_NONE ?
6058                                        22 : 20));
6059 
6060                 if (oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)) {
6061                     focus.rect = frame;
6062                 } else if (opts.comboSplitter) {
6063                     focus.rect = (reverse ? field.adjusted(0, -1, 1, 1) :
6064                                   field.adjusted(-1, -1, 0, 1));
6065 
6066                     if(listViewCombo)
6067                         focus.rect.adjust(0, -2, 0, 2);
6068                 }
6069                 else if(listViewCombo)
6070                     focus.rect=frame.adjusted(1, 1, -1, -1);
6071                 else
6072                     focus.rect=frame.adjusted(3, 3, -3, -3);
6073 
6074                 // Draw glow over top of filled focus
6075                 if(glowOverFocus && !(opts.thin&THIN_FRAMES))
6076                     drawGlow(painter, frame.adjusted(-1, -1, 1, 1), WIDGET_COMBO);
6077                 else
6078                     drawPrimitive(PE_FrameFocusRect, &focus, painter, widget);
6079             }
6080             painter->restore();
6081         }
6082         break;
6083     default:
6084         ParentStyleClass::drawComplexControl(control, option, painter, widget);
6085         break;
6086     }
6087 }
6088 
6089 void
drawItemText(QPainter * painter,const QRect & rect,int flags,const QPalette & pal,bool enabled,const QString & text,QPalette::ColorRole textRole) const6090 Style::drawItemText(QPainter *painter, const QRect &rect, int flags,
6091                     const QPalette &pal, bool enabled, const QString &text,
6092                     QPalette::ColorRole textRole) const
6093 {
6094     if (textRole == QPalette::ButtonText && !opts.stdSidebarButtons) {
6095         const QAbstractButton *button = getButton(nullptr, painter);
6096         if (button && isMultiTabBarTab(button) && button->isChecked()) {
6097             QPalette p(pal);
6098             if (m_inactiveChangeSelectionColor &&
6099                 p.currentColorGroup() == QPalette::Inactive) {
6100                 p.setCurrentColorGroup(QPalette::Active);
6101             }
6102             ParentStyleClass::drawItemText(painter, rect, flags, p, enabled,
6103                                        text, QPalette::HighlightedText);
6104             return;
6105         }
6106     }
6107 
6108     ParentStyleClass::drawItemText(painter, rect, flags, pal,
6109                                enabled, text, textRole);
6110 }
6111 
sizeFromContents(ContentsType type,const QStyleOption * option,const QSize & size,const QWidget * widget) const6112 QSize Style::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const
6113 {
6114     prePolish(widget);
6115     QSize newSize(ParentStyleClass::sizeFromContents(type, option, size, widget));
6116 
6117     switch (type)
6118     {
6119     case CT_TabBarTab:
6120         newSize+=QSize(1, 1);
6121         break;
6122     case CT_Splitter:
6123     {
6124         int sw=pixelMetric(PM_SplitterWidth, 0L, 0L);
6125         return QSize(sw, sw);
6126     }
6127     case CT_PushButton:
6128     {
6129         newSize=size;
6130         newSize.setWidth(newSize.width()+(ROUND_MAX==opts.round ? 12 : 8));
6131 
6132         if (auto btn = styleOptCast<QStyleOptionButton>(option)) {
6133             if (!opts.stdBtnSizes) {
6134                 // Cant rely on AutoDefaultButton
6135                 //   - as VirtualBox does not set this!!!
6136                 bool allowIcon = styleHint(SH_DialogButtonBox_ButtonsHaveIcons, btn, widget) || btn->text.isEmpty();
6137                 if (allowIcon && (qtcCheckType<QDialogButtonBox>(getParent(widget)) ||
6138                     qtcCheckType(getParent(widget), "KFileWidget"))) {
6139                     int iconHeight = (btn->icon.isNull() ?
6140                                       btn->iconSize.height() : 16);
6141                     if (size.height() < iconHeight + 2) {
6142                         newSize.setHeight(iconHeight + 2);
6143                     }
6144                 }
6145             }
6146 
6147             int margin = (pixelMetric(PM_ButtonMargin, btn, widget)+
6148                           (pixelMetric(PM_DefaultFrameWidth, btn, widget) * 2))-MAX_ROUND_BTN_PAD;
6149 
6150             newSize+=QSize(margin, margin);
6151 
6152             if (btn->features&QStyleOptionButton::HasMenu)
6153                 newSize+=QSize(4, 0);
6154 
6155             if (!btn->text.isEmpty() && "..."!=btn->text && newSize.width() < 80)
6156                 newSize.setWidth(80);
6157 
6158             newSize.rheight() += ((1 - newSize.rheight()) & 1);
6159         }
6160         break;
6161     }
6162 //         case CT_RadioButton:
6163 //             ++newSize.rheight();
6164 //             ++newSize.rwidth();
6165 //             break;
6166     case CT_RadioButton:
6167     case CT_CheckBox:
6168         if (auto btn = styleOptCast<QStyleOptionButton>(option)) {
6169             bool isRadio = CT_RadioButton==type;
6170             int  w = /*proxy()->*/pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth : PM_IndicatorWidth, btn, widget),
6171                 h = /*proxy()->*/pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight : PM_IndicatorHeight, btn, widget),
6172                 margins = 0;
6173 
6174             newSize=size;
6175             // we add 4 pixels for label margins
6176             if (btn->icon.isNull() || !btn->text.isEmpty())
6177                 margins = 0+/*proxy()->*/pixelMetric(isRadio ? PM_RadioButtonLabelSpacing : PM_CheckBoxLabelSpacing, option, widget)+
6178                     (opts.crHighlight ? 4 : 0);
6179 
6180             newSize += QSize(w + margins, 4);
6181             newSize.setHeight(qMax(newSize.height(), h));
6182         }
6183         break;
6184     case CT_ScrollBar:
6185         if (auto scrollBar = styleOptCast<QStyleOptionSlider>(option)) {
6186             int scrollBarExtent =
6187                 pixelMetric(PM_ScrollBarExtent, option, widget);
6188             // See https://github.com/QtCurve/qtcurve-qt4/issues/7
6189             // and https://bugs.kde.org/show_bug.cgi?id=317690.
6190             int scrollBarLen =
6191                 (qtcMax(scrollBarExtent, 13) *
6192                  qtcScrollbarButtonNumSize(opts.scrollbarType) +
6193                  pixelMetric(PM_ScrollBarSliderMin, option, widget));
6194 
6195             if (scrollBar->orientation == Qt::Horizontal) {
6196                 newSize = QSize(scrollBarLen, scrollBarExtent);
6197             } else {
6198                 newSize = QSize(scrollBarExtent, scrollBarLen);
6199             }
6200         }
6201         break;
6202     case CT_LineEdit:
6203         if (auto f = styleOptCast<QStyleOptionFrame>(option)) {
6204             newSize = size + QSize(2 * f->lineWidth, 2 * f->lineWidth);
6205         }
6206         break;
6207     case CT_SpinBox:
6208         if(!opts.unifySpin)
6209             newSize.rheight() -= ((1 - newSize.rheight()) & 1);
6210         break;
6211     case CT_ToolButton:
6212     {
6213         newSize = QSize(size.width()+8, size.height()+8);
6214         // -- from kstyle & oxygen --
6215         // We want to avoid super-skiny buttons, for things like "up" when icons + text
6216         // For this, we would like to make width >= height.
6217         // However, once we get here, QToolButton may have already put in the menu area
6218         // (PM_MenuButtonIndicator) into the width. So we may have to take it out, fix things
6219         // up, and add it back in. So much for class-independent rendering...
6220         int menuAreaWidth(0);
6221 
6222         if (auto tbOpt = styleOptCast<QStyleOptionToolButton>(option)) {
6223             // Make Kate/KWrite's option toolbuton have the same size as the next/prev buttons...
6224             if (widget && !getToolBar(widget) && !tbOpt->text.isEmpty() &&
6225                 tbOpt->features & QStyleOptionToolButton::MenuButtonPopup) {
6226                 QStyleOptionButton btn;
6227 
6228                 btn.init(widget);
6229                 btn.text = tbOpt->text;
6230                 btn.icon = tbOpt->icon;
6231                 btn.iconSize = tbOpt->iconSize;
6232                 btn.features = ((tbOpt->features &
6233                                 QStyleOptionToolButton::MenuButtonPopup) ?
6234                                 QStyleOptionButton::HasMenu :
6235                                 QStyleOptionButton::None);
6236                 return sizeFromContents(CT_PushButton, &btn, size, widget);
6237             }
6238 
6239             if (!tbOpt->icon.isNull() && !tbOpt->text.isEmpty() && Qt::ToolButtonTextUnderIcon==tbOpt->toolButtonStyle)
6240                 newSize.setHeight(newSize.height()-4);
6241 
6242             if (tbOpt->features & QStyleOptionToolButton::MenuButtonPopup)
6243                 menuAreaWidth = pixelMetric(QStyle::PM_MenuButtonIndicator,
6244                                             option, widget);
6245             else if (tbOpt->features & QStyleOptionToolButton::HasMenu)
6246                 switch(tbOpt->toolButtonStyle)
6247                 {
6248                 case Qt::ToolButtonIconOnly:
6249                     newSize.setWidth(newSize.width()+LARGE_ARR_WIDTH+2);
6250                     break;
6251                 case Qt::ToolButtonTextBesideIcon:
6252                     newSize.setWidth(newSize.width()+3);
6253                     break;
6254                 case Qt::ToolButtonTextOnly:
6255                     newSize.setWidth(newSize.width()+8);
6256                     break;
6257                 case Qt::ToolButtonTextUnderIcon:
6258                     newSize.setWidth(newSize.width()+8);
6259                     break;
6260                 default:
6261                     break;
6262                 }
6263         }
6264 
6265         newSize.setWidth(newSize.width() - menuAreaWidth);
6266         if (newSize.width() < newSize.height())
6267             newSize.setWidth(newSize.height());
6268         newSize.setWidth(newSize.width() + menuAreaWidth);
6269 
6270         break;
6271     }
6272     case CT_ComboBox: {
6273         newSize = size;
6274         newSize.setWidth(newSize.width() + 4);
6275 
6276         auto combo = styleOptCast<QStyleOptionComboBox>(option);
6277         int  margin = (pixelMetric(PM_ButtonMargin, option, widget)+
6278                        (pixelMetric(PM_DefaultFrameWidth, option, widget) * 2))-MAX_ROUND_BTN_PAD,
6279             textMargins = 2*(pixelMetric(PM_FocusFrameHMargin) + 1),
6280             // QItemDelegate::sizeHint expands the textMargins two times, thus the 2*textMargins...
6281             other = qMax(opts.buttonEffect != EFFECT_NONE ? 20 : 18,
6282                          2 * textMargins +
6283                          pixelMetric(QStyle::PM_ScrollBarExtent,
6284                                      option, widget));
6285         bool editable=combo ? combo->editable : false;
6286         newSize+=QSize(margin+other, margin-2);
6287         newSize.rheight() += ((1 - newSize.rheight()) & 1);
6288 
6289         if (!opts.etchEntry && opts.buttonEffect != EFFECT_NONE && editable)
6290             newSize.rheight()-=2;
6291         // KWord's zoom combo clips 'Fit Page Width' without the following...
6292         if(editable)
6293             newSize.rwidth()+=6;
6294         break;
6295     }
6296     case CT_MenuItem:
6297         if (auto mi = styleOptCast<QStyleOptionMenuItem>(option)) {
6298             initFontTickData(opts, mi->font, widget);
6299             // Taken from QWindowStyle...
6300             int w = size.width();
6301 
6302             if (QStyleOptionMenuItem::Separator==mi->menuItemType) {
6303                 newSize = QSize(10, windowsSepHeight);
6304             } else {
6305                 if (mi->icon.isNull()) {
6306                     newSize.setHeight(newSize.height() - 2);
6307                     w -= 6;
6308                 } else {
6309                     int iconExtent = pixelMetric(PM_SmallIconSize, option, widget);
6310                     newSize.setHeight(qMax(newSize.height(),
6311                                         mi->icon.actualSize(QSize(iconExtent, iconExtent)).height()
6312                                         + 2 * windowsItemFrame));
6313                 }
6314                 int dx;
6315                 if (menuTickCompensation(opts, 20, dx)) {
6316                     w += dx;
6317                 }
6318             }
6319             int maxpmw = mi->maxIconWidth,
6320                 tabSpacing = 20;
6321 
6322             if (!opts.buttonStyleMenuSections && QStyleOptionMenuItem::Separator == mi->menuItemType && !mi->text.isEmpty())
6323             {
6324                 QFont fontBold = mi->font;
6325                 fontBold.setBold(true);
6326                 QFontMetrics fmBold(fontBold);
6327                 // _set_ w, it will have been initialised to something inappropriately small
6328                 w = fmBold.width(mi->text);
6329             }
6330             else if (mi->text.contains(QLatin1Char('\t')))
6331                 w += tabSpacing;
6332             else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu)
6333                 w += 2 * windowsArrowHMargin;
6334             else if (mi->menuItemType == QStyleOptionMenuItem::DefaultItem)
6335             {
6336                 // adjust the font and add the difference in size.
6337                 // it would be better if the font could be adjusted in the initStyleOption qmenu func!!
6338                 QFontMetrics fm(mi->font);
6339                 QFont fontBold = mi->font;
6340                 fontBold.setBold(true);
6341                 QFontMetrics fmBold(fontBold);
6342                 w += fmBold.width(mi->text) - fm.width(mi->text);
6343             }
6344 
6345             if (QStyleOptionMenuItem::Separator != mi->menuItemType || opts.buttonStyleMenuSections)
6346             {
6347                 int checkcol = qMax<int>(maxpmw, windowsCheckMarkWidth); // Windows always shows a check column
6348                 w += checkcol + windowsRightBorder;
6349             }
6350             else
6351             {
6352                 w += 5;
6353             }
6354             w += 10;
6355             newSize.setWidth(w);
6356             // ....
6357 
6358             int h(newSize.height()-8); // Fix mainly for Qt4.4
6359 
6360             if (QStyleOptionMenuItem::Separator==mi->menuItemType && mi->text.isEmpty())
6361                 h = 7;
6362             else
6363             {
6364                 h = qMax(h, mi->fontMetrics.height());
6365                 if (!mi->icon.isNull())
6366                     h = qMax(h, mi->icon.pixmap(pixelMetric(PM_SmallIconSize), QIcon::Normal).height());
6367 
6368                 if (h < 18)
6369                     h = 18;
6370                 h+=((opts.thin&THIN_MENU_ITEMS) ? 2 : 4);
6371 
6372                 if(QStyleOptionMenuItem::Separator==mi->menuItemType)
6373                     h+=4;
6374             }
6375 
6376             newSize.setHeight(h);
6377             // Gtk2's icon->text spacing is 2 pixels smaller - so adjust here...
6378             newSize.setWidth(newSize.width()-2);
6379         }
6380         break;
6381     case CT_MenuBarItem:
6382         if (!size.isEmpty())
6383             newSize = size + QSize((windowsItemHMargin * 4) + 2,
6384                                    windowsItemVMargin + 1);
6385         break;
6386     default:
6387         break;
6388     }
6389 
6390     return newSize;
6391 }
6392 
subElementRect(SubElement element,const QStyleOption * option,const QWidget * widget) const6393 QRect Style::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
6394 {
6395     prePolish(widget);
6396     QRect rect;
6397     switch (element) {
6398     case SE_SliderFocusRect:
6399     case SE_ToolBoxTabContents:
6400         return visualRect(option->direction, option->rect, option->rect);
6401     case SE_DockWidgetTitleBarText: {
6402         auto dwopt = styleOptCast<QStyleOptionDockWidget>(option);
6403         bool verticalTitleBar = dwopt ? dwopt->verticalTitleBar : false;
6404         int m = pixelMetric(PM_DockWidgetTitleMargin, option, widget);
6405 
6406         rect = ParentStyleClass::subElementRect(element, option, widget);
6407 
6408         if (verticalTitleBar)
6409             rect.adjust(0, 0, 0, -m);
6410         else if (Qt::LeftToRight==option->direction )
6411             rect.adjust(m, 0, 0, 0);
6412         else
6413             rect.adjust(0, 0, -m, 0);
6414         return rect;
6415     }
6416     case SE_TabBarTabLeftButton:
6417         return ParentStyleClass::subElementRect(element, option, widget).translated(-2, -1);
6418     case SE_TabBarTabRightButton:
6419         return ParentStyleClass::subElementRect(element, option, widget).translated(2, -1);
6420     case SE_TabBarTabText:
6421         if (auto _tab = styleOptCast<QStyleOptionTab>(option)) {
6422             QStyleOptionTab tab(*_tab);
6423             bool verticalTabs = QTabBar::RoundedEast == tab.shape ||
6424                 QTabBar::RoundedWest == tab.shape ||
6425                 QTabBar::TriangularEast == tab.shape ||
6426                 QTabBar::TriangularWest == tab.shape;
6427 
6428             rect=tab.rect;
6429             if (verticalTabs)
6430                 rect.setRect(0, 0, rect.height(), rect.width());
6431             int verticalShift = pixelMetric(QStyle::PM_TabBarTabShiftVertical,
6432                                             _tab, widget);
6433             int horizontalShift = pixelMetric(QStyle::PM_TabBarTabShiftHorizontal,
6434                                               _tab, widget);
6435             if (tab.shape == QTabBar::RoundedSouth ||
6436                 tab.shape == QTabBar::TriangularSouth)
6437                 verticalShift = -verticalShift;
6438             rect.adjust(0, 0, horizontalShift, verticalShift);
6439             bool selected = tab.state & State_Selected;
6440             if (selected) {
6441                 rect.setBottom(rect.bottom() - verticalShift);
6442                 rect.setRight(rect.right() - horizontalShift);
6443             }
6444 
6445             // left widget
6446             if(opts.centerTabText) {
6447                 if (!tab.leftButtonSize.isEmpty())  // left widget
6448                     rect.setLeft(rect.left() + constTabPad +
6449                                  (verticalTabs ? tab.leftButtonSize.height() :
6450                                   tab.leftButtonSize.width()));
6451                 if (!tab.rightButtonSize.isEmpty()) // right widget
6452                     rect.setRight(rect.right() - constTabPad -
6453                                   (verticalTabs ? tab.rightButtonSize.height() :
6454                                    tab.rightButtonSize.width()));
6455             } else {
6456                 if (tab.leftButtonSize.isNull()) {
6457                     rect.setLeft(rect.left()+constTabPad);
6458                 } else if(tab.leftButtonSize.width()>0) {
6459                     rect.setLeft(rect.left() + constTabPad + 2 +
6460                                  (verticalTabs ? tab.leftButtonSize.height() :
6461                                   tab.leftButtonSize.width()));
6462                 } else if(tab.icon.isNull()) {
6463                     rect.setLeft(rect.left() + constTabPad);
6464                 } else {
6465                     rect.setLeft(rect.left() + 2);
6466                 }
6467             }
6468 
6469             // icon
6470             if (!tab.icon.isNull()) {
6471                 QSize iconSize = tab.iconSize;
6472                 if (!iconSize.isValid()) {
6473                     int iconExtent = pixelMetric(PM_SmallIconSize);
6474                     iconSize = QSize(iconExtent, iconExtent);
6475                 }
6476                 QSize tabIconSize = tab.icon.actualSize(iconSize,
6477                                                         (tab.state &
6478                                                          State_Enabled) ?
6479                                                         QIcon::Normal :
6480                                                         QIcon::Disabled);
6481                 int offset = 4;
6482 
6483                 if (!opts.centerTabText && tab.leftButtonSize.isNull())
6484                     offset += 2;
6485 
6486                 QRect iconRect = QRect(rect.left() + offset, rect.center().y() - tabIconSize.height() / 2,
6487                                        tabIconSize.width(), tabIconSize .height());
6488                 if (!verticalTabs)
6489                     iconRect = visualRect(option->direction, option->rect, iconRect);
6490                 rect.setLeft(rect.left() + tabIconSize.width() + offset + 2);
6491             }
6492 
6493             // right widget
6494             if (!opts.centerTabText && !tab.rightButtonSize.isNull() &&
6495                 tab.rightButtonSize.width() > 0) {
6496                 rect.setRight(rect.right() - constTabPad - 2 -
6497                               (verticalTabs ? tab.rightButtonSize.height() :
6498                                tab.rightButtonSize.width()));
6499             } else {
6500                 rect.setRight(rect.right() - constTabPad);
6501             }
6502 
6503             if (!verticalTabs)
6504                 rect = visualRect(option->direction, option->rect, rect);
6505             return rect;
6506         }
6507         break;
6508     case SE_RadioButtonIndicator:
6509         rect = visualRect(option->direction, option->rect,
6510                           ParentStyleClass::subElementRect(element, option, widget)).adjusted(0, 0, 1, 1);
6511         break;
6512     case SE_ProgressBarContents:
6513         return (opts.fillProgress ? opts.buttonEffect != EFFECT_NONE &&
6514                 opts.borderProgress ? option->rect.adjusted(1, 1, -1, -1) :
6515                 option->rect : opts.buttonEffect != EFFECT_NONE &&
6516                 opts.borderProgress ? option->rect.adjusted(3, 3, -3, -3) :
6517                 option->rect.adjusted(2, 2, -2, -2));
6518     case SE_ProgressBarGroove:
6519     case SE_ProgressBarLabel:
6520         return option->rect;
6521     case SE_GroupBoxLayoutItem:
6522         rect = option->rect;
6523 //             if (auto groupBoxOpt = styleOptCast<QStyleOptionGroupBox>(option))
6524 //                 if (groupBoxOpt->subControls & (SC_GroupBoxCheckBox | SC_GroupBoxLabel))
6525 //                     rect.setTop(rect.top() + 2);    // eat the top margin a little bit
6526         break;
6527     case SE_PushButtonFocusRect:
6528         if (oneOf(opts.focus, FOCUS_FULL, FOCUS_FILLED)) {
6529             rect = subElementRect(SE_PushButtonContents, option, widget);
6530             if (opts.buttonEffect != EFFECT_NONE) {
6531                 rect.adjust(-1, -1, 1, 1);
6532             } else {
6533                 rect.adjust(-2, -2, 2, 2);
6534             }
6535         } else {
6536             rect = ParentStyleClass::subElementRect(element, option, widget);
6537             if (opts.buttonEffect != EFFECT_NONE) {
6538                 rect.adjust(1, 1, -1, -1);
6539             }
6540         }
6541         return rect;
6542     default:
6543         return ParentStyleClass::subElementRect(element, option, widget);
6544     }
6545 
6546     return visualRect(option->direction, option->rect, rect);
6547 }
6548 
subControlRect(ComplexControl control,const QStyleOptionComplex * option,SubControl subControl,const QWidget * widget) const6549 QRect Style::subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const
6550 {
6551     prePolish(widget);
6552     QRect r(option->rect);
6553     bool  reverse(Qt::RightToLeft==option->direction);
6554 
6555     switch (control) {
6556     case CC_ComboBox:
6557         if (auto comboBox = styleOptCast<QStyleOptionComboBox>(option)) {
6558             bool ed = comboBox->editable;
6559             bool doEtch = ((!ed || opts.etchEntry) &&
6560                            opts.buttonEffect != EFFECT_NONE);
6561             int  x(r.x()),
6562                 y(r.y()),
6563                 w(r.width()),
6564                 h(r.height());
6565 
6566             switch (subControl)
6567             {
6568             case SC_ComboBoxFrame:
6569                 if(ed)
6570                 {
6571                     int btnWidth(doEtch ? 22 : 20);
6572 
6573                     r=QRect(x+w-btnWidth, y, btnWidth, h);
6574                 }
6575                 break;
6576             case SC_ComboBoxArrow:
6577             {
6578                 int bmarg(comboBox->frame ? 2 : 0);
6579 
6580                 r.setRect(x + w - bmarg - (doEtch ? 17 : 16), y + bmarg, 16, h - 2*bmarg);
6581                 if(ed && opts.unifyCombo)
6582                     r.adjust(-1, 0, 0, 0);
6583                 break;
6584             }
6585             case SC_ComboBoxEditField:
6586             {
6587                 int margin(comboBox->frame ? 3 : 0);
6588 
6589                 r.setRect(x + margin+(opts.unifyCombo ? 0 : 2), y + margin,
6590                           w - 2 * margin - (opts.unifyCombo ? 15 : 23), h - 2 * margin);
6591                 if(doEtch)
6592                     r.adjust(ed ? 0 : 1, 1, ed ? 0 : -1, -1);
6593                 if(ed)
6594                     r.adjust(-1, -2, 1, 2);
6595                 break;
6596             }
6597             case SC_ComboBoxListBoxPopup:
6598             default:
6599                 break;
6600             }
6601             return visualRect(comboBox->direction, comboBox->rect, r);
6602         }
6603         break;
6604     case CC_SpinBox:
6605         if (auto spinbox = styleOptCast<QStyleOptionSpinBox>(option)) {
6606             int fw(spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0);
6607             QSize bs;
6608 
6609             bs.setHeight(r.height()>>1);
6610             if(bs.height()< 8)
6611                 bs.setHeight(8);
6612             bs.setWidth(opts.buttonEffect != EFFECT_NONE && opts.etchEntry ?
6613                         16 : 15);
6614             bs=bs.expandedTo(QApplication::globalStrut());
6615 
6616             int y(0), x(reverse ? 0 : r.width()-bs.width());
6617 
6618             switch(subControl)
6619             {
6620             case SC_SpinBoxUp:
6621                 return QAbstractSpinBox::NoButtons==spinbox->buttonSymbols
6622                     ? QRect()
6623                     : QRect(x, y, bs.width(), bs.height());
6624             case SC_SpinBoxDown:
6625                 if(QAbstractSpinBox::NoButtons==spinbox->buttonSymbols)
6626                     return QRect();
6627                 else
6628                     return QRect(x, y+bs.height(), bs.width(), bs.height()+(bs.height()*2==r.height() ? 0 : 1));
6629             case SC_SpinBoxEditField:
6630             {
6631                 int pad=opts.round>ROUND_FULL ? 2 : 0;
6632 
6633                 if (QAbstractSpinBox::NoButtons==spinbox->buttonSymbols)
6634                     return QRect(fw, fw, (x-fw*2)-pad, r.height()-2*fw);
6635                 else
6636                     return QRect(fw+(reverse ? bs.width() : 0), fw, (x-fw*2)-pad, r.height()-2*fw);
6637             }
6638             case SC_SpinBoxFrame:
6639             default:
6640                 return visualRect(spinbox->direction, spinbox->rect, spinbox->rect);
6641             }
6642         }
6643         break;
6644     case CC_ScrollBar:
6645         if (auto scrollBar = styleOptCast<QStyleOptionSlider>(option)) {
6646             // Taken from kstyle.cpp (KDE 3) , and modified so as to allow
6647             // for no scrollbar butttons...
6648             bool  threeButtonScrollBar(SCROLLBAR_KDE==opts.scrollbarType),
6649                 platinumScrollBar(SCROLLBAR_PLATINUM==opts.scrollbarType),
6650                 nextScrollBar(SCROLLBAR_NEXT==opts.scrollbarType),
6651                 noButtons(SCROLLBAR_NONE==opts.scrollbarType);
6652             QRect ret;
6653             bool  horizontal(Qt::Horizontal==scrollBar->orientation);
6654             int   sbextent(pixelMetric(PM_ScrollBarExtent, scrollBar, widget)),
6655                 sliderMaxLength(((scrollBar->orientation == Qt::Horizontal) ?
6656                                  scrollBar->rect.width() : scrollBar->rect.height()) - (sbextent * qtcScrollbarButtonNum(opts.scrollbarType))),
6657                 sliderMinLength(pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget)),
6658                 sliderLength;
6659 
6660             if (scrollBar->maximum != scrollBar->minimum)
6661             {
6662                 uint valueRange = scrollBar->maximum - scrollBar->minimum;
6663                 sliderLength = (scrollBar->pageStep * sliderMaxLength) / (valueRange + scrollBar->pageStep);
6664 
6665                 if (sliderLength < sliderMinLength || (!isOOWidget(widget) && valueRange > INT_MAX / 2))
6666                     sliderLength = sliderMinLength;
6667                 if (sliderLength > sliderMaxLength)
6668                     sliderLength = sliderMaxLength;
6669             }
6670             else
6671                 sliderLength = sliderMaxLength;
6672 
6673             int sliderstart(sliderPositionFromValue(scrollBar->minimum,
6674                                                     scrollBar->maximum,
6675                                                     scrollBar->sliderPosition,
6676                                                     sliderMaxLength - sliderLength,
6677                                                     scrollBar->upsideDown));
6678 
6679             switch(opts.scrollbarType)
6680             {
6681             case SCROLLBAR_KDE:
6682             case SCROLLBAR_WINDOWS:
6683                 sliderstart+=sbextent;
6684                 break;
6685             case SCROLLBAR_NEXT:
6686                 sliderstart+=sbextent*2;
6687             default:
6688                 break;
6689             }
6690 
6691             // Subcontrols
6692             switch(subControl)
6693             {
6694             case SC_ScrollBarSubLine:
6695                 if(noButtons)
6696                     return QRect();
6697 
6698                 // top/left button
6699                 if (platinumScrollBar)
6700                     if (horizontal)
6701                         ret.setRect(scrollBar->rect.width() - 2 * sbextent, 0, sbextent, sbextent);
6702                     else
6703                         ret.setRect(0, scrollBar->rect.height() - 2 * sbextent, sbextent, sbextent);
6704                 else if(threeButtonScrollBar)
6705                     if (horizontal)
6706                         ret.setRect(0, 0, scrollBar->rect.width() - sbextent +1, sbextent);
6707                     else
6708                         ret.setRect(0, 0, sbextent, scrollBar->rect.height() - sbextent +1);
6709                 else
6710                     ret.setRect(0, 0, sbextent, sbextent);
6711                 break;
6712             case SB_SUB2:
6713                 if(threeButtonScrollBar)
6714                     if (horizontal)
6715                         if(reverse)
6716                             ret.setRect(sbextent, 0, sbextent, sbextent);
6717                         else
6718                             ret.setRect(scrollBar->rect.width() - 2 * sbextent, 0, sbextent, sbextent);
6719                     else
6720                         ret.setRect(0, scrollBar->rect.height() - 2 * sbextent, sbextent, sbextent);
6721                 else
6722                     return QRect();
6723                 break;
6724             case SC_ScrollBarAddLine:
6725                 if(noButtons)
6726                     return QRect();
6727 
6728                 // bottom/right button
6729                 if (nextScrollBar)
6730                     if (horizontal)
6731                         ret.setRect(sbextent, 0, sbextent, sbextent);
6732                     else
6733                         ret.setRect(0, sbextent, sbextent, sbextent);
6734                 else
6735                     if (horizontal)
6736                         ret.setRect(scrollBar->rect.width() - sbextent, 0, sbextent, sbextent);
6737                     else
6738                         ret.setRect(0, scrollBar->rect.height() - sbextent, sbextent, sbextent);
6739                 break;
6740             case SC_ScrollBarSubPage:
6741                 // between top/left button and slider
6742                 if (platinumScrollBar)
6743                     if (horizontal)
6744                         ret.setRect(0, 0, sliderstart, sbextent);
6745                     else
6746                         ret.setRect(0, 0, sbextent, sliderstart);
6747                 else if (nextScrollBar)
6748                     if (horizontal)
6749                         ret.setRect(sbextent*2, 0, sliderstart-2*sbextent, sbextent);
6750                     else
6751                         ret.setRect(0, sbextent*2, sbextent, sliderstart-2*sbextent);
6752                 else
6753                     if (horizontal)
6754                         ret.setRect(noButtons ? 0 : sbextent, 0,
6755                                     noButtons ? sliderstart
6756                                     : (sliderstart - sbextent), sbextent);
6757                     else
6758                         ret.setRect(0, noButtons ? 0 : sbextent, sbextent,
6759                                     noButtons ? sliderstart : (sliderstart - sbextent));
6760                 break;
6761             case SC_ScrollBarAddPage:
6762             {
6763                 // between bottom/right button and slider
6764                 int fudge;
6765 
6766                 if (platinumScrollBar)
6767                     fudge = 0;
6768                 else if (nextScrollBar)
6769                     fudge = 2*sbextent;
6770                 else if(noButtons)
6771                     fudge = 0;
6772                 else
6773                     fudge = sbextent;
6774 
6775                 if (horizontal)
6776                     ret.setRect(sliderstart + sliderLength, 0,
6777                                 sliderMaxLength - sliderstart - sliderLength + fudge, sbextent);
6778                 else
6779                     ret.setRect(0, sliderstart + sliderLength, sbextent,
6780                                 sliderMaxLength - sliderstart - sliderLength + fudge);
6781                 break;
6782             }
6783             case SC_ScrollBarGroove:
6784                 if(noButtons)
6785                 {
6786                     if (horizontal)
6787                         ret=QRect(0, 0, scrollBar->rect.width(), scrollBar->rect.height());
6788                     else
6789                         ret=QRect(0, 0, scrollBar->rect.width(), scrollBar->rect.height());
6790                 }
6791                 else
6792                 {
6793                     int multi = threeButtonScrollBar ? 3 : 2,
6794                         fudge;
6795 
6796                     if (platinumScrollBar)
6797                         fudge = 0;
6798                     else if (nextScrollBar)
6799                         fudge = 2*sbextent;
6800                     else
6801                         fudge = sbextent;
6802 
6803                     if (horizontal)
6804                         ret=QRect(fudge, 0, scrollBar->rect.width() - sbextent * multi, scrollBar->rect.height());
6805                     else
6806                         ret=QRect(0, fudge, scrollBar->rect.width(), scrollBar->rect.height() - sbextent * multi);
6807                 }
6808                 break;
6809             case SC_ScrollBarSlider:
6810                 if (horizontal)
6811                     ret=QRect(sliderstart, 0, sliderLength, sbextent);
6812                 else
6813                     ret=QRect(0, sliderstart, sbextent, sliderLength);
6814                 break;
6815             default:
6816                 ret = ParentStyleClass::subControlRect(control, option, subControl, widget);
6817                 break;
6818             }
6819             return visualRect(scrollBar->direction/*Qt::LeftToRight*/, scrollBar->rect, ret);
6820         }
6821         break;
6822     case CC_Slider:
6823         if (auto slider = styleOptCast<QStyleOptionSlider>(option)) {
6824             if (SLIDER_TRIANGULAR == opts.sliderStyle) {
6825                 int tickSize(pixelMetric(PM_SliderTickmarkOffset, option, widget)),
6826                     mod=MO_GLOW==opts.coloredMouseOver && opts.buttonEffect != EFFECT_NONE ? 2 : 0;
6827                 QRect rect(ParentStyleClass::subControlRect(control, option, subControl, widget));
6828 
6829                 switch (subControl) {
6830                 case SC_SliderHandle:
6831                     if (slider->orientation == Qt::Horizontal) {
6832                         rect.setWidth(11 + mod);
6833                         rect.setHeight(15 + mod);
6834                         int centerY = r.center().y() - rect.height() / 2;
6835                         if (slider->tickPosition & QSlider::TicksAbove) {
6836                             centerY += tickSize;
6837                         }
6838                         if (slider->tickPosition & QSlider::TicksBelow) {
6839                             centerY -= tickSize - 1;
6840                         }
6841                         rect.moveTop(centerY);
6842                     } else {
6843                         rect.setWidth(15 + mod);
6844                         rect.setHeight(11 + mod);
6845                         int centerX = r.center().x() - rect.width() / 2;
6846                         if (slider->tickPosition & QSlider::TicksAbove) {
6847                             centerX += tickSize;
6848                         }
6849                         if (slider->tickPosition & QSlider::TicksBelow) {
6850                             centerX -= tickSize - 1;
6851                         }
6852                         rect.moveLeft(centerX);
6853                     }
6854                     break;
6855                 case SC_SliderGroove: {
6856                     QPoint grooveCenter = r.center();
6857 
6858                     if (Qt::Horizontal == slider->orientation) {
6859                         rect.setHeight(13);
6860                         --grooveCenter.ry();
6861                         if (slider->tickPosition & QSlider::TicksAbove) {
6862                             grooveCenter.ry() += tickSize + 2;
6863                         }
6864                         if (slider->tickPosition & QSlider::TicksBelow) {
6865                             grooveCenter.ry() -= tickSize - 1;
6866                         }
6867                     } else {
6868                         rect.setWidth(13);
6869                         --grooveCenter.rx();
6870                         if (slider->tickPosition & QSlider::TicksAbove) {
6871                             grooveCenter.rx() += tickSize + 2;
6872                         }
6873                         if (slider->tickPosition & QSlider::TicksBelow) {
6874                             grooveCenter.rx() -= tickSize - 1;
6875                         }
6876                     }
6877                     rect.moveCenter(grooveCenter);
6878                     break;
6879                 }
6880                 default:
6881                     break;
6882                 }
6883                 return rect;
6884             } else {
6885                 bool horizontal = Qt::Horizontal == slider->orientation;
6886                 int thickness = pixelMetric(PM_SliderControlThickness,
6887                                             slider, widget);
6888                 int tickOffset = (slider->tickPosition & QSlider::TicksAbove ||
6889                                   slider->tickPosition & QSlider::TicksBelow ?
6890                                   pixelMetric(PM_SliderTickmarkOffset, slider,
6891                                               widget) :
6892                                   ((horizontal ? r.height() :
6893                                     r.width()) - thickness) / 2);
6894 
6895                 switch (subControl) {
6896                 case SC_SliderHandle: {
6897                     int len = pixelMetric(PM_SliderLength, slider, widget);
6898                     int sliderPos =
6899                         sliderPositionFromValue(slider->minimum, slider->maximum,
6900                                                 slider->sliderPosition,
6901                                                 (horizontal ? r.width() :
6902                                                  r.height()) - len,
6903                                                 slider->upsideDown);
6904 
6905                     if (horizontal) {
6906                         r.setRect(r.x() + sliderPos, r.y() + tickOffset,
6907                                   len, thickness);
6908                     } else {
6909                         r.setRect(r.x() + tickOffset, r.y() + sliderPos,
6910                                   thickness, len);
6911                     }
6912                     break;
6913                 }
6914                 case SC_SliderGroove:
6915                     if (horizontal) {
6916                         r.setRect(r.x(), r.y() + tickOffset,
6917                                   r.width(), thickness);
6918                     } else {
6919                         r.setRect(r.x() + tickOffset, r.y(),
6920                                   thickness, r.height());
6921                     }
6922                     break;
6923                 default:
6924                     break;
6925                 }
6926                 return visualRect(slider->direction, r, r);
6927             }
6928         }
6929         break;
6930     case CC_GroupBox:
6931         if (oneOf(subControl, SC_GroupBoxCheckBox, SC_GroupBoxLabel))
6932             if (auto groupBox = styleOptCast<QStyleOptionGroupBox>(option)) {
6933                 QFont font = widget ? widget->font() : QApplication::font();
6934                 font.setBold(opts.gbLabel & GB_LBL_BOLD);
6935                 QFontMetrics fontMetrics(font);
6936                 int h = fontMetrics.height();
6937                 int tw = fontMetrics.size(Qt::TextShowMnemonic,
6938                                           groupBox->text +
6939                                           QLatin1Char(' ')).width();
6940                 int marg = ((groupBox->features & QStyleOptionFrame::Flat) ||
6941                             qtcNoFrame(opts.groupBox) ||
6942                             opts.gbLabel & GB_LBL_OUTSIDE ? 0 :
6943                             opts.gbLabel & GB_LBL_INSIDE ? 2 : 6);
6944                 int indicatorWidth = pixelMetric(PM_IndicatorWidth,
6945                                                  option, widget);
6946                 int indicatorSpace = pixelMetric(PM_CheckBoxLabelSpacing,
6947                                                  option, widget) - 1;
6948                 bool hasCheckBox(groupBox->subControls & QStyle::SC_GroupBoxCheckBox);
6949                 int checkBoxSize(hasCheckBox ? (indicatorWidth + indicatorSpace) : 0),
6950                     checkAdjust(qtcNoFrame(opts.groupBox) ||
6951                                 opts.gbLabel & GB_LBL_OUTSIDE ? 0 : 2);
6952 
6953                 if(0==checkAdjust)
6954                     checkBoxSize-=2;
6955 
6956                 r.adjust(marg, 0, -marg, 0);
6957                 if(!qtcNoFrame(opts.groupBox) && opts.gbLabel & GB_LBL_INSIDE)
6958                     r.adjust(0, 2, 0, 2);
6959                 r.setHeight(h);
6960 
6961                 // Adjusted rect for label + indicatorWidth + indicatorSpace
6962                 Qt::Alignment align = groupBox->textAlignment;
6963                 if (opts.gbLabel & GB_LBL_CENTRED) {
6964                     align &= ~(Qt::AlignLeft | Qt::AlignRight);
6965                     align |= Qt::AlignHCenter;
6966                 }
6967                 r = alignedRect(groupBox->direction, align,
6968                                 QSize(tw + checkBoxSize, h), r);
6969 
6970                 // Adjust totalRect if checkbox is set
6971                 if (hasCheckBox) {
6972                     if (SC_GroupBoxCheckBox == subControl) {
6973                         // Adjust for check box
6974                         int indicatorHeight(pixelMetric(PM_IndicatorHeight, option, widget)),
6975                             top(r.top() + (fontMetrics.height() - indicatorHeight) / 2);
6976 
6977                         r.setRect(reverse ? (r.right() - indicatorWidth) : r.left()+checkAdjust, top, indicatorWidth, indicatorHeight);
6978                     } else {
6979                         // Adjust for label
6980                         r.setRect(reverse ? r.left() :
6981                                   (r.left() + checkBoxSize), r.top(),
6982                                   r.width() - checkBoxSize, r.height());
6983                     }
6984                 }
6985                 return r;
6986             }
6987         break;
6988     case CC_TitleBar:
6989         if (auto tb = styleOptCast<QStyleOptionTitleBar>(option)) {
6990             bool isMinimized(tb->titleBarState&Qt::WindowMinimized),
6991                 isMaximized(tb->titleBarState&Qt::WindowMaximized);
6992 
6993             if( (isMaximized && SC_TitleBarMaxButton==subControl) ||
6994                 (isMinimized && SC_TitleBarMinButton==subControl) ||
6995                 (isMinimized && SC_TitleBarShadeButton==subControl) ||
6996                 (!isMinimized && SC_TitleBarUnshadeButton==subControl))
6997                 return QRect();
6998 
6999             readMdiPositions();
7000 
7001             const int controlSize(tb->rect.height() - constWindowMargin *2);
7002             int sc = (subControl == SC_TitleBarUnshadeButton ?
7003                       SC_TitleBarShadeButton :
7004                       subControl == SC_TitleBarNormalButton ?
7005                       isMaximized ? SC_TitleBarMaxButton :
7006                       SC_TitleBarMinButton : subControl);
7007             int pos = 0;
7008             int totalLeft = 0;
7009             int totalRight = 0;
7010             bool rhs = false;
7011             bool found = false;
7012 
7013             for (int hint: const_(m_mdiButtons[0])) {
7014                 if (hint == SC_TitleBarCloseButton ||
7015                     hint == WINDOWTITLE_SPACER ||
7016                     tb->titleBarFlags & toHint(hint)) {
7017                     totalLeft += (hint == WINDOWTITLE_SPACER ?
7018                                   controlSize / 2 : controlSize);
7019                     if (hint == sc) {
7020                         found = true;
7021                     } else if (!found) {
7022                         pos += (hint == WINDOWTITLE_SPACER ?
7023                                 controlSize / 2 : controlSize);
7024                     }
7025                 }
7026             }
7027             if (!found) {
7028                 pos = 0;
7029                 rhs = true;
7030             }
7031 
7032             for (int hint: const_(m_mdiButtons[1])) {
7033                 if (hint == SC_TitleBarCloseButton ||
7034                     hint == WINDOWTITLE_SPACER ||
7035                     tb->titleBarFlags & toHint(hint)) {
7036                     if (hint != WINDOWTITLE_SPACER || totalRight) {
7037                         totalRight += (hint == WINDOWTITLE_SPACER ?
7038                                        controlSize / 2 : controlSize);
7039                     }
7040                     if (rhs) {
7041                         if (hint == sc) {
7042                             pos += controlSize;
7043                             found = true;
7044                         } else if (found) {
7045                             pos += (hint == WINDOWTITLE_SPACER ?
7046                                     controlSize / 2 : controlSize);
7047                         }
7048                     }
7049                 }
7050             }
7051 
7052             totalLeft += constWindowMargin * (totalLeft ? 2 : 1);
7053             totalRight += constWindowMargin * (totalRight ? 2 : 1);
7054 
7055             if (subControl == SC_TitleBarLabel) {
7056                 r.adjust(totalLeft, 0, -totalRight, 0);
7057             } else if (!found) {
7058                 return QRect();
7059             } else if (rhs) {
7060                 r.setRect(r.right() - (pos + constWindowMargin),
7061                           r.top() + constWindowMargin,
7062                           controlSize, controlSize);
7063             } else {
7064                 r.setRect(r.left() + constWindowMargin + pos,
7065                           r.top() + constWindowMargin,
7066                           controlSize, controlSize);
7067             }
7068             if (r.height() % 2 == 0)
7069                 r.adjust(0, 0, 1, 1);
7070             return visualRect(tb->direction, tb->rect, r);
7071         }
7072     default:
7073         break;
7074     }
7075     return ParentStyleClass::subControlRect(control, option, subControl, widget);
7076 }
7077 
7078 QStyle::SubControl
hitTestComplexControl(ComplexControl control,const QStyleOptionComplex * option,const QPoint & pos,const QWidget * widget) const7079 Style::hitTestComplexControl(ComplexControl control,
7080                              const QStyleOptionComplex *option,
7081                              const QPoint &pos, const QWidget *widget) const
7082 {
7083     prePolish(widget);
7084     m_sbWidget = nullptr;
7085     switch (control) {
7086     case CC_ScrollBar:
7087         if (auto scrollBar = styleOptCast<QStyleOptionSlider>(option)) {
7088             if (subControlRect(control, scrollBar,
7089                                SC_ScrollBarSlider, widget).contains(pos)) {
7090                 return SC_ScrollBarSlider;
7091             }
7092             if (subControlRect(control, scrollBar,
7093                                SC_ScrollBarAddLine, widget).contains(pos)) {
7094                 return SC_ScrollBarAddLine;
7095             }
7096             if (subControlRect(control, scrollBar,
7097                                SC_ScrollBarSubPage, widget).contains(pos)) {
7098                 return SC_ScrollBarSubPage;
7099             }
7100             if (subControlRect(control, scrollBar,
7101                                SC_ScrollBarAddPage, widget).contains(pos)) {
7102                 return SC_ScrollBarAddPage;
7103             }
7104             if (subControlRect(control, scrollBar,
7105                                SC_ScrollBarSubLine, widget).contains(pos)) {
7106                 if (opts.scrollbarType == SCROLLBAR_KDE &&
7107                     subControlRect(control, scrollBar,
7108                                    SB_SUB2, widget).contains(pos)) {
7109                     m_sbWidget = widget;
7110                 }
7111                 return SC_ScrollBarSubLine;
7112             }
7113         }
7114     default:
7115         break;
7116     }
7117     return ParentStyleClass::hitTestComplexControl(control, option,  pos, widget);
7118 }
7119 
7120 }
7121