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, ©, 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