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_p.h"
24 #include "qtcurve_plugin.h"
25 #include <qtcurve-utils/qtprops.h>
26 
27 #include <QDBusConnection>
28 #include <QDBusInterface>
29 #include "windowmanager.h"
30 #include "blurhelper.h"
31 #include "shortcuthandler.h"
32 #include <common/config_file.h>
33 #include "check_on-png.h"
34 #include "check_x_on-png.h"
35 
36 #ifndef QTC_QT5_ENABLE_KDE
37 #  include "dialog_error-png.h"
38 #  include "dialog_warning-png.h"
39 #  include "dialog_information-png.h"
40 #endif
41 
42 #include <QFormLayout>
43 #include <QAbstractItemView>
44 #include <QDialog>
45 #include <QSplitter>
46 #include <QMdiSubWindow>
47 #include <QMainWindow>
48 #include <QComboBox>
49 #include <QTreeView>
50 #include <QGroupBox>
51 #include <QListView>
52 #include <QCheckBox>
53 #include <QRadioButton>
54 #include <QTextEdit>
55 #include <QDial>
56 #include <QLabel>
57 #include <QStackedLayout>
58 #include <QMenuBar>
59 #include <QMouseEvent>
60 #include <QScrollBar>
61 #include <QWizard>
62 #include <QDialogButtonBox>
63 #include <QHeaderView>
64 #include <QLineEdit>
65 #include <QSpinBox>
66 #include <QDir>
67 #include <QSettings>
68 #include <QPixmapCache>
69 #include <QTextStream>
70 #include <QtDebug>
71 
72 #include "shadowhelper.h"
73 #include <qtcurve-utils/x11qtc.h>
74 #include <sys/time.h>
75 
76 #ifdef QTC_QT5_ENABLE_KDE
77 // KDE4 support headers
78 #include <KDE/KApplication>
79 #include <KDE/KAboutData>
80 #include <KDE/KGlobal>
81 #include <KDE/KGlobalSettings>
82 #include <KDE/KConfig>
83 #include <KDE/KConfigGroup>
84 #include <KDE/KColorScheme>
85 #include <KDE/KStandardDirs>
86 #include <KDE/KTitleWidget>
87 #include <KDE/KTabBar>
88 #include <KDE/KFileDialog>
89 #include <KDE/KPassivePopup>
90 #include <KDE/KXmlGuiWindow>
91 #include <KDE/KStandardAction>
92 #include <KDE/KActionCollection>
93 #include <KDE/KMenu>
94 #include <KDE/KAboutApplicationDialog>
95 // KF5 headers
96 #include <KConfigCore/KSharedConfig>
97 #include <KWindowSystem/KWindowSystem>
98 #endif
99 
100 #include <qtcurve-utils/color.h>
101 
102 namespace QtCurve {
103 
setPainterPen(QPainter * p,const QColor & col,const qreal width=1.0)104 static inline void setPainterPen(QPainter *p, const QColor &col, const qreal width=1.0)
105 {
106     p->setPen(QPen(col, width));
107 }
108 
109 static Style::Icon
pix2Icon(QStyle::StandardPixmap pix)110 pix2Icon(QStyle::StandardPixmap pix)
111 {
112     switch (pix) {
113     case QStyle::SP_TitleBarNormalButton:
114         return Style::ICN_RESTORE;
115     case QStyle::SP_TitleBarShadeButton:
116         return Style::ICN_SHADE;
117     case QStyle::SP_ToolBarHorizontalExtensionButton:
118         return Style::ICN_RIGHT;
119     case QStyle::SP_ToolBarVerticalExtensionButton:
120         return Style::ICN_DOWN;
121     case QStyle::SP_TitleBarUnshadeButton:
122         return Style::ICN_UNSHADE;
123     default:
124     case QStyle::SP_DockWidgetCloseButton:
125     case QStyle::SP_TitleBarCloseButton:
126         return Style::ICN_CLOSE;
127     }
128 }
129 
130 static Style::Icon
subControlToIcon(QStyle::SubControl sc)131 subControlToIcon(QStyle::SubControl sc)
132 {
133     switch (sc) {
134     case QStyle::SC_TitleBarMinButton:
135         return Style::ICN_MIN;
136     case QStyle::SC_TitleBarMaxButton:
137         return Style::ICN_MAX;
138     case QStyle::SC_TitleBarCloseButton:
139     default:
140         return Style::ICN_CLOSE;
141     case QStyle::SC_TitleBarNormalButton:
142         return Style::ICN_RESTORE;
143     case QStyle::SC_TitleBarShadeButton:
144         return Style::ICN_SHADE;
145     case QStyle::SC_TitleBarUnshadeButton:
146         return Style::ICN_UNSHADE;
147     case QStyle::SC_TitleBarSysMenu:
148         return Style::ICN_MENU;
149     }
150 }
151 
152 QtcThemedApp theThemedApp = APP_OTHER;
153 
154 static QString getFile(const QString &f);
155 QString appName = getFile(qApp->arguments()[0]);
156 
157 static QColor
checkColour(const QStyleOption * option,QPalette::ColorRole role)158 checkColour(const QStyleOption *option, QPalette::ColorRole role)
159 {
160     QColor col(option->palette.brush(role).color());
161 
162     if (col.alpha() == 255 && isBlack(col))
163         return QApplication::palette().brush(role).color();
164     return col;
165 }
166 
167 static void
addStripes(QPainter * p,const QPainterPath & path,const QRect & rect,bool horizontal)168 addStripes(QPainter *p, const QPainterPath &path,
169            const QRect &rect, bool horizontal)
170 {
171     QColor col(Qt::white);
172     QLinearGradient patternGradient(rect.topLeft(),
173                                     rect.topLeft() +
174                                     (horizontal ? QPoint(STRIPE_WIDTH, 0) :
175                                      QPoint(0, STRIPE_WIDTH)));
176 
177     col.setAlphaF(0.0);
178     patternGradient.setColorAt(0.0, col);
179     col.setAlphaF(0.15);
180     patternGradient.setColorAt(1.0, col);
181     patternGradient.setSpread(QGradient::ReflectSpread);
182     if (path.isEmpty()) {
183         p->fillRect(rect, patternGradient);
184     } else {
185         p->save();
186         p->setRenderHint(QPainter::Antialiasing, true);
187         p->fillPath(path, patternGradient);
188         p->restore();
189     }
190 }
191 
192 #ifndef QTC_QT5_ENABLE_KDE
193 static void
setRgb(QColor * col,const QStringList & rgb)194 setRgb(QColor *col, const QStringList &rgb)
195 {
196     if (rgb.size() == 3) {
197         *col = QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt());
198     }
199 }
200 
201 static QString
kdeHome()202 kdeHome()
203 {
204     static QString kdeHomePath;
205     if (kdeHomePath.isEmpty()) {
206         kdeHomePath = QString::fromLocal8Bit(qgetenv("KDEHOME"));
207         if (kdeHomePath.isEmpty()) {
208             QDir homeDir(QDir::homePath());
209             QString kdeConfDir(QLatin1String("/.kde"));
210             if (homeDir.exists(QLatin1String(".kde4")))
211                 kdeConfDir = QLatin1String("/.kde4");
212             kdeHomePath = QDir::homePath() + kdeConfDir;
213         }
214     }
215     return kdeHomePath;
216 }
217 #endif
218 
219 static bool
isHoriz(const QStyleOption * option,EWidget w,bool joinedTBar)220 isHoriz(const QStyleOption *option, EWidget w, bool joinedTBar)
221 {
222     return (option->state & QStyle::State_Horizontal ||
223             (WIDGET_BUTTON(w) &&
224              (!joinedTBar || noneOf(w, WIDGET_TOOLBAR_BUTTON,
225                                     WIDGET_NO_ETCH_BTN,
226                                     WIDGET_MENU_BUTTON))));
227 }
228 
229 static bool
isOnToolbar(const QWidget * widget)230 isOnToolbar(const QWidget *widget)
231 {
232     const QWidget *wid = widget ? widget->parentWidget() : 0L;
233     while (wid) {
234         if (qobject_cast<const QToolBar*>(wid)) {
235             return true;
236         }
237         wid = wid->parentWidget();
238     }
239     return false;
240 }
241 
242 /*
243   Cache key:
244   widgettype 2
245   app        5
246   size      15
247   horiz      1
248   alpha      8
249   blue       8
250   green      8
251   red        8
252   type       1  (0 for widget, 1 for pixmap)
253   ------------
254   56
255 */
256 enum ECacheType {
257     CACHE_STD,
258     CACHE_PBAR,
259     CACHE_TAB_TOP,
260     CACHE_TAB_BOT
261 };
262 
263 static QtcKey
createKey(qulonglong size,const QColor & color,bool horiz,int app,EWidget w)264 createKey(qulonglong size, const QColor &color, bool horiz, int app, EWidget w)
265 {
266     ECacheType type=WIDGET_TAB_TOP==w
267         ? CACHE_TAB_TOP
268         : WIDGET_TAB_BOT==w
269         ? CACHE_TAB_BOT
270         : WIDGET_PROGRESSBAR==w
271         ? CACHE_PBAR
272         : CACHE_STD;
273 
274     return (color.rgba()<<1)+
275         (((qulonglong)(horiz ? 1 : 0))<<33)+
276         (((qulonglong)(size&0xFFFF))<<34)+
277         (((qulonglong)(app&0x1F))<<50)+
278         (((qulonglong)(type&0x03))<<55);
279 }
280 
createKey(const QColor & color,EPixmap p)281 static QtcKey createKey(const QColor &color, EPixmap p)
282 {
283     return 1 +
284         ((color.rgb()&RGB_MASK)<<1)+
285         (((qulonglong)(p&0x1F))<<33)+
286         (((qulonglong)1)<<38);
287 }
288 
289 #ifdef QTC_QT5_ENABLE_KDE
parseWindowLine(const QString & line,QList<int> & data)290 static void parseWindowLine(const QString &line, QList<int> &data)
291 {
292     int len(line.length());
293 
294     for(int i = 0;i < len;++i) {
295         switch(line[i].toLatin1()) {
296         case 'M':
297             data.append(QStyle::SC_TitleBarSysMenu);
298             break;
299         case '_':
300             data.append(WINDOWTITLE_SPACER);
301             break;
302         case 'H':
303             data.append(QStyle::SC_TitleBarContextHelpButton);
304             break;
305         case 'L':
306             data.append(QStyle::SC_TitleBarShadeButton);
307             break;
308         case 'I':
309             data.append(QStyle::SC_TitleBarMinButton);
310             break;
311         case 'A':
312             data.append(QStyle::SC_TitleBarMaxButton);
313             break;
314         case 'X':
315             data.append(QStyle::SC_TitleBarCloseButton);
316         default:
317             break;
318         }
319     }
320 }
321 #endif
322 
Style()323 Style::Style() :
324     m_popupMenuCols(0L),
325     m_sliderCols(0L),
326     m_defBtnCols(0L),
327     m_comboBtnCols(0L),
328     m_checkRadioSelCols(0L),
329     m_sortedLvColors(0L),
330     m_ooMenuCols(0L),
331     m_progressCols(0L),
332     m_saveMenuBarStatus(false),
333     m_usePixmapCache(true),
334     m_inactiveChangeSelectionColor(false),
335     m_isPreview(PREVIEW_FALSE),
336     m_sidebarButtonsCols(0L),
337     m_activeMdiColors(0L),
338     m_mdiColors(0L),
339     m_pixmapCache(150000),
340     m_active(true),
341     m_sbWidget(0L),
342     m_clickedLabel(0L),
343     m_progressBarAnimateTimer(0),
344     m_animateStep(0),
345     m_titlebarHeight(0),
346     m_dBus(0),
347     m_shadowHelper(new ShadowHelper(this)),
348     m_sViewSBar(0L),
349     m_windowManager(new WindowManager(this)),
350     m_blurHelper(new BlurHelper(this)),
351     m_shortcutHandler(new ShortcutHandler(this)),
352     m_dbusConnected(false)
353 {
354     const char *env = getenv(QTCURVE_PREVIEW_CONFIG);
355 #ifdef QTC_QT5_ENABLE_KDE
356     m_configFile = KSharedConfig::openConfig();
357     m_kdeGlobals = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::NoGlobals);
358 #endif
359     if (env && strcmp(env, QTCURVE_PREVIEW_CONFIG) == 0) {
360         // To enable preview of QtCurve settings, the style config module will set QTCURVE_PREVIEW_CONFIG
361         // and use CE_QtC_SetOptions to set options. If this is set, we do not use the QPixmapCache as it
362         // will interfere with that of the kcm's widgets!
363         m_isPreview=PREVIEW_MDI;
364         m_usePixmapCache=false;
365     } else if(env && strcmp(env, QTCURVE_PREVIEW_CONFIG_FULL) == 0) {
366         // As above, but preview is in window - so can use opacity settings!
367         m_isPreview=PREVIEW_WINDOW;
368         m_usePixmapCache=false;
369     } else {
370         init(true);
371     }
372 }
373 
init(bool initial)374 void Style::init(bool initial)
375 {
376     if(!initial)
377         freeColors();
378 
379     if (m_isPreview) {
380         if (m_isPreview != PREVIEW_WINDOW) {
381             opts.bgndOpacity = opts.dlgOpacity = opts.menuBgndOpacity = 100;
382         }
383     } else {
384         qtcReadConfig(QString(), &opts);
385 
386         if (initial) {
387 #ifdef Q_OS_MACOS
388             if (opts.nonnativeMenubarApps.contains("kde") || opts.nonnativeMenubarApps.contains(appName)) {
389                 QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
390                 opts.currentNonnativeMenubarApps << appName;
391             }
392 #endif
393             connectDBus();
394 #ifdef QTC_QT5_ENABLE_KDE
395             connect(KWindowSystem::self(), &KWindowSystem::compositingChanged, this, &Style::compositingToggled);
396 #endif
397         }
398     }
399 
400     opts.contrast=QSettings(QLatin1String("Trolltech")).value("/Qt/KDE/contrast", DEFAULT_CONTRAST).toInt();
401     if(opts.contrast<0 || opts.contrast>10)
402         opts.contrast=DEFAULT_CONTRAST;
403 
404     shadeColors(QApplication::palette().color(QPalette::Active, QPalette::Highlight), m_highlightCols);
405     shadeColors(QApplication::palette().color(QPalette::Active, QPalette::Background), m_backgroundCols);
406     shadeColors(QApplication::palette().color(QPalette::Active, QPalette::Button), m_buttonCols);
407 
408     // Set defaults for Hover and Focus, these will be changed when KDE4 palette is applied...
409     shadeColors(QApplication::palette().color(QPalette::Active,
410                                               QPalette::Highlight), m_focusCols);
411     shadeColors(QApplication::palette().color(QPalette::Active, QPalette::Highlight), m_mouseOverCols);
412 // Dont setup KDE4 fonts/colours here - seems to mess things up when using proxy styles.
413 // See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=638629
414 //#ifdef QTC_QT5_ENABLE_KDE
415 //    setupKde4();
416 //#endif
417 
418     m_windowManager->initialize(opts.windowDrag, opts.windowDragWhiteList.toList(), opts.windowDragBlackList.toList());
419 
420     switch(opts.shadeSliders)
421     {
422     default:
423     case SHADE_DARKEN:
424     case SHADE_NONE:
425         break;
426     case SHADE_SELECTED:
427         m_sliderCols=m_highlightCols;
428         break;
429     case SHADE_BLEND_SELECTED:
430     case SHADE_CUSTOM:
431         if (!m_sliderCols) {
432             m_sliderCols = new QColor[TOTAL_SHADES + 1];
433         }
434         shadeColors(opts.shadeSliders == SHADE_BLEND_SELECTED ?
435                     midColor(m_highlightCols[ORIGINAL_SHADE],
436                              m_buttonCols[ORIGINAL_SHADE]) :
437                     opts.customSlidersColor, m_sliderCols);
438     }
439 
440     switch(opts.defBtnIndicator)
441     {
442     case IND_GLOW:
443     case IND_SELECTED:
444         m_defBtnCols=m_highlightCols;
445         break;
446     case IND_TINT:
447         m_defBtnCols=new QColor [TOTAL_SHADES+1];
448         shadeColors(tint(m_buttonCols[ORIGINAL_SHADE],
449                          m_highlightCols[ORIGINAL_SHADE], DEF_BNT_TINT),
450                     m_defBtnCols);
451         break;
452     default:
453         break;
454     case IND_COLORED:
455         if (opts.shadeSliders == SHADE_BLEND_SELECTED) {
456             m_defBtnCols = m_sliderCols;
457         } else {
458             m_defBtnCols = new QColor[TOTAL_SHADES + 1];
459             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE],
460                                  m_buttonCols[ORIGINAL_SHADE]), m_defBtnCols);
461         }
462     }
463 
464     switch(opts.comboBtn) {
465     default:
466     case SHADE_DARKEN:
467     case SHADE_NONE:
468         break;
469     case SHADE_SELECTED:
470         m_comboBtnCols=m_highlightCols;
471         break;
472     case SHADE_BLEND_SELECTED:
473         if (opts.shadeSliders == SHADE_BLEND_SELECTED) {
474             m_comboBtnCols = m_sliderCols;
475             break;
476         }
477     case SHADE_CUSTOM:
478         if (opts.shadeSliders == SHADE_CUSTOM &&
479             opts.customSlidersColor == opts.customComboBtnColor) {
480             m_comboBtnCols = m_sliderCols;
481             break;
482         }
483         if (!m_comboBtnCols) {
484             m_comboBtnCols = new QColor[TOTAL_SHADES + 1];
485         }
486         shadeColors(opts.comboBtn == SHADE_BLEND_SELECTED ?
487                     midColor(m_highlightCols[ORIGINAL_SHADE],
488                              m_buttonCols[ORIGINAL_SHADE]) :
489                     opts.customComboBtnColor, m_comboBtnCols);
490     }
491 
492     switch (opts.sortedLv) {
493     case SHADE_DARKEN:
494         if (!m_sortedLvColors) {
495             m_sortedLvColors = new QColor[TOTAL_SHADES + 1];
496         }
497         shadeColors(shade(opts.lvButton ? m_buttonCols[ORIGINAL_SHADE] : m_backgroundCols[ORIGINAL_SHADE], LV_HEADER_DARK_FACTOR), m_sortedLvColors);
498         break;
499     default:
500     case SHADE_NONE:
501         break;
502     case SHADE_SELECTED:
503         m_sortedLvColors=m_highlightCols;
504         break;
505     case SHADE_BLEND_SELECTED:
506         if (opts.shadeSliders == SHADE_BLEND_SELECTED) {
507             m_sortedLvColors = m_sliderCols;
508             break;
509         } else if (opts.comboBtn == SHADE_BLEND_SELECTED) {
510             m_sortedLvColors = m_comboBtnCols;
511             break;
512         }
513     case SHADE_CUSTOM:
514         if (opts.shadeSliders == SHADE_CUSTOM &&
515             opts.customSlidersColor == opts.customSortedLvColor) {
516             m_sortedLvColors = m_sliderCols;
517             break;
518         }
519         if (opts.comboBtn == SHADE_CUSTOM &&
520             opts.customComboBtnColor == opts.customSortedLvColor) {
521             m_sortedLvColors = m_comboBtnCols;
522             break;
523         }
524         if (!m_sortedLvColors) {
525             m_sortedLvColors = new QColor[TOTAL_SHADES + 1];
526         }
527         shadeColors(opts.sortedLv == SHADE_BLEND_SELECTED ?
528                     midColor(m_highlightCols[ORIGINAL_SHADE],
529                              (opts.lvButton ? m_buttonCols[ORIGINAL_SHADE] :
530                               m_backgroundCols[ORIGINAL_SHADE])) :
531                     opts.customSortedLvColor, m_sortedLvColors);
532     }
533 
534     switch (opts.crColor) {
535     default:
536     case SHADE_NONE:
537         m_checkRadioSelCols = m_buttonCols;
538         break;
539     case SHADE_DARKEN:
540         if (!m_checkRadioSelCols) {
541             m_checkRadioSelCols = new QColor[TOTAL_SHADES + 1];
542         }
543         shadeColors(shade(m_buttonCols[ORIGINAL_SHADE], LV_HEADER_DARK_FACTOR),
544                     m_checkRadioSelCols);
545         break;
546     case SHADE_SELECTED:
547         m_checkRadioSelCols = m_highlightCols;
548         break;
549     case SHADE_CUSTOM:
550         if(SHADE_CUSTOM==opts.shadeSliders && opts.customSlidersColor==opts.customCrBgndColor)
551             m_checkRadioSelCols=m_sliderCols;
552         else if(SHADE_CUSTOM==opts.comboBtn && opts.customComboBtnColor==opts.customCrBgndColor)
553             m_checkRadioSelCols=m_comboBtnCols;
554         else if(SHADE_CUSTOM==opts.sortedLv && opts.customSortedLvColor==opts.customCrBgndColor)
555             m_checkRadioSelCols=m_sortedLvColors;
556         else
557         {
558             if(!m_checkRadioSelCols)
559                 m_checkRadioSelCols=new QColor [TOTAL_SHADES+1];
560             shadeColors(opts.customCrBgndColor, m_checkRadioSelCols);
561         }
562         break;
563     case SHADE_BLEND_SELECTED:
564         if(SHADE_BLEND_SELECTED==opts.shadeSliders)
565             m_checkRadioSelCols=m_sliderCols;
566         else if(SHADE_BLEND_SELECTED==opts.comboBtn)
567             m_checkRadioSelCols=m_comboBtnCols;
568         else if(SHADE_BLEND_SELECTED==opts.sortedLv)
569             m_checkRadioSelCols=m_sortedLvColors;
570         else
571         {
572             if(!m_checkRadioSelCols)
573                 m_checkRadioSelCols=new QColor [TOTAL_SHADES+1];
574             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE], m_buttonCols[ORIGINAL_SHADE]), m_checkRadioSelCols);
575         }
576     }
577 
578     switch(opts.progressColor)
579     {
580     case SHADE_NONE:
581         m_progressCols=m_backgroundCols;
582         break;
583     default:
584         // Not set!
585         break;
586     case SHADE_CUSTOM:
587         if(SHADE_CUSTOM==opts.shadeSliders && opts.customSlidersColor==opts.customProgressColor)
588             m_progressCols=m_sliderCols;
589         else if(SHADE_CUSTOM==opts.comboBtn && opts.customComboBtnColor==opts.customProgressColor)
590             m_progressCols=m_comboBtnCols;
591         else if(SHADE_CUSTOM==opts.sortedLv && opts.customSortedLvColor==opts.customProgressColor)
592             m_progressCols=m_sortedLvColors;
593         else if(SHADE_CUSTOM==opts.crColor && opts.customCrBgndColor==opts.customProgressColor)
594             m_progressCols=m_checkRadioSelCols;
595         else
596         {
597             if(!m_progressCols)
598                 m_progressCols=new QColor [TOTAL_SHADES+1];
599             shadeColors(opts.customProgressColor, m_progressCols);
600         }
601         break;
602     case SHADE_BLEND_SELECTED:
603         if(SHADE_BLEND_SELECTED==opts.shadeSliders)
604             m_progressCols=m_sliderCols;
605         else if(SHADE_BLEND_SELECTED==opts.comboBtn)
606             m_progressCols=m_comboBtnCols;
607         else if(SHADE_BLEND_SELECTED==opts.sortedLv)
608             m_progressCols=m_sortedLvColors;
609         else
610         {
611             if(!m_progressCols)
612                 m_progressCols=new QColor [TOTAL_SHADES+1];
613             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE], m_backgroundCols[ORIGINAL_SHADE]), m_progressCols);
614         }
615     }
616 
617     setMenuColors(QApplication::palette().color(QPalette::Active, QPalette::Background));
618 
619     switch(opts.shadeCheckRadio)
620     {
621     default:
622         m_checkRadioCol=QApplication::palette().color(QPalette::Active, opts.crButton ? QPalette::ButtonText : QPalette::Text);
623         break;
624     case SHADE_BLEND_SELECTED:
625     case SHADE_SELECTED:
626         m_checkRadioCol=QApplication::palette().color(QPalette::Active, QPalette::Highlight);
627         break;
628     case SHADE_CUSTOM:
629         m_checkRadioCol=opts.customCheckRadioColor;
630     }
631 
632     if(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR && opts.titlebarButtonColors.size()>=NUM_TITLEBAR_BUTTONS)
633         for(int i=0; i<NUM_TITLEBAR_BUTTONS; ++i)
634         {
635             QColor *cols=new QColor [TOTAL_SHADES+1];
636             shadeColors(opts.titlebarButtonColors[(ETitleBarButtons)i], cols);
637             m_titleBarButtonsCols[i]=cols;
638         }
639     else
640         opts.titlebarButtons&=~TITLEBAR_BUTTON_COLOR;
641 
642     if (oneOf(opts.bgndImage.type, IMG_PLAIN_RINGS, IMG_BORDERED_RINGS,
643               IMG_SQUARE_RINGS) ||
644         oneOf(opts.menuBgndImage.type, IMG_PLAIN_RINGS, IMG_BORDERED_RINGS,
645               IMG_SQUARE_RINGS)) {
646         qtcCalcRingAlphas(&m_backgroundCols[ORIGINAL_SHADE]);
647     }
648 
649     m_blurHelper->setEnabled(opts.bgndOpacity != 100 ||
650                              opts.dlgOpacity != 100 ||
651                              opts.menuBgndOpacity != 100);
652 
653     opts.fontTickWidth=-1;
654     opts.menuTick=QString(QChar(0x2713));
655 
656 #ifdef QTC_QT5_ENABLE_KDE
657     // We need to set the decoration colours for the preview now...
658     if (m_isPreview) {
659         setDecorationColors();
660     }
661 #endif
662 }
663 
connectDBus()664 void Style::connectDBus()
665 {
666     if (m_dbusConnected)
667         return;
668     auto bus = QDBusConnection::sessionBus();
669     if (bus.isConnected()) {
670         m_dbusConnected = true;
671         if (QCoreApplication::instance()) {
672             connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &Style::disconnectDBus);
673         }
674         bus.connect(QString(), "/KGlobalSettings", "org.kde.KGlobalSettings",
675                     "notifyChange", this, SLOT(kdeGlobalSettingsChange(int, int)));
676 #ifndef QTC_QT5_ENABLE_KDE
677         bus.connect("org.kde.kwin", "/KWin", "org.kde.KWin", "compositingToggled",
678                     this, SLOT(compositingToggled()));
679 #endif
680 
681         QString arg0 = qApp? qApp->arguments()[0] : QString();
682         if (!qApp || (arg0 != "kwin" && arg0 != "kwin_x11" && arg0 != "kwin_wayland")) {
683             // don't connect to signals if we know we're sending them out ourselves
684             bus.connect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
685                         "borderSizesChanged", this, SLOT(borderSizesChanged()));
686             if (opts.menubarHiding & HIDE_KWIN)
687                 bus.connect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
688                             "toggleMenuBar",
689                             this, SLOT(toggleMenuBar(unsigned int)));
690 
691             if (opts.statusbarHiding & HIDE_KWIN) {
692                 bus.connect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
693                             "toggleStatusBar",
694                             this, SLOT(toggleStatusBar(unsigned int)));
695             }
696         }
697     }
698 }
699 
disconnectDBus()700 void Style::disconnectDBus()
701 {
702     if (!m_dbusConnected)
703         return;
704     m_dbusConnected = false;
705     auto bus = QDBusConnection::sessionBus();
706     if (getenv("QTCURVE_DEBUG")) {
707         qWarning() << Q_FUNC_INFO << this << "Disconnecting from" << bus.name() << "/" << bus.baseService();
708     }
709     bus.disconnect(QString(), "/KGlobalSettings", "org.kde.KGlobalSettings",
710                    "notifyChange",
711                    this, SLOT(kdeGlobalSettingsChange(int, int)));
712 #ifndef QTC_QT5_ENABLE_KDE
713     bus.disconnect("org.kde.kwin", "/KWin", "org.kde.KWin", "compositingToggled",
714                    this, SLOT(compositingToggled()));
715 #endif
716 
717     QString arg0 = qApp? qApp->arguments()[0] : QString();
718     if (!qApp || (arg0 != "kwin" && arg0 != "kwin_x11" && arg0 != "kwin_wayland")) {
719         bus.disconnect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
720                     "borderSizesChanged", this, SLOT(borderSizesChanged()));
721         if (opts.menubarHiding & HIDE_KWIN)
722             bus.disconnect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
723                            "toggleMenuBar",
724                            this, SLOT(toggleMenuBar(unsigned int)));
725 
726         if (opts.statusbarHiding & HIDE_KWIN) {
727             bus.disconnect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
728                            "toggleStatusBar",
729                            this, SLOT(toggleStatusBar(unsigned int)));
730         }
731     }
732 }
733 
~Style()734 Style::~Style()
735 {
736     qtcInfo("Deleting style instance %p\n", this);
737     disconnectDBus();
738     if (m_plugin && m_plugin->m_styleInstances.contains(this)) {
739         m_plugin->m_styleInstances.removeAll(this);
740     }
741     freeColors();
742     if (m_dBus) {
743         delete m_dBus;
744     }
745 }
746 
freeColor(QSet<QColor * > & freedColors,QColor ** cols)747 void Style::freeColor(QSet<QColor *> &freedColors, QColor **cols)
748 {
749     if(!freedColors.contains(*cols) &&
750        *cols!=m_highlightCols &&
751        *cols!=m_backgroundCols &&
752        *cols!=m_menubarCols &&
753        *cols!=m_focusCols &&
754        *cols!=m_mouseOverCols &&
755        *cols!=m_buttonCols &&
756        *cols!=m_coloredButtonCols &&
757        *cols!=m_coloredBackgroundCols &&
758        *cols!=m_coloredHighlightCols) {
759         freedColors.insert(*cols);
760         delete [] *cols;
761     }
762     *cols=0L;
763 }
764 
freeColors()765 void Style::freeColors()
766 {
767     if(0!=m_progressBarAnimateTimer) {
768         killTimer(m_progressBarAnimateTimer);
769         m_progressBarAnimateTimer = 0;
770     }
771 
772     QSet<QColor*> freedColors;
773 
774     freeColor(freedColors, &m_sidebarButtonsCols);
775     freeColor(freedColors, &m_popupMenuCols);
776     freeColor(freedColors, &m_activeMdiColors);
777     freeColor(freedColors, &m_mdiColors);
778     freeColor(freedColors, &m_progressCols);
779     freeColor(freedColors, &m_checkRadioSelCols);
780     freeColor(freedColors, &m_sortedLvColors);
781     freeColor(freedColors, &m_comboBtnCols);
782     freeColor(freedColors, &m_defBtnCols);
783     freeColor(freedColors, &m_sliderCols);
784 
785     if (opts.titlebarButtons & TITLEBAR_BUTTON_COLOR) {
786         for (int i = 0;i < NUM_TITLEBAR_BUTTONS;i++) {
787             delete []m_titleBarButtonsCols[i];
788             m_titleBarButtonsCols[i] = 0L;
789         }
790     }
791     if (m_ooMenuCols) {
792         delete []m_ooMenuCols;
793         m_ooMenuCols = 0L;
794     }
795 }
796 
getFile(const QString & f)797 static QString getFile(const QString &f)
798 {
799     QString d(f);
800 
801     int slashPos(d.lastIndexOf('/'));
802 
803     if(slashPos!=-1)
804         d.remove(0, slashPos+1);
805 
806     return d;
807 }
808 
809 #if 1
styledFontMetrics(const QStyleOption * option,const QWidget * widget)810 static QFontMetrics styledFontMetrics(const QStyleOption *option, const QWidget *widget)
811 {
812     return option
813         ? option->fontMetrics
814         : widget
815         ? widget->fontMetrics()
816         : qApp->fontMetrics();
817 }
818 
fontHeight(const QStyleOption * option,const QWidget * widget)819 static int fontHeight(const QStyleOption *option, const QWidget *widget)
820 {
821     return styledFontMetrics(option, widget).height();
822 }
823 
824 // Taken from skulpture 0.2.3
polishFormLayout(QFormLayout * layout)825 void Style::polishFormLayout(QFormLayout *layout)
826 {
827     int widgetSize=-1;
828 
829     if (layout->labelAlignment() & Qt::AlignVCenter)
830         return;
831 
832     int addedHeight = -1;
833     for (int row = 0; row < layout->rowCount(); ++row)
834     {
835         QLayoutItem *labelItem = layout->itemAt(row, QFormLayout::LabelRole);
836         if (!labelItem)
837             continue;
838 
839         QLayoutItem *fieldItem = layout->itemAt(row, QFormLayout::FieldRole);
840         if (!fieldItem)
841             continue;
842 
843         QWidget *label = labelItem->widget();
844         if (!label)
845             continue;
846 
847         int labelHeight;
848         if (addedHeight < 0)
849             addedHeight = 4 + 2 * widgetSize;
850         if (qobject_cast<QLabel *>(label))
851             labelHeight = label->sizeHint().height() + addedHeight;
852         else if (qobject_cast<QCheckBox *>(label))
853             labelHeight = label->sizeHint().height();
854         else
855             continue;
856 
857         int fieldHeight = fieldItem->sizeHint().height();
858         /* for large fields, we don't center */
859         if (fieldHeight <= 2 * fontHeight(0, label) + addedHeight)
860         {
861             if (fieldHeight > labelHeight)
862                 labelHeight = fieldHeight;
863         }
864 //         else if (verticalTextShift(label->fontMetrics()) & 1)
865 //                 labelHeight += 1;
866         if (qobject_cast<QCheckBox *>(label)) {
867             label->setMinimumHeight(labelHeight);
868         } else {
869             label->setMinimumHeight((labelHeight * 4 + 6) / 7);
870         }
871     }
872 }
873 
polishLayout(QLayout * layout)874 void Style::polishLayout(QLayout *layout)
875 {
876     if (QFormLayout *formLayout = qobject_cast<QFormLayout *>(layout))
877         polishFormLayout(formLayout);
878     // recurse into layouts
879     for (int i = 0; i < layout->count(); ++i)
880         if (QLayout *l = layout->itemAt(i)->layout())
881             polishLayout(l);
882 }
883 #endif
884 
885 // Taken from oxygen!
polishScrollArea(QAbstractScrollArea * scrollArea,bool isKFilePlacesView) const886 void Style::polishScrollArea(QAbstractScrollArea *scrollArea, bool isKFilePlacesView) const
887 {
888     if(!scrollArea)
889         return;
890 
891     // HACK: add exception for KPIM transactionItemView, which is an overlay widget and must have filled background. This is a temporary workaround
892     // until a more robust solution is found.
893     if(scrollArea->inherits("KPIM::TransactionItemView"))
894     {
895         // also need to make the scrollarea background plain (using autofill background) so that optional vertical scrollbar background is not
896         // transparent either.
897         // TODO: possibly add an event filter to use the "normal" window background instead of something flat.
898         scrollArea->setAutoFillBackground(true);
899         return;
900     }
901 
902     // check frame style and background role
903     if(QFrame::NoFrame!=scrollArea->frameShape() || QPalette::Window!=scrollArea->backgroundRole())
904         return;
905 
906     // get viewport and check background role
907     QWidget *viewport(scrollArea->viewport());
908     if(!(viewport && viewport->backgroundRole() == QPalette::Window) &&
909        !isKFilePlacesView) {
910         return;
911     }
912 
913     // change viewport autoFill background.
914     // do the same for children if the background role is QPalette::Window
915     viewport->setAutoFillBackground(false);
916     for (QWidget *child: viewport->findChildren<QWidget*>()) {
917         if (child->parent() == viewport &&
918             child->backgroundRole() == QPalette::Window) {
919             child->setAutoFillBackground(false);
920         }
921     }
922 }
923 
standardIcon(StandardPixmap pix,const QStyleOption * option,const QWidget * widget) const924 QIcon Style::standardIcon(StandardPixmap pix, const QStyleOption *option,
925                           const QWidget *widget) const
926 {
927     switch (pix) {
928     // case SP_TitleBarMenuButton:
929     // case SP_TitleBarMinButton:
930     // case SP_TitleBarMaxButton:
931     // case SP_TitleBarContextHelpButton:
932     case SP_TitleBarNormalButton:
933     case SP_TitleBarShadeButton:
934     case SP_TitleBarUnshadeButton:
935     case SP_DockWidgetCloseButton:
936     case SP_TitleBarCloseButton: {
937         QPixmap pm(13, 13);
938 
939         pm.fill(Qt::transparent);
940 
941         QPainter painter(&pm);
942 
943         drawIcon(&painter, Qt::color1, QRect(0, 0, pm.width(), pm.height()),
944                  false, pix2Icon(pix), oneOf(pix, SP_TitleBarShadeButton,
945                                              SP_TitleBarUnshadeButton));
946         return QIcon(pm);
947     }
948     case SP_ToolBarHorizontalExtensionButton:
949     case SP_ToolBarVerticalExtensionButton:
950     {
951         QPixmap pm(9, 9);
952 
953         pm.fill(Qt::transparent);
954 
955         QPainter painter(&pm);
956 
957         drawIcon(&painter, Qt::color1, QRect(0, 0, pm.width(), pm.height()), false, pix2Icon(pix), true);
958         return QIcon(pm);
959     }
960 #ifndef QTC_QT5_ENABLE_KDE
961     case SP_MessageBoxQuestion:
962     case SP_MessageBoxInformation: {
963         static QIcon icn(QPixmap::fromImage(qtc_dialog_information));
964         return icn;
965     }
966     case SP_MessageBoxWarning: {
967         static QIcon icn(QPixmap::fromImage(qtc_dialog_warning));
968         return icn;
969     }
970     case SP_MessageBoxCritical: {
971         static QIcon icn(QPixmap::fromImage(qtc_dialog_error));
972         return icn;
973     }
974 /*
975   case SP_DialogYesButton:
976   case SP_DialogOkButton:
977   {
978   static QIcon icn(load(dialog_ok_png_len, dialog_ok_png_data));
979   return icn;
980   }
981   case SP_DialogNoButton:
982   case SP_DialogCancelButton:
983   {
984   static QIcon icn(load(dialog_cancel_png_len, dialog_cancel_png_data));
985   return icn;
986   }
987   case SP_DialogHelpButton:
988   {
989   static QIcon icn(load(help_contents_png_len, help_contents_png_data));
990   return icn;
991   }
992   case SP_DialogCloseButton:
993   {
994   static QIcon icn(load(dialog_close_png_len, dialog_close_png_data));
995   return icn;
996   }
997   case SP_DialogApplyButton:
998   {
999   static QIcon icn(load(dialog_ok_apply_png_len, dialog_ok_apply_png_data));
1000   return icn;
1001   }
1002   case SP_DialogResetButton:
1003   {
1004   static QIcon icn(load(document_revert_png_len, document_revert_png_data));
1005   return icn;
1006   }
1007 */
1008 #else
1009     case SP_MessageBoxInformation:
1010         return QIcon::fromTheme(QStringLiteral("dialog-information"));
1011     case SP_MessageBoxWarning:
1012         return QIcon::fromTheme(QStringLiteral("dialog-warning"));
1013     case SP_MessageBoxCritical:
1014         return QIcon::fromTheme(QStringLiteral("dialog-error"));
1015     case SP_MessageBoxQuestion:
1016         return QIcon::fromTheme(QStringLiteral("dialog-information"));
1017     case SP_DesktopIcon:
1018         return QIcon::fromTheme(QStringLiteral("user-desktop"));
1019     case SP_TrashIcon:
1020         return QIcon::fromTheme(QStringLiteral("user-trash"));
1021     case SP_ComputerIcon:
1022         return QIcon::fromTheme(QStringLiteral("computer"));
1023     case SP_DriveFDIcon:
1024         return QIcon::fromTheme(QStringLiteral("media-floppy"));
1025     case SP_DriveHDIcon:
1026         return QIcon::fromTheme(QStringLiteral("drive-harddisk"));
1027     case SP_DriveCDIcon:
1028     case SP_DriveDVDIcon:
1029         return QIcon::fromTheme(QStringLiteral("media-optical"));
1030     case SP_DriveNetIcon:
1031         return QIcon::fromTheme(QStringLiteral("network-server"));
1032     case SP_DirOpenIcon:
1033         return QIcon::fromTheme(QStringLiteral("document-open"));
1034     case SP_DirIcon:
1035     case SP_DirClosedIcon:
1036         return QIcon::fromTheme(QStringLiteral("folder"));
1037     // case SP_DirLinkIcon:
1038     case SP_FileIcon:
1039         return QIcon::fromTheme(QStringLiteral("application-x-zerosize"));
1040     // case SP_FileLinkIcon:
1041     case SP_FileDialogStart:
1042         return QIcon::fromTheme(QApplication::layoutDirection() == Qt::RightToLeft ?
1043                      QStringLiteral("go-edn") : QStringLiteral("go-first"));
1044     case SP_FileDialogEnd:
1045         return QIcon::fromTheme(QApplication::layoutDirection() == Qt::RightToLeft ?
1046                      QStringLiteral("go-first") : QStringLiteral("go-end"));
1047     case SP_FileDialogToParent:
1048         return QIcon::fromTheme(QStringLiteral("go-up"));
1049     case SP_FileDialogNewFolder:
1050         return QIcon::fromTheme(QStringLiteral("folder-new"));
1051     case SP_FileDialogDetailedView:
1052         return QIcon::fromTheme(QStringLiteral("view-list-details"));
1053     // case SP_FileDialogInfoView:
1054     //     return QIcon::fromTheme(QStringLiteral("dialog-ok"));
1055     // case SP_FileDialogContentsView:
1056     //     return QIcon::fromTheme(QStringLiteral("dialog-ok"));
1057     case SP_FileDialogListView:
1058         return QIcon::fromTheme(QStringLiteral("view-list-icons"));
1059     case SP_FileDialogBack:
1060         return QIcon::fromTheme(QApplication::layoutDirection() == Qt::RightToLeft ?
1061                      QStringLiteral("go-next") : QStringLiteral("go-previous"));
1062     case SP_DialogOkButton:
1063         return QIcon::fromTheme(QStringLiteral("dialog-ok"));
1064     case SP_DialogCancelButton:
1065         return QIcon::fromTheme(QStringLiteral("dialog-cancel"));
1066     case SP_DialogHelpButton:
1067         return QIcon::fromTheme(QStringLiteral("help-contents"));
1068     case SP_DialogOpenButton:
1069         return QIcon::fromTheme(QStringLiteral("document-open"));
1070     case SP_DialogSaveButton:
1071         return QIcon::fromTheme(QStringLiteral("document-save"));
1072     case SP_DialogCloseButton:
1073         return QIcon::fromTheme(QStringLiteral("dialog-close"));
1074     case SP_DialogApplyButton:
1075         return QIcon::fromTheme(QStringLiteral("dialog-ok-apply"));
1076     case SP_DialogResetButton:
1077         return QIcon::fromTheme(QStringLiteral("document-revert"));
1078     // case SP_DialogDiscardButton:
1079     //     return QIcon::fromTheme(QStringLiteral("dialog-cancel"));
1080     case SP_DialogYesButton:
1081         return QIcon::fromTheme(QStringLiteral("dialog-ok"));
1082     case SP_DialogNoButton:
1083         return QIcon::fromTheme(QStringLiteral("dialog-cancel"));
1084     case SP_ArrowUp:
1085         return QIcon::fromTheme(QStringLiteral("arrow-up"));
1086     case SP_ArrowDown:
1087         return QIcon::fromTheme(QStringLiteral("arrow-down"));
1088     case SP_ArrowLeft:
1089         return QIcon::fromTheme(QStringLiteral("arrow-left"));
1090     case SP_ArrowRight:
1091         return QIcon::fromTheme(QStringLiteral("arrow-right"));
1092     case SP_ArrowBack:
1093         return QIcon::fromTheme(QApplication::layoutDirection() == Qt::RightToLeft ?
1094                      QStringLiteral("go-next") : QStringLiteral("go-previous"));
1095     case SP_ArrowForward:
1096         return QIcon::fromTheme(QApplication::layoutDirection() == Qt::RightToLeft ?
1097                      QStringLiteral("go-previous") : QStringLiteral("go-next"));
1098     case SP_DirHomeIcon:
1099         return QIcon::fromTheme(QStringLiteral("user-home"));
1100     // case SP_CommandLink:
1101     // case SP_VistaShield:
1102     case SP_BrowserReload:
1103         return QIcon::fromTheme(QStringLiteral("view-refresh"));
1104     case SP_BrowserStop:
1105         return QIcon::fromTheme(QStringLiteral("process-stop"));
1106     case SP_MediaPlay:
1107         return QIcon::fromTheme(QStringLiteral("media-playback-start"));
1108     case SP_MediaStop:
1109         return QIcon::fromTheme(QStringLiteral("media-playback-stop"));
1110     case SP_MediaPause:
1111         return QIcon::fromTheme(QStringLiteral("media-playback-pause"));
1112     case SP_MediaSkipForward:
1113         return QIcon::fromTheme(QStringLiteral("media-skip-forward"));
1114     case SP_MediaSkipBackward:
1115         return QIcon::fromTheme(QStringLiteral("media-skip-backward"));
1116     case SP_MediaSeekForward:
1117         return QIcon::fromTheme(QStringLiteral("media-seek-forward"));
1118     case SP_MediaSeekBackward:
1119         return QIcon::fromTheme(QStringLiteral("media-seek-backward"));
1120     case SP_MediaVolume:
1121         return QIcon::fromTheme(QStringLiteral("player-volume"));
1122     case SP_MediaVolumeMuted:
1123         return QIcon::fromTheme(QStringLiteral("player-volume-muted"));
1124 #endif
1125     default:
1126         break;
1127     }
1128     // TODO ?
1129     return ParentStyleClass::standardIcon(pix, option, widget);
1130 }
1131 
layoutSpacing(QSizePolicy::ControlType control1,QSizePolicy::ControlType control2,Qt::Orientation orientation,const QStyleOption * option,const QWidget * widget) const1132 int Style::layoutSpacing(QSizePolicy::ControlType control1,
1133                          QSizePolicy::ControlType control2,
1134                          Qt::Orientation orientation,
1135                          const QStyleOption *option, const QWidget *widget) const
1136 {
1137     Q_UNUSED(control1);
1138     Q_UNUSED(control2);
1139     Q_UNUSED(orientation);
1140     return pixelMetric(PM_DefaultLayoutSpacing, option, widget);
1141 }
1142 
1143 // Use 'drawItemTextWithRole' when already know which role to use.
1144 void
drawItemTextWithRole(QPainter * painter,const QRect & rect,int flags,const QPalette & pal,bool enabled,const QString & text,QPalette::ColorRole textRole) const1145 Style::drawItemTextWithRole(QPainter *painter, const QRect &rect, int flags,
1146                             const QPalette &pal, bool enabled,
1147                             const QString &text,
1148                             QPalette::ColorRole textRole) const
1149 {
1150     ParentStyleClass::drawItemText(painter, rect, flags, pal,
1151                                enabled, text, textRole);
1152 }
1153 
drawSideBarButton(QPainter * painter,const QRect & r,const QStyleOption * option,const QWidget * widget) const1154 void Style::drawSideBarButton(QPainter *painter, const QRect &r, const QStyleOption *option, const QWidget *widget) const
1155 {
1156     const QPalette &palette(option->palette);
1157     QRect          r2(r);
1158     QStyleOption   opt(*option);
1159 
1160     if(r2.height()>r2.width() || (r2.height()<r2.width() && r2.width()<=32))
1161         opt.state&=~State_Horizontal;
1162     else
1163         opt.state|=State_Horizontal;
1164 
1165     const QColor *use(opt.state&State_On ? getSidebarButtons() : buttonColors(option));
1166     bool         horiz(opt.state&State_Horizontal);
1167 
1168     painter->save();
1169     if(opt.state&State_On || opt.state&State_MouseOver)
1170     {
1171         r2.adjust(-1, -1, 1, 1);
1172         drawLightBevel(painter, r2, &opt, widget, ROUNDED_NONE,
1173                        getFill(&opt, use), use, false, WIDGET_MENU_ITEM);
1174     }
1175     else
1176         painter->fillRect(r2, palette.background().color());
1177 
1178     if (opt.state & State_MouseOver && opts.coloredMouseOver) {
1179         r2 = r;
1180         if (opts.coloredMouseOver == MO_PLASTIK) {
1181             if (horiz) {
1182                 r2.adjust(0, 1, 0, -1);
1183             } else {
1184                 r2.adjust(1, 0, -1, 0);
1185             }
1186         } else {
1187             r2.adjust(1, 1, -1, -1);
1188         }
1189         if (opts.coloredMouseOver == MO_GLOW) {
1190             QColor col(m_mouseOverCols[opt.state&State_On ? 0 : 1]);
1191 
1192             col.setAlphaF(GLOW_ALPHA(false));
1193             painter->setPen(col);
1194             drawRect(painter, r);
1195             col = m_mouseOverCols[opt.state&State_On ? 4 : 3];
1196             col.setAlphaF(0.8);
1197             painter->setPen(col);
1198             drawRect(painter, r2);
1199         } else {
1200             painter->setPen(m_mouseOverCols[opt.state&State_On ? 0 : 1]);
1201 
1202             if (horiz || MO_PLASTIK!=opts.coloredMouseOver)
1203             {
1204                 painter->drawLine(r.x(), r.y(), r.x()+r.width()-1, r.y());
1205                 painter->drawLine(r2.x(), r2.y(), r2.x()+r2.width()-1, r2.y());
1206             }
1207 
1208             if(!horiz || MO_PLASTIK!=opts.coloredMouseOver)
1209             {
1210                 painter->drawLine(r.x(), r.y(), r.x(), r.y()+r.height()-1);
1211                 painter->drawLine(r2.x(), r2.y(), r2.x(), r2.y()+r2.height()-1);
1212                 if(MO_PLASTIK!=opts.coloredMouseOver)
1213                     painter->setPen(m_mouseOverCols[opt.state&State_On ? 1 : 2]);
1214             }
1215 
1216             if(horiz || MO_PLASTIK!=opts.coloredMouseOver)
1217             {
1218                 painter->drawLine(r.x(), r.y()+r.height()-1, r.x()+r.width()-1, r.y()+r.height()-1);
1219                 painter->drawLine(r2.x(), r2.y()+r2.height()-1, r2.x()+r2.width()-1, r2.y()+r2.height()-1);
1220             }
1221 
1222             if(!horiz || MO_PLASTIK!=opts.coloredMouseOver)
1223             {
1224                 painter->drawLine(r.x()+r.width()-1, r.y(), r.x()+r.width()-1, r.y()+r.height()-1);
1225                 painter->drawLine(r2.x()+r2.width()-1, r2.y(), r2.x()+r2.width()-1, r2.y()+r2.height()-1);
1226             }
1227         }
1228     }
1229 
1230     painter->restore();
1231 }
1232 
drawHighlight(QPainter * p,const QRect & r,bool horiz,bool inc) const1233 void Style::drawHighlight(QPainter *p, const QRect &r, bool horiz, bool inc) const
1234 {
1235     QColor col1(m_mouseOverCols[ORIGINAL_SHADE]);
1236 
1237     col1.setAlphaF(0.5);
1238     drawFadedLine(p, r, inc ? col1 : m_mouseOverCols[ORIGINAL_SHADE], true, true, horiz);
1239     drawFadedLine(p, r.adjusted(horiz ? 0 : 1, horiz ? 1 : 0, 0, 0), inc ? m_mouseOverCols[ORIGINAL_SHADE] : col1, true, true, horiz);
1240 }
1241 
1242 void
drawFadedLine(QPainter * p,const QRect & r,const QColor & col,bool fadeStart,bool fadeEnd,bool horiz,double fadeSizeStart,double fadeSizeEnd) const1243 Style::drawFadedLine(QPainter *p, const QRect &r, const QColor &col,
1244                      bool fadeStart, bool fadeEnd, bool horiz,
1245                      double fadeSizeStart, double fadeSizeEnd) const
1246 {
1247     bool            aa(p->testRenderHint(QPainter::Antialiasing));
1248     QPointF         start(r.x()+(aa ? 0.5 : 0.0), r.y()+(aa ? 0.5 : 0.0)),
1249         end(r.x()+(horiz ? r.width()-1 : 0)+(aa ? 0.5 : 0.0),
1250             r.y()+(horiz ? 0 : r.height()-1)+(aa ? 0.5 : 0.0));
1251 
1252     if(opts.fadeLines && (fadeStart || fadeEnd))
1253     {
1254         QLinearGradient grad(start, end);
1255         QColor          fade(col);
1256 
1257         fade.setAlphaF(0.0);
1258         grad.setColorAt(0, fadeStart && opts.fadeLines ? fade : col);
1259         if(fadeSizeStart>=0 && fadeSizeStart<=1.0)
1260             grad.setColorAt(fadeSizeStart, col);
1261         if(fadeSizeEnd>=0 && fadeSizeEnd<=1.0)
1262             grad.setColorAt(1.0-fadeSizeEnd, col);
1263         grad.setColorAt(1, fadeEnd && opts.fadeLines ? fade : col);
1264         p->setPen(QPen(QBrush(grad), QPENWIDTH1));
1265     }
1266     else
1267         p->setPen(col);
1268     p->drawLine(start, end);
1269 }
1270 
drawLines(QPainter * p,const QRect & r,bool horiz,int nLines,int offset,const QColor * cols,int startOffset,int dark,ELine type) const1271 void Style::drawLines(QPainter *p, const QRect &r, bool horiz, int nLines, int offset, const QColor *cols, int startOffset,
1272                       int dark, ELine type) const
1273 {
1274     int  space((nLines*2)+(LINE_DASHES!=type ? (nLines-1) : 0)),
1275         step(LINE_DASHES!=type ? 3 : 2),
1276         etchedDisp(type == LINE_SUNKEN ? 1 : 0),
1277         x(horiz ? r.x() : r.x()+((r.width()-space)>>1)),
1278         y(horiz ? r.y()+((r.height()-space)>>1) : r.y()),
1279         x2(r.x()+r.width()-1),
1280         y2(r.y()+r.height()-1),
1281         i;
1282     QPen dp(cols[dark], QPENWIDTH1),
1283         lp(cols[0], QPENWIDTH1);
1284 
1285     if(opts.fadeLines && (horiz ? r.width() : r.height())>16)
1286     {
1287         QLinearGradient grad(r.topLeft(), horiz ? r.topRight() : r.bottomLeft());
1288         QColor          fade(cols[dark]);
1289 
1290         fade.setAlphaF(0.0);
1291         grad.setColorAt(0, fade);
1292         grad.setColorAt(0.4, cols[dark]);
1293         grad.setColorAt(0.6, cols[dark]);
1294         grad.setColorAt(1, fade);
1295 
1296         dp=QPen(QBrush(grad), QPENWIDTH1);
1297 
1298         if(LINE_FLAT!=type)
1299         {
1300             fade=QColor(cols[0]);
1301 
1302             fade.setAlphaF(0.0);
1303             grad.setColorAt(0, fade);
1304             grad.setColorAt(0.4, cols[0]);
1305             grad.setColorAt(0.6, cols[0]);
1306             grad.setColorAt(1, fade);
1307             lp=QPen(QBrush(grad), QPENWIDTH1);
1308         }
1309     }
1310 
1311     p->setRenderHint(QPainter::Antialiasing, true);
1312     if(horiz)
1313     {
1314         if(startOffset && y+startOffset>0)
1315             y+=startOffset;
1316 
1317         p->setPen(dp);
1318         for(i=0; i<space; i+=step)
1319             drawAaLine(p, x+offset, y+i, x2-offset, y+i);
1320 
1321         if(LINE_FLAT!=type)
1322         {
1323             p->setPen(lp);
1324             x+=etchedDisp;
1325             x2+=etchedDisp;
1326             for(i=1; i<space; i+=step)
1327                 drawAaLine(p, x+offset, y+i, x2-offset, y+i);
1328         }
1329     }
1330     else
1331     {
1332         if(startOffset && x+startOffset>0)
1333             x+=startOffset;
1334 
1335         p->setPen(dp);
1336         for(i=0; i<space; i+=step)
1337             drawAaLine(p, x+i, y+offset, x+i, y2-offset);
1338 
1339         if(LINE_FLAT!=type)
1340         {
1341             p->setPen(lp);
1342             y+=etchedDisp;
1343             y2+=etchedDisp;
1344             for(i=1; i<space; i+=step)
1345                 drawAaLine(p, x+i, y+offset, x+i, y2-offset);
1346         }
1347     }
1348     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
1349 }
1350 
drawProgressBevelGradient(QPainter * p,const QRect & origRect,const QStyleOption * option,bool horiz,EAppearance bevApp,const QColor * cols) const1351 void Style::drawProgressBevelGradient(QPainter *p, const QRect &origRect, const QStyleOption *option, bool horiz, EAppearance bevApp,
1352                                       const QColor *cols) const
1353 {
1354     bool    vertical(!horiz),
1355         inCache(true);
1356     QRect   r(0, 0, horiz ? PROGRESS_CHUNK_WIDTH*2 : origRect.width(),
1357               horiz ? origRect.height() : PROGRESS_CHUNK_WIDTH*2);
1358     QtcKey  key(createKey(horiz ? r.height() : r.width(), cols[ORIGINAL_SHADE], horiz, bevApp, WIDGET_PROGRESSBAR));
1359     QPixmap *pix(m_pixmapCache.object(key));
1360 
1361     if(!pix)
1362     {
1363         pix=new QPixmap(r.width(), r.height());
1364 
1365         QPainter pixPainter(pix);
1366 
1367         if(qtcIsFlat(bevApp))
1368             pixPainter.fillRect(r, cols[ORIGINAL_SHADE]);
1369         else
1370             drawBevelGradientReal(cols[ORIGINAL_SHADE], &pixPainter, r, horiz, false, bevApp, WIDGET_PROGRESSBAR);
1371 
1372         switch(opts.stripedProgress)
1373         {
1374         default:
1375         case STRIPE_NONE:
1376             break;
1377         case STRIPE_PLAIN:
1378         {
1379             QRect r2(horiz
1380                      ? QRect(r.x(), r.y(), PROGRESS_CHUNK_WIDTH, r.height())
1381                      : QRect(r.x(), r.y(), r.width(), PROGRESS_CHUNK_WIDTH));
1382 
1383             if(qtcIsFlat(bevApp))
1384                 pixPainter.fillRect(r2, cols[1]);
1385             else
1386                 drawBevelGradientReal(cols[1], &pixPainter, r2, horiz, false, bevApp, WIDGET_PROGRESSBAR);
1387             break;
1388         }
1389         case STRIPE_DIAGONAL:
1390         {
1391             QRegion reg;
1392             int     size(vertical ? origRect.width() : origRect.height());
1393 
1394             for(int offset=0; offset<(size*2); offset+=(PROGRESS_CHUNK_WIDTH*2))
1395             {
1396                 QPolygon a;
1397 
1398                 if(vertical)
1399                     a.setPoints(4, r.x(),           r.y()+offset,
1400                                 r.x()+r.width(), (r.y()+offset)-size,
1401                                 r.x()+r.width(), (r.y()+offset+PROGRESS_CHUNK_WIDTH)-size,
1402                                 r.x(),           r.y()+offset+PROGRESS_CHUNK_WIDTH);
1403                 else
1404                     a.setPoints(4, r.x()+offset,                             r.y(),
1405                                 r.x()+offset+PROGRESS_CHUNK_WIDTH,        r.y(),
1406                                 (r.x()+offset+PROGRESS_CHUNK_WIDTH)-size, r.y()+r.height(),
1407                                 (r.x()+offset)-size,                      r.y()+r.height());
1408 
1409                 reg+=QRegion(a);
1410             }
1411 
1412             pixPainter.setClipRegion(reg);
1413             if(qtcIsFlat(bevApp))
1414                 pixPainter.fillRect(r, cols[1]);
1415             else
1416                 drawBevelGradientReal(cols[1], &pixPainter, r, horiz, false, bevApp, WIDGET_PROGRESSBAR);
1417         }
1418         }
1419 
1420         pixPainter.end();
1421         int cost(pix->width()*pix->height()*(pix->depth()/8));
1422 
1423         if(cost<m_pixmapCache.maxCost())
1424             m_pixmapCache.insert(key, pix, cost);
1425         else
1426             inCache=false;
1427     }
1428     QRect fillRect(origRect);
1429 
1430     if(opts.animatedProgress)
1431     {
1432         int animShift=vertical || option->state&STATE_REVERSE ? PROGRESS_CHUNK_WIDTH : -PROGRESS_CHUNK_WIDTH;
1433 
1434         if(vertical || option->state&STATE_REVERSE)
1435             animShift -= (m_animateStep/2) % (PROGRESS_CHUNK_WIDTH*2);
1436         else
1437             animShift += (m_animateStep/2) % (PROGRESS_CHUNK_WIDTH*2);
1438 
1439         if(horiz)
1440             fillRect.adjust(animShift-PROGRESS_CHUNK_WIDTH, 0, PROGRESS_CHUNK_WIDTH, 0);
1441         else
1442             fillRect.adjust(0, animShift-PROGRESS_CHUNK_WIDTH, 0, PROGRESS_CHUNK_WIDTH);
1443     }
1444 
1445     p->save();
1446     p->setClipRect(origRect, Qt::IntersectClip);
1447     p->drawTiledPixmap(fillRect, *pix);
1448     if (opts.stripedProgress == STRIPE_FADE && fillRect.width() > 4 &&
1449         fillRect.height() > 4) {
1450         addStripes(p, QPainterPath(), fillRect, !vertical);
1451     }
1452     p->restore();
1453 
1454     if (!inCache) {
1455         delete pix;
1456     }
1457 }
1458 
1459 void
drawBevelGradient(const QColor & base,QPainter * p,const QRect & origRect,const QPainterPath & path,bool horiz,bool sel,EAppearance bevApp,EWidget w,bool useCache) const1460 Style::drawBevelGradient(const QColor &base, QPainter *p, const QRect &origRect,
1461                          const QPainterPath &path, bool horiz, bool sel,
1462                          EAppearance bevApp, EWidget w, bool useCache) const
1463 {
1464     if (origRect.width() < 1 || origRect.height() < 1) {
1465         return;
1466     }
1467     if (qtcIsFlat(bevApp)) {
1468         if (noneOf(w, WIDGET_TAB_TOP, WIDGET_TAB_BOT) ||
1469             !qtcIsCustomBgnd(opts) || opts.tabBgnd || !sel) {
1470             if (path.isEmpty()) {
1471                 p->fillRect(origRect, base);
1472             } else {
1473                 p->fillPath(path, base);
1474             }
1475         }
1476     } else {
1477         bool tab = oneOf(w, WIDGET_TAB_TOP, WIDGET_TAB_BOT);
1478         bool selected = tab ? false : sel;
1479         EAppearance app =
1480             (selected ? opts.sunkenAppearance :
1481              w == WIDGET_LISTVIEW_HEADER && bevApp == APPEARANCE_BEVELLED ?
1482              APPEARANCE_LV_BEVELLED : bevApp != APPEARANCE_BEVELLED ||
1483              WIDGET_BUTTON(w) ||
1484              oneOf(w, WIDGET_LISTVIEW_HEADER, WIDGET_TROUGH,
1485                    WIDGET_NO_ETCH_BTN, WIDGET_MENU_BUTTON) ? bevApp :
1486              APPEARANCE_GRADIENT);
1487 
1488         if (w == WIDGET_PROGRESSBAR || !useCache) {
1489             drawBevelGradientReal(base, p, origRect, path, horiz, sel, app, w);
1490         } else {
1491             QRect r(0, 0, horiz ? PIXMAP_DIMENSION : origRect.width(),
1492                     horiz ? origRect.height() : PIXMAP_DIMENSION);
1493             QtcKey key(createKey(horiz ? r.height() : r.width(),
1494                                  base, horiz, app, w));
1495             QPixmap *pix(m_pixmapCache.object(key));
1496             bool inCache(true);
1497 
1498             if (!pix) {
1499                 pix = new QPixmap(r.width(), r.height());
1500                 pix->fill(Qt::transparent);
1501 
1502                 QPainter pixPainter(pix);
1503 
1504                 drawBevelGradientReal(base, &pixPainter, r, horiz, sel, app, w);
1505                 pixPainter.end();
1506 
1507                 int cost(pix->width()*pix->height()*(pix->depth()/8));
1508 
1509                 if (cost < m_pixmapCache.maxCost()) {
1510                     m_pixmapCache.insert(key, pix, cost);
1511                 } else {
1512                     inCache = false;
1513                 }
1514             }
1515 
1516             if(!path.isEmpty())
1517             {
1518                 p->save();
1519                 p->setClipPath(path, Qt::IntersectClip);
1520             }
1521 
1522             p->drawTiledPixmap(origRect, *pix);
1523             if(!path.isEmpty())
1524                 p->restore();
1525             if(!inCache)
1526                 delete pix;
1527         }
1528     }
1529 }
1530 
1531 void
drawBevelGradientReal(const QColor & base,QPainter * p,const QRect & r,const QPainterPath & path,bool horiz,bool sel,EAppearance app,EWidget w) const1532 Style::drawBevelGradientReal(const QColor &base, QPainter *p, const QRect &r,
1533                              const QPainterPath &path, bool horiz, bool sel,
1534                              EAppearance app, EWidget w) const
1535 {
1536     bool topTab = (w == WIDGET_TAB_TOP);
1537     bool botTab = (w == WIDGET_TAB_BOT);
1538     bool dwt = qtcIsCustomBgnd(opts) && (w == WIDGET_DOCK_WIDGET_TITLE);
1539     bool titleBar = (opts.windowBorder & WINDOW_BORDER_BLEND_TITLEBAR &&
1540                      (oneOf(w, WIDGET_MDI_WINDOW, WIDGET_MDI_WINDOW_TITLE) ||
1541                       (opts.dwtSettings & DWT_COLOR_AS_PER_TITLEBAR &&
1542                        w == WIDGET_DOCK_WIDGET_TITLE && !dwt)));
1543     bool reverse = QApplication::layoutDirection() == Qt::RightToLeft;
1544     const Gradient *grad = qtcGetGradient(app, &opts);
1545     QLinearGradient g(r.topLeft(), horiz ? r.bottomLeft() : r.topRight());
1546     GradientStopCont::const_iterator it(grad->stops.begin());
1547     GradientStopCont::const_iterator end(grad->stops.end());
1548     int numStops(grad->stops.size());
1549 
1550     for (int i = 0;it != end;++it, ++i) {
1551         QColor col;
1552 
1553         if ((topTab || botTab || dwt || titleBar) && i == numStops-1) {
1554             if (titleBar) {
1555                 col = m_backgroundCols[ORIGINAL_SHADE];
1556                 col.setAlphaF(0.0);
1557             } else {
1558                 col = base;
1559                 if ((sel && opts.tabBgnd == 0 && !reverse) || dwt) {
1560                     col.setAlphaF(0.0);
1561                 }
1562             }
1563         } else {
1564             shade(base, &col, botTab && opts.invertBotTab ?
1565                   qMax(INVERT_SHADE((*it).val), 0.9) : (*it).val);
1566         }
1567         if (w != WIDGET_TOOLTIP && (*it).alpha < 1.0) {
1568             col.setAlphaF(col.alphaF() * (*it).alpha);
1569         }
1570         g.setColorAt(botTab ? 1.0 - (*it).pos : (*it).pos, col);
1571     }
1572 
1573     if (app == APPEARANCE_AGUA && !(topTab || botTab || dwt) &&
1574         (horiz ? r.height() : r.width()) > AGUA_MAX) {
1575         QColor col;
1576         double pos = AGUA_MAX/((horiz ? r.height() : r.width())*2.0);
1577         shade(base, &col, AGUA_MID_SHADE);
1578         g.setColorAt(pos, col);
1579         g.setColorAt(1.0-pos, col);
1580     }
1581 
1582     //p->fillRect(r, base);
1583     if (path.isEmpty()) {
1584         p->fillRect(r, QBrush(g));
1585     } else {
1586         p->fillPath(path, QBrush(g));
1587     }
1588 }
1589 
drawSunkenBevel(QPainter * p,const QRect & r,const QColor & col) const1590 void Style::drawSunkenBevel(QPainter *p, const QRect &r, const QColor &col) const
1591 {
1592     double          radius=opts.titlebarButtons&TITLEBAR_BUTTON_ROUND
1593         ? r.height()/2.0
1594         : opts.round>ROUND_FULL
1595         ? 5.0
1596         : opts.round>ROUND_SLIGHT
1597         ? 3.0
1598         : 2.0;
1599     QPainterPath    path(buildPath(QRectF(r), WIDGET_OTHER, ROUNDED_ALL, radius));
1600     QLinearGradient g(r.topLeft(), r.bottomLeft());
1601     QColor          black(Qt::black),
1602         white(Qt::white);
1603 
1604     black.setAlphaF(SUNKEN_BEVEL_DARK_ALPHA(col));
1605     white.setAlphaF(SUNKEN_BEVEL_LIGHT_ALPHA(col));
1606     g.setColorAt(0, black);
1607     g.setColorAt(1, white);
1608     p->save();
1609     p->setRenderHint(QPainter::Antialiasing, true);
1610     p->fillPath(path, QBrush(g));
1611     p->restore();
1612 }
1613 
1614 void
drawLightBevel(QPainter * p,const QRect & r,const QStyleOption * option,const QWidget * widget,int round,const QColor & fill,const QColor * custom,bool doBorder,EWidget w) const1615 Style::drawLightBevel(QPainter *p, const QRect &r, const QStyleOption *option,
1616                       const QWidget *widget, int round, const QColor &fill,
1617                       const QColor *custom, bool doBorder, EWidget w) const
1618 {
1619     bool onToolbar = (opts.tbarBtnAppearance != APPEARANCE_NONE &&
1620                       (w == WIDGET_TOOLBAR_BUTTON ||
1621                        (WIDGET_BUTTON(w) && isOnToolbar(widget))));
1622 
1623     if (oneOf(w, WIDGET_PROGRESSBAR, WIDGET_SB_BUTTON) ||
1624         (w == WIDGET_SPIN && !opts.unifySpin)/* || !m_usePixmapCache*/) {
1625         drawLightBevelReal(p, r, option, widget, round, fill, custom,
1626                            doBorder, w, true, opts.round, onToolbar);
1627     } else {
1628         static const int constMaxCachePixmap = 128;
1629 
1630         int endSize = 0;
1631         int middleSize = 8;
1632         bool horiz = (CIRCULAR_SLIDER(w) ||
1633                       isHoriz(option, w, opts.tbarBtns == TBTN_JOINED));
1634         bool circular = ((w == WIDGET_MDI_WINDOW_BUTTON &&
1635                           (opts.titlebarButtons & TITLEBAR_BUTTON_ROUND)) ||
1636                          oneOf(w, WIDGET_RADIO_BUTTON, WIDGET_DIAL) ||
1637                          CIRCULAR_SLIDER(w));
1638         double radius = 0;
1639         ERound realRound = qtcGetWidgetRound(&opts, r.width(), r.height(), w);
1640 
1641         if (!circular) {
1642             switch (realRound) {
1643             case ROUND_SLIGHT:
1644             case ROUND_NONE:
1645             case ROUND_FULL:
1646                 endSize = (SLIDER(w) && opts.coloredMouseOver == MO_PLASTIK &&
1647                            option->state&State_MouseOver ? 9 : 5);
1648                 break;
1649             case ROUND_EXTRA:
1650                 endSize = 7;
1651                 break;
1652             case ROUND_MAX:
1653                 radius = qtcGetRadius(&opts, r.width(), r.height(),
1654                                       w, RADIUS_ETCH);
1655                 endSize = (SLIDER(w) ? qMax((opts.sliderWidth / 2) + 1,
1656                                             int(radius + 1.5)) :
1657                            int(radius + 2.5));
1658                 middleSize = MIN_ROUND_MAX_WIDTH - (endSize * 2) + 4;
1659                 if (middleSize < 4)
1660                     middleSize = 4;
1661                 break;
1662             }
1663         }
1664 
1665         int size = 2 * endSize + middleSize;
1666 
1667         if (size > constMaxCachePixmap) {
1668             drawLightBevelReal(p, r, option, widget, round, fill, custom,
1669                                doBorder, w, true, realRound, onToolbar);
1670         } else {
1671             QString key;
1672             bool small(circular || (horiz ? r.width() : r.height())<(2*endSize));
1673             QPixmap pix;
1674             const QSize pixSize(small ? QSize(r.width(), r.height()) :
1675                                 QSize(horiz ? size : r.width(),
1676                                       horiz ? r.height() : size));
1677             uint state(option->state&(State_Raised|State_Sunken|State_On|State_Horizontal|State_HasFocus|State_MouseOver|
1678                                          (WIDGET_MDI_WINDOW_BUTTON==w ? State_Active : State_None)));
1679 
1680             key.sprintf("qtc-%x-%x-%x-%x-%x-%x-%x-%x-%x", w, onToolbar ? 1 : 0,
1681                         round, (int)realRound, pixSize.width(), pixSize.height(),
1682                         state, fill.rgba(), (int)(radius * 100));
1683             if (!m_usePixmapCache || !QPixmapCache::find(key, pix)) {
1684                 pix = QPixmap(pixSize);
1685                 pix.fill(Qt::transparent);
1686 
1687                 QPainter pixPainter(&pix);
1688                 ERound oldRound = opts.round;
1689                 opts.round = realRound;
1690                 pixPainter.setRenderHint(QPainter::Antialiasing, true);
1691                 drawLightBevelReal(&pixPainter, QRect(0, 0, pixSize.width(),
1692                                                       pixSize.height()), option,
1693                                    widget, round, fill, custom, doBorder, w,
1694                                    false, realRound, onToolbar);
1695                 opts.round = oldRound;
1696                 pixPainter.end();
1697 
1698                 if (m_usePixmapCache) {
1699                     QPixmapCache::insert(key, pix);
1700                 }
1701             }
1702 
1703             if (small) {
1704                 p->drawPixmap(r.topLeft(), pix);
1705             } else if (horiz) {
1706                 int middle(qMin(r.width()-(2*endSize), middleSize));
1707                 if(middle>0)
1708                     p->drawTiledPixmap(r.x()+endSize, r.y(), r.width()-(2*endSize), pix.height(), pix.copy(endSize, 0, middle, pix.height()));
1709                 p->drawPixmap(r.x(), r.y(), pix.copy(0, 0, endSize, pix.height()));
1710                 p->drawPixmap(r.x()+r.width()-endSize, r.y(), pix.copy(pix.width()-endSize, 0, endSize, pix.height()));
1711             } else {
1712                 int middle(qMin(r.height()-(2*endSize), middleSize));
1713                 if (middle > 0) {
1714                     p->drawTiledPixmap(r.x(), r.y() + endSize, pix.width(),
1715                                        r.height() - 2 * endSize,
1716                                        pix.copy(0, endSize,
1717                                                 pix.width(), middle));
1718                 }
1719                 p->drawPixmap(r.x(), r.y(),
1720                               pix.copy(0, 0, pix.width(), endSize));
1721                 p->drawPixmap(r.x(), r.y() + r.height() - endSize,
1722                               pix.copy(0, pix.height() - endSize, pix.width(),
1723                                        endSize));
1724             }
1725 
1726             if (w == WIDGET_SB_SLIDER && opts.stripedSbar) {
1727                 QRect rx(r.adjusted(1, 1, -1, -1));
1728                 addStripes(p, buildPath(rx, WIDGET_SB_SLIDER, realRound,
1729                                         qtcGetRadius(&opts, rx.width() - 1,
1730                                                      rx.height() - 1,
1731                                                      WIDGET_SB_SLIDER,
1732                                                      RADIUS_INTERNAL)),
1733                            rx, horiz);
1734             }
1735         }
1736     }
1737 }
1738 
1739 void
drawLightBevelReal(QPainter * p,const QRect & rOrig,const QStyleOption * option,const QWidget * widget,int round,const QColor & fill,const QColor * custom,bool doBorder,EWidget w,bool useCache,ERound realRound,bool onToolbar) const1740 Style::drawLightBevelReal(QPainter *p, const QRect &rOrig,
1741                           const QStyleOption *option, const QWidget *widget,
1742                           int round, const QColor &fill, const QColor *custom,
1743                           bool doBorder, EWidget w, bool useCache,
1744                           ERound realRound, bool onToolbar) const
1745 {
1746     EAppearance app(qtcWidgetApp(onToolbar ? WIDGET_TOOLBAR_BUTTON : w,
1747                                   &opts, option->state&State_Active));
1748     QRect r(rOrig);
1749     bool bevelledButton((WIDGET_BUTTON(w) || WIDGET_NO_ETCH_BTN == w ||
1750                          WIDGET_MENU_BUTTON == w) && APPEARANCE_BEVELLED == app);
1751     bool sunken(option->state &(/*State_Down | */State_On | State_Sunken));
1752     bool flatWidget((WIDGET_MDI_WINDOW_BUTTON==w &&
1753                      (opts.round==ROUND_MAX ||
1754                       opts.titlebarButtons&TITLEBAR_BUTTON_ROUND)) ||
1755                     (WIDGET_PROGRESSBAR==w && !opts.borderProgress));
1756     bool lightBorder(!flatWidget && DRAW_LIGHT_BORDER(sunken, w, app));
1757     bool draw3dfull(!flatWidget && !lightBorder &&
1758                     DRAW_3D_FULL_BORDER(sunken, app));
1759     bool draw3d(!flatWidget && (draw3dfull ||
1760                                 (!lightBorder && DRAW_3D_BORDER(sunken, app))));
1761     bool drawShine(DRAW_SHINE(sunken, app));
1762     bool doColouredMouseOver(doBorder && option->state&State_Enabled &&
1763                              WIDGET_MDI_WINDOW_BUTTON!=w && WIDGET_SPIN!=w &&
1764                              WIDGET_COMBO_BUTTON!=w && WIDGET_SB_BUTTON!=w &&
1765                              (!SLIDER(w) || !opts.colorSliderMouseOver) &&
1766                              !(option->state&STATE_KWIN_BUTTON) &&
1767                              (opts.coloredTbarMo ||
1768                               !(option->state&STATE_TBAR_BUTTON)) &&
1769                              opts.coloredMouseOver &&
1770                              option->state&State_MouseOver &&
1771                              WIDGET_PROGRESSBAR!=w &&
1772                              (option->state&STATE_TOGGLE_BUTTON || !sunken));
1773     bool plastikMouseOver(doColouredMouseOver &&
1774                           MO_PLASTIK==opts.coloredMouseOver);
1775     bool colouredMouseOver(doColouredMouseOver && WIDGET_MENU_BUTTON!=w &&
1776                            (MO_COLORED==opts.coloredMouseOver ||
1777                             MO_COLORED_THICK==opts.coloredMouseOver ||
1778                             (MO_GLOW==opts.coloredMouseOver &&
1779                              !(opts.buttonEffect != EFFECT_NONE)))),
1780         doEtch(doBorder && ETCH_WIDGET(w) && opts.buttonEffect != EFFECT_NONE),
1781         glowFocus(doEtch && USE_GLOW_FOCUS(option->state&State_MouseOver) && option->state&State_HasFocus &&
1782                   option->state&State_Enabled),
1783         horiz(CIRCULAR_SLIDER(w) || isHoriz(option, w, TBTN_JOINED==opts.tbarBtns)),
1784         sunkenToggleMo(sunken && !(option->state&State_Sunken) && option->state&(State_MouseOver|STATE_TOGGLE_BUTTON));
1785     const QColor *cols(custom ? custom : m_backgroundCols),
1786         *border(colouredMouseOver ? borderColors(option, cols) : cols);
1787 
1788     p->save();
1789 
1790     if (doEtch)
1791         r.adjust(1, 1, -1, -1);
1792 
1793     if (WIDGET_TROUGH == w && !opts.borderSbarGroove)
1794         doBorder = false;
1795 
1796     p->setRenderHint(QPainter::Antialiasing, true);
1797 
1798     if (r.width() > 0 && r.height() > 0) {
1799         if (w == WIDGET_PROGRESSBAR && opts.stripedProgress != STRIPE_NONE) {
1800             drawProgressBevelGradient(p, opts.borderProgress ?
1801                                       r.adjusted(1, 1, -1, -1) : r,
1802                                       option, horiz, app, custom);
1803         } else {
1804             drawBevelGradient(fill, p, WIDGET_PROGRESSBAR==w && opts.borderProgress ? r.adjusted(1, 1, -1, -1) : r,
1805                               doBorder
1806                               ? buildPath(r, w, round, qtcGetRadius(&opts, r.width()-2, r.height()-2, w, RADIUS_INTERNAL))
1807                               : buildPath(QRectF(r), w, round, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_EXTERNAL)),
1808                               horiz, sunken, app, w, useCache);
1809 
1810             if(!sunken || sunkenToggleMo)
1811                 if(plastikMouseOver) // && !sunken)
1812                 {
1813                     p->save();
1814                     p->setClipPath(buildPath(r.adjusted(0, 0, 0, -1), w, round,
1815                                              qtcGetRadius(&opts, r.width()-2, r.height()-2, w, RADIUS_INTERNAL)));
1816                     if (SLIDER(w)) {
1817                         int len = sbSliderMOLen(opts, horiz ? r.width() :
1818                                                 r.height()) + 1;
1819                         int so = lightBorder ? SLIDER_MO_PLASTIK_BORDER : 1;
1820                         int eo = len + so;
1821                         int col = SLIDER_MO_SHADE;
1822 
1823                         if (horiz) {
1824                             drawBevelGradient(m_mouseOverCols[col], p, QRect(r.x()+so-1, r.y(), len, r.height()-1), horiz, sunken, app, w, useCache);
1825                             drawBevelGradient(m_mouseOverCols[col], p, QRect(r.x()+r.width()-eo+1, r.y(), len, r.height()-1), horiz, sunken, app, w, useCache);
1826                         }
1827                         else
1828                         {
1829                             drawBevelGradient(m_mouseOverCols[col], p, QRect(r.x(), r.y()+so-1, r.width()-1, len), horiz, sunken, app, w, useCache);
1830                             drawBevelGradient(m_mouseOverCols[col], p, QRect(r.x(), r.y()+r.height()-eo+1, r.width()-1, len), horiz, sunken, app, w, useCache);
1831                         }
1832                     }
1833                     else
1834                     {
1835                         bool horizontal((horiz && WIDGET_SB_BUTTON!=w)|| (!horiz && WIDGET_SB_BUTTON==w)),
1836                             thin(WIDGET_SB_BUTTON==w || WIDGET_SPIN==w || ((horiz ? r.height() : r.width())<16));
1837 
1838                         setPainterPen(p, m_mouseOverCols[MO_PLASTIK_DARK(w)], QPENWIDTH1);
1839                         if(horizontal)
1840                         {
1841                             drawAaLine(p, r.x()+1, r.y()+1, r.x()+r.width()-2, r.y()+1);
1842                             drawAaLine(p, r.x()+1, r.y()+r.height()-2, r.x()+r.width()-2, r.y()+r.height()-2);
1843                         }
1844                         else
1845                         {
1846                             drawAaLine(p, r.x()+1, r.y()+1, r.x()+1, r.y()+r.height()-2);
1847                             drawAaLine(p, r.x()+r.width()-2, r.y()+1, r.x()+r.width()-2, r.y()+r.height()-2);
1848                         }
1849                         if(!thin)
1850                         {
1851                             setPainterPen(p, m_mouseOverCols[MO_PLASTIK_LIGHT(w)], QPENWIDTH1);
1852                             if(horizontal)
1853                             {
1854                                 drawAaLine(p, r.x()+1, r.y()+2, r.x()+r.width()-2, r.y()+2);
1855                                 drawAaLine(p, r.x()+1, r.y()+r.height()-3, r.x()+r.width()-2, r.y()+r.height()-3);
1856                             }
1857                             else
1858                             {
1859                                 drawAaLine(p, r.x()+2, r.y()+1, r.x()+2, r.y()+r.height()-2);
1860                                 drawAaLine(p, r.x()+r.width()-3, r.y()+1, r.x()+r.width()-3, r.y()+r.height()-2);
1861                             }
1862                         }
1863                     }
1864                     p->restore();
1865                 }
1866         }
1867 
1868         if(drawShine)
1869         {
1870             bool   mo(option->state&State_Enabled && option->state&State_MouseOver && opts.highlightFactor);
1871             QColor white(Qt::white);
1872 
1873             if(WIDGET_MDI_WINDOW_BUTTON==w || WIDGET_RADIO_BUTTON==w || CIRCULAR_SLIDER(w))
1874             {
1875                 QRectF          ra(r.x()+0.5, r.y()+0.5, r.width(), r.height());
1876                 double          topSize=(ra.height()*0.4),
1877                     topWidthAdjust=WIDGET_RADIO_BUTTON==w || WIDGET_SLIDER==w ? 4 : 4.75;
1878                 QRectF          topGradRect(ra.x()+topWidthAdjust, ra.y(),
1879                                             ra.width()-(topWidthAdjust*2)-1, topSize-1);
1880                 QLinearGradient topGrad(topGradRect.topLeft(), topGradRect.bottomLeft());
1881 
1882                 white.setAlphaF(mo ? (opts.highlightFactor>0 ? 0.8 : 0.7) : 0.75);
1883                 topGrad.setColorAt(0.0, white);
1884                 white.setAlphaF(/*mo ? (opts.highlightFactor>0 ? 0.3 : 0.1) : */0.2);
1885                 topGrad.setColorAt(1.0, white);
1886                 p->fillPath(buildPath(topGradRect, w, round, topSize), QBrush(topGrad));
1887             }
1888             else
1889             {
1890                 QRectF ra(r.x()+0.5, r.y()+0.5, r.width(), r.height());
1891                 double size = qtcMin((horiz ? ra.height() : ra.width()) / 2.0,
1892                                      16),
1893                     rad=size/2.0;
1894                 int    mod=4;
1895 
1896                 if(horiz)
1897                 {
1898                     if(!(ROUNDED_LEFT&round))
1899                         ra.adjust(-8, 0, 0, 0);
1900                     if(!(ROUNDED_RIGHT&round))
1901                         ra.adjust(0, 0, 8, 0);
1902                 }
1903                 else
1904                 {
1905                     if(!(ROUNDED_TOP&round))
1906                         ra.adjust(0, -8, 0, 0);
1907                     if(!(ROUNDED_BOTTOM&round))
1908                         ra.adjust(0, 0, 0, 8);
1909                 }
1910 
1911                 if (realRound < ROUND_MAX ||
1912                     (!isMaxRoundWidget(w) && !IS_SLIDER(w))) {
1913                     rad /= 2.0;
1914                     mod = mod >> 1;
1915                 }
1916 
1917                 QRectF          gr(horiz ? QRectF(ra.x()+mod, ra.y(), ra.width()-(mod*2)-1, size-1)
1918                                    : QRectF(ra.x(), ra.y()+mod, size-1, ra.height()-(mod*2)-1));
1919                 QLinearGradient g(gr.topLeft(), horiz ? gr.bottomLeft() : gr.topRight());
1920 
1921                 white.setAlphaF(mo ? (opts.highlightFactor>0 ? 0.95 : 0.85) : 0.9);
1922                 g.setColorAt(0.0, white);
1923                 white.setAlphaF(mo ? (opts.highlightFactor>0 ? 0.3 : 0.1) : 0.2);
1924                 g.setColorAt(1.0, white);
1925                 if(WIDGET_SB_BUTTON==w)
1926                 {
1927                     p->save();
1928                     p->setClipRect(r);
1929                 }
1930                 p->fillPath(buildPath(gr, w, round, rad), QBrush(g));
1931                 if(WIDGET_SB_BUTTON==w)
1932                     p->restore();
1933             }
1934         }
1935     }
1936 
1937     r.adjust(1, 1, -1, -1);
1938 
1939     if (plastikMouseOver && (!sunken  || sunkenToggleMo)) {
1940         bool thin = (oneOf(w, WIDGET_SB_BUTTON, WIDGET_SPIN) ||
1941                      (horiz ? r.height() : r.width()) < 16);
1942         bool horizontal = (SLIDER(w) ? !horiz :
1943                            (horiz && w != WIDGET_SB_BUTTON) ||
1944                            (!horiz && w == WIDGET_SB_BUTTON));
1945         int len = SLIDER(w) ? sbSliderMOLen(opts, horiz ? r.width() :
1946                                             r.height()) : (thin ? 1 : 2);
1947 
1948         p->save();
1949         if (horizontal) {
1950             p->setClipRect(r.x(), r.y() + len, r.width(), r.height() - len * 2);
1951         } else {
1952             p->setClipRect(r.x() + len, r.y(), r.width() - len * 2, r.height());
1953         }
1954     }
1955 
1956     if (!colouredMouseOver && lightBorder) {
1957         setPainterPen(p, cols[LIGHT_BORDER(app)], QPENWIDTH1);
1958         p->drawPath(buildPath(r, w, round,
1959                               qtcGetRadius(&opts, r.width(),
1960                                            r.height(), w, RADIUS_INTERNAL)));
1961     } else if (colouredMouseOver || (draw3d && option->state & State_Raised)) {
1962         QPainterPath innerTlPath;
1963         QPainterPath innerBrPath;
1964         int dark(/*bevelledButton ? */2/* : 4*/);
1965 
1966         buildSplitPath(r, round, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_INTERNAL),
1967                        innerTlPath, innerBrPath);
1968 
1969         setPainterPen(p, border[colouredMouseOver ? MO_STD_LIGHT(w, sunken) : (sunken ? dark : 0)], QPENWIDTH1);
1970         p->drawPath(innerTlPath);
1971         if(colouredMouseOver || bevelledButton || draw3dfull)
1972         {
1973             setPainterPen(p, border[colouredMouseOver ? MO_STD_DARK(w) : (sunken ? 0 : dark)], QPENWIDTH1);
1974             p->drawPath(innerBrPath);
1975         }
1976     }
1977     if(plastikMouseOver && (!sunken  || sunkenToggleMo))
1978         p->restore();
1979     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
1980 
1981     if(doEtch || glowFocus)
1982     {
1983         if( !(opts.thin&THIN_FRAMES) && (!sunken || sunkenToggleMo ||
1984                                          (sunken && glowFocus && widget && qobject_cast<const QAbstractButton *>(widget) &&
1985                                           static_cast<const QAbstractButton *>(widget)->isCheckable())) &&
1986             ((WIDGET_OTHER!=w && WIDGET_SLIDER_TROUGH!=w && MO_GLOW==opts.coloredMouseOver && option->state&State_MouseOver) ||
1987              (WIDGET_DEF_BUTTON==w && IND_GLOW==opts.defBtnIndicator) ||
1988              glowFocus) )
1989             drawGlow(p, rOrig, WIDGET_DEF_BUTTON==w && option->state&State_MouseOver ? WIDGET_STD_BUTTON : w,
1990                      glowFocus ? m_focusCols : 0L);
1991         else
1992             drawEtch(p, rOrig, widget, w, EFFECT_SHADOW==opts.buttonEffect && WIDGET_BUTTON(w) && !sunken);
1993     }
1994 
1995     if(doBorder)
1996     {
1997         const QColor *borderCols=glowFocus || ( (WIDGET_COMBO==w || WIDGET_MENU_BUTTON==w || (WIDGET_NO_ETCH_BTN==w && ROUNDED_ALL!=round)) &&
1998                                                 USE_GLOW_FOCUS(option->state&State_MouseOver) &&
1999                                                 option->state&State_HasFocus && option->state&State_Enabled)
2000             ? m_focusCols
2001             : (WIDGET_COMBO==w || WIDGET_COMBO_BUTTON==w) && border==m_comboBtnCols
2002             ? option->state&State_MouseOver && MO_GLOW==opts.coloredMouseOver && !sunken
2003             ? m_mouseOverCols
2004             : m_buttonCols
2005             : cols;
2006 
2007         r.adjust(-1, -1, 1, 1);
2008         if(!sunken && option->state&State_Enabled && !glowFocus &&
2009            ( ( ( (doEtch && WIDGET_OTHER!=w && WIDGET_SLIDER_TROUGH!=w) || SLIDER(w) || WIDGET_COMBO==w || WIDGET_MENU_BUTTON==w ) &&
2010                (MO_GLOW==opts.coloredMouseOver/* || MO_COLORED==opts.colorMenubarMouseOver*/) && option->state&State_MouseOver) ||
2011              glowFocus || (doEtch && WIDGET_DEF_BUTTON==w && IND_GLOW==opts.defBtnIndicator)))
2012             drawBorder(p, r, option, round,
2013                        WIDGET_DEF_BUTTON==w && IND_GLOW==opts.defBtnIndicator && !(option->state&State_MouseOver)
2014                        ? m_defBtnCols : m_mouseOverCols, w);
2015         else
2016             drawBorder(p, r, option, round,
2017                        colouredMouseOver && MO_COLORED_THICK==opts.coloredMouseOver ? m_mouseOverCols : borderCols, w);
2018     }
2019 
2020     p->restore();
2021 }
2022 
drawGlow(QPainter * p,const QRect & r,EWidget w,const QColor * cols) const2023 void Style::drawGlow(QPainter *p, const QRect &r, EWidget w, const QColor *cols) const
2024 {
2025     bool   def(WIDGET_DEF_BUTTON==w && IND_GLOW==opts.defBtnIndicator),
2026         defShade=def && (!m_defBtnCols ||
2027                          (m_defBtnCols[ORIGINAL_SHADE]==m_mouseOverCols[ORIGINAL_SHADE]));
2028     QColor col(cols ? cols[GLOW_MO]
2029                : def && m_defBtnCols
2030                ? m_defBtnCols[GLOW_DEFBTN] : m_mouseOverCols[GLOW_MO]);
2031 
2032     col.setAlphaF(GLOW_ALPHA(defShade));
2033     p->setBrush(Qt::NoBrush);
2034     p->setRenderHint(QPainter::Antialiasing, true);
2035     setPainterPen(p, col, QPENWIDTH1);
2036     p->drawPath(buildPath(r, w, ROUNDED_ALL, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_ETCH)));
2037     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
2038 }
2039 
drawEtch(QPainter * p,const QRect & r,const QWidget * widget,EWidget w,bool raised,int round) const2040 void Style::drawEtch(QPainter *p, const QRect &r, const QWidget *widget,  EWidget w, bool raised, int round) const
2041 {
2042     QPainterPath tl,
2043         br;
2044     QColor       col(Qt::black);
2045 
2046     if(WIDGET_TOOLBAR_BUTTON==w && EFFECT_ETCH==opts.tbarBtnEffect)
2047         raised=false;
2048 
2049     buildSplitPath(r, round, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_ETCH), tl, br);
2050 
2051     col.setAlphaF(USE_CUSTOM_ALPHAS(opts) ? opts.customAlphas[ALPHA_ETCH_DARK] : ETCH_TOP_ALPHA);
2052     p->setBrush(Qt::NoBrush);
2053     p->setRenderHint(QPainter::Antialiasing, true);
2054     setPainterPen(p, col, QPENWIDTH1);
2055 
2056     if(!raised && WIDGET_SLIDER!=w)
2057     {
2058         p->drawPath(tl);
2059         if(WIDGET_SLIDER_TROUGH==w && opts.thinSbarGroove && widget && qobject_cast<const QScrollBar *>(widget))
2060         {
2061             QColor col(Qt::white);
2062             col.setAlphaF(USE_CUSTOM_ALPHAS(opts) ? opts.customAlphas[ALPHA_ETCH_LIGHT] : ETCH_BOTTOM_ALPHA); // 0.25);
2063             setPainterPen(p, col, QPENWIDTH1);
2064         }
2065         else
2066             setPainterPen(p, getLowerEtchCol(widget), QPENWIDTH1);
2067     }
2068 
2069     p->drawPath(br);
2070     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
2071 }
2072 
drawBgndRing(QPainter & painter,int x,int y,int size,int size2,bool isWindow) const2073 void Style::drawBgndRing(QPainter &painter, int x, int y, int size, int size2, bool isWindow) const
2074 {
2075     double width=(size-size2)/2.0,
2076         width2=width/2.0;
2077     QColor col(Qt::white);
2078 
2079     col.setAlphaF(RINGS_INNER_ALPHA(isWindow ? opts.bgndImage.type : opts.menuBgndImage.type));
2080     if (width == 1) {
2081         width = QPENWIDTH1;
2082     }
2083     painter.setPen(QPen(col, width));
2084     painter.drawEllipse(QRectF(x+width2, y+width2, size-width, size-width));
2085 
2086     if(IMG_BORDERED_RINGS==(isWindow ? opts.bgndImage.type : opts.menuBgndImage.type))
2087     {
2088         col.setAlphaF(RINGS_OUTER_ALPHA);
2089         painter.setPen(QPen(col, QPENWIDTH1));
2090         painter.drawEllipse(QRectF(x, y, size, size));
2091         if(size2)
2092             painter.drawEllipse(QRectF(x+width, y+width, size2, size2));
2093     }
2094 }
2095 
drawStripes(const QColor & color,int opacity) const2096 QPixmap Style::drawStripes(const QColor &color, int opacity) const
2097 {
2098     QPixmap pix;
2099     QString key;
2100     QColor  col(color);
2101 
2102     if(100!=opacity)
2103         col.setAlphaF(opacity/100.0);
2104 
2105     key.sprintf("qtc-stripes-%x", col.rgba());
2106     if(!m_usePixmapCache || !QPixmapCache::find(key, pix))
2107     {
2108         pix=QPixmap(QSize(64, 64));
2109 
2110         if(100!=opacity)
2111             pix.fill(Qt::transparent);
2112 
2113         QPainter pixPainter(&pix);
2114         QColor   col2(shade(col, BGND_STRIPE_SHADE));
2115 
2116         if(100!=opacity)
2117         {
2118             col2.setAlphaF(opacity/100.0);
2119             pixPainter.setPen(QPen(col, QPENWIDTH1));
2120             for(int i=0; i<pix.height(); i+=4)
2121                 pixPainter.drawLine(0, i, pix.width()-1, i);
2122         }
2123         else
2124             pixPainter.fillRect(pix.rect(), col);
2125         pixPainter.setPen(QPen(QColor((3*col.red()+col2.red())/4,
2126                                  (3*col.green()+col2.green())/4,
2127                                  (3*col.blue()+col2.blue())/4,
2128                                  100!=opacity ? col2.alpha() : 255), QPENWIDTH1));
2129 
2130         for(int i=1; i<pix.height(); i+=4)
2131         {
2132             pixPainter.drawLine(0, i, pix.width()-1, i);
2133             pixPainter.drawLine(0, i+2, pix.width()-1, i+2);
2134         }
2135         pixPainter.setPen(QPen(col2, QPENWIDTH1));
2136         for(int i=2; i<pix.height()-1; i+=4)
2137             pixPainter.drawLine(0, i, pix.width()-1, i);
2138 
2139         if(m_usePixmapCache)
2140             QPixmapCache::insert(key, pix);
2141     }
2142 
2143     return pix;
2144 }
2145 
2146 void
drawBackground(QPainter * p,const QColor & bgnd,const QRect & r,int opacity,BackgroundType type,EAppearance app,const QPainterPath & path) const2147 Style::drawBackground(QPainter *p, const QColor &bgnd, const QRect &r,
2148                       int opacity, BackgroundType type, EAppearance app,
2149                       const QPainterPath &path) const
2150 {
2151     bool isWindow = type != BGND_MENU;
2152 
2153     if (!qtcIsFlatBgnd(app)) {
2154         static const int constPixmapWidth  = 16;
2155         static const int constPixmapHeight = 512;
2156 
2157         QColor col(bgnd);
2158         QPixmap pix;
2159         QSize scaledSize;
2160         EGradType grad = isWindow ? opts.bgndGrad : opts.menuBgndGrad;
2161 
2162         if (app == APPEARANCE_STRIPED) {
2163             pix = drawStripes(col, opacity);
2164         } else if (app == APPEARANCE_FILE) {
2165             pix = isWindow ? opts.bgndPixmap.img : opts.menuBgndPixmap.img;
2166         } else {
2167             QString key;
2168             scaledSize = QSize(grad == GT_HORIZ ? constPixmapWidth : r.width(),
2169                                grad == GT_HORIZ ? r.height() :
2170                                constPixmapWidth);
2171 
2172             if (opacity != 100)
2173                 col.setAlphaF(opacity / 100.0);
2174 
2175             key.sprintf("qtc-bgnd-%x-%d-%d", col.rgba(), grad, app);
2176             if (!m_usePixmapCache || !QPixmapCache::find(key, pix)) {
2177                 pix = QPixmap(QSize(grad == GT_HORIZ ? constPixmapWidth :
2178                                     constPixmapHeight, grad == GT_HORIZ ?
2179                                     constPixmapHeight : constPixmapWidth));
2180                 pix.fill(Qt::transparent);
2181 
2182                 QPainter pixPainter(&pix);
2183                 drawBevelGradientReal(col, &pixPainter,
2184                                       QRect(0, 0, pix.width(), pix.height()),
2185                                       grad == GT_HORIZ, false, app,
2186                                       WIDGET_OTHER);
2187                 pixPainter.end();
2188                 if (m_usePixmapCache) {
2189                     QPixmapCache::insert(key, pix);
2190                 }
2191             }
2192         }
2193 
2194         if (path.isEmpty()) {
2195             p->drawTiledPixmap(r, oneOf(app, APPEARANCE_STRIPED,
2196                                         APPEARANCE_FILE) ||
2197                                scaledSize == pix.size() ? pix :
2198                                pix.scaled(scaledSize, Qt::IgnoreAspectRatio));
2199         } else {
2200             p->save();
2201             p->setBrushOrigin(r.x(), r.y());
2202             p->fillPath(path,
2203                         QBrush(oneOf(app, APPEARANCE_STRIPED,
2204                                      APPEARANCE_FILE) ||
2205                                scaledSize == pix.size() ? pix :
2206                                pix.scaled(scaledSize, Qt::IgnoreAspectRatio)));
2207             p->restore();
2208         }
2209 
2210         if (isWindow && noneOf(app, APPEARANCE_STRIPED, APPEARANCE_FILE) &&
2211             grad == GT_HORIZ &&
2212             qtcGetGradient(app, &opts)->border == GB_SHINE) {
2213             int size = qMin(BGND_SHINE_SIZE, qMin(r.height() * 2, r.width()));
2214             QString key;
2215             key.sprintf("qtc-radial-%x", size / BGND_SHINE_STEPS);
2216             if (!m_usePixmapCache || !QPixmapCache::find(key, pix)) {
2217                 size /= BGND_SHINE_STEPS;
2218                 size *= BGND_SHINE_STEPS;
2219                 pix = QPixmap(size, size / 2);
2220                 pix.fill(Qt::transparent);
2221                 QRadialGradient gradient(QPointF(pix.width() / 2.0, 0),
2222                                          pix.width() / 2.0,
2223                                          QPointF(pix.width() / 2.0, 0));
2224                 QColor c(Qt::white);
2225                 double alpha = qtcShineAlpha(&col);
2226 
2227                 c.setAlphaF(alpha);
2228                 gradient.setColorAt(0, c);
2229                 c.setAlphaF(alpha * 0.625);
2230                 gradient.setColorAt(0.5, c);
2231                 c.setAlphaF(alpha * 0.175);
2232                 gradient.setColorAt(0.75, c);
2233                 c.setAlphaF(0);
2234                 gradient.setColorAt(1, c);
2235                 QPainter pixPainter(&pix);
2236                 pixPainter.fillRect(QRect(0, 0, pix.width(), pix.height()),
2237                                     gradient);
2238                 pixPainter.end();
2239                 if (m_usePixmapCache) {
2240                     QPixmapCache::insert(key, pix);
2241                 }
2242             }
2243             p->drawPixmap(r.x() + ((r.width() - pix.width()) / 2), r.y(), pix);
2244         }
2245     } else {
2246         QColor col(bgnd);
2247         if (opacity != 100) {
2248             col.setAlphaF(opacity / 100.0);
2249         }
2250         if (path.isEmpty()) {
2251             p->fillRect(r, col);
2252         } else {
2253             p->save();
2254             p->setBrushOrigin(r.x(), r.y());
2255             p->fillPath(path, col);
2256             p->restore();
2257         }
2258     }
2259 }
2260 
2261 void
drawBackgroundImage(QPainter * p,bool isWindow,const QRect & r) const2262 Style::drawBackgroundImage(QPainter *p, bool isWindow, const QRect &r) const
2263 {
2264     QtCImage &img = isWindow ? opts.bgndImage : opts.menuBgndImage;
2265     int imgWidth = img.type == IMG_FILE ? img.width : RINGS_WIDTH(img.type);
2266     int imgHeight = img.type == IMG_FILE ? img.height : RINGS_HEIGHT(img.type);
2267 
2268     switch (img.type) {
2269     case IMG_NONE:
2270         break;
2271     case IMG_FILE:
2272         qtcLoadBgndImage(&img);
2273         if (!img.pixmap.img.isNull()) {
2274             switch (img.pos) {
2275             case PP_TL:
2276                 p->drawPixmap(r.x(), r.y(), img.pixmap.img);
2277                 break;
2278             case PP_TM:
2279                 p->drawPixmap(r.x() + (r.width() - img.pixmap.img.width()) / 2,
2280                               r.y(), img.pixmap.img);
2281                 break;
2282             default:
2283             case PP_TR:
2284                 p->drawPixmap(r.right() - img.pixmap.img.width(), r.y(),
2285                               img.pixmap.img);
2286                 break;
2287             case PP_BL:
2288                 p->drawPixmap(r.x(), r.bottom() - img.pixmap.img.height(),
2289                               img.pixmap.img);
2290                 break;
2291             case PP_BM:
2292                 p->drawPixmap(r.x() + (r.width() - img.pixmap.img.width()) / 2,
2293                               r.bottom() - img.pixmap.img.height(),
2294                               img.pixmap.img);
2295                 break;
2296             case PP_BR:
2297                 p->drawPixmap(r.right() - img.pixmap.img.width(),
2298                               r.bottom() - img.pixmap.img.height(),
2299                               img.pixmap.img);
2300                 break;
2301             case PP_LM:
2302                 p->drawPixmap(r.left(), r.y() + (r.height() -
2303                                                  img.pixmap.img.height()) / 2,
2304                               img.pixmap.img);
2305                 break;
2306             case PP_RM:
2307                 p->drawPixmap(r.right() - img.pixmap.img.width(),
2308                               r.y() + (r.height() -
2309                                        img.pixmap.img.height()) / 2,
2310                               img.pixmap.img);
2311                 break;
2312             case PP_CENTRED:
2313                 p->drawPixmap(r.x() + (r.width() - img.pixmap.img.width()) / 2,
2314                               r.y() + (r.height() -
2315                                        img.pixmap.img.height()) / 2,
2316                               img.pixmap.img);
2317             }
2318         }
2319         break;
2320     case IMG_PLAIN_RINGS:
2321     case IMG_BORDERED_RINGS:
2322         if (img.pixmap.img.isNull()) {
2323             img.pixmap.img = QPixmap(imgWidth, imgHeight);
2324             img.pixmap.img.fill(Qt::transparent);
2325             QPainter pixPainter(&img.pixmap.img);
2326 
2327             pixPainter.setRenderHint(QPainter::Antialiasing);
2328             drawBgndRing(pixPainter, 0, 0, 200, 140, isWindow);
2329 
2330             drawBgndRing(pixPainter, 210, 10, 230, 214, isWindow);
2331             drawBgndRing(pixPainter, 226, 26, 198, 182, isWindow);
2332             drawBgndRing(pixPainter, 300, 100, 50, 0, isWindow);
2333 
2334             drawBgndRing(pixPainter, 100, 96, 160, 144, isWindow);
2335             drawBgndRing(pixPainter, 116, 112, 128, 112, isWindow);
2336 
2337             drawBgndRing(pixPainter, 250, 160, 200, 140, isWindow);
2338             drawBgndRing(pixPainter, 310, 220, 80, 0, isWindow);
2339             pixPainter.end();
2340         }
2341         p->drawPixmap(r.right() - img.pixmap.img.width(),
2342                       r.y() + 1, img.pixmap.img);
2343         break;
2344     case IMG_SQUARE_RINGS:
2345         if (img.pixmap.img.isNull()) {
2346             img.pixmap.img = QPixmap(imgWidth, imgHeight);
2347             img.pixmap.img.fill(Qt::transparent);
2348             QPainter pixPainter(&img.pixmap.img);
2349             QColor col(Qt::white);
2350             double halfWidth = RINGS_SQUARE_LINE_WIDTH / 2.0;
2351 
2352             col.setAlphaF(RINGS_SQUARE_SMALL_ALPHA);
2353             pixPainter.setRenderHint(QPainter::Antialiasing);
2354             pixPainter.setPen(QPen(col, RINGS_SQUARE_LINE_WIDTH, Qt::SolidLine,
2355                                    Qt::SquareCap, Qt::RoundJoin));
2356             pixPainter.drawPath(buildPath(QRectF(halfWidth + 0.5,
2357                                                  halfWidth + 0.5,
2358                                                  RINGS_SQUARE_SMALL_SIZE,
2359                                                  RINGS_SQUARE_SMALL_SIZE),
2360                                           WIDGET_OTHER, ROUNDED_ALL,
2361                                           RINGS_SQUARE_RADIUS));
2362             pixPainter.drawPath(buildPath(QRectF(halfWidth + 0.5 +
2363                                                  (imgWidth -
2364                                                   (RINGS_SQUARE_SMALL_SIZE +
2365                                                    RINGS_SQUARE_LINE_WIDTH)),
2366                                                  halfWidth + 0.5 +
2367                                                  (imgHeight -
2368                                                   (RINGS_SQUARE_SMALL_SIZE +
2369                                                    RINGS_SQUARE_LINE_WIDTH)),
2370                                                  RINGS_SQUARE_SMALL_SIZE,
2371                                                  RINGS_SQUARE_SMALL_SIZE),
2372                                           WIDGET_OTHER, ROUNDED_ALL,
2373                                           RINGS_SQUARE_RADIUS));
2374             col.setAlphaF(RINGS_SQUARE_LARGE_ALPHA);
2375             pixPainter.setPen(QPen(col, RINGS_SQUARE_LINE_WIDTH, Qt::SolidLine,
2376                                    Qt::SquareCap, Qt::RoundJoin));
2377             pixPainter.drawPath(buildPath(QRectF(halfWidth + 0.5 +
2378                                                  (imgWidth -
2379                                                   RINGS_SQUARE_LARGE_SIZE -
2380                                                   RINGS_SQUARE_LINE_WIDTH) / 2.0,
2381                                                  halfWidth + 0.5 +
2382                                                  (imgHeight -
2383                                                   RINGS_SQUARE_LARGE_SIZE -
2384                                                   RINGS_SQUARE_LINE_WIDTH) / 2.0,
2385                                                  RINGS_SQUARE_LARGE_SIZE,
2386                                                  RINGS_SQUARE_LARGE_SIZE),
2387                                           WIDGET_OTHER, ROUNDED_ALL,
2388                                           RINGS_SQUARE_RADIUS));
2389             pixPainter.end();
2390         }
2391         p->drawPixmap(r.right() - img.pixmap.img.width(),
2392                       r.y() + 1, img.pixmap.img);
2393         break;
2394     }
2395 }
2396 
2397 void
drawBackground(QPainter * p,const QWidget * widget,BackgroundType type) const2398 Style::drawBackground(QPainter *p, const QWidget *widget,
2399                       BackgroundType type) const
2400 {
2401     bool isWindow = type != BGND_MENU;
2402     bool previewMdi = (isWindow && m_isPreview &&
2403                        qobject_cast<const QMdiSubWindow*>(widget));
2404     const QWidget *window = m_isPreview ? widget : widget->window();
2405     int opacity = (type == BGND_MENU ? opts.menuBgndOpacity :
2406                    type == BGND_DIALOG ? opts.dlgOpacity : opts.bgndOpacity);
2407     QRect bgndRect = widget->rect();
2408     QRect imgRect = bgndRect;
2409     QtcQWidgetProps props(widget);
2410 
2411     if (opacity != 100 && !(qobject_cast<const QMdiSubWindow*>(widget) ||
2412                             Utils::hasAlphaChannel(window))) {
2413         opacity = 100;
2414     }
2415     if (widget) {
2416         props->opacity = opacity;
2417     }
2418 
2419     p->setClipRegion(widget->rect(), Qt::IntersectClip);
2420 
2421     if (isWindow) {
2422         if (!previewMdi) {
2423             WindowBorders borders = qtcGetWindowBorderSize(false);
2424             bgndRect.adjust(-borders.sides, -borders.titleHeight,
2425                             borders.sides, borders.bottom);
2426         } else {
2427             bgndRect.adjust(0, -pixelMetric(PM_TitleBarHeight,
2428                                             0L, widget), 0, 0);
2429         }
2430         if (opts.bgndImage.type == IMG_FILE && opts.bgndImage.onBorder) {
2431             imgRect = bgndRect;
2432         }
2433     }
2434 
2435     drawBackground(p, (isWindow ? window->palette().window().color() :
2436                        popupMenuCols()[ORIGINAL_SHADE]), bgndRect, opacity,
2437                    type, (type != BGND_MENU ? opts.bgndAppearance :
2438                           opts.menuBgndAppearance));
2439     // FIXME, workaround only, the non transparent part of the image will have
2440     // a different overall opacity.
2441     p->save();
2442     p->setCompositionMode(QPainter::CompositionMode_SourceOver);
2443     drawBackgroundImage(p, isWindow, imgRect);
2444     p->restore();
2445 }
2446 
2447 QPainterPath
buildPath(const QRectF & r,EWidget w,int round,double radius) const2448 Style::buildPath(const QRectF &r, EWidget w, int round, double radius) const
2449 {
2450     QPainterPath path;
2451 
2452     if (oneOf(w, WIDGET_RADIO_BUTTON, WIDGET_DIAL) ||
2453         (w == WIDGET_MDI_WINDOW_BUTTON &&
2454          opts.titlebarButtons & TITLEBAR_BUTTON_ROUND) || CIRCULAR_SLIDER(w)) {
2455         path.addEllipse(r);
2456         return path;
2457     }
2458 
2459     if (opts.round == ROUND_NONE || radius < 0.01) {
2460         round = ROUNDED_NONE;
2461     }
2462 
2463     double diameter = radius * 2;
2464 
2465     if (w != WIDGET_MDI_WINDOW_TITLE && round & CORNER_BR) {
2466         path.moveTo(r.x() + r.width(), r.y() + r.height() - radius);
2467     } else {
2468         path.moveTo(r.x() + r.width(), r.y() + r.height());
2469     }
2470     if (round & CORNER_TR) {
2471         path.arcTo(r.x() + r.width() - diameter, r.y(),
2472                    diameter, diameter, 0, 90);
2473     } else {
2474         path.lineTo(r.x() + r.width(), r.y());
2475     }
2476     if (round & CORNER_TL) {
2477         path.arcTo(r.x(), r.y(), diameter, diameter, 90, 90);
2478     } else {
2479         path.lineTo(r.x(), r.y());
2480     }
2481     if (w != WIDGET_MDI_WINDOW_TITLE && round & CORNER_BL) {
2482         path.arcTo(r.x(), r.y() + r.height() - diameter,
2483                    diameter, diameter, 180, 90);
2484     } else {
2485         path.lineTo(r.x(), r.y() + r.height());
2486     }
2487 
2488     if (w != WIDGET_MDI_WINDOW_TITLE) {
2489         if (round & CORNER_BR) {
2490             path.arcTo(r.x() + r.width() - diameter,
2491                        r.y() + r.height() - diameter,
2492                        diameter, diameter, 270, 90);
2493         } else {
2494             path.lineTo(r.x() + r.width(), r.y() + r.height());
2495         }
2496     }
2497     return path;
2498 }
2499 
2500 QPainterPath
buildPath(const QRect & r,EWidget w,int round,double radius) const2501 Style::buildPath(const QRect &r, EWidget w, int round, double radius) const
2502 {
2503     return buildPath(QRectF(r.x() + 0.5, r.y() + 0.5,
2504                             r.width() - 1, r.height() - 1), w, round, radius);
2505 }
2506 
2507 void
buildSplitPath(const QRect & r,int round,double radius,QPainterPath & tl,QPainterPath & br) const2508 Style::buildSplitPath(const QRect &r, int round, double radius,
2509                       QPainterPath &tl, QPainterPath &br) const
2510 {
2511     double xd = r.x() + 0.5;
2512     double yd = r.y() + 0.5;
2513     double diameter = radius * 2;
2514     bool rounded = diameter > 0.0;
2515     int width = r.width() - 1;
2516     int height = r.height() - 1;
2517 
2518     if (rounded && round & CORNER_TR) {
2519         tl.arcMoveTo(xd + width - diameter, yd, diameter, diameter, 45);
2520         tl.arcTo(xd + width - diameter, yd, diameter, diameter, 45, 45);
2521         if (width > diameter) {
2522             tl.lineTo(xd + width - diameter, yd);
2523         }
2524     } else {
2525         tl.moveTo(xd + width, yd);
2526     }
2527 
2528     if (rounded && round & CORNER_TL) {
2529         tl.arcTo(xd, yd, diameter, diameter, 90, 90);
2530     } else {
2531         tl.lineTo(xd, yd);
2532     }
2533 
2534     if (rounded && round & CORNER_BL) {
2535         tl.arcTo(xd, yd + height - diameter, diameter, diameter, 180, 45);
2536         br.arcMoveTo(xd, yd + height - diameter, diameter, diameter, 180 + 45);
2537         br.arcTo(xd, yd + height - diameter, diameter, diameter, 180 + 45, 45);
2538     } else {
2539         tl.lineTo(xd, yd + height);
2540         br.moveTo(xd, yd + height);
2541     }
2542 
2543     if (rounded && round & CORNER_BR) {
2544         br.arcTo(xd + width - diameter, yd + height - diameter, diameter,
2545                  diameter, 270, 90);
2546     } else {
2547         br.lineTo(xd + width, yd + height);
2548     }
2549 
2550     if (rounded && round & CORNER_TR) {
2551         br.arcTo(xd + width - diameter, yd, diameter, diameter, 0, 45);
2552     } else {
2553         br.lineTo(xd + width, yd);
2554     }
2555 }
2556 
2557 void
drawBorder(QPainter * p,const QRect & r,const QStyleOption * option,int round,const QColor * custom,EWidget w,EBorder borderProfile,bool doBlend,int borderVal) const2558 Style::drawBorder(QPainter *p, const QRect &r, const QStyleOption *option,
2559                   int round, const QColor *custom, EWidget w,
2560                   EBorder borderProfile, bool doBlend, int borderVal) const
2561 {
2562     if(ROUND_NONE==opts.round)
2563         round=ROUNDED_NONE;
2564 
2565     State        state(option->state);
2566     bool         enabled(state&State_Enabled),
2567         entry(WIDGET_ENTRY==w || (WIDGET_SCROLLVIEW==w && opts.highlightScrollViews)),
2568         hasFocus(enabled && entry && state&State_HasFocus),
2569         hasMouseOver(enabled && entry && state & State_MouseOver &&
2570                      opts.unifyCombo && opts.unifySpin);
2571     const QColor *cols(enabled && hasMouseOver && opts.coloredMouseOver && entry
2572                        ? m_mouseOverCols
2573                        : enabled && hasFocus && entry
2574                        ? m_focusCols
2575                        : custom
2576                        ? custom
2577                        : APP_KRUNNER==theThemedApp ? m_backgroundCols : backgroundColors(option));
2578     QColor       border(WIDGET_DEF_BUTTON==w && IND_FONT_COLOR==opts.defBtnIndicator && enabled
2579                         ? option->palette.buttonText().color()
2580                         : cols[WIDGET_PROGRESSBAR==w
2581                                ? PBAR_BORDER
2582                                : !enabled && (WIDGET_BUTTON(w) || WIDGET_SLIDER_TROUGH==w)
2583                                ? QTC_DISABLED_BORDER
2584                                : m_mouseOverCols==cols && IS_SLIDER(w)
2585                                ? SLIDER_MO_BORDER_VAL
2586                                : borderVal]);
2587 
2588     p->setRenderHint(QPainter::Antialiasing, true);
2589     p->setBrush(Qt::NoBrush);
2590 
2591     if(WIDGET_TAB_BOT==w || WIDGET_TAB_TOP==w)
2592         cols=m_backgroundCols;
2593 
2594     if(!(opts.thin&THIN_FRAMES) && (WIDGET_SCROLLVIEW!=w || !(opts.square&SQUARE_SCROLLVIEW) || opts.highlightScrollViews))
2595         switch(borderProfile)
2596         {
2597         case BORDER_FLAT:
2598             break;
2599         case BORDER_RAISED:
2600         case BORDER_SUNKEN:
2601         case BORDER_LIGHT:
2602         {
2603             int          dark=FRAME_DARK_SHADOW;
2604             QColor       tl(cols[BORDER_RAISED==borderProfile || BORDER_LIGHT==borderProfile ? 0 : dark]),
2605                 br(cols[BORDER_RAISED==borderProfile ? dark : 0]);
2606             QPainterPath topPath,
2607                 botPath;
2608 
2609             if( ((hasMouseOver || hasFocus) && WIDGET_ENTRY==w) ||
2610                 (hasFocus && WIDGET_SCROLLVIEW==w))
2611             {
2612                 tl.setAlphaF(ENTRY_INNER_ALPHA);
2613                 br.setAlphaF(ENTRY_INNER_ALPHA);
2614             }
2615             else if(doBlend)
2616             {
2617                 tl.setAlphaF(BORDER_BLEND_ALPHA(w));
2618                 br.setAlphaF(BORDER_SUNKEN==borderProfile ? 0.0 : BORDER_BLEND_ALPHA(w));
2619             }
2620 
2621             QRect inner(r.adjusted(1, 1, -1, -1));
2622 
2623             buildSplitPath(inner, round, qtcGetRadius(&opts, inner.width(), inner.height(), w, RADIUS_INTERNAL), topPath, botPath);
2624 
2625             setPainterPen(p, (enabled || BORDER_SUNKEN==borderProfile) /*&&
2626                                                                   (BORDER_RAISED==borderProfile || BORDER_LIGHT==borderProfile || hasFocus || APPEARANCE_FLAT!=app)*/
2627                       ? tl
2628                       : option->palette.background().color(), QPENWIDTH1);
2629             p->drawPath(topPath);
2630             if(WIDGET_SCROLLVIEW==w || // Because of list view headers, need to draw dark line on right!
2631                (! ( (WIDGET_ENTRY==w && !hasFocus && !hasMouseOver) ||
2632                     (WIDGET_ENTRY!=w && doBlend && BORDER_SUNKEN==borderProfile) ) ) )
2633             {
2634                 if(!hasFocus && !hasMouseOver && BORDER_LIGHT!=borderProfile && WIDGET_SCROLLVIEW!=w)
2635                     setPainterPen(p, /*WIDGET_SCROLLVIEW==w && !hasFocus
2636                                 ? checkColour(option, QPalette::Window)
2637                                 : WIDGET_ENTRY==w && !hasFocus
2638                                 ? checkColour(option, QPalette::Base)
2639                                 : */enabled && (BORDER_SUNKEN==borderProfile || hasFocus || /*APPEARANCE_FLAT!=app ||*/
2640                                                 WIDGET_TAB_TOP==w || WIDGET_TAB_BOT==w)
2641                                 ? br
2642                                 : checkColour(option, QPalette::Window), QPENWIDTH1);
2643                 p->drawPath(botPath);
2644             }
2645         }
2646         }
2647 
2648     if(BORDER_SUNKEN==borderProfile &&
2649        (WIDGET_FRAME==w || ((WIDGET_ENTRY==w || WIDGET_SCROLLVIEW==w) && !opts.etchEntry && !hasFocus && !hasMouseOver)))
2650     {
2651         QPainterPath topPath,
2652             botPath;
2653         QColor       col(border);
2654 
2655         col.setAlphaF(LOWER_BORDER_ALPHA);
2656         buildSplitPath(r, round, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_EXTERNAL), topPath, botPath);
2657         p->setPen(QPen(/*enabled ? */border/* : col*/, QPENWIDTH1));
2658         p->drawPath(topPath);
2659 //         if(enabled)
2660         p->setPen(col);
2661         p->drawPath(botPath);
2662     }
2663     else
2664     {
2665         p->setPen(QPen(border, QPENWIDTH1));
2666         p->drawPath(buildPath(r, w, round, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_EXTERNAL)));
2667     }
2668 
2669     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
2670 }
2671 
drawMdiControl(QPainter * p,const QStyleOptionTitleBar * titleBar,SubControl sc,const QWidget * widget,ETitleBarButtons btn,const QColor & iconColor,const QColor * btnCols,const QColor * bgndCols,int adjust,bool activeWindow) const2672 void Style::drawMdiControl(QPainter *p, const QStyleOptionTitleBar *titleBar, SubControl sc, const QWidget *widget,
2673                            ETitleBarButtons btn, const QColor &iconColor, const QColor *btnCols, const QColor *bgndCols,
2674                            int adjust, bool activeWindow) const
2675 {
2676     bool hover((titleBar->activeSubControls&sc) && (titleBar->state&State_MouseOver));
2677 
2678     if(!activeWindow && !hover && opts.titlebarButtons&TITLEBAR_BUTTOM_HIDE_ON_INACTIVE_WINDOW)
2679         return;
2680 
2681     QRect rect(subControlRect(CC_TitleBar, titleBar, sc, widget));
2682 
2683     if (rect.isValid())
2684     {
2685         rect.adjust(adjust, adjust, -adjust, -adjust);
2686 
2687         bool sunken((titleBar->activeSubControls&sc) && (titleBar->state&State_Sunken)),
2688             colored(coloredMdiButtons(titleBar->state&State_Active, hover)),
2689             useBtnCols(opts.titlebarButtons&TITLEBAR_BUTTON_STD_COLOR &&
2690                        (hover ||
2691                         !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_MOUSE_OVER) ||
2692                         opts.titlebarButtons&TITLEBAR_BUTTON_COLOR));
2693         const QColor *buttonColors=colored && !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_SYMBOL)
2694             ? m_titleBarButtonsCols[btn] : (useBtnCols ? btnCols : bgndCols);
2695         const QColor &icnColor=opts.titlebarButtons&TITLEBAR_BUTTON_ICON_COLOR
2696             ? opts.titlebarButtonColors[btn+(NUM_TITLEBAR_BUTTONS*(titleBar->state&State_Active ? 1 : 2))]
2697             : colored && opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_SYMBOL
2698             ? m_titleBarButtonsCols[btn][ORIGINAL_SHADE]
2699             : SC_TitleBarCloseButton==sc && hover && !sunken && !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR)
2700             ? CLOSE_COLOR
2701             : SC_TitleBarCloseButton!=sc && hover && !sunken &&
2702             !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR) &&
2703             opts.titlebarButtons&TITLEBAR_BUTTON_USE_HOVER_COLOR
2704             ? m_mouseOverCols[ORIGINAL_SHADE]
2705             : iconColor;
2706 
2707         bool drewFrame=drawMdiButton(p, rect, hover, sunken, buttonColors);
2708         drawMdiIcon(p, icnColor, (drewFrame ? buttonColors : bgndCols)[ORIGINAL_SHADE],
2709                     rect, hover, sunken, subControlToIcon(sc), true, drewFrame);
2710     }
2711 }
2712 
drawDwtControl(QPainter * p,const State & state,const QRect & rect,ETitleBarButtons btn,Icon icon,const QColor & iconColor,const QColor * btnCols,const QColor * bgndCols) const2713 void Style::drawDwtControl(QPainter *p, const State &state, const QRect &rect, ETitleBarButtons btn, Icon icon,
2714                            const QColor &iconColor, const QColor *btnCols, const QColor *bgndCols) const
2715 {
2716     bool    sunken(state&State_Sunken),
2717         hover(state&State_MouseOver),
2718         colored(coloredMdiButtons(state&State_Active, hover)),
2719         useBtnCols(opts.titlebarButtons&TITLEBAR_BUTTON_STD_COLOR &&
2720                    (hover ||
2721                     !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_MOUSE_OVER) ||
2722                     opts.titlebarButtons&TITLEBAR_BUTTON_COLOR));
2723     const QColor *buttonColors=colored && !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_SYMBOL)
2724         ? m_titleBarButtonsCols[btn] : (useBtnCols ? btnCols : bgndCols);
2725     const QColor &icnColor=opts.dwtSettings&DWT_ICON_COLOR_AS_PER_TITLEBAR && opts.titlebarButtons&TITLEBAR_BUTTON_ICON_COLOR
2726         ? opts.titlebarButtonColors[btn+(NUM_TITLEBAR_BUTTONS/**(titleBar->state&State_Active ? 1 : 2)*/)]
2727         : colored && opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_SYMBOL
2728         ? m_titleBarButtonsCols[btn][ORIGINAL_SHADE]
2729         : (TITLEBAR_CLOSE==btn && !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR) && (hover || sunken)
2730            ? CLOSE_COLOR
2731            : iconColor);
2732 
2733     bool drewFrame=drawMdiButton(p, rect, hover, sunken, buttonColors);
2734     drawMdiIcon(p, icnColor, (drewFrame ? buttonColors : bgndCols)[ORIGINAL_SHADE], rect, hover, sunken, icon, false, drewFrame);
2735 }
2736 
drawMdiButton(QPainter * painter,const QRect & r,bool hover,bool sunken,const QColor * cols) const2737 bool Style::drawMdiButton(QPainter *painter, const QRect &r, bool hover, bool sunken, const QColor *cols) const
2738 {
2739     if(!(opts.titlebarButtons&TITLEBAR_BUTTON_NO_FRAME) &&
2740        (hover || sunken || !(opts.titlebarButtons&TITLEBAR_BUTTON_HOVER_FRAME)))
2741     {
2742         QStyleOption opt;
2743 
2744         opt.rect=r; // .adjusted(1, 1, -1, -1);
2745         if(opts.titlebarButtons&TITLEBAR_BUTTON_ROUND)
2746             opt.rect.adjust(1, 1, -1, -1);
2747         opt.state=State_Enabled|State_Horizontal|State_Raised;
2748         if(hover)
2749             opt.state|=State_MouseOver;
2750         if(sunken)
2751             opt.state|=State_Sunken;
2752 
2753         drawLightBevel(painter, opt.rect, &opt, 0L, ROUNDED_ALL, getFill(&opt, cols), cols, true, WIDGET_MDI_WINDOW_BUTTON);
2754         return true;
2755     }
2756 
2757     return false;
2758 }
2759 
drawMdiIcon(QPainter * painter,const QColor & color,const QColor & bgnd,const QRect & r,bool hover,bool sunken,Icon icon,bool stdSize,bool drewFrame) const2760 void Style::drawMdiIcon(QPainter *painter, const QColor &color, const QColor &bgnd,  const QRect &r, bool hover, bool sunken, Icon icon,
2761                         bool stdSize, bool drewFrame) const
2762 {
2763     if(!(opts.titlebarButtons&TITLEBAR_BUTTON_HOVER_SYMBOL_FULL) || hover || sunken)
2764     {
2765         bool faded=!sunken && !hover && opts.titlebarButtons&TITLEBAR_BUTTON_HOVER_SYMBOL;
2766 
2767         if(!sunken && !faded && EFFECT_NONE!=opts.titlebarEffect)
2768             //         // && hover && !(opts.titlebarButtons&TITLEBAR_BUTTON_HOVER_SYMBOL) && !customCol)
2769         {
2770             EEffect effect=opts.titlebarEffect;
2771 
2772             if(EFFECT_ETCH==opts.titlebarEffect && drewFrame)
2773                 effect=EFFECT_SHADOW;
2774 
2775             drawIcon(painter, blendColors(WINDOW_SHADOW_COLOR(effect), bgnd, WINDOW_TEXT_SHADOW_ALPHA(effect)),
2776                      EFFECT_SHADOW==effect
2777                      ? r.adjusted(1, 1, 1, 1)
2778                      : r.adjusted(0, 1, 0, 1),
2779                      sunken, icon, stdSize);
2780         }
2781 
2782         QColor col(color);
2783 
2784         if(faded)
2785             col=blendColors(col, bgnd, HOVER_BUTTON_ALPHA(col));
2786 
2787         drawIcon(painter, col, r, sunken, icon, stdSize);
2788     }
2789 }
2790 
drawIcon(QPainter * painter,const QColor & color,const QRect & r,bool sunken,Icon icon,bool stdSize) const2791 void Style::drawIcon(QPainter *painter, const QColor &color, const QRect &r, bool sunken, Icon icon, bool stdSize) const
2792 {
2793     static const int constIconSize=9;
2794     static const int constSmallIconSize=7;
2795 
2796     painter->setPen(color);
2797 
2798     QSize    iconSize(stdSize
2799                       ? constIconSize
2800                       : constSmallIconSize,
2801                       stdSize
2802                       ? constIconSize
2803                       : (ICN_RESTORE==icon && !(opts.titlebarButtons&TITLEBAR_BUTTOM_ARROW_MIN_MAX)
2804                          ? constSmallIconSize+1
2805                          : constSmallIconSize));
2806     QRect    br(r.x()+((r.width()-iconSize.width())>>1),
2807                 r.y()+((r.height()-iconSize.height())>>1),
2808                 iconSize.width(), iconSize.height());
2809     if(sunken)
2810         br.adjust(1, 1, 1, 1);
2811 
2812     switch(icon)
2813     {
2814     case ICN_MIN:
2815         if(opts.titlebarButtons&TITLEBAR_BUTTOM_ARROW_MIN_MAX)
2816             drawArrow(painter, opts.vArrows ? br.adjusted(0, 1, 0, 1) : br, PE_IndicatorArrowDown, color, false);
2817         else
2818             drawRect(painter, QRect(br.left(), br.bottom()-1, br.width(), 2));
2819         break;
2820     case ICN_MAX:
2821         if(opts.titlebarButtons&TITLEBAR_BUTTOM_ARROW_MIN_MAX)
2822             drawArrow(painter, opts.vArrows ? br.adjusted(0, -1, 0, -1) : br, PE_IndicatorArrowUp, color, false);
2823         else
2824         {
2825             drawRect(painter, br);
2826             painter->drawLine(br.left() + 1, br.top() + 1,  br.right() - 1, br.top() + 1);
2827         }
2828         break;
2829     case ICN_CLOSE:
2830         if(stdSize && opts.titlebarButtons&TITLEBAR_BUTTON_SUNKEN_BACKGROUND)
2831             br.adjust(1, 1, -1, -1);
2832         painter->save();
2833         painter->setClipRect(br);
2834         painter->setPen(QPen(color, 2));
2835         painter->drawLine(br.left(), br.top(), br.right(), br.bottom());
2836         painter->drawLine(br.right(), br.top(), br.left(), br.bottom());
2837         painter->restore();
2838         break;
2839     case ICN_RESTORE:
2840         if(opts.titlebarButtons&TITLEBAR_BUTTOM_ARROW_MIN_MAX)
2841         {
2842             painter->drawLine(br.x()+1, br.y(), br.x()+br.width()-2, br.y());
2843             painter->drawLine(br.x()+1, br.y()+br.height()-1, br.x()+br.width()-2, br.y()+br.height()-1);
2844             painter->drawLine(br.x(), br.y()+1, br.x(), br.y()+br.height()-2);
2845             painter->drawLine(br.x()+br.width()-1, br.y()+1, br.x()+br.width()-1, br.y()+br.height()-2);
2846             drawRect(painter, br.adjusted(1, 1, -1, -1));
2847         }
2848         else
2849         {
2850             drawRect(painter, QRect(br.x(), br.y()+3, br.width()-2, br.height()-3));
2851             painter->drawLine(br.x()+1, br.y()+4, br.x()+br.width()-4, br.y()+4);
2852             painter->drawLine(br.x()+2, br.y(), br.x()+br.width()-1, br.y());
2853             painter->drawLine(br.x()+2, br.y()+1, br.x()+br.width()-1, br.y()+1);
2854             painter->drawLine(br.x()+br.width()-1, br.y()+2, br.x()+br.width()-1, br.y()+(stdSize ? 5 : 4));
2855             painter->drawPoint(br.x()+br.width()-2, br.y()+(stdSize ? 5 : 4));
2856             painter->drawPoint(br.x()+2, br.y()+2);
2857         }
2858         break;
2859     case ICN_UP:
2860         drawArrow(painter, br, PE_IndicatorArrowUp, color, false);
2861         break;
2862     case ICN_DOWN:
2863         drawArrow(painter, opts.vArrows ? br.adjusted(0, 1, 0, 1) : br, PE_IndicatorArrowDown, color, false);
2864         break;
2865     case ICN_RIGHT:
2866         drawArrow(painter, br, PE_IndicatorArrowRight, color, false);
2867         break;
2868     case ICN_MENU:
2869         for(int i=1; i<=constIconSize; i+=3)
2870             painter->drawLine(br.left() + 1, br.top() + i,  br.right() - 1, br.top() + i);
2871         break;
2872     case ICN_SHADE:
2873     case ICN_UNSHADE:
2874     {
2875         bool isDwt=opts.dwtSettings&DWT_BUTTONS_AS_PER_TITLEBAR;
2876         br.adjust(0, -2, 0, 0);
2877         drawRect(painter, isDwt ? QRect(br.left(), br.bottom(), br.width(), 2) : QRect(br.left()+1, br.bottom()-1, br.width()-2, 2));
2878         br.adjust(0, ICN_SHADE==icon ? -3 : -5, 0, 0);
2879         drawArrow(painter, opts.vArrows ? br.adjusted(0, 1, 0, 1) : br,
2880                   ICN_SHADE==icon ? PE_IndicatorArrowDown : PE_IndicatorArrowUp, color, false);
2881         break;
2882     }
2883     default:
2884         break;
2885     }
2886 }
2887 
drawEntryField(QPainter * p,const QRect & rx,const QWidget * widget,const QStyleOption * option,int round,bool fill,bool doEtch,EWidget w) const2888 void Style::drawEntryField(QPainter *p, const QRect &rx,  const QWidget *widget, const QStyleOption *option,
2889                            int round, bool fill, bool doEtch, EWidget w) const
2890 {
2891     QRect r(rx);
2892 
2893     if(doEtch && opts.etchEntry)
2894         r.adjust(1, 1, -1, -1);
2895 
2896     p->setRenderHint(QPainter::Antialiasing, true);
2897     if(fill)
2898         p->fillPath(buildPath(QRectF(r).adjusted(1, 1, -1, -1), WIDGET_SCROLLVIEW==w ? w : WIDGET_ENTRY, round,
2899                               qtcGetRadius(&opts, r.width()-2, r.height()-2, WIDGET_SCROLLVIEW==w ? w : WIDGET_ENTRY, RADIUS_INTERNAL)),
2900                     option->palette.brush(QPalette::Base));
2901     else
2902     {
2903         p->setPen(WIDGET_SCROLLVIEW!=w || !(opts.square&SQUARE_SCROLLVIEW) || opts.highlightScrollViews ? checkColour(option, QPalette::Base)
2904                   : backgroundColors(option)[ORIGINAL_SHADE]);
2905         p->drawPath(buildPath(r.adjusted(1, 1, -1, -1), WIDGET_SCROLLVIEW==w ? w : WIDGET_ENTRY, round,
2906                               qtcGetRadius(&opts, r.width()-2, r.height()-2, WIDGET_SCROLLVIEW==w ? w : WIDGET_ENTRY, RADIUS_INTERNAL)));
2907     }
2908     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
2909 
2910     if(doEtch && opts.etchEntry)
2911         drawEtch(p, rx, widget, WIDGET_SCROLLVIEW==w ? w : WIDGET_ENTRY, false);
2912 
2913     drawBorder(p, r, option, round, 0L, w, BORDER_SUNKEN);
2914 }
2915 
drawMenuItem(QPainter * p,const QRect & r,const QStyleOption * option,MenuItemType type,int round,const QColor * cols) const2916 void Style::drawMenuItem(QPainter *p, const QRect &r, const QStyleOption *option, MenuItemType type, int round, const QColor *cols) const
2917 {
2918     QColor altCols[TOTAL_SHADES+1];
2919     if (theThemedApp == APP_KWIN) {
2920         QWidget *w = qobject_cast<QWidget*>(option->styleObject);
2921         QPalette::ColorRole role = (opts.useHighlightForMenu || (option->state & (State_On|State_Sunken))) ?
2922             QPalette::HighlightedText : QPalette::WindowText;
2923         if (w && w->palette().color(QPalette::Active, role)
2924                 != QApplication::palette().color(QPalette::Active, role)) {
2925 //             qWarning() << "drawMenuItem: widget" << w << "bgCol" << w->palette().color(QPalette::Active, role)
2926 //                 << "differs from app bgCol" << QApplication::palette().color(QPalette::Active, role);
2927             shadeColors(w->palette().color(QPalette::Active, role), altCols);
2928             cols = altCols;
2929         }
2930     }
2931 
2932     int fill=opts.useHighlightForMenu && ((MENU_BAR!=type) || m_highlightCols==cols || APP_OPENOFFICE==theThemedApp) ? ORIGINAL_SHADE : 4,
2933         border=opts.borderMenuitems ? 0 : fill;
2934 
2935     if(m_highlightCols!=cols && MENU_BAR==type && !(option->state&(State_On|State_Sunken)) &&
2936        !opts.colorMenubarMouseOver && (opts.borderMenuitems || !qtcIsFlat(opts.menuitemAppearance)))
2937         fill=ORIGINAL_SHADE;
2938 
2939     if(MENU_BAR!=type && APPEARANCE_FADE==opts.menuitemAppearance)
2940     {
2941         bool reverse = Qt::RightToLeft==option->direction;
2942         QColor trans(Qt::white);
2943         QRect r2(opts.round != ROUND_NONE ? r.adjusted(1, 1, -1, -1) : r);
2944         QRectF rf(r2);
2945         double fadePercent = ((double)MENUITEM_FADE_SIZE)/rf.width();
2946         QLinearGradient grad(r2.topLeft(), r2.topRight());
2947 
2948         trans.setAlphaF(0.0);
2949         grad.setColorAt(0, reverse ? trans : cols[fill]);
2950         grad.setColorAt(reverse ? fadePercent : 1.0-fadePercent, cols[fill]);
2951         grad.setColorAt(1, reverse ? cols[fill] : trans);
2952         if (opts.round != ROUND_NONE) {
2953             p->save();
2954             p->setRenderHint(QPainter::Antialiasing, true);
2955             p->fillPath(buildPath(rf, WIDGET_OTHER,
2956                                   reverse ? ROUNDED_RIGHT : ROUNDED_LEFT, 4),
2957                         QBrush(grad));
2958             p->restore();
2959         } else {
2960             p->fillRect(r2, QBrush(grad));
2961         }
2962     } else if (MENU_BAR==type || opts.borderMenuitems) {
2963         bool stdColor(MENU_BAR!=type || (SHADE_BLEND_SELECTED!=opts.shadeMenubars && SHADE_SELECTED!=opts.shadeMenubars));
2964 
2965         QStyleOption opt(*option);
2966 
2967         opt.state|=State_Horizontal|State_Raised;
2968         opt.state&=~(State_Sunken|State_On);
2969 
2970         if(stdColor && opts.borderMenuitems)
2971             drawLightBevel(p, r, &opt, 0L, round, cols[fill], cols, stdColor, WIDGET_MENU_ITEM);
2972         else
2973         {
2974             QRect fr(r);
2975 
2976             fr.adjust(1, 1, -1, -1);
2977 
2978             if(fr.width()>0 && fr.height()>0)
2979                 drawBevelGradient(cols[fill], p, fr, true, false, opts.menuitemAppearance, WIDGET_MENU_ITEM);
2980             drawBorder(p, r, &opt, round, cols, WIDGET_MENU_ITEM, BORDER_FLAT, false, border);
2981         }
2982     }
2983     else
2984     {
2985         // For now dont round combos - getting weird effects with shadow/clipping in Gtk2 style :-(
2986         if (/*MENU_COMBO==type || */opts.square & SQUARE_POPUP_MENUS) {
2987             drawBevelGradient(cols[fill], p, r, true, false,
2988                               opts.menuitemAppearance, WIDGET_MENU_ITEM);
2989         } else {
2990             p->save();
2991             p->setRenderHint(QPainter::Antialiasing, true);
2992             drawBevelGradient(
2993                 cols[fill], p, r,
2994                 buildPath(QRectF(r), WIDGET_OTHER, ROUNDED_ALL,
2995                           (opts.round >= ROUND_FULL ? 5.0 : 2.5) -
2996                           (opts.round > ROUND_SLIGHT ? 1.0 : 0.5)), true, false,
2997                 opts.menuitemAppearance, WIDGET_MENU_ITEM, false);
2998             p->restore();
2999         }
3000     }
3001 }
3002 
drawProgress(QPainter * p,const QRect & r,const QStyleOption * option,bool vertical,bool reverse) const3003 void Style::drawProgress(QPainter *p, const QRect &r, const QStyleOption *option, bool vertical, bool reverse) const
3004 {
3005     QStyleOption opt(*option);
3006     QRect        rx(r);
3007 
3008     opt.state|=State_Raised;
3009 
3010     if(vertical)
3011         opt.state&=~State_Horizontal;
3012     else
3013         opt.state|=State_Horizontal;
3014 
3015     if(reverse)
3016         opt.state|=STATE_REVERSE;
3017     else
3018         opt.state&=~STATE_REVERSE;
3019 
3020     if((vertical ? r.height() : r.width())<1)
3021         return;
3022 
3023     if(vertical && r.height()<3)
3024         rx.setHeight(3);
3025 
3026     if(!vertical && rx.width()<3)
3027         rx.setWidth(3);
3028 
3029     // KTorrent's progressbars seem to have state==State_None
3030     const QColor *use=option->state&State_Enabled || State_None==option->state || ECOLOR_BACKGROUND==opts.progressGrooveColor
3031         ? m_progressCols
3032         ? m_progressCols
3033         : highlightColors(option, true)
3034         : m_backgroundCols;
3035 
3036     drawLightBevel(p, rx, &opt, 0L, ROUNDED_ALL, use[ORIGINAL_SHADE], use, opts.borderProgress, WIDGET_PROGRESSBAR);
3037 
3038     if(opts.glowProgress && (vertical ? rx.height() : rx.width())>3)
3039     {
3040         QRect           ri(opts.borderProgress ? rx.adjusted(1, 1, -1, -1) : rx);
3041         QLinearGradient grad(0, 0, vertical ? 0 : 1, vertical ? 1 : 0);
3042         QColor          glow(Qt::white),
3043             blank(Qt::white);
3044 
3045         blank.setAlphaF(0);
3046         glow.setAlphaF(GLOW_PROG_ALPHA);
3047         grad.setCoordinateMode(QGradient::ObjectBoundingMode);
3048         grad.setColorAt(0, (reverse ? GLOW_END : GLOW_START)==opts.glowProgress ? glow : blank);
3049         if(GLOW_MIDDLE==opts.glowProgress)
3050             grad.setColorAt(0.5, glow);
3051         grad.setColorAt(1, (reverse ? GLOW_START : GLOW_END)==opts.glowProgress ? glow : blank);
3052         p->fillRect(ri, grad);
3053     }
3054 
3055     if(!opts.borderProgress)
3056     {
3057         p->setPen(use[PBAR_BORDER]);
3058         if(!vertical)
3059         {
3060             p->drawLine(rx.topLeft(), rx.topRight());
3061             p->drawLine(rx.bottomLeft(), rx.bottomRight());
3062         }
3063         else
3064         {
3065             p->drawLine(rx.topLeft(), rx.bottomLeft());
3066             p->drawLine(rx.topRight(), rx.bottomRight());
3067         }
3068     }
3069 }
3070 
rotate(const QPolygon & p,double angle)3071 static QPolygon rotate(const QPolygon &p, double angle)
3072 {
3073     QTransform transform;
3074     transform.rotate(angle);
3075     return transform.map(p);
3076 }
3077 
3078 void
drawArrow(QPainter * p,const QRect & rx,PrimitiveElement pe,QColor col,bool small,bool kwin) const3079 Style::drawArrow(QPainter *p, const QRect &rx, PrimitiveElement pe,
3080                  QColor col, bool small, bool kwin) const
3081 {
3082     QPolygon a;
3083     QRect r(rx);
3084     int m = !small && kwin ? ((r.height() - 7) / 2) : 0;
3085 
3086     if(small)
3087         a.setPoints(opts.vArrows ? 6 : 3,  2,0,  0,-2,  -2,0,   -2,1, 0,-1, 2,1);
3088     else
3089         a.setPoints(opts.vArrows ? 8 : 3,  3+m,1+m,  0,-2,  -(3+m),1+m,    -(3+m),2+m,  -(2+m),2+m, 0,0,  2+m,2+m, 3+m,2+m);
3090 
3091     switch (pe) {
3092     case PE_IndicatorArrowUp:
3093         if(m)
3094             r.adjust(0, -m, 0, -m);
3095         break;
3096     case PE_IndicatorArrowDown:
3097         if(m)
3098             r.adjust(0, m, 0, m);
3099         a=rotate(a, 180);
3100         break;
3101     case PE_IndicatorArrowRight:
3102         a=rotate(a, 90);
3103         break;
3104     case PE_IndicatorArrowLeft:
3105         a=rotate(a, 270);
3106         break;
3107     default:
3108         return;
3109     }
3110     a.translate((r.x()+(r.width()>>1)), (r.y()+(r.height()>>1)));
3111     p->save();
3112     col.setAlpha(255);
3113     p->setPen(col);
3114     p->setBrush(col);
3115     // Qt5 changes how coordinates is calculate for non-AA drawing.
3116     // use QPainter::Qt4CompatiblePainting for now.
3117     // A better solution should be shifting the coordinates by 0.5
3118     // or maybe use QPainterPath
3119     p->setRenderHint(QPainter::Qt4CompatiblePainting, true);
3120     // Qt >= 4.8.5 has problem drawing polygons correctly. Enabling
3121     // antialiasing can work around the problem although it will also make
3122     // the arrow blurry.
3123     // QtCurve issue:
3124     // https://github.com/QtCurve/qtcurve-qt4/issues/3.
3125     // Upstream bug report:
3126     // https://bugreports.qt-project.org/browse/QTBUG-33512
3127     p->setRenderHint(QPainter::Antialiasing, opts.vArrows);
3128     p->drawPolygon(a);
3129     p->restore();
3130 }
3131 
drawSbSliderHandle(QPainter * p,const QRect & rOrig,const QStyleOption * option,bool slider) const3132 void Style::drawSbSliderHandle(QPainter *p, const QRect &rOrig, const QStyleOption *option, bool slider) const
3133 {
3134     QStyleOption opt(*option);
3135     QRect        r(rOrig);
3136 
3137     if(opt.state&(State_Sunken|State_On))
3138         opt.state|=State_MouseOver;
3139 
3140     if(r.width()>r.height())
3141         opt.state|=State_Horizontal;
3142 
3143     opt.state &= ~(State_Sunken | State_On);
3144     opt.state |= State_Raised;
3145 
3146     if (auto slider = styleOptCast<QStyleOptionSlider>(option)) {
3147         if (slider->minimum == slider->maximum) {
3148             opt.state &= ~(State_MouseOver | State_Enabled);
3149         }
3150     }
3151 
3152     int          min(MIN_SLIDER_SIZE(opts.sliderThumbs));
3153     const QColor *use(sliderColors(&opt));
3154 
3155     drawLightBevel(p, r, &opt, 0L, (slider && (!(opts.square&SQUARE_SLIDER) ||
3156                                                (SLIDER_ROUND==opts.sliderStyle || SLIDER_ROUND_ROTATED==opts.sliderStyle)))
3157 #ifndef SIMPLE_SCROLLBARS
3158                    || (!slider && !(opts.square&SQUARE_SB_SLIDER) && (SCROLLBAR_NONE==opts.scrollbarType || opts.flatSbarButtons))
3159 #endif
3160                    ? ROUNDED_ALL : ROUNDED_NONE,
3161                    getFill(&opt, use, false, SHADE_DARKEN==opts.shadeSliders), use, true,
3162                    slider ? WIDGET_SLIDER : WIDGET_SB_SLIDER);
3163 
3164     if(LINE_NONE!=opts.sliderThumbs && (slider || ((opt.state&State_Horizontal && r.width()>=min)|| r.height()>=min)) &&
3165        (!slider || SLIDER_CIRCULAR!=opts.sliderStyle))
3166     {
3167         const QColor *markers(use);
3168         bool         horiz(opt.state&State_Horizontal);
3169 
3170         if(LINE_SUNKEN==opts.sliderThumbs)
3171             if(horiz)
3172                 r.adjust(0, -1, 0, 0);
3173             else
3174                 r.adjust(-1, 0, 0, 0);
3175         else
3176             r.adjust(horiz ? 1 : 0, horiz ? 0 : 1, 0, 0);
3177 
3178         switch(opts.sliderThumbs)
3179         {
3180         case LINE_1DOT:
3181             p->drawPixmap(r.x()+((r.width()-5)/2), r.y()+((r.height()-5)/2), *getPixmap(markers[QTC_STD_BORDER], PIX_DOT, 1.0));
3182             break;
3183         case LINE_FLAT:
3184             drawLines(p, r, !horiz, 3, 5, markers, 0, 5, opts.sliderThumbs);
3185             break;
3186         case LINE_SUNKEN:
3187             drawLines(p, r, !horiz, 4, 3, markers, 0, 3, opts.sliderThumbs);
3188             break;
3189         case LINE_DOTS:
3190         default:
3191             drawDots(p, r, !horiz, slider ? 3 : 5, slider ? 4 : 2, markers, 0, 5);
3192         }
3193     }
3194 }
3195 
drawSliderHandle(QPainter * p,const QRect & r,const QStyleOptionSlider * option) const3196 void Style::drawSliderHandle(QPainter *p, const QRect &r, const QStyleOptionSlider *option) const
3197 {
3198     bool         horiz(SLIDER_TRIANGULAR==opts.sliderStyle ? r.height()>r.width() : r.width()>r.height());
3199     QStyleOption opt(*option);
3200 
3201     if(!(option->activeSubControls&SC_SliderHandle) || !(opt.state&State_Enabled))
3202         opt.state&=~State_MouseOver;
3203 
3204     if (opts.sliderStyle == SLIDER_TRIANGULAR) {
3205         if (r.width() > r.height()) {
3206             opt.state |= State_Horizontal;
3207         }
3208         opt.state &= ~(State_Sunken | State_On);
3209         opt.state |= State_Raised;
3210         const QColor *use = sliderColors(&opt);
3211         const QColor *border = (opt.state & State_MouseOver &&
3212                                 oneOf(opts.coloredMouseOver, MO_GLOW,
3213                                       MO_COLORED) ? m_mouseOverCols : use);
3214         const QColor &fill(getFill(&opt, use, false,
3215                                    opts.shadeSliders == SHADE_DARKEN));
3216         int x = r.x();
3217         int y = r.y();
3218         PrimitiveElement direction(horiz ? PE_IndicatorArrowDown :
3219                                    PE_IndicatorArrowRight);
3220         QPolygon clipRegion;
3221         bool drawLight(MO_PLASTIK!=opts.coloredMouseOver || !(opt.state&State_MouseOver));
3222         int size(SLIDER_TRIANGULAR==opts.sliderStyle ? 15 : 13),
3223             borderVal(m_mouseOverCols==border ? SLIDER_MO_BORDER_VAL : BORDER_VAL(opt.state&State_Enabled));
3224 
3225         if(option->tickPosition & QSlider::TicksBelow)
3226             direction=horiz ? PE_IndicatorArrowDown : PE_IndicatorArrowRight;
3227         else if(option->tickPosition & QSlider::TicksAbove)
3228             direction=horiz ? PE_IndicatorArrowUp : PE_IndicatorArrowLeft;
3229 
3230         if (MO_GLOW==opts.coloredMouseOver && opts.buttonEffect != EFFECT_NONE)
3231             x++, y++;
3232 
3233         switch(direction)
3234         {
3235         default:
3236         case PE_IndicatorArrowDown:
3237             clipRegion.setPoints(7,   x, y+2,    x+2, y,   x+8, y,    x+10, y+2,   x+10, y+9,   x+5, y+14,    x, y+9);
3238             break;
3239         case PE_IndicatorArrowUp:
3240             clipRegion.setPoints(7,   x, y+12,   x+2, y+14,   x+8, y+14,   x+10, y+12,   x+10, y+5,   x+5, y,    x, y+5);
3241             break;
3242         case PE_IndicatorArrowLeft:
3243             clipRegion.setPoints(7,   x+12, y,   x+14, y+2,   x+14, y+8,   x+12, y+10,   x+5, y+10,    x, y+5,    x+5, y );
3244             break;
3245         case PE_IndicatorArrowRight:
3246             clipRegion.setPoints(7,   x+2, y,    x, y+2,   x, y+8,    x+2, y+10,   x+9, y+10,   x+14, y+5,    x+9, y);
3247         }
3248 
3249         p->save();
3250         p->setClipRegion(QRegion(clipRegion)); // , QPainter::CoordPainter);
3251         if(qtcIsFlat(opts.sliderAppearance))
3252         {
3253             p->fillRect(r, fill);
3254 
3255             if(MO_PLASTIK==opts.coloredMouseOver && opt.state&State_MouseOver && !opts.colorSliderMouseOver)
3256             {
3257                 int col(SLIDER_MO_SHADE),
3258                     len(SLIDER_MO_LEN);
3259 
3260                 if(horiz)
3261                 {
3262                     p->fillRect(QRect(x+1, y+1, len, size-2), m_mouseOverCols[col]);
3263                     p->fillRect(QRect(x+r.width()-(1+len), y+1, len, r.height()-2), m_mouseOverCols[col]);
3264                 }
3265                 else
3266                 {
3267                     p->fillRect(QRect(x+1, y+1, size-2, len), m_mouseOverCols[col]);
3268                     p->fillRect(QRect(x+1, y+r.height()-(1+len), r.width()-2, len), m_mouseOverCols[col]);
3269                 }
3270             }
3271         }
3272         else
3273         {
3274             drawBevelGradient(fill, p, QRect(x, y, horiz ? r.width()-1 : size, horiz ? size : r.height()-1),
3275                               horiz, false, MODIFY_AGUA(opts.sliderAppearance));
3276 
3277             if(MO_PLASTIK==opts.coloredMouseOver && opt.state&State_MouseOver && !opts.colorSliderMouseOver)
3278             {
3279                 int col(SLIDER_MO_SHADE),
3280                     len(SLIDER_MO_LEN);
3281 
3282                 if(horiz)
3283                 {
3284                     drawBevelGradient(m_mouseOverCols[col], p, QRect(x+1, y+1, len, size-2),
3285                                       horiz, false, MODIFY_AGUA(opts.sliderAppearance));
3286                     drawBevelGradient(m_mouseOverCols[col], p,  QRect(x+r.width()-(1+len), y+1, len, size-2),
3287                                       horiz, false, MODIFY_AGUA(opts.sliderAppearance));
3288                 }
3289                 else
3290                 {
3291                     drawBevelGradient(m_mouseOverCols[col], p, QRect(x+1, y+1, size-2, len),
3292                                       horiz, false, MODIFY_AGUA(opts.sliderAppearance));
3293                     drawBevelGradient(m_mouseOverCols[col], p,QRect(x+1, y+r.height()-(1+len), size-2, len),
3294                                       horiz, false, MODIFY_AGUA(opts.sliderAppearance));
3295                 }
3296             }
3297         }
3298 
3299         p->restore();
3300         p->save();
3301 
3302         QPainterPath path;
3303         double       xd(x+0.5),
3304             yd(y+0.5),
3305             radius(2.5),
3306             diameter(radius*2),
3307             xdg(x-0.5),
3308             ydg(y-0.5),
3309             radiusg(radius+1),
3310             diameterg(radiusg*2);
3311         bool         glowMo(MO_GLOW==opts.coloredMouseOver && opt.state&State_MouseOver);
3312         QColor       glowCol(border[GLOW_MO]);
3313 
3314         glowCol.setAlphaF(GLOW_ALPHA(false));
3315 
3316         p->setPen(glowMo ? glowCol : border[borderVal]);
3317 
3318         switch(direction)
3319         {
3320         default:
3321         case PE_IndicatorArrowDown:
3322             p->setRenderHint(QPainter::Antialiasing, true);
3323             if(glowMo)
3324             {
3325                 path.moveTo(xdg+12-radiusg, ydg);
3326                 path.arcTo(xdg, ydg, diameterg, diameterg, 90, 90);
3327                 path.lineTo(xdg, ydg+10.5);
3328                 path.lineTo(xdg+6, ydg+16.5);
3329                 path.lineTo(xdg+12, ydg+10.5);
3330                 path.arcTo(xdg+12-diameterg, ydg, diameterg, diameterg, 0, 90);
3331                 p->drawPath(path);
3332                 path=QPainterPath();
3333                 p->setPen(border[borderVal]);
3334             }
3335             path.moveTo(xd+10-radius, yd);
3336             path.arcTo(xd, yd, diameter, diameter, 90, 90);
3337             path.lineTo(xd, yd+9);
3338             path.lineTo(xd+5, yd+14);
3339             path.lineTo(xd+10, yd+9);
3340             path.arcTo(xd+10-diameter, yd, diameter, diameter, 0, 90);
3341             p->drawPath(path);
3342             QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
3343             if(drawLight)
3344             {
3345                 p->setPen(use[APPEARANCE_DULL_GLASS==opts.sliderAppearance ? 1 : 0]);
3346                 p->drawLine(x+1, y+2, x+1, y+8);
3347                 p->drawLine(x+2, y+1, x+7, y+1);
3348             }
3349             break;
3350         case PE_IndicatorArrowUp:
3351             p->setRenderHint(QPainter::Antialiasing, true);
3352             if(glowMo)
3353             {
3354                 path.moveTo(xdg, ydg+6);
3355                 path.arcTo(xdg, ydg+16-diameterg, diameterg, diameterg, 180, 90);
3356                 path.arcTo(xdg+12-diameterg, ydg+16-diameterg, diameterg, diameterg, 270, 90);
3357                 path.lineTo(xdg+12, ydg+5.5);
3358                 path.lineTo(xdg+6, ydg-0.5);
3359                 path.lineTo(xdg, ydg+5.5);
3360                 p->drawPath(path);
3361                 path=QPainterPath();
3362                 p->setPen(border[borderVal]);
3363             }
3364             path.moveTo(xd, yd+5);
3365             path.arcTo(xd, yd+14-diameter, diameter, diameter, 180, 90);
3366             path.arcTo(xd+10-diameter, yd+14-diameter, diameter, diameter, 270, 90);
3367             path.lineTo(xd+10, yd+5);
3368             path.lineTo(xd+5, yd);
3369             path.lineTo(xd, yd+5);
3370             p->drawPath(path);
3371             QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
3372             if(drawLight)
3373             {
3374                 p->setPen(use[APPEARANCE_DULL_GLASS==opts.sliderAppearance ? 1 : 0]);
3375                 p->drawLine(x+5, y+1, x+1, y+5);
3376                 p->drawLine(x+1, y+5, x+1, y+11);
3377             }
3378             break;
3379         case PE_IndicatorArrowLeft:
3380             p->setRenderHint(QPainter::Antialiasing, true);
3381             if(glowMo)
3382             {
3383                 path.moveTo(xdg+6, ydg+12);
3384                 path.arcTo(xdg+16-diameterg, ydg+12-diameterg, diameterg, diameterg, 270, 90);
3385                 path.arcTo(xdg+16-diameterg, ydg, diameterg, diameterg, 0, 90);
3386                 path.lineTo(xdg+5.5, ydg);
3387                 path.lineTo(xdg-0.5, ydg+6);
3388                 path.lineTo(xdg+5.5, ydg+12);
3389                 p->drawPath(path);
3390                 path=QPainterPath();
3391                 p->setPen(border[borderVal]);
3392             }
3393             path.moveTo(xd+5, yd+10);
3394             path.arcTo(xd+14-diameter, yd+10-diameter, diameter, diameter, 270, 90);
3395             path.arcTo(xd+14-diameter, yd, diameter, diameter, 0, 90);
3396             path.lineTo(xd+5, yd);
3397             path.lineTo(xd, yd+5);
3398             path.lineTo(xd+5, yd+10);
3399             p->drawPath(path);
3400             QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
3401             if(drawLight)
3402             {
3403                 p->setPen(use[APPEARANCE_DULL_GLASS==opts.sliderAppearance ? 1 : 0]);
3404                 p->drawLine(x+1, y+5, x+5, y+1);
3405                 p->drawLine(x+5, y+1, x+11, y+1);
3406             }
3407             break;
3408         case PE_IndicatorArrowRight:
3409             p->setRenderHint(QPainter::Antialiasing, true);
3410             if(glowMo)
3411             {
3412                 path.moveTo(xdg+11, ydg);
3413                 path.arcTo(xdg, ydg, diameterg, diameterg, 90, 90);
3414                 path.arcTo(xdg, ydg+12-diameterg, diameterg, diameterg, 180, 90);
3415                 path.lineTo(xdg+10.5, ydg+12);
3416                 path.lineTo(xdg+16.5, ydg+6);
3417                 path.lineTo(xdg+10.5, ydg);
3418                 p->drawPath(path);
3419                 path=QPainterPath();
3420                 p->setPen(border[borderVal]);
3421             }
3422             path.moveTo(xd+9, yd);
3423             path.arcTo(xd, yd, diameter, diameter, 90, 90);
3424             path.arcTo(xd, yd+10-diameter, diameter, diameter, 180, 90);
3425             path.lineTo(xd+9, yd+10);
3426             path.lineTo(xd+14, yd+5);
3427             path.lineTo(xd+9, yd);
3428             p->drawPath(path);
3429             QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
3430             if(drawLight)
3431             {
3432                 p->setPen(use[APPEARANCE_DULL_GLASS==opts.sliderAppearance ? 1 : 0]);
3433                 p->drawLine(x+2, y+1, x+7, y+1);
3434                 p->drawLine(x+1, y+2, x+1, y+8);
3435             }
3436             break;
3437         }
3438         p->restore();
3439     } else {
3440         if (oneOf(opts.sliderStyle, SLIDER_PLAIN_ROTATED,
3441                   SLIDER_ROUND_ROTATED)) {
3442             opt.state ^= State_Horizontal;
3443         }
3444         drawSbSliderHandle(p, r, &opt, true);
3445     }
3446 }
3447 
drawSliderGroove(QPainter * p,const QRect & groove,const QRect & handle,const QStyleOptionSlider * slider,const QWidget * widget) const3448 void Style::drawSliderGroove(QPainter *p, const QRect &groove, const QRect &handle,  const QStyleOptionSlider *slider,
3449                              const QWidget *widget) const
3450 {
3451     bool               horiz(Qt::Horizontal==slider->orientation);
3452     QRect              grv(groove);
3453     QStyleOptionSlider opt(*slider);
3454 
3455     opt.state&=~(State_HasFocus|State_On|State_Sunken|State_MouseOver);
3456 
3457     if(horiz)
3458     {
3459         int dh=(grv.height()-5)>>1;
3460         grv.adjust(0, dh, 0, -dh);
3461         opt.state|=State_Horizontal;
3462 
3463         if (opts.buttonEffect != EFFECT_NONE)
3464             grv.adjust(0, -1, 0, 1);
3465     }
3466     else
3467     {
3468         int dw=(grv.width()-5)>>1;
3469         grv.adjust(dw, 0, -dw, 0);
3470         opt.state&=~State_Horizontal;
3471 
3472         if (opts.buttonEffect != EFFECT_NONE)
3473             grv.adjust(-1, 0, 1, 0);
3474     }
3475 
3476     if(grv.height()>0 && grv.width()>0)
3477     {
3478         drawLightBevel(p, grv, &opt, widget,
3479                        opts.square&SQUARE_SLIDER ? ROUNDED_NONE : ROUNDED_ALL,
3480                        m_backgroundCols[slider->state&State_Enabled ? 2 : ORIGINAL_SHADE],
3481                        m_backgroundCols, true, WIDGET_SLIDER_TROUGH);
3482 
3483         if(opts.fillSlider && slider->maximum!=slider->minimum && slider->state&State_Enabled)
3484         {
3485             const QColor *usedCols=m_sliderCols ? m_sliderCols : m_highlightCols;
3486 
3487             if (horiz)
3488                 if (slider->upsideDown)
3489                     grv=QRect(handle.right()-4, grv.top(), (grv.right()-handle.right())+4, grv.height());
3490                 else
3491                     grv=QRect(grv.left(), grv.top(), handle.left()+4, grv.height());
3492             else
3493                 if (slider->upsideDown)
3494                     grv=QRect(grv.left(), handle.bottom()-4, grv.width(), (grv.height() - handle.bottom())+4);
3495                 else
3496                     grv=QRect(grv.left(), grv.top(), grv.width(), (handle.top() - grv.top())+4);
3497 
3498             if(grv.height()>0 && grv.width()>0)
3499                 drawLightBevel(p, grv, &opt, widget, opts.square&SQUARE_SLIDER ? ROUNDED_NONE : ROUNDED_ALL,
3500                                usedCols[ORIGINAL_SHADE], usedCols, true, WIDGET_FILLED_SLIDER_TROUGH);
3501         }
3502     }
3503 }
3504 
3505 void
drawMenuOrToolBarBackground(const QWidget * widget,QPainter * p,const QRect & r,const QStyleOption * option,bool menu,bool horiz) const3506 Style::drawMenuOrToolBarBackground(const QWidget *widget, QPainter *p,
3507                                    const QRect &r, const QStyleOption *option,
3508                                    bool menu, bool horiz) const
3509 {
3510     // LibreOffice - when drawMenuOrToolBarBackground is called with menuRect,
3511     // this is empty!
3512     if (r.width() < 1 || r.height() < 1)
3513         return;
3514 
3515     EAppearance app = menu ? opts.menubarAppearance : opts.toolbarAppearance;
3516     if (!qtcIsCustomBgnd(opts) || !qtcIsFlat(app) ||
3517         (menu && opts.shadeMenubars != SHADE_NONE)) {
3518         p->save();
3519 #if 0
3520         // Revert for now
3521         // This is necessary for correct opacity on the menubar but may
3522         // break transparent gradient.
3523         p->setCompositionMode(QPainter::CompositionMode_Source);
3524 #endif
3525         QRect rx(r);
3526 #ifdef Q_OS_MACOS
3527         QColor col(menu ?
3528                    menuColors(option, m_active)[ORIGINAL_SHADE] :
3529                    option->palette.background().color());
3530 #else
3531         QColor col(menu && (option->state & State_Enabled ||
3532                             opts.shadeMenubars != SHADE_NONE) ?
3533                    menuColors(option, m_active)[ORIGINAL_SHADE] :
3534                    option->palette.background().color());
3535 #endif
3536         // TODO: QtQuick
3537         int opacity = qtcGetOpacity(widget ? widget : getWidget(p));
3538 
3539         if (menu && BLEND_TITLEBAR) {
3540             rx.adjust(0, -qtcGetWindowBorderSize(false).titleHeight, 0, 0);
3541         }
3542         if (opacity < 100) {
3543             col.setAlphaF(opacity / 100.0);
3544         }
3545         drawBevelGradient(col, p, rx, horiz, false, MODIFY_AGUA(app));
3546         p->restore();
3547     }
3548 }
3549 
drawHandleMarkers(QPainter * p,const QRect & rx,const QStyleOption * option,bool tb,ELine handles) const3550 void Style::drawHandleMarkers(QPainter *p, const QRect &rx, const QStyleOption *option, bool tb, ELine handles) const
3551 {
3552     if(rx.width()<2 || rx.height()<2)
3553         return;
3554 
3555     QRect r(rx);
3556 
3557     if(APP_OPENOFFICE==theThemedApp)
3558     {
3559         r.setX(r.x()+2);
3560         r.setWidth(10);
3561     }
3562 
3563     // CPD: Mouse over of toolbar handles not working - the whole toolbar seems to be active :-(
3564     QStyleOption opt(*option);
3565 
3566     opt.state&=~State_MouseOver;
3567 
3568     const QColor *border(borderColors(&opt, m_backgroundCols));
3569 
3570     switch(handles)
3571     {
3572     case LINE_NONE:
3573         break;
3574     case LINE_1DOT:
3575         p->drawPixmap(r.x()+((r.width()-5)/2), r.y()+((r.height()-5)/2), *getPixmap(border[QTC_STD_BORDER], PIX_DOT, 1.0));
3576         break;
3577     case LINE_DOTS:
3578         drawDots(p, r, !(option->state&State_Horizontal), 2, tb ? 5 : 3, border, tb ? -2 : 0, 5);
3579         break;
3580     case LINE_DASHES:
3581         if(option->state&State_Horizontal)
3582             drawLines(p, QRect(r.x()+(tb ? 2 : (r.width()-6)/2), r.y(), 3, r.height()), true, (r.height()-8)/2,
3583                       tb ? 0 : (r.width()-5)/2, border, 0, 5, handles);
3584         else
3585             drawLines(p, QRect(r.x(), r.y()+(tb ? 2 : (r.height()-6)/2), r.width(), 3), false, (r.width()-8)/2,
3586                       tb ? 0 : (r.height()-5)/2, border, 0, 5, handles);
3587         break;
3588     case LINE_FLAT:
3589         drawLines(p, r, !(option->state&State_Horizontal), 2, tb ? 4 : 2, border, tb ? -2 : 0, 4, handles);
3590         break;
3591     default:
3592         drawLines(p, r, !(option->state&State_Horizontal), 2, tb ? 4 : 2, border, tb ? -2 : 0, 3, handles);
3593     }
3594 }
3595 
fillTab(QPainter * p,const QRect & r,const QStyleOption * option,const QColor & fill,bool horiz,EWidget tab,bool tabOnly) const3596 void Style::fillTab(QPainter *p, const QRect &r, const QStyleOption *option, const QColor &fill, bool horiz, EWidget tab,
3597                     bool tabOnly) const
3598 {
3599     bool   invertedSel=option->state&State_Selected && APPEARANCE_INVERTED==opts.appearance;
3600     QColor col(invertedSel ? option->palette.background().color() : fill);
3601 
3602     if(opts.tabBgnd && !tabOnly)
3603         col=shade(col, TO_FACTOR(opts.tabBgnd));
3604 
3605     if(invertedSel)
3606         p->fillRect(r, col);
3607     else
3608     {
3609         bool        selected(option->state&State_Selected);
3610         EAppearance app(selected ? SEL_TAB_APP : NORM_TAB_APP);
3611 
3612         drawBevelGradient(col, p, r, horiz, selected, app, tab);
3613     }
3614 }
3615 
colorTab(QPainter * p,const QRect & r,bool horiz,EWidget tab,int round) const3616 void Style::colorTab(QPainter *p, const QRect &r, bool horiz, EWidget tab, int round) const
3617 {
3618     p->save();
3619     p->setRenderHint(QPainter::Antialiasing, true);
3620     QLinearGradient grad(r.topLeft(), horiz ? r.bottomLeft() : r.topRight());
3621     QColor          start(m_highlightCols[ORIGINAL_SHADE]),
3622         end(m_highlightCols[ORIGINAL_SHADE]);
3623 
3624     start.setAlphaF(TO_ALPHA(opts.colorSelTab));
3625     end.setAlphaF(0.0);
3626     grad.setColorAt(0, WIDGET_TAB_TOP==tab ? start : end);
3627     grad.setColorAt(1, WIDGET_TAB_TOP==tab ? end : start);
3628     p->fillPath(buildPath(r, tab, round, qtcGetRadius(&opts, r.width(), r.height(), tab, RADIUS_EXTERNAL)), grad);
3629     p->restore();
3630 }
3631 
shadeColors(const QColor & base,QColor * vals) const3632 void Style::shadeColors(const QColor &base, QColor *vals) const
3633 {
3634     bool useCustom(USE_CUSTOM_SHADES(opts));
3635     double hl=TO_FACTOR(opts.highlightFactor);
3636 
3637     for(int i=0; i<QTC_NUM_STD_SHADES; ++i)
3638         shade(base, &vals[i], useCustom ? opts.customShades[i] :
3639               qtcShadeGetIntern(opts.contrast, i,
3640                                 opts.darkerBorders, opts.shading));
3641     shade(base, &vals[SHADE_ORIG_HIGHLIGHT], hl);
3642     shade(vals[4], &vals[SHADE_4_HIGHLIGHT], hl);
3643     shade(vals[2], &vals[SHADE_2_HIGHLIGHT], hl);
3644     vals[ORIGINAL_SHADE]=base;
3645 }
3646 
buttonColors(const QStyleOption * option) const3647 const QColor * Style::buttonColors(const QStyleOption *option) const
3648 {
3649     if(option && option->version>=TBAR_VERSION_HACK &&
3650        option->version<TBAR_VERSION_HACK+NUM_TITLEBAR_BUTTONS &&
3651        coloredMdiButtons(option->state&State_Active, option->state&(State_MouseOver|State_Sunken)))
3652         return m_titleBarButtonsCols[option->version-TBAR_VERSION_HACK];
3653 
3654     if(option && option->palette.button()!=m_buttonCols[ORIGINAL_SHADE])
3655     {
3656         shadeColors(option->palette.button().color(), m_coloredButtonCols);
3657         return m_coloredButtonCols;
3658     }
3659 
3660     return m_buttonCols;
3661 }
3662 
titlebarIconColor(const QStyleOption * option) const3663 QColor Style::titlebarIconColor(const QStyleOption *option) const
3664 {
3665     if(option && option->version>=TBAR_VERSION_HACK)
3666     {
3667         if(opts.titlebarButtons&TITLEBAR_BUTTON_ICON_COLOR && option->version<TBAR_VERSION_HACK+(NUM_TITLEBAR_BUTTONS*3))
3668             return opts.titlebarButtonColors[option->version-TBAR_VERSION_HACK];
3669         if(option->version<TBAR_VERSION_HACK+NUM_TITLEBAR_BUTTONS &&
3670            coloredMdiButtons(option->state&State_Active, option->state&(State_MouseOver|State_Sunken)))
3671             return m_titleBarButtonsCols[option->version-TBAR_VERSION_HACK][ORIGINAL_SHADE];
3672     }
3673 
3674     return buttonColors(option)[ORIGINAL_SHADE];
3675 }
3676 
popupMenuCols(const QStyleOption * option) const3677 const QColor * Style::popupMenuCols(const QStyleOption *option) const
3678 {
3679     return (opts.lighterPopupMenuBgnd || opts.shadePopupMenu || !option ?
3680             m_popupMenuCols : backgroundColors(option));
3681 }
3682 
3683 const QColor*
checkRadioColors(const QStyleOption * option) const3684 Style::checkRadioColors(const QStyleOption *option) const
3685 {
3686     return (opts.crColor && option && option->state & State_Enabled &&
3687             (option->state & State_On || option->state & State_NoChange)
3688             ? m_checkRadioSelCols : buttonColors(option));
3689 }
3690 
sliderColors(const QStyleOption * option) const3691 const QColor * Style::sliderColors(const QStyleOption *option) const
3692 {
3693     return (option && option->state&State_Enabled)
3694         ? SHADE_NONE!=opts.shadeSliders && m_sliderCols &&
3695         (!opts.colorSliderMouseOver || option->state&State_MouseOver)
3696         ? m_sliderCols
3697         : m_buttonCols //buttonColors(option)
3698         : m_backgroundCols;
3699 }
3700 
backgroundColors(const QColor & col) const3701 const QColor * Style::backgroundColors(const QColor &col) const
3702 {
3703     if(col.alpha()!=0 && col!=m_backgroundCols[ORIGINAL_SHADE])
3704     {
3705         shadeColors(col, m_coloredBackgroundCols);
3706         return m_coloredBackgroundCols;
3707     }
3708 
3709     return m_backgroundCols;
3710 }
3711 
highlightColors(const QColor & col) const3712 const QColor * Style::highlightColors(const QColor &col) const
3713 {
3714     if(col.alpha()!=0 && col!=m_highlightCols[ORIGINAL_SHADE])
3715     {
3716         shadeColors(col, m_coloredHighlightCols);
3717         return m_coloredHighlightCols;
3718     }
3719 
3720     return m_highlightCols;
3721 }
3722 
borderColors(const QStyleOption * option,const QColor * use) const3723 const QColor * Style::borderColors(const QStyleOption *option, const QColor *use) const
3724 {
3725     return opts.coloredMouseOver && option && option->state&State_MouseOver && option->state&State_Enabled ? m_mouseOverCols : use;
3726 }
3727 
getSidebarButtons() const3728 const QColor * Style::getSidebarButtons() const
3729 {
3730     if(!m_sidebarButtonsCols)
3731     {
3732         if(SHADE_BLEND_SELECTED==opts.shadeSliders)
3733             m_sidebarButtonsCols=m_sliderCols;
3734         else if(IND_COLORED==opts.defBtnIndicator)
3735             m_sidebarButtonsCols=m_defBtnCols;
3736         else
3737         {
3738             m_sidebarButtonsCols=new QColor [TOTAL_SHADES+1];
3739             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE], m_buttonCols[ORIGINAL_SHADE]),
3740                         m_sidebarButtonsCols);
3741         }
3742     }
3743 
3744     return m_sidebarButtonsCols;
3745 }
3746 
setMenuColors(const QColor & bgnd)3747 void Style::setMenuColors(const QColor &bgnd)
3748 {
3749     switch(opts.shadeMenubars)
3750     {
3751     case SHADE_NONE:
3752         memcpy(m_menubarCols, m_backgroundCols, sizeof(QColor)*(TOTAL_SHADES+1));
3753         break;
3754     case SHADE_BLEND_SELECTED:
3755         shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE], m_backgroundCols[ORIGINAL_SHADE]), m_menubarCols);
3756         break;
3757     case SHADE_SELECTED:
3758         shadeColors(IS_GLASS(opts.appearance)
3759                     ? shade(m_highlightCols[ORIGINAL_SHADE], MENUBAR_GLASS_SELECTED_DARK_FACTOR)
3760                     : m_highlightCols[ORIGINAL_SHADE],
3761                     m_menubarCols);
3762         break;
3763     case SHADE_CUSTOM:
3764         shadeColors(opts.customMenubarsColor, m_menubarCols);
3765         break;
3766     case SHADE_DARKEN:
3767         shadeColors(shade(bgnd, MENUBAR_DARK_FACTOR), m_menubarCols);
3768         break;
3769     case SHADE_WINDOW_BORDER:
3770         break;
3771     }
3772 
3773     QColor *base=opts.shadePopupMenu
3774         ? SHADE_WINDOW_BORDER==opts.shadeMenubars
3775         ? (QColor *)getMdiColors(0L, true) // TODO: option!!!
3776         : m_menubarCols
3777         : m_backgroundCols;
3778 
3779     if (opts.lighterPopupMenuBgnd) {
3780         if (!m_popupMenuCols) {
3781             m_popupMenuCols = new QColor[TOTAL_SHADES + 1];
3782         }
3783         shadeColors(shade(base[ORIGINAL_SHADE],
3784                           TO_FACTOR(opts.lighterPopupMenuBgnd)),
3785                     m_popupMenuCols);
3786     } else {
3787         m_popupMenuCols = base;
3788     }
3789 }
3790 
setMenuTextColors(QWidget * widget,bool isMenuBar) const3791 void Style::setMenuTextColors(QWidget *widget, bool isMenuBar) const
3792 {
3793     if(SHADE_WINDOW_BORDER==opts.shadeMenubars)
3794     {
3795         QPalette pal(widget->palette());
3796         QStyleOption opt;
3797 
3798         opt.init(widget);
3799         getMdiColors(&opt, false);
3800 
3801         pal.setBrush(QPalette::Active, QPalette::Foreground, m_activeMdiTextColor);
3802         pal.setBrush(QPalette::Active, QPalette::Text, pal.brush(QPalette::Active, QPalette::Foreground));
3803         if(isMenuBar)
3804         {
3805             pal.setBrush(QPalette::Inactive, QPalette::Foreground,
3806                          opts.shadeMenubarOnlyWhenActive ? m_mdiTextColor : m_activeMdiTextColor);
3807             pal.setBrush(QPalette::Inactive, QPalette::Text, pal.brush(QPalette::Inactive, QPalette::Foreground));
3808         }
3809         else if(opts.shadePopupMenu)
3810         {
3811             pal.setBrush(QPalette::Disabled, QPalette::Foreground, midColor(m_activeMdiTextColor, popupMenuCols()[ORIGINAL_SHADE]));
3812             pal.setBrush(QPalette::Disabled, QPalette::Text, pal.brush(QPalette::Disabled, QPalette::Foreground));
3813         }
3814 
3815         widget->setPalette(pal);
3816     } else if (opts.customMenuTextColor ||
3817                oneOf(opts.shadeMenubars, SHADE_BLEND_SELECTED,
3818                      SHADE_SELECTED) ||
3819                (opts.shadeMenubars == SHADE_CUSTOM &&
3820                 TOO_DARK(m_menubarCols[ORIGINAL_SHADE]))) {
3821         QPalette pal(widget->palette());
3822 
3823         pal.setBrush(QPalette::Active, QPalette::Foreground,
3824                      opts.customMenuTextColor ? opts.customMenuNormTextColor :
3825                      pal.highlightedText().color());
3826         pal.setBrush(QPalette::Active, QPalette::Text, pal.brush(QPalette::Active, QPalette::Foreground));
3827 
3828         if(isMenuBar && !opts.shadeMenubarOnlyWhenActive)
3829         {
3830             pal.setBrush(QPalette::Inactive, QPalette::Foreground, opts.customMenuTextColor
3831                          ? opts.customMenuNormTextColor
3832                          : pal.highlightedText().color());
3833             pal.setBrush(QPalette::Inactive, QPalette::Text, pal.brush(QPalette::Inactive, QPalette::Foreground));
3834         }
3835         else if(!isMenuBar && opts.shadePopupMenu)
3836         {
3837             pal.setBrush(QPalette::Disabled, QPalette::Foreground,
3838                          midColor(pal.brush(QPalette::Active, QPalette::Foreground).color(), popupMenuCols()[ORIGINAL_SHADE]));
3839             pal.setBrush(QPalette::Disabled, QPalette::Text, pal.brush(QPalette::Disabled, QPalette::Foreground));
3840         }
3841         widget->setPalette(pal);
3842     }
3843 }
3844 
menuColors(const QStyleOption * option,bool active) const3845 const QColor * Style::menuColors(const QStyleOption *option, bool active) const
3846 {
3847     if(SHADE_WINDOW_BORDER == opts.shadeMenubars)
3848     {
3849         return getMdiColors(option, active);
3850     }
3851 #ifdef Q_OS_MACOS
3852     else if(opts.shadeMenubarOnlyWhenActive && !active)
3853 #else
3854     else if(opts.shadeMenubars == SHADE_NONE || (opts.shadeMenubarOnlyWhenActive && !active))
3855 #endif
3856     {
3857         return backgroundColors(option);
3858     }
3859     return m_menubarCols;
3860 }
3861 
3862 bool
coloredMdiButtons(bool active,bool mouseOver) const3863 Style::coloredMdiButtons(bool active, bool mouseOver) const
3864 {
3865     return (opts.titlebarButtons & TITLEBAR_BUTTON_COLOR &&
3866             (active ?
3867              (mouseOver || !(opts.titlebarButtons &
3868                              TITLEBAR_BUTTON_COLOR_MOUSE_OVER)) :
3869              ((opts.titlebarButtons & TITLEBAR_BUTTON_COLOR_MOUSE_OVER &&
3870                mouseOver) ||
3871               (!(opts.titlebarButtons & TITLEBAR_BUTTON_COLOR_MOUSE_OVER) &&
3872                opts.titlebarButtons & TITLEBAR_BUTTON_COLOR_INACTIVE))));
3873 }
3874 
3875 const QColor*
getMdiColors(const QStyleOption * option,bool active) const3876 Style::getMdiColors(const QStyleOption *option, bool active) const
3877 {
3878     if (!m_activeMdiColors) {
3879 #ifndef QTC_QT5_ENABLE_KDE
3880         m_activeMdiTextColor = (option ? option->palette.text().color() :
3881                                  QApplication::palette().text().color());
3882         m_mdiTextColor = (option ? option->palette.text().color() :
3883                            QApplication::palette().text().color());
3884 
3885         QFile f(kdeHome() + "/share/config/kdeglobals");
3886 
3887         if (f.open(QIODevice::ReadOnly)) {
3888             QTextStream in(&f);
3889             bool inPal = false;
3890 
3891             while (!in.atEnd()) {
3892                 QString line(in.readLine());
3893                 if (inPal) {
3894                     if (!m_activeMdiColors &&
3895                         line.indexOf("activeBackground=") == 0) {
3896                         QColor col;
3897                         setRgb(&col, line.mid(17).split(","));
3898                         if (col != m_highlightCols[ORIGINAL_SHADE]) {
3899                             m_activeMdiColors = new QColor[TOTAL_SHADES + 1];
3900                             shadeColors(col, m_activeMdiColors);
3901                         }
3902                     } else if (!m_mdiColors &&
3903                                line.indexOf("inactiveBackground=") == 0) {
3904                         QColor col;
3905                         setRgb(&col, line.mid(19).split(","));
3906                         if (col != m_buttonCols[ORIGINAL_SHADE]) {
3907                             m_mdiColors = new QColor[TOTAL_SHADES+1];
3908                             shadeColors(col, m_mdiColors);
3909                         }
3910                     } else if(line.indexOf("activeForeground=") == 0) {
3911                         setRgb(&m_activeMdiTextColor, line.mid(17).split(","));
3912                     } else if(line.indexOf("inactiveForeground=") == 0) {
3913                         setRgb(&m_mdiTextColor, line.mid(19).split(","));
3914                     } else if (line.indexOf('[') != -1) {
3915                         break;
3916                     }
3917                 } else if(line.indexOf("[WM]") == 0) {
3918                     inPal = true;
3919                 }
3920             }
3921             f.close();
3922         }
3923 #else
3924         Q_UNUSED(option);
3925         KConfigGroup cg(m_kdeGlobals, "WM");
3926 
3927 //         QColor col = KGlobalSettings::activeTitleColor();
3928         QColor col = cg.readEntry("activeBackground", QColor(48, 174, 232));
3929 
3930         if (col != m_backgroundCols[ORIGINAL_SHADE]) {
3931             m_activeMdiColors = new QColor[TOTAL_SHADES + 1];
3932             shadeColors(col, m_activeMdiColors);
3933         }
3934 
3935 //         col = KGlobalSettings::inactiveTitleColor();
3936         col = cg.readEntry("inactiveBackground", QColor(224, 223, 222));;
3937         if (col != m_backgroundCols[ORIGINAL_SHADE]) {
3938             m_mdiColors = new QColor[TOTAL_SHADES+1];
3939             shadeColors(col, m_mdiColors);
3940         }
3941 
3942 //         m_activeMdiTextColor = KGlobalSettings::activeTextColor();
3943 //         m_mdiTextColor = KGlobalSettings::inactiveTextColor();
3944         m_activeMdiTextColor = cg.readEntry("activeForeground", QColor(255, 255, 255));
3945         m_mdiTextColor = cg.readEntry("inactiveForeground", QColor(75, 71, 67));
3946 #endif
3947 
3948         if(!m_activeMdiColors)
3949             m_activeMdiColors=(QColor *)m_backgroundCols;
3950         if(!m_mdiColors)
3951             m_mdiColors=(QColor *)m_backgroundCols;
3952 
3953         if(opts.shadeMenubarOnlyWhenActive && SHADE_WINDOW_BORDER==opts.shadeMenubars &&
3954            m_activeMdiColors[ORIGINAL_SHADE]==m_mdiColors[ORIGINAL_SHADE])
3955             opts.shadeMenubarOnlyWhenActive=false;
3956     }
3957 
3958     return active ? m_activeMdiColors : m_mdiColors;
3959 }
3960 
readMdiPositions() const3961 void Style::readMdiPositions() const
3962 {
3963     if (0==m_mdiButtons[0].size() && 0==m_mdiButtons[1].size()) {
3964 #ifdef Q_OS_MACOS
3965         // no control over where the system menu appears, so we have little choice
3966         // but to keep it at its default position. The user can still override this.
3967         m_mdiButtons[0].append(SC_TitleBarSysMenu);
3968         m_mdiButtons[0].append(SC_TitleBarCloseButton);
3969         m_mdiButtons[0].append(SC_TitleBarMinButton);
3970         m_mdiButtons[0].append(SC_TitleBarMaxButton);
3971 
3972         m_mdiButtons[1].append(SC_TitleBarShadeButton);
3973         m_mdiButtons[1].append(SC_TitleBarContextHelpButton);
3974 #else
3975         // Set defaults...
3976         m_mdiButtons[0].append(SC_TitleBarSysMenu);
3977         m_mdiButtons[0].append(SC_TitleBarShadeButton);
3978 
3979         m_mdiButtons[1].append(SC_TitleBarContextHelpButton);
3980         m_mdiButtons[1].append(SC_TitleBarMinButton);
3981         m_mdiButtons[1].append(SC_TitleBarMaxButton);
3982         m_mdiButtons[1].append(WINDOWTITLE_SPACER);
3983         m_mdiButtons[1].append(SC_TitleBarCloseButton);
3984 #endif
3985 
3986 #ifdef QTC_QT5_ENABLE_KDE
3987         KSharedConfigPtr cfg = KSharedConfig::openConfig("kwinrc");
3988         KConfigGroup grp = cfg->group("org.kde.kdecoration2");
3989 
3990         QString left=grp.readEntry("ButtonsOnLeft", QString()),
3991             right=grp.readEntry("ButtonsOnRight", QString());
3992 
3993         if(!left.isEmpty() || !right.isEmpty())
3994             m_mdiButtons[0].clear(), m_mdiButtons[1].clear();
3995 
3996         if(!left.isEmpty())
3997             parseWindowLine(left, m_mdiButtons[0]);
3998 
3999         if(!right.isEmpty())
4000             parseWindowLine(right, m_mdiButtons[1]);
4001 
4002         // Designer uses shade buttons, not min/max - so if we don't have shade in our kwin config.
4003         // then add this button near the max button...
4004         if (-1==m_mdiButtons[0].indexOf(SC_TitleBarShadeButton) && -1==m_mdiButtons[1].indexOf(SC_TitleBarShadeButton)) {
4005             int maxPos=m_mdiButtons[0].indexOf(SC_TitleBarMaxButton);
4006 
4007             if(-1==maxPos) // Left doesnt have max button, assume right does and add shade there
4008             {
4009                 int minPos=m_mdiButtons[1].indexOf(SC_TitleBarMinButton);
4010                 maxPos=m_mdiButtons[1].indexOf(SC_TitleBarMaxButton);
4011 
4012                 m_mdiButtons[1].insert(minPos<maxPos ? (minPos==-1 ? 0 : minPos)
4013                                         : (maxPos==-1 ? 0 : maxPos), SC_TitleBarShadeButton);
4014             }
4015             else // Add to left button
4016             {
4017                 int minPos=m_mdiButtons[0].indexOf(SC_TitleBarMinButton);
4018 
4019                 m_mdiButtons[1].insert(minPos>maxPos ? (minPos==-1 ? 0 : minPos)
4020                                         : (maxPos==-1 ? 0 : maxPos), SC_TitleBarShadeButton);
4021             }
4022         }
4023 #endif
4024     }
4025 }
4026 
getFill(const QStyleOption * option,const QColor * use,bool cr,bool darker) const4027 const QColor & Style::getFill(const QStyleOption *option, const QColor *use, bool cr, bool darker) const
4028 {
4029     return !option || !(option->state&State_Enabled)
4030         ? use[darker ? 2 : ORIGINAL_SHADE]
4031         : option->state&State_Sunken  // State_Down ????
4032         ? use[darker ? 5 : 4]
4033         : option->state&State_MouseOver
4034         ? !cr && option->state&State_On
4035         ? use[darker ? 3 : SHADE_4_HIGHLIGHT]
4036         : use[darker ? SHADE_2_HIGHLIGHT : SHADE_ORIG_HIGHLIGHT]
4037         : !cr && option->state&State_On
4038         ? use[darker ? 5 : 4]
4039         : use[darker ? 2 : ORIGINAL_SHADE];
4040 }
4041 
getPixmap(const QColor col,EPixmap p,double shade) const4042 QPixmap * Style::getPixmap(const QColor col, EPixmap p, double shade) const
4043 {
4044     QtcKey  key(createKey(col, p));
4045     QPixmap *pix=m_pixmapCache.object(key);
4046 
4047     if (!pix) {
4048         if (p == PIX_DOT) {
4049             pix=new QPixmap(5, 5);
4050             pix->fill(Qt::transparent);
4051 
4052             QColor          c(col);
4053             QPainter        p(pix);
4054             QLinearGradient g1(0, 0, 5, 5),
4055                 g2(0, 0, 3, 3);
4056 
4057             g1.setColorAt(0.0, c);
4058             c.setAlphaF(0.4);
4059             g1.setColorAt(1.0, c);
4060             c=Qt::white;
4061             c.setAlphaF(0.9);
4062             g2.setColorAt(0.0, c);
4063             c.setAlphaF(0.7);
4064             g2.setColorAt(1.0, c);
4065             p.setRenderHint(QPainter::Antialiasing, true);
4066             p.setPen(Qt::NoPen);
4067             p.setBrush(g1);
4068             p.drawEllipse(0, 0, 5, 5);
4069             p.setBrush(g2);
4070             p.drawEllipse(1, 1, 4, 4);
4071             p.end();
4072         }
4073         else
4074         {
4075             pix=new QPixmap();
4076 
4077             QImage img;
4078 
4079             switch(p)
4080             {
4081             case PIX_CHECK:
4082                 if(opts.xCheck) {
4083                     img = qtc_check_x_on;
4084                 } else {
4085                     img = qtc_check_on;
4086                 }
4087                 break;
4088             default:
4089                 break;
4090             }
4091 
4092             if (img.depth()<32)
4093                 img=img.convertToFormat(QImage::Format_ARGB32);
4094 
4095             qtcAdjustPix(img.bits(), 4, img.width(), img.height(),
4096                          img.bytesPerLine(), col.red(), col.green(),
4097                          col.blue(), shade, QTC_PIXEL_QT);
4098             *pix=QPixmap::fromImage(img);
4099         }
4100         m_pixmapCache.insert(key, pix, pix->depth()/8);
4101     }
4102 
4103     return pix;
4104 }
4105 
getTabFill(bool current,bool highlight,const QColor * use) const4106 const QColor & Style::getTabFill(bool current, bool highlight, const QColor *use) const
4107 {
4108     return (current ? use[ORIGINAL_SHADE] : highlight ?
4109             use[SHADE_2_HIGHLIGHT] : use[2]);
4110 }
4111 
menuStripeCol() const4112 QColor Style::menuStripeCol() const
4113 {
4114     switch(opts.menuStripe)
4115     {
4116     default:
4117     case SHADE_NONE:
4118         return m_backgroundCols[ORIGINAL_SHADE];
4119     case SHADE_CUSTOM:
4120         return opts.customMenuStripeColor;
4121     case SHADE_BLEND_SELECTED:
4122         // Hack! Use opts.customMenuStripeColor to store this setting!
4123         if (isBlack(opts.customMenuStripeColor)) {
4124             opts.customMenuStripeColor =
4125                 midColor(m_highlightCols[ORIGINAL_SHADE],
4126                          popupMenuCols()[ORIGINAL_SHADE]);
4127         }
4128         return opts.customMenuStripeColor;
4129     case SHADE_SELECTED:
4130         return m_highlightCols[MENU_STRIPE_SHADE];
4131     case SHADE_DARKEN:
4132         return popupMenuCols()[MENU_STRIPE_SHADE];
4133     }
4134 }
4135 
checkRadioCol(const QStyleOption * opt) const4136 const QColor & Style::checkRadioCol(const QStyleOption *opt) const
4137 {
4138     return opt->state&State_Enabled
4139         ? m_checkRadioCol
4140         : opts.crButton
4141         ? opt->palette.buttonText().color()
4142         : opt->palette.text().color();
4143 }
4144 
shade(const QColor & a,double k) const4145 QColor Style::shade(const QColor &a, double k) const
4146 {
4147     QColor mod;
4148     qtcShade(&a, &mod, k, opts.shading);
4149     return mod;
4150 }
4151 
shade(const QColor & ca,QColor * cb,double k) const4152 void Style::shade(const QColor &ca, QColor *cb, double k) const
4153 {
4154     qtcShade(&ca, cb, k, opts.shading);
4155 }
4156 
getLowerEtchCol(const QWidget * widget) const4157 QColor Style::getLowerEtchCol(const QWidget *widget) const
4158 {
4159     if(USE_CUSTOM_ALPHAS(opts))
4160     {
4161         QColor col(Qt::white);
4162         col.setAlphaF(opts.customAlphas[ALPHA_ETCH_LIGHT]);
4163         return col;
4164     }
4165 
4166     if (qtcIsFlatBgnd(opts.bgndAppearance)) {
4167         QtcQWidgetProps props(widget);
4168         bool doEtch = widget && widget->parentWidget() && !props->noEtch;
4169         // CPD: Don't really want to check here for every widget, when
4170         // (so far) on problem seems to be in KPackageKit, and thats with
4171         // its KTextBrowser - so just check when we draw scrollviews...
4172         // if (doEtch && isInQAbstractItemView(widget->parentWidget())) {
4173         //     doEtch = false;
4174         //     props->noEtch = true;
4175         // }
4176 
4177         if(doEtch)
4178         {
4179             QColor bgnd(widget->parentWidget()->palette().color(widget->parentWidget()->backgroundRole()));
4180 
4181             if(bgnd.alpha()>0)
4182                 return shade(bgnd, 1.06);
4183         }
4184     }
4185 
4186     QColor col(Qt::white);
4187     col.setAlphaF(0.1); // qtcIsFlatBgnd(opts.bgndAppearance) ? 0.25 : 0.4);
4188 
4189     return col;
4190 }
4191 
4192 int
getFrameRound(const QWidget * widget) const4193 Style::getFrameRound(const QWidget *widget) const
4194 {
4195     if (opts.square & SQUARE_FRAME) {
4196         return ROUNDED_NONE;
4197     }
4198     const QWidget *window = widget ? widget->window() : nullptr;
4199 
4200     if (window) {
4201         if (widget->rect() == window->rect()) {
4202             return ROUNDED_NONE;
4203         }
4204     }
4205 
4206     if ((opts.square & SQUARE_ENTRY) && widget &&
4207         qobject_cast<const QLabel*>(widget)) {
4208         return ROUNDED_NONE;
4209     }
4210     return ROUNDED_ALL;
4211 }
4212 
4213 void
widgetDestroyed(QObject * o)4214 Style::widgetDestroyed(QObject *o)
4215 {
4216     QWidget *w = static_cast<QWidget*>(o);
4217     if (theThemedApp == APP_KONTACT) {
4218         m_sViewContainers.remove(w);
4219         QMap<QWidget*, QSet<QWidget*> >::Iterator it(m_sViewContainers.begin());
4220         QMap<QWidget*, QSet<QWidget*> >::Iterator end(m_sViewContainers.end());
4221         QSet<QWidget*> rem;
4222 
4223         for (;it != end;++it) {
4224             (*it).remove(w);
4225             if ((*it).isEmpty()) {
4226                 rem.insert(it.key());
4227             }
4228         }
4229         for (QWidget *widget: const_(rem)) {
4230             m_sViewContainers.remove(widget);
4231         }
4232     }
4233 }
4234 
4235 #ifdef QTC_QT5_ENABLE_KDE
setupKde4()4236 void Style::setupKde4()
4237 {
4238     if(kapp) {
4239         setDecorationColors();
4240     } else {
4241         applyKdeSettings(true);
4242         applyKdeSettings(false);
4243     }
4244 }
4245 
4246 void
setDecorationColors()4247 Style::setDecorationColors()
4248 {
4249     KColorScheme kcs(QPalette::Active);
4250     if (opts.coloredMouseOver) {
4251         shadeColors(kcs.decoration(KColorScheme::HoverColor).color(),
4252                     m_mouseOverCols);
4253     }
4254     shadeColors(kcs.decoration(KColorScheme::FocusColor).color(), m_focusCols);
4255 }
4256 
applyKdeSettings(bool pal)4257 void Style::applyKdeSettings(bool pal)
4258 {
4259     if(pal)
4260     {
4261         if(!kapp)
4262             QApplication::setPalette(standardPalette());
4263         setDecorationColors();
4264     }
4265     else
4266     {
4267         KConfigGroup g(m_configFile, "General");
4268         QFont        mnu=g.readEntry("menuFont", QApplication::font());
4269 
4270         QApplication::setFont(g.readEntry("font", QApplication::font()));
4271         QApplication::setFont(mnu, "QMenuBar");
4272         QApplication::setFont(mnu, "QMenu");
4273         QApplication::setFont(mnu, "KPopupTitle");
4274         QApplication::setFont(KGlobalSettings::toolBarFont(), "QToolBar");
4275     }
4276 }
4277 #endif
4278 
kdeGlobalSettingsChange(int type,int)4279 void Style::kdeGlobalSettingsChange(int type, int)
4280 {
4281 #ifndef QTC_QT5_ENABLE_KDE
4282     Q_UNUSED(type);
4283 #else
4284     switch(type) {
4285     case KGlobalSettings::StyleChanged: {
4286         m_configFile->reparseConfiguration();
4287         if (m_usePixmapCache)
4288             QPixmapCache::clear();
4289         init(false);
4290 
4291         for (QWidget *widget: QApplication::topLevelWidgets()) {
4292             widget->update();
4293         }
4294         break;
4295     }
4296     case KGlobalSettings::PaletteChanged:
4297         m_configFile->reparseConfiguration();
4298         applyKdeSettings(true);
4299         if (m_usePixmapCache)
4300             QPixmapCache::clear();
4301         break;
4302     case KGlobalSettings::FontChanged:
4303         m_configFile->reparseConfiguration();
4304         applyKdeSettings(false);
4305         break;
4306     }
4307 #endif
4308 
4309     m_blurHelper->setEnabled(Utils::compositingActive());
4310     m_windowManager->initialize(opts.windowDrag);
4311 }
4312 
borderSizesChanged()4313 void Style::borderSizesChanged()
4314 {
4315 #ifdef QTC_QT5_ENABLE_KDE
4316     int old = qtcGetWindowBorderSize(false).titleHeight;
4317 
4318     if (old != qtcGetWindowBorderSize(true).titleHeight) {
4319         for (QWidget *widget: QApplication::topLevelWidgets()) {
4320             if (qobject_cast<QMainWindow*>(widget) &&
4321                 static_cast<QMainWindow*>(widget)->menuBar()) {
4322                 static_cast<QMainWindow*>(widget)->menuBar()->update();
4323             }
4324         }
4325     }
4326 #endif
4327 }
4328 
4329 static QMainWindow*
getWindow(unsigned int xid)4330 getWindow(unsigned int xid)
4331 {
4332     QTC_RET_IF_FAIL(xid, nullptr);
4333     for (QWidget *widget: QApplication::topLevelWidgets()) {
4334         if (qobject_cast<QMainWindow*>(widget) && qtcGetWid(widget) == xid) {
4335             return static_cast<QMainWindow*>(widget);
4336         }
4337     }
4338     return nullptr;
4339 }
4340 
4341 static bool
diffTime(struct timeval * lastTime)4342 diffTime(struct timeval *lastTime)
4343 {
4344     struct timeval now, diff;
4345 
4346     gettimeofday(&now, nullptr);
4347     timersub(&now, lastTime, &diff);
4348     *lastTime = now;
4349     return diff.tv_sec > 0 || diff.tv_usec > 500000;
4350 }
4351 
4352 void
toggleMenuBar(unsigned int xid)4353 Style::toggleMenuBar(unsigned int xid)
4354 {
4355     static unsigned int lastXid = 0;
4356     static struct timeval lastTime = {0, 0};
4357 
4358     if (diffTime(&lastTime) || lastXid != xid) {
4359         QMainWindow *win = getWindow(xid);
4360         if (win) {
4361             toggleMenuBar(win);
4362         }
4363     }
4364     lastXid = xid;
4365 }
4366 
4367 void
toggleStatusBar(unsigned int xid)4368 Style::toggleStatusBar(unsigned int xid)
4369 {
4370     static unsigned int lastXid = 0;
4371     static struct timeval lastTime = {0, 0};
4372 
4373     if (diffTime(&lastTime) || lastXid != xid) {
4374         QMainWindow *win = getWindow(xid);
4375         if (win) {
4376             toggleStatusBar(win);
4377         }
4378     }
4379     lastXid = xid;
4380 }
4381 
compositingToggled()4382 void Style::compositingToggled()
4383 {
4384     for (QWidget *widget: QApplication::topLevelWidgets()) {
4385         widget->update();
4386     }
4387 }
4388 
toggleMenuBar(QMainWindow * window)4389 void Style::toggleMenuBar(QMainWindow *window)
4390 {
4391     bool triggeredAction(false);
4392 
4393 #ifdef QTC_QT5_ENABLE_KDE
4394     if (qobject_cast<KXmlGuiWindow*>(window)) {
4395         KActionCollection *collection=static_cast<KXmlGuiWindow *>(window)->actionCollection();
4396         QAction           *act=collection ? collection->action(KStandardAction::name(KStandardAction::ShowMenubar)) : 0L;
4397         if(act)
4398         {
4399             act->trigger();
4400             triggeredAction=true;
4401         }
4402     }
4403 #endif
4404     if(!triggeredAction)
4405     {
4406         QWidget *menubar=window->menuWidget();
4407         if(m_saveMenuBarStatus)
4408             qtcSetMenuBarHidden(appName, menubar->isVisible());
4409 
4410         window->menuWidget()->setHidden(menubar->isVisible());
4411     }
4412 }
4413 
toggleStatusBar(QMainWindow * window)4414 void Style::toggleStatusBar(QMainWindow *window)
4415 {
4416     bool triggeredAction(false);
4417 
4418 #ifdef QTC_QT5_ENABLE_KDE
4419     if (qobject_cast<KXmlGuiWindow*>(window)) {
4420         KActionCollection *collection=static_cast<KXmlGuiWindow *>(window)->actionCollection();
4421         QAction           *act=collection ? collection->action(KStandardAction::name(KStandardAction::ShowStatusbar)) : 0L;
4422         if(act)
4423         {
4424             act->trigger();
4425             triggeredAction=true;
4426             //emitStatusBarState(true); // TODO: ???
4427         }
4428     }
4429 #endif
4430     if (!triggeredAction) {
4431         QList<QStatusBar*> sb = getStatusBars(window);
4432 
4433         if (sb.count()) {
4434             if (m_saveStatusBarStatus) {
4435                 qtcSetStatusBarHidden(appName, sb.first()->isVisible());
4436             }
4437             for (QStatusBar *statusBar: const_(sb)) {
4438                 statusBar->setHidden(statusBar->isVisible());
4439             }
4440             emitStatusBarState(sb.first());
4441         }
4442     }
4443 }
4444 
emitMenuSize(QWidget * w,unsigned short size,bool force)4445 void Style::emitMenuSize(QWidget *w, unsigned short size, bool force)
4446 {
4447     // DO NOT condition compile on QTC_ENABLE_X11.
4448     // There's no direct linkage on X11 and the following code will just do
4449     // nothing if X11 is not enabled (either at compile time or at run time).
4450     QTC_RET_IF_FAIL(qtcX11Enabled());
4451 
4452     if (WId wid = qtcGetWid(w->window())) {
4453         static const char *constMenuSizeProperty = "qtcMenuSize";
4454         unsigned short oldSize = 2000;
4455 
4456         if (!force) {
4457             QVariant prop(w->property(constMenuSizeProperty));
4458             if (prop.isValid()) {
4459                 bool ok;
4460                 oldSize = prop.toUInt(&ok);
4461                 if (!ok) {
4462                     oldSize = 2000;
4463                 }
4464             }
4465         }
4466 
4467         if (oldSize != size) {
4468             w->setProperty(constMenuSizeProperty, size);
4469             qtcX11SetMenubarSize(wid, size);
4470             if(!m_dBus)
4471                 m_dBus = new QDBusInterface("org.kde.kwin", "/QtCurve",
4472                                              "org.kde.QtCurve");
4473             m_dBus->call(QDBus::NoBlock, "menuBarSize",
4474                           (unsigned int)wid, (int)size);
4475         }
4476     }
4477 }
4478 
emitStatusBarState(QStatusBar * sb)4479 void Style::emitStatusBarState(QStatusBar *sb)
4480 {
4481     if (opts.statusbarHiding & HIDE_KWIN) {
4482         if (!m_dBus)
4483             m_dBus = new QDBusInterface("org.kde.kwin", "/QtCurve",
4484                                         "org.kde.QtCurve");
4485         m_dBus->call(QDBus::NoBlock, "statusBarState",
4486                      (unsigned int)qtcGetWid(sb->window()),
4487                      sb->isVisible());
4488     }
4489 }
4490 }
4491