File indexing completed on 2024-04-28 05:47:19

0001 /*****************************************************************************
0002  *   Copyright 2007 - 2010 Craig Drummond <craig.p.drummond@gmail.com>       *
0003  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
0004  *                                                                           *
0005  *   This program is free software; you can redistribute it and/or modify    *
0006  *   it under the terms of the GNU Lesser General Public License as          *
0007  *   published by the Free Software Foundation; either version 2.1 of the    *
0008  *   License, or (at your option) version 3, or any later version accepted   *
0009  *   by the membership of KDE e.V. (or its successor approved by the         *
0010  *   membership of KDE e.V.), which shall act as a proxy defined in          *
0011  *   Section 6 of version 3 of the license.                                  *
0012  *                                                                           *
0013  *   This program is distributed in the hope that it will be useful,         *
0014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
0015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
0016  *   Lesser General Public License for more details.                         *
0017  *                                                                           *
0018  *   You should have received a copy of the GNU Lesser General Public        *
0019  *   License along with this library. If not,                                *
0020  *   see <http://www.gnu.org/licenses/>.                                     *
0021  *****************************************************************************/
0022 
0023 #include "qtcurve_p.h"
0024 #include "qtcurve_plugin.h"
0025 #include "qtcurve_fonthelper.h"
0026 #include <qtcurve-utils/qtprops.h>
0027 
0028 #include <qglobal.h>
0029 #include <QDBusConnection>
0030 #include <QDBusInterface>
0031 #include "windowmanager.h"
0032 #include "blurhelper.h"
0033 #include "shortcuthandler.h"
0034 #include <common/config_file.h>
0035 #include "check_on-png.h"
0036 #include "check_x_on-png.h"
0037 
0038 #ifndef QTC_QT5_ENABLE_KDE
0039 #  include "dialog_error-png.h"
0040 #  include "dialog_warning-png.h"
0041 #  include "dialog_information-png.h"
0042 #endif
0043 
0044 #include <QFormLayout>
0045 #include <QAbstractItemView>
0046 #include <QDialog>
0047 #include <QSplitter>
0048 #include <QMdiSubWindow>
0049 #include <QMainWindow>
0050 #include <QComboBox>
0051 #include <QTreeView>
0052 #include <QGroupBox>
0053 #include <QListView>
0054 #include <QCheckBox>
0055 #include <QRadioButton>
0056 #include <QTextEdit>
0057 #include <QDial>
0058 #include <QLabel>
0059 #include <QStackedLayout>
0060 #include <QMenuBar>
0061 #include <QMouseEvent>
0062 #include <QScrollBar>
0063 #include <QWizard>
0064 #include <QDialogButtonBox>
0065 #include <QHeaderView>
0066 #include <QLineEdit>
0067 #include <QSpinBox>
0068 #include <QDir>
0069 #include <QSettings>
0070 #include <QPixmapCache>
0071 #include <QTextStream>
0072 #include <QtDebug>
0073 
0074 #include "shadowhelper.h"
0075 #include <qtcurve-utils/x11qtc.h>
0076 #include <sys/time.h>
0077 
0078 #ifdef QTC_QT5_ENABLE_KDE
0079 #include <KConfigCore/KSharedConfig>
0080 #include <KWindowSystem/KWindowSystem>
0081 #include <KConfigWidgets/KColorScheme>
0082 #include <KConfigWidgets/KStandardAction>
0083 #include <KXmlGui/KActionCollection>
0084 #include <KXmlGui/KXmlGuiWindow>
0085 #endif
0086 
0087 #include <qtcurve-utils/color.h>
0088 
0089 namespace QtCurve {
0090 
0091 class Style::DBusHelper {
0092 public:
0093     DBusHelper()
0094         : m_dBus(0)
0095         , m_dbusConnected(false)
0096     {}
0097     ~DBusHelper()
0098     {
0099         if (m_dBus) {
0100             m_dBus->disconnect();
0101             m_dBus->deleteLater();
0102             m_dBus = 0;
0103         }
0104     }
0105 
0106     std::once_flag m_aboutToQuitInit;
0107     QDBusInterface *m_dBus;
0108     bool m_dbusConnected;
0109 };
0110 
0111 static inline void setPainterPen(QPainter *p, const QColor &col, const qreal width=1.0)
0112 {
0113     p->setPen(QPen(col, width));
0114 }
0115 
0116 static Style::Icon
0117 pix2Icon(QStyle::StandardPixmap pix)
0118 {
0119     switch (pix) {
0120     case QStyle::SP_TitleBarNormalButton:
0121         return Style::ICN_RESTORE;
0122     case QStyle::SP_TitleBarShadeButton:
0123         return Style::ICN_SHADE;
0124     case QStyle::SP_ToolBarHorizontalExtensionButton:
0125         return Style::ICN_RIGHT;
0126     case QStyle::SP_ToolBarVerticalExtensionButton:
0127         return Style::ICN_DOWN;
0128     case QStyle::SP_TitleBarUnshadeButton:
0129         return Style::ICN_UNSHADE;
0130     default:
0131     case QStyle::SP_DockWidgetCloseButton:
0132     case QStyle::SP_TitleBarCloseButton:
0133         return Style::ICN_CLOSE;
0134     }
0135 }
0136 
0137 static Style::Icon
0138 subControlToIcon(QStyle::SubControl sc)
0139 {
0140     switch (sc) {
0141     case QStyle::SC_TitleBarMinButton:
0142         return Style::ICN_MIN;
0143     case QStyle::SC_TitleBarMaxButton:
0144         return Style::ICN_MAX;
0145     case QStyle::SC_TitleBarCloseButton:
0146     default:
0147         return Style::ICN_CLOSE;
0148     case QStyle::SC_TitleBarNormalButton:
0149         return Style::ICN_RESTORE;
0150     case QStyle::SC_TitleBarShadeButton:
0151         return Style::ICN_SHADE;
0152     case QStyle::SC_TitleBarUnshadeButton:
0153         return Style::ICN_UNSHADE;
0154     case QStyle::SC_TitleBarSysMenu:
0155         return Style::ICN_MENU;
0156     }
0157 }
0158 
0159 QtcThemedApp theThemedApp = APP_OTHER;
0160 
0161 // do not initialise the variable here by calling qApp->arguments(). Normally it will
0162 // be safe when we're loaded as a style plugin in a Qt application (which happens during
0163 // the Q*Application initialisation phase so the qApp instance exists). However, when
0164 // we're loaded in a different context this can happen:
0165 // `QCoreApplication::arguments: Please instantiate the QApplication object first`
0166 // `Segmentation fault`
0167 QString appName;
0168 
0169 static QColor
0170 checkColour(const QStyleOption *option, QPalette::ColorRole role)
0171 {
0172     QColor col(option->palette.brush(role).color());
0173 
0174     if (col.alpha() == 255 && isBlack(col))
0175         return QApplication::palette().brush(role).color();
0176     return col;
0177 }
0178 
0179 static void
0180 addStripes(QPainter *p, const QPainterPath &path,
0181            const QRect &rect, bool horizontal)
0182 {
0183     QColor col(Qt::white);
0184     QLinearGradient patternGradient(rect.topLeft(),
0185                                     rect.topLeft() +
0186                                     (horizontal ? QPoint(STRIPE_WIDTH, 0) :
0187                                      QPoint(0, STRIPE_WIDTH)));
0188 
0189     col.setAlphaF(0.0);
0190     patternGradient.setColorAt(0.0, col);
0191     col.setAlphaF(0.15);
0192     patternGradient.setColorAt(1.0, col);
0193     patternGradient.setSpread(QGradient::ReflectSpread);
0194     if (path.isEmpty()) {
0195         p->fillRect(rect, patternGradient);
0196     } else {
0197         p->save();
0198         p->setRenderHint(QPainter::Antialiasing, true);
0199         p->fillPath(path, patternGradient);
0200         p->restore();
0201     }
0202 }
0203 
0204 #ifndef QTC_QT5_ENABLE_KDE
0205 static void
0206 setRgb(QColor *col, const QStringList &rgb)
0207 {
0208     if (rgb.size() == 3) {
0209         *col = QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt());
0210     }
0211 }
0212 
0213 static QString
0214 kdeHome()
0215 {
0216     static QString kdeHomePath;
0217     if (kdeHomePath.isEmpty()) {
0218         kdeHomePath = QString::fromLocal8Bit(qgetenv("KDEHOME"));
0219         if (kdeHomePath.isEmpty()) {
0220             QDir homeDir(QDir::homePath());
0221             QString kdeConfDir(QLatin1String("/.kde"));
0222             if (homeDir.exists(QLatin1String(".kde4")))
0223                 kdeConfDir = QLatin1String("/.kde4");
0224             kdeHomePath = QDir::homePath() + kdeConfDir;
0225         }
0226     }
0227     return kdeHomePath;
0228 }
0229 #endif
0230 
0231 static bool
0232 isHoriz(const QStyleOption *option, EWidget w, bool joinedTBar)
0233 {
0234     return (option->state & QStyle::State_Horizontal ||
0235             (WIDGET_BUTTON(w) &&
0236              (!joinedTBar || noneOf(w, WIDGET_TOOLBAR_BUTTON,
0237                                     WIDGET_NO_ETCH_BTN,
0238                                     WIDGET_MENU_BUTTON))));
0239 }
0240 
0241 static bool
0242 isOnToolbar(const QWidget *widget)
0243 {
0244     const QWidget *wid = widget ? widget->parentWidget() : 0L;
0245     while (wid) {
0246         if (qobject_cast<const QToolBar*>(wid)) {
0247             return true;
0248         }
0249         wid = wid->parentWidget();
0250     }
0251     return false;
0252 }
0253 
0254 /*
0255   Cache key:
0256   widgettype 2
0257   app        5
0258   size      15
0259   horiz      1
0260   alpha      8
0261   blue       8
0262   green      8
0263   red        8
0264   type       1  (0 for widget, 1 for pixmap)
0265   ------------
0266   56
0267 */
0268 enum ECacheType {
0269     CACHE_STD,
0270     CACHE_PBAR,
0271     CACHE_TAB_TOP,
0272     CACHE_TAB_BOT
0273 };
0274 
0275 static QtcKey
0276 createKey(qulonglong size, const QColor &color, bool horiz, int app, EWidget w)
0277 {
0278     ECacheType type=WIDGET_TAB_TOP==w
0279         ? CACHE_TAB_TOP
0280         : WIDGET_TAB_BOT==w
0281         ? CACHE_TAB_BOT
0282         : WIDGET_PROGRESSBAR==w
0283         ? CACHE_PBAR
0284         : CACHE_STD;
0285 
0286     return (color.rgba()<<1)+
0287         (((qulonglong)(horiz ? 1 : 0))<<33)+
0288         (((qulonglong)(size&0xFFFF))<<34)+
0289         (((qulonglong)(app&0x1F))<<50)+
0290         (((qulonglong)(type&0x03))<<55);
0291 }
0292 
0293 static QtcKey createKey(const QColor &color, EPixmap p)
0294 {
0295     return 1 +
0296         ((color.rgb()&RGB_MASK)<<1)+
0297         (((qulonglong)(p&0x1F))<<33)+
0298         (((qulonglong)1)<<38);
0299 }
0300 
0301 #ifdef QTC_QT5_ENABLE_KDE
0302 static void parseWindowLine(const QString &line, QList<int> &data)
0303 {
0304     int len(line.length());
0305 
0306     for(int i = 0;i < len;++i) {
0307         switch(line[i].toLatin1()) {
0308         case 'M':
0309             data.append(QStyle::SC_TitleBarSysMenu);
0310             break;
0311         case '_':
0312             data.append(WINDOWTITLE_SPACER);
0313             break;
0314         case 'H':
0315             data.append(QStyle::SC_TitleBarContextHelpButton);
0316             break;
0317         case 'L':
0318             data.append(QStyle::SC_TitleBarShadeButton);
0319             break;
0320         case 'I':
0321             data.append(QStyle::SC_TitleBarMinButton);
0322             break;
0323         case 'A':
0324             data.append(QStyle::SC_TitleBarMaxButton);
0325             break;
0326         case 'X':
0327             data.append(QStyle::SC_TitleBarCloseButton);
0328         default:
0329             break;
0330         }
0331     }
0332 }
0333 #endif
0334 
0335 Style::Style() :
0336     m_dBusHelper(new DBusHelper()),
0337     m_fntHelper(new FontHelper()),
0338     m_popupMenuCols(0L),
0339     m_sliderCols(0L),
0340     m_defBtnCols(0L),
0341     m_comboBtnCols(0L),
0342     m_checkRadioSelCols(0L),
0343     m_sortedLvColors(0L),
0344     m_ooMenuCols(0L),
0345     m_progressCols(0L),
0346     m_saveMenuBarStatus(false),
0347     m_usePixmapCache(true),
0348     m_inactiveChangeSelectionColor(false),
0349     m_isPreview(PREVIEW_FALSE),
0350     m_sidebarButtonsCols(0L),
0351     m_activeMdiColors(0L),
0352     m_mdiColors(0L),
0353     m_pixmapCache(150000),
0354     m_active(true),
0355     m_sbWidget(0L),
0356     m_clickedLabel(0L),
0357     m_progressBarAnimateTimer(0),
0358     m_animateStep(0),
0359     m_titlebarHeight(0),
0360     m_shadowHelper(new ShadowHelper(this)),
0361     m_sViewSBar(0L),
0362     m_windowManager(new WindowManager(this)),
0363     m_blurHelper(new BlurHelper(this)),
0364     m_shortcutHandler(new ShortcutHandler(this))
0365 {
0366     const char *env = getenv(QTCURVE_PREVIEW_CONFIG);
0367 #ifdef QTC_QT5_ENABLE_KDE
0368     m_configFile = KSharedConfig::openConfig();
0369     m_kdeGlobals = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::NoGlobals);
0370 #endif
0371     if (env && strcmp(env, QTCURVE_PREVIEW_CONFIG) == 0) {
0372         // To enable preview of QtCurve settings, the style config module will set QTCURVE_PREVIEW_CONFIG
0373         // and use CE_QtC_SetOptions to set options. If this is set, we do not use the QPixmapCache as it
0374         // will interfere with that of the kcm's widgets!
0375         m_isPreview=PREVIEW_MDI;
0376         m_usePixmapCache=false;
0377     } else if(env && strcmp(env, QTCURVE_PREVIEW_CONFIG_FULL) == 0) {
0378         // As above, but preview is in window - so can use opacity settings!
0379         m_isPreview=PREVIEW_WINDOW;
0380         m_usePixmapCache=false;
0381     } else {
0382         init(true);
0383     }
0384 }
0385 
0386 void Style::init(bool initial)
0387 {
0388     if(!initial)
0389         freeColors();
0390 
0391     if (m_isPreview) {
0392         if (m_isPreview != PREVIEW_WINDOW) {
0393             opts.bgndOpacity = opts.dlgOpacity = opts.menuBgndOpacity = 100;
0394         }
0395     } else {
0396         qtcReadConfig(QString(), &opts);
0397 
0398         if (initial) {
0399             if (QCoreApplication::instance()) {
0400                 // we can obtain the application name safely.
0401                 appName = QFileInfo(QCoreApplication::instance()->arguments()[0]).fileName();
0402             }
0403 #ifdef Q_OS_MACOS
0404             if (opts.nonnativeMenubarApps.contains("kde") || opts.nonnativeMenubarApps.contains(appName)) {
0405                 QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
0406                 opts.currentNonnativeMenubarApps << appName;
0407             }
0408 #endif
0409             connectDBus();
0410 #ifdef QTC_QT5_ENABLE_KDE
0411             connect(KWindowSystem::self(), &KWindowSystem::compositingChanged, this, &Style::compositingToggled);
0412 #endif
0413             // prepare the cleanup handler
0414             if (QCoreApplication::instance()) {
0415                 std::call_once(m_dBusHelper->m_aboutToQuitInit, [this] {
0416                     connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, [this] () {
0417                             // disconnect from the session DBus. We're no longer interested in the
0418                             // information it might send when the app we're serving is shutting down.
0419                             disconnectDBus();
0420                             // Stop listening to select signals. We shouldn't stop emitting signals
0421                             // (like QObject::destroyed) but we can reduce the likelihood that pending
0422                             // signals will be sent to us post-mortem.
0423 #ifdef QTC_QT5_ENABLE_KDE
0424                             disconnect(KWindowSystem::self(), &KWindowSystem::compositingChanged,
0425                                        this, &Style::compositingToggled);
0426 #endif
0427                         } );
0428                 } );
0429             }
0430         }
0431     }
0432 
0433     opts.contrast=QSettings(QLatin1String("Trolltech")).value("/Qt/KDE/contrast", DEFAULT_CONTRAST).toInt();
0434     if(opts.contrast<0 || opts.contrast>10)
0435         opts.contrast=DEFAULT_CONTRAST;
0436 
0437     shadeColors(QApplication::palette().color(QPalette::Active, QPalette::Highlight), m_highlightCols);
0438     shadeColors(QApplication::palette().color(QPalette::Active, QPalette::Background), m_backgroundCols);
0439     shadeColors(QApplication::palette().color(QPalette::Active, QPalette::Button), m_buttonCols);
0440 
0441     // Set defaults for Hover and Focus, these will be changed when KDE4 palette is applied...
0442     shadeColors(QApplication::palette().color(QPalette::Active,
0443                                               QPalette::Highlight), m_focusCols);
0444     shadeColors(QApplication::palette().color(QPalette::Active, QPalette::Highlight), m_mouseOverCols);
0445 // Dont setup KDE4 fonts/colours here - seems to mess things up when using proxy styles.
0446 // See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=638629
0447 //#ifdef QTC_QT5_ENABLE_KDE
0448 //    setupKde4();
0449 //#endif
0450 
0451     m_windowManager->initialize(opts.windowDrag, opts.windowDragWhiteList.values(), opts.windowDragBlackList.values());
0452 
0453     switch(opts.shadeSliders)
0454     {
0455     default:
0456     case SHADE_DARKEN:
0457     case SHADE_NONE:
0458         break;
0459     case SHADE_SELECTED:
0460         m_sliderCols=m_highlightCols;
0461         break;
0462     case SHADE_BLEND_SELECTED:
0463     case SHADE_CUSTOM:
0464         if (!m_sliderCols) {
0465             m_sliderCols = new QColor[TOTAL_SHADES + 1];
0466         }
0467         shadeColors(opts.shadeSliders == SHADE_BLEND_SELECTED ?
0468                     midColor(m_highlightCols[ORIGINAL_SHADE],
0469                              m_buttonCols[ORIGINAL_SHADE]) :
0470                     opts.customSlidersColor, m_sliderCols);
0471     }
0472 
0473     switch(opts.defBtnIndicator)
0474     {
0475     case IND_GLOW:
0476     case IND_SELECTED:
0477         m_defBtnCols=m_highlightCols;
0478         break;
0479     case IND_TINT:
0480         m_defBtnCols=new QColor [TOTAL_SHADES+1];
0481         shadeColors(tint(m_buttonCols[ORIGINAL_SHADE],
0482                          m_highlightCols[ORIGINAL_SHADE], DEF_BNT_TINT),
0483                     m_defBtnCols);
0484         break;
0485     default:
0486         break;
0487     case IND_COLORED:
0488         if (opts.shadeSliders == SHADE_BLEND_SELECTED) {
0489             m_defBtnCols = m_sliderCols;
0490         } else {
0491             m_defBtnCols = new QColor[TOTAL_SHADES + 1];
0492             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE],
0493                                  m_buttonCols[ORIGINAL_SHADE]), m_defBtnCols);
0494         }
0495     }
0496 
0497     switch(opts.comboBtn) {
0498     default:
0499     case SHADE_DARKEN:
0500     case SHADE_NONE:
0501         break;
0502     case SHADE_SELECTED:
0503         m_comboBtnCols=m_highlightCols;
0504         break;
0505     case SHADE_BLEND_SELECTED:
0506         if (opts.shadeSliders == SHADE_BLEND_SELECTED) {
0507             m_comboBtnCols = m_sliderCols;
0508             break;
0509         }
0510         QTC_FALLTHROUGH();
0511     case SHADE_CUSTOM:
0512         if (opts.shadeSliders == SHADE_CUSTOM &&
0513             opts.customSlidersColor == opts.customComboBtnColor) {
0514             m_comboBtnCols = m_sliderCols;
0515             break;
0516         }
0517         if (!m_comboBtnCols) {
0518             m_comboBtnCols = new QColor[TOTAL_SHADES + 1];
0519         }
0520         shadeColors(opts.comboBtn == SHADE_BLEND_SELECTED ?
0521                     midColor(m_highlightCols[ORIGINAL_SHADE],
0522                              m_buttonCols[ORIGINAL_SHADE]) :
0523                     opts.customComboBtnColor, m_comboBtnCols);
0524     }
0525 
0526     switch (opts.sortedLv) {
0527     case SHADE_DARKEN:
0528         if (!m_sortedLvColors) {
0529             m_sortedLvColors = new QColor[TOTAL_SHADES + 1];
0530         }
0531         shadeColors(shade(opts.lvButton ? m_buttonCols[ORIGINAL_SHADE] : m_backgroundCols[ORIGINAL_SHADE], LV_HEADER_DARK_FACTOR), m_sortedLvColors);
0532         break;
0533     default:
0534     case SHADE_NONE:
0535         break;
0536     case SHADE_SELECTED:
0537         m_sortedLvColors=m_highlightCols;
0538         break;
0539     case SHADE_BLEND_SELECTED:
0540         if (opts.shadeSliders == SHADE_BLEND_SELECTED) {
0541             m_sortedLvColors = m_sliderCols;
0542             break;
0543         } else if (opts.comboBtn == SHADE_BLEND_SELECTED) {
0544             m_sortedLvColors = m_comboBtnCols;
0545             break;
0546         }
0547         QTC_FALLTHROUGH();
0548     case SHADE_CUSTOM:
0549         if (opts.shadeSliders == SHADE_CUSTOM &&
0550             opts.customSlidersColor == opts.customSortedLvColor) {
0551             m_sortedLvColors = m_sliderCols;
0552             break;
0553         }
0554         if (opts.comboBtn == SHADE_CUSTOM &&
0555             opts.customComboBtnColor == opts.customSortedLvColor) {
0556             m_sortedLvColors = m_comboBtnCols;
0557             break;
0558         }
0559         if (!m_sortedLvColors) {
0560             m_sortedLvColors = new QColor[TOTAL_SHADES + 1];
0561         }
0562         shadeColors(opts.sortedLv == SHADE_BLEND_SELECTED ?
0563                     midColor(m_highlightCols[ORIGINAL_SHADE],
0564                              (opts.lvButton ? m_buttonCols[ORIGINAL_SHADE] :
0565                               m_backgroundCols[ORIGINAL_SHADE])) :
0566                     opts.customSortedLvColor, m_sortedLvColors);
0567     }
0568 
0569     switch (opts.crColor) {
0570     default:
0571     case SHADE_NONE:
0572         m_checkRadioSelCols = m_buttonCols;
0573         break;
0574     case SHADE_DARKEN:
0575         if (!m_checkRadioSelCols) {
0576             m_checkRadioSelCols = new QColor[TOTAL_SHADES + 1];
0577         }
0578         shadeColors(shade(m_buttonCols[ORIGINAL_SHADE], LV_HEADER_DARK_FACTOR),
0579                     m_checkRadioSelCols);
0580         break;
0581     case SHADE_SELECTED:
0582         m_checkRadioSelCols = m_highlightCols;
0583         break;
0584     case SHADE_CUSTOM:
0585         if(SHADE_CUSTOM==opts.shadeSliders && opts.customSlidersColor==opts.customCrBgndColor)
0586             m_checkRadioSelCols=m_sliderCols;
0587         else if(SHADE_CUSTOM==opts.comboBtn && opts.customComboBtnColor==opts.customCrBgndColor)
0588             m_checkRadioSelCols=m_comboBtnCols;
0589         else if(SHADE_CUSTOM==opts.sortedLv && opts.customSortedLvColor==opts.customCrBgndColor)
0590             m_checkRadioSelCols=m_sortedLvColors;
0591         else
0592         {
0593             if(!m_checkRadioSelCols)
0594                 m_checkRadioSelCols=new QColor [TOTAL_SHADES+1];
0595             shadeColors(opts.customCrBgndColor, m_checkRadioSelCols);
0596         }
0597         break;
0598     case SHADE_BLEND_SELECTED:
0599         if(SHADE_BLEND_SELECTED==opts.shadeSliders)
0600             m_checkRadioSelCols=m_sliderCols;
0601         else if(SHADE_BLEND_SELECTED==opts.comboBtn)
0602             m_checkRadioSelCols=m_comboBtnCols;
0603         else if(SHADE_BLEND_SELECTED==opts.sortedLv)
0604             m_checkRadioSelCols=m_sortedLvColors;
0605         else
0606         {
0607             if(!m_checkRadioSelCols)
0608                 m_checkRadioSelCols=new QColor [TOTAL_SHADES+1];
0609             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE], m_buttonCols[ORIGINAL_SHADE]), m_checkRadioSelCols);
0610         }
0611     }
0612 
0613     switch(opts.progressColor)
0614     {
0615     case SHADE_NONE:
0616         m_progressCols=m_backgroundCols;
0617         break;
0618     default:
0619         // Not set!
0620         break;
0621     case SHADE_CUSTOM:
0622         if(SHADE_CUSTOM==opts.shadeSliders && opts.customSlidersColor==opts.customProgressColor)
0623             m_progressCols=m_sliderCols;
0624         else if(SHADE_CUSTOM==opts.comboBtn && opts.customComboBtnColor==opts.customProgressColor)
0625             m_progressCols=m_comboBtnCols;
0626         else if(SHADE_CUSTOM==opts.sortedLv && opts.customSortedLvColor==opts.customProgressColor)
0627             m_progressCols=m_sortedLvColors;
0628         else if(SHADE_CUSTOM==opts.crColor && opts.customCrBgndColor==opts.customProgressColor)
0629             m_progressCols=m_checkRadioSelCols;
0630         else
0631         {
0632             if(!m_progressCols)
0633                 m_progressCols=new QColor [TOTAL_SHADES+1];
0634             shadeColors(opts.customProgressColor, m_progressCols);
0635         }
0636         break;
0637     case SHADE_BLEND_SELECTED:
0638         if(SHADE_BLEND_SELECTED==opts.shadeSliders)
0639             m_progressCols=m_sliderCols;
0640         else if(SHADE_BLEND_SELECTED==opts.comboBtn)
0641             m_progressCols=m_comboBtnCols;
0642         else if(SHADE_BLEND_SELECTED==opts.sortedLv)
0643             m_progressCols=m_sortedLvColors;
0644         else
0645         {
0646             if(!m_progressCols)
0647                 m_progressCols=new QColor [TOTAL_SHADES+1];
0648             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE], m_backgroundCols[ORIGINAL_SHADE]), m_progressCols);
0649         }
0650     }
0651 
0652     setMenuColors(QApplication::palette().color(QPalette::Active, QPalette::Background));
0653 
0654     switch(opts.shadeCheckRadio)
0655     {
0656     default:
0657         m_checkRadioCol=QApplication::palette().color(QPalette::Active, opts.crButton ? QPalette::ButtonText : QPalette::Text);
0658         break;
0659     case SHADE_BLEND_SELECTED:
0660     case SHADE_SELECTED:
0661         m_checkRadioCol=QApplication::palette().color(QPalette::Active, QPalette::Highlight);
0662         break;
0663     case SHADE_CUSTOM:
0664         m_checkRadioCol=opts.customCheckRadioColor;
0665     }
0666 
0667     if(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR && opts.titlebarButtonColors.size()>=NUM_TITLEBAR_BUTTONS)
0668         for(int i=0; i<NUM_TITLEBAR_BUTTONS; ++i)
0669         {
0670             QColor *cols=new QColor [TOTAL_SHADES+1];
0671             shadeColors(opts.titlebarButtonColors[(ETitleBarButtons)i], cols);
0672             m_titleBarButtonsCols[i]=cols;
0673         }
0674     else
0675         opts.titlebarButtons&=~TITLEBAR_BUTTON_COLOR;
0676 
0677     if (oneOf(opts.bgndImage.type, IMG_PLAIN_RINGS, IMG_BORDERED_RINGS,
0678               IMG_SQUARE_RINGS) ||
0679         oneOf(opts.menuBgndImage.type, IMG_PLAIN_RINGS, IMG_BORDERED_RINGS,
0680               IMG_SQUARE_RINGS)) {
0681         qtcCalcRingAlphas(&m_backgroundCols[ORIGINAL_SHADE]);
0682     }
0683 
0684     m_blurHelper->setEnabled(opts.bgndOpacity != 100 ||
0685                              opts.dlgOpacity != 100 ||
0686                              opts.menuBgndOpacity != 100);
0687 
0688     opts.fontTickWidth=-1;
0689     opts.menuTick=QString(QChar(0x2713));
0690 
0691 #ifdef QTC_QT5_ENABLE_KDE
0692     // We need to set the decoration colours for the preview now...
0693     if (m_isPreview) {
0694         setDecorationColors();
0695     }
0696 #endif
0697 }
0698 
0699 void Style::connectDBus()
0700 {
0701     if (m_dBusHelper->m_dbusConnected)
0702         return;
0703     auto bus = QDBusConnection::sessionBus();
0704     if (bus.isConnected()) {
0705         m_dBusHelper->m_dbusConnected = true;
0706         bus.connect(QString(), "/KGlobalSettings", "org.kde.KGlobalSettings",
0707                     "notifyChange", this, SLOT(kdeGlobalSettingsChange(int, int)));
0708 #ifndef QTC_QT5_ENABLE_KDE
0709         bus.connect("org.kde.kwin", "/KWin", "org.kde.KWin", "compositingToggled",
0710                     this, SLOT(compositingToggled()));
0711 #endif
0712 
0713         if (!qApp || (appName != "kwin" && appName != "kwin_x11" && appName != "kwin_wayland")) {
0714             // don't connect to signals if we know we're sending them out ourselves
0715             bus.connect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
0716                         "borderSizesChanged", this, SLOT(borderSizesChanged()));
0717             if (opts.menubarHiding & HIDE_KWIN)
0718                 bus.connect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
0719                             "toggleMenuBar",
0720                             this, SLOT(toggleMenuBar(unsigned int)));
0721 
0722             if (opts.statusbarHiding & HIDE_KWIN) {
0723                 bus.connect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
0724                             "toggleStatusBar",
0725                             this, SLOT(toggleStatusBar(unsigned int)));
0726             }
0727         }
0728     }
0729 }
0730 
0731 void Style::disconnectDBus()
0732 {
0733     if (!m_dBusHelper->m_dbusConnected)
0734         return;
0735     auto bus = QDBusConnection::sessionBus();
0736     if (!bus.isConnected())
0737         return;
0738     m_dBusHelper->m_dbusConnected = false;
0739     if (getenv("QTCURVE_DEBUG")) {
0740         qWarning() << Q_FUNC_INFO << this << "Disconnecting from" << bus.name() << "/" << bus.baseService();
0741         dumpObjectInfo();
0742     }
0743     bus.disconnect(QString(), "/KGlobalSettings", "org.kde.KGlobalSettings",
0744                    "notifyChange",
0745                    this, SLOT(kdeGlobalSettingsChange(int, int)));
0746 #ifndef QTC_QT5_ENABLE_KDE
0747     bus.disconnect("org.kde.kwin", "/KWin", "org.kde.KWin", "compositingToggled",
0748                    this, SLOT(compositingToggled()));
0749 #endif
0750 
0751     if (!qApp || (appName != "kwin" && appName != "kwin_x11" && appName != "kwin_wayland")) {
0752         bus.disconnect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
0753                     "borderSizesChanged", this, SLOT(borderSizesChanged()));
0754         if (opts.menubarHiding & HIDE_KWIN)
0755             bus.disconnect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
0756                            "toggleMenuBar",
0757                            this, SLOT(toggleMenuBar(unsigned int)));
0758 
0759         if (opts.statusbarHiding & HIDE_KWIN) {
0760             bus.disconnect("org.kde.kwin", "/QtCurve", "org.kde.QtCurve",
0761                            "toggleStatusBar",
0762                            this, SLOT(toggleStatusBar(unsigned int)));
0763         }
0764     }
0765 }
0766 
0767 Style::~Style()
0768 {
0769     qtcInfo("Deleting style instance %p\n", this);
0770     disconnectDBus();
0771     if (m_plugin && m_plugin->m_styleInstances.contains(this)) {
0772         m_plugin->m_styleInstances.removeAll(this);
0773     }
0774     freeColors();
0775     delete m_fntHelper;
0776     delete m_dBusHelper;
0777 }
0778 
0779 void Style::freeColor(QSet<QColor *> &freedColors, QColor **cols)
0780 {
0781     if(!freedColors.contains(*cols) &&
0782        *cols!=m_highlightCols &&
0783        *cols!=m_backgroundCols &&
0784        *cols!=m_menubarCols &&
0785        *cols!=m_focusCols &&
0786        *cols!=m_mouseOverCols &&
0787        *cols!=m_buttonCols &&
0788        *cols!=m_coloredButtonCols &&
0789        *cols!=m_coloredBackgroundCols &&
0790        *cols!=m_coloredHighlightCols) {
0791         freedColors.insert(*cols);
0792         delete [] *cols;
0793     }
0794     *cols=0L;
0795 }
0796 
0797 void Style::freeColors()
0798 {
0799     if(0!=m_progressBarAnimateTimer) {
0800         killTimer(m_progressBarAnimateTimer);
0801         m_progressBarAnimateTimer = 0;
0802     }
0803 
0804     QSet<QColor*> freedColors;
0805 
0806     freeColor(freedColors, &m_sidebarButtonsCols);
0807     freeColor(freedColors, &m_popupMenuCols);
0808     freeColor(freedColors, &m_activeMdiColors);
0809     freeColor(freedColors, &m_mdiColors);
0810     freeColor(freedColors, &m_progressCols);
0811     freeColor(freedColors, &m_checkRadioSelCols);
0812     freeColor(freedColors, &m_sortedLvColors);
0813     freeColor(freedColors, &m_comboBtnCols);
0814     freeColor(freedColors, &m_defBtnCols);
0815     freeColor(freedColors, &m_sliderCols);
0816 
0817     if (opts.titlebarButtons & TITLEBAR_BUTTON_COLOR) {
0818         for (int i = 0;i < NUM_TITLEBAR_BUTTONS;i++) {
0819             delete []m_titleBarButtonsCols[i];
0820             m_titleBarButtonsCols[i] = 0L;
0821         }
0822     }
0823     if (m_ooMenuCols) {
0824         delete []m_ooMenuCols;
0825         m_ooMenuCols = 0L;
0826     }
0827 }
0828 
0829 #if 1
0830 static QFontMetrics styledFontMetrics(const QStyleOption *option, const QWidget *widget)
0831 {
0832     return option
0833         ? option->fontMetrics
0834         : widget
0835         ? widget->fontMetrics()
0836         : qApp->fontMetrics();
0837 }
0838 
0839 static int fontHeight(const QStyleOption *option, const QWidget *widget)
0840 {
0841     return styledFontMetrics(option, widget).height();
0842 }
0843 
0844 // Taken from skulpture 0.2.3
0845 void Style::polishFormLayout(QFormLayout *layout)
0846 {
0847     int widgetSize=-1;
0848 
0849     if (layout->labelAlignment() & Qt::AlignVCenter)
0850         return;
0851 
0852     int addedHeight = -1;
0853     for (int row = 0; row < layout->rowCount(); ++row)
0854     {
0855         QLayoutItem *labelItem = layout->itemAt(row, QFormLayout::LabelRole);
0856         if (!labelItem)
0857             continue;
0858 
0859         QLayoutItem *fieldItem = layout->itemAt(row, QFormLayout::FieldRole);
0860         if (!fieldItem)
0861             continue;
0862 
0863         QWidget *label = labelItem->widget();
0864         if (!label)
0865             continue;
0866 
0867         int labelHeight;
0868         if (addedHeight < 0)
0869             addedHeight = 4 + 2 * widgetSize;
0870         if (qobject_cast<QLabel *>(label))
0871             labelHeight = label->sizeHint().height() + addedHeight;
0872         else if (qobject_cast<QCheckBox *>(label))
0873             labelHeight = label->sizeHint().height();
0874         else
0875             continue;
0876 
0877         int fieldHeight = fieldItem->sizeHint().height();
0878         /* for large fields, we don't center */
0879         if (fieldHeight <= 2 * fontHeight(0, label) + addedHeight)
0880         {
0881             if (fieldHeight > labelHeight)
0882                 labelHeight = fieldHeight;
0883         }
0884 //         else if (verticalTextShift(label->fontMetrics()) & 1)
0885 //                 labelHeight += 1;
0886         if (qobject_cast<QCheckBox *>(label)) {
0887             label->setMinimumHeight(labelHeight);
0888         } else {
0889             label->setMinimumHeight((labelHeight * 4 + 6) / 7);
0890         }
0891     }
0892 }
0893 
0894 void Style::polishLayout(QLayout *layout)
0895 {
0896     if (QFormLayout *formLayout = qobject_cast<QFormLayout *>(layout))
0897         polishFormLayout(formLayout);
0898     // recurse into layouts
0899     for (int i = 0; i < layout->count(); ++i)
0900         if (QLayout *l = layout->itemAt(i)->layout())
0901             polishLayout(l);
0902 }
0903 #endif
0904 
0905 // Taken from oxygen!
0906 void Style::polishScrollArea(QAbstractScrollArea *scrollArea, bool isKFilePlacesView) const
0907 {
0908     if(!scrollArea)
0909         return;
0910 
0911     // HACK: add exception for KPIM transactionItemView, which is an overlay widget and must have filled background. This is a temporary workaround
0912     // until a more robust solution is found.
0913     if(scrollArea->inherits("KPIM::TransactionItemView"))
0914     {
0915         // also need to make the scrollarea background plain (using autofill background) so that optional vertical scrollbar background is not
0916         // transparent either.
0917         // TODO: possibly add an event filter to use the "normal" window background instead of something flat.
0918         scrollArea->setAutoFillBackground(true);
0919         return;
0920     }
0921 
0922     // check frame style and background role
0923     if(QFrame::NoFrame!=scrollArea->frameShape() || QPalette::Window!=scrollArea->backgroundRole())
0924         return;
0925 
0926     // get viewport and check background role
0927     QWidget *viewport(scrollArea->viewport());
0928     if(!(viewport && viewport->backgroundRole() == QPalette::Window) &&
0929        !isKFilePlacesView) {
0930         return;
0931     }
0932 
0933     // change viewport autoFill background.
0934     // do the same for children if the background role is QPalette::Window
0935     viewport->setAutoFillBackground(false);
0936     for (QWidget *child: viewport->findChildren<QWidget*>()) {
0937         if (child->parent() == viewport &&
0938             child->backgroundRole() == QPalette::Window) {
0939             child->setAutoFillBackground(false);
0940         }
0941     }
0942 }
0943 
0944 QIcon Style::standardIcon(StandardPixmap pix, const QStyleOption *option,
0945                           const QWidget *widget) const
0946 {
0947     switch (pix) {
0948     // case SP_TitleBarMenuButton:
0949     // case SP_TitleBarMinButton:
0950     // case SP_TitleBarMaxButton:
0951     // case SP_TitleBarContextHelpButton:
0952     case SP_TitleBarNormalButton:
0953     case SP_TitleBarShadeButton:
0954     case SP_TitleBarUnshadeButton:
0955     case SP_DockWidgetCloseButton:
0956     case SP_TitleBarCloseButton: {
0957         QPixmap pm(13, 13);
0958 
0959         pm.fill(Qt::transparent);
0960 
0961         QPainter painter(&pm);
0962 
0963         drawIcon(&painter, Qt::color1, QRect(0, 0, pm.width(), pm.height()),
0964                  false, pix2Icon(pix), oneOf(pix, SP_TitleBarShadeButton,
0965                                              SP_TitleBarUnshadeButton));
0966         return QIcon(pm);
0967     }
0968     case SP_ToolBarHorizontalExtensionButton:
0969     case SP_ToolBarVerticalExtensionButton:
0970     {
0971         QPixmap pm(9, 9);
0972 
0973         pm.fill(Qt::transparent);
0974 
0975         QPainter painter(&pm);
0976 
0977         drawIcon(&painter, Qt::color1, QRect(0, 0, pm.width(), pm.height()), false, pix2Icon(pix), true);
0978         return QIcon(pm);
0979     }
0980 #ifndef QTC_QT5_ENABLE_KDE
0981     case SP_MessageBoxQuestion:
0982     case SP_MessageBoxInformation: {
0983         static QIcon icn(QPixmap::fromImage(qtc_dialog_information));
0984         return icn;
0985     }
0986     case SP_MessageBoxWarning: {
0987         static QIcon icn(QPixmap::fromImage(qtc_dialog_warning));
0988         return icn;
0989     }
0990     case SP_MessageBoxCritical: {
0991         static QIcon icn(QPixmap::fromImage(qtc_dialog_error));
0992         return icn;
0993     }
0994 /*
0995   case SP_DialogYesButton:
0996   case SP_DialogOkButton:
0997   {
0998   static QIcon icn(load(dialog_ok_png_len, dialog_ok_png_data));
0999   return icn;
1000   }
1001   case SP_DialogNoButton:
1002   case SP_DialogCancelButton:
1003   {
1004   static QIcon icn(load(dialog_cancel_png_len, dialog_cancel_png_data));
1005   return icn;
1006   }
1007   case SP_DialogHelpButton:
1008   {
1009   static QIcon icn(load(help_contents_png_len, help_contents_png_data));
1010   return icn;
1011   }
1012   case SP_DialogCloseButton:
1013   {
1014   static QIcon icn(load(dialog_close_png_len, dialog_close_png_data));
1015   return icn;
1016   }
1017   case SP_DialogApplyButton:
1018   {
1019   static QIcon icn(load(dialog_ok_apply_png_len, dialog_ok_apply_png_data));
1020   return icn;
1021   }
1022   case SP_DialogResetButton:
1023   {
1024   static QIcon icn(load(document_revert_png_len, document_revert_png_data));
1025   return icn;
1026   }
1027 */
1028 #else
1029     case SP_MessageBoxInformation:
1030         return QIcon::fromTheme(QStringLiteral("dialog-information"));
1031     case SP_MessageBoxWarning:
1032         return QIcon::fromTheme(QStringLiteral("dialog-warning"));
1033     case SP_MessageBoxCritical:
1034         return QIcon::fromTheme(QStringLiteral("dialog-error"));
1035     case SP_MessageBoxQuestion:
1036         return QIcon::fromTheme(QStringLiteral("dialog-information"));
1037     case SP_DesktopIcon:
1038         return QIcon::fromTheme(QStringLiteral("user-desktop"));
1039     case SP_TrashIcon:
1040         return QIcon::fromTheme(QStringLiteral("user-trash"));
1041     case SP_ComputerIcon:
1042         return QIcon::fromTheme(QStringLiteral("computer"));
1043     case SP_DriveFDIcon:
1044         return QIcon::fromTheme(QStringLiteral("media-floppy"));
1045     case SP_DriveHDIcon:
1046         return QIcon::fromTheme(QStringLiteral("drive-harddisk"));
1047     case SP_DriveCDIcon:
1048     case SP_DriveDVDIcon:
1049         return QIcon::fromTheme(QStringLiteral("media-optical"));
1050     case SP_DriveNetIcon:
1051         return QIcon::fromTheme(QStringLiteral("network-server"));
1052     case SP_DirOpenIcon:
1053         return QIcon::fromTheme(QStringLiteral("document-open"));
1054     case SP_DirIcon:
1055     case SP_DirClosedIcon:
1056         return QIcon::fromTheme(QStringLiteral("folder"));
1057     // case SP_DirLinkIcon:
1058     case SP_FileIcon:
1059         return QIcon::fromTheme(QStringLiteral("application-x-zerosize"));
1060     // case SP_FileLinkIcon:
1061     case SP_FileDialogStart:
1062         return QIcon::fromTheme(QApplication::layoutDirection() == Qt::RightToLeft ?
1063                      QStringLiteral("go-edn") : QStringLiteral("go-first"));
1064     case SP_FileDialogEnd:
1065         return QIcon::fromTheme(QApplication::layoutDirection() == Qt::RightToLeft ?
1066                      QStringLiteral("go-first") : QStringLiteral("go-end"));
1067     case SP_FileDialogToParent:
1068         return QIcon::fromTheme(QStringLiteral("go-up"));
1069     case SP_FileDialogNewFolder:
1070         return QIcon::fromTheme(QStringLiteral("folder-new"));
1071     case SP_FileDialogDetailedView:
1072         return QIcon::fromTheme(QStringLiteral("view-list-details"));
1073     // case SP_FileDialogInfoView:
1074     //     return QIcon::fromTheme(QStringLiteral("dialog-ok"));
1075     // case SP_FileDialogContentsView:
1076     //     return QIcon::fromTheme(QStringLiteral("dialog-ok"));
1077     case SP_FileDialogListView:
1078         return QIcon::fromTheme(QStringLiteral("view-list-icons"));
1079     case SP_FileDialogBack:
1080         return QIcon::fromTheme(QApplication::layoutDirection() == Qt::RightToLeft ?
1081                      QStringLiteral("go-next") : QStringLiteral("go-previous"));
1082     case SP_DialogOkButton:
1083         return QIcon::fromTheme(QStringLiteral("dialog-ok"));
1084     case SP_DialogCancelButton:
1085         return QIcon::fromTheme(QStringLiteral("dialog-cancel"));
1086     case SP_DialogHelpButton:
1087         return QIcon::fromTheme(QStringLiteral("help-contents"));
1088     case SP_DialogOpenButton:
1089         return QIcon::fromTheme(QStringLiteral("document-open"));
1090     case SP_DialogSaveButton:
1091         return QIcon::fromTheme(QStringLiteral("document-save"));
1092     case SP_DialogCloseButton:
1093         return QIcon::fromTheme(QStringLiteral("dialog-close"));
1094     case SP_DialogApplyButton:
1095         return QIcon::fromTheme(QStringLiteral("dialog-ok-apply"));
1096     case SP_DialogResetButton:
1097         return QIcon::fromTheme(QStringLiteral("document-revert"));
1098     // case SP_DialogDiscardButton:
1099     //     return QIcon::fromTheme(QStringLiteral("dialog-cancel"));
1100     case SP_DialogYesButton:
1101         return QIcon::fromTheme(QStringLiteral("dialog-ok"));
1102     case SP_DialogNoButton:
1103         return QIcon::fromTheme(QStringLiteral("dialog-cancel"));
1104     case SP_ArrowUp:
1105         return QIcon::fromTheme(QStringLiteral("arrow-up"));
1106     case SP_ArrowDown:
1107         return QIcon::fromTheme(QStringLiteral("arrow-down"));
1108     case SP_ArrowLeft:
1109         return QIcon::fromTheme(QStringLiteral("arrow-left"));
1110     case SP_ArrowRight:
1111         return QIcon::fromTheme(QStringLiteral("arrow-right"));
1112     case SP_ArrowBack:
1113         return QIcon::fromTheme(QApplication::layoutDirection() == Qt::RightToLeft ?
1114                      QStringLiteral("go-next") : QStringLiteral("go-previous"));
1115     case SP_ArrowForward:
1116         return QIcon::fromTheme(QApplication::layoutDirection() == Qt::RightToLeft ?
1117                      QStringLiteral("go-previous") : QStringLiteral("go-next"));
1118     case SP_DirHomeIcon:
1119         return QIcon::fromTheme(QStringLiteral("user-home"));
1120     // case SP_CommandLink:
1121     // case SP_VistaShield:
1122     case SP_BrowserReload:
1123         return QIcon::fromTheme(QStringLiteral("view-refresh"));
1124     case SP_BrowserStop:
1125         return QIcon::fromTheme(QStringLiteral("process-stop"));
1126     case SP_MediaPlay:
1127         return QIcon::fromTheme(QStringLiteral("media-playback-start"));
1128     case SP_MediaStop:
1129         return QIcon::fromTheme(QStringLiteral("media-playback-stop"));
1130     case SP_MediaPause:
1131         return QIcon::fromTheme(QStringLiteral("media-playback-pause"));
1132     case SP_MediaSkipForward:
1133         return QIcon::fromTheme(QStringLiteral("media-skip-forward"));
1134     case SP_MediaSkipBackward:
1135         return QIcon::fromTheme(QStringLiteral("media-skip-backward"));
1136     case SP_MediaSeekForward:
1137         return QIcon::fromTheme(QStringLiteral("media-seek-forward"));
1138     case SP_MediaSeekBackward:
1139         return QIcon::fromTheme(QStringLiteral("media-seek-backward"));
1140     case SP_MediaVolume:
1141         return QIcon::fromTheme(QStringLiteral("player-volume"));
1142     case SP_MediaVolumeMuted:
1143         return QIcon::fromTheme(QStringLiteral("player-volume-muted"));
1144 #endif
1145     default:
1146         break;
1147     }
1148     // TODO ?
1149     return ParentStyleClass::standardIcon(pix, option, widget);
1150 }
1151 
1152 int Style::layoutSpacing(QSizePolicy::ControlType control1,
1153                          QSizePolicy::ControlType control2,
1154                          Qt::Orientation orientation,
1155                          const QStyleOption *option, const QWidget *widget) const
1156 {
1157     Q_UNUSED(control1);
1158     Q_UNUSED(control2);
1159     Q_UNUSED(orientation);
1160     return pixelMetric(PM_DefaultLayoutSpacing, option, widget);
1161 }
1162 
1163 // Use 'drawItemTextWithRole' when already know which role to use.
1164 void
1165 Style::drawItemTextWithRole(QPainter *painter, const QRect &rect, int flags,
1166                             const QPalette &pal, bool enabled,
1167                             const QString &text,
1168                             QPalette::ColorRole textRole) const
1169 {
1170     ParentStyleClass::drawItemText(painter, rect, flags, pal,
1171                                enabled, text, textRole);
1172 }
1173 
1174 void Style::drawSideBarButton(QPainter *painter, const QRect &r, const QStyleOption *option, const QWidget *widget) const
1175 {
1176     const QPalette &palette(option->palette);
1177     QRect          r2(r);
1178     QStyleOption   opt(*option);
1179 
1180     if(r2.height()>r2.width() || (r2.height()<r2.width() && r2.width()<=32))
1181         opt.state&=~State_Horizontal;
1182     else
1183         opt.state|=State_Horizontal;
1184 
1185     const QColor *use(opt.state&State_On ? getSidebarButtons() : buttonColors(option));
1186     bool         horiz(opt.state&State_Horizontal);
1187 
1188     painter->save();
1189     if(opt.state&State_On || opt.state&State_MouseOver)
1190     {
1191         r2.adjust(-1, -1, 1, 1);
1192         drawLightBevel(painter, r2, &opt, widget, ROUNDED_NONE,
1193                        getFill(&opt, use), use, false, WIDGET_MENU_ITEM);
1194     }
1195     else
1196         painter->fillRect(r2, palette.window().color());
1197 
1198     if (opt.state & State_MouseOver && opts.coloredMouseOver) {
1199         r2 = r;
1200         if (opts.coloredMouseOver == MO_PLASTIK) {
1201             if (horiz) {
1202                 r2.adjust(0, 1, 0, -1);
1203             } else {
1204                 r2.adjust(1, 0, -1, 0);
1205             }
1206         } else {
1207             r2.adjust(1, 1, -1, -1);
1208         }
1209         if (opts.coloredMouseOver == MO_GLOW) {
1210             QColor col(m_mouseOverCols[opt.state&State_On ? 0 : 1]);
1211 
1212             col.setAlphaF(GLOW_ALPHA(false));
1213             painter->setPen(col);
1214             drawRect(painter, r);
1215             col = m_mouseOverCols[opt.state&State_On ? 4 : 3];
1216             col.setAlphaF(0.8);
1217             painter->setPen(col);
1218             drawRect(painter, r2);
1219         } else {
1220             painter->setPen(m_mouseOverCols[opt.state&State_On ? 0 : 1]);
1221 
1222             if (horiz || MO_PLASTIK!=opts.coloredMouseOver)
1223             {
1224                 painter->drawLine(r.x(), r.y(), r.x()+r.width()-1, r.y());
1225                 painter->drawLine(r2.x(), r2.y(), r2.x()+r2.width()-1, r2.y());
1226             }
1227 
1228             if(!horiz || MO_PLASTIK!=opts.coloredMouseOver)
1229             {
1230                 painter->drawLine(r.x(), r.y(), r.x(), r.y()+r.height()-1);
1231                 painter->drawLine(r2.x(), r2.y(), r2.x(), r2.y()+r2.height()-1);
1232                 if(MO_PLASTIK!=opts.coloredMouseOver)
1233                     painter->setPen(m_mouseOverCols[opt.state&State_On ? 1 : 2]);
1234             }
1235 
1236             if(horiz || MO_PLASTIK!=opts.coloredMouseOver)
1237             {
1238                 painter->drawLine(r.x(), r.y()+r.height()-1, r.x()+r.width()-1, r.y()+r.height()-1);
1239                 painter->drawLine(r2.x(), r2.y()+r2.height()-1, r2.x()+r2.width()-1, r2.y()+r2.height()-1);
1240             }
1241 
1242             if(!horiz || MO_PLASTIK!=opts.coloredMouseOver)
1243             {
1244                 painter->drawLine(r.x()+r.width()-1, r.y(), r.x()+r.width()-1, r.y()+r.height()-1);
1245                 painter->drawLine(r2.x()+r2.width()-1, r2.y(), r2.x()+r2.width()-1, r2.y()+r2.height()-1);
1246             }
1247         }
1248     }
1249 
1250     painter->restore();
1251 }
1252 
1253 void Style::drawHighlight(QPainter *p, const QRect &r, bool horiz, bool inc) const
1254 {
1255     QColor col1(m_mouseOverCols[ORIGINAL_SHADE]);
1256 
1257     col1.setAlphaF(0.5);
1258     drawFadedLine(p, r, inc ? col1 : m_mouseOverCols[ORIGINAL_SHADE], true, true, horiz);
1259     drawFadedLine(p, r.adjusted(horiz ? 0 : 1, horiz ? 1 : 0, 0, 0), inc ? m_mouseOverCols[ORIGINAL_SHADE] : col1, true, true, horiz);
1260 }
1261 
1262 void
1263 Style::drawFadedLine(QPainter *p, const QRect &r, const QColor &col,
1264                      bool fadeStart, bool fadeEnd, bool horiz,
1265                      double fadeSizeStart, double fadeSizeEnd) const
1266 {
1267     bool            aa(p->testRenderHint(QPainter::Antialiasing));
1268     QPointF         start(r.x()+(aa ? 0.5 : 0.0), r.y()+(aa ? 0.5 : 0.0)),
1269         end(r.x()+(horiz ? r.width()-1 : 0)+(aa ? 0.5 : 0.0),
1270             r.y()+(horiz ? 0 : r.height()-1)+(aa ? 0.5 : 0.0));
1271 
1272     if(opts.fadeLines && (fadeStart || fadeEnd))
1273     {
1274         QLinearGradient grad(start, end);
1275         QColor          fade(col);
1276 
1277         fade.setAlphaF(0.0);
1278         grad.setColorAt(0, fadeStart && opts.fadeLines ? fade : col);
1279         if(fadeSizeStart>=0 && fadeSizeStart<=1.0)
1280             grad.setColorAt(fadeSizeStart, col);
1281         if(fadeSizeEnd>=0 && fadeSizeEnd<=1.0)
1282             grad.setColorAt(1.0-fadeSizeEnd, col);
1283         grad.setColorAt(1, fadeEnd && opts.fadeLines ? fade : col);
1284         p->setPen(QPen(QBrush(grad), QPENWIDTH1));
1285     }
1286     else
1287         p->setPen(col);
1288     p->drawLine(start, end);
1289 }
1290 
1291 void Style::drawLines(QPainter *p, const QRect &r, bool horiz, int nLines, int offset, const QColor *cols, int startOffset,
1292                       int dark, ELine type) const
1293 {
1294     int  space((nLines*2)+(LINE_DASHES!=type ? (nLines-1) : 0)),
1295         step(LINE_DASHES!=type ? 3 : 2),
1296         etchedDisp(type == LINE_SUNKEN ? 1 : 0),
1297         x(horiz ? r.x() : r.x()+((r.width()-space)>>1)),
1298         y(horiz ? r.y()+((r.height()-space)>>1) : r.y()),
1299         x2(r.x()+r.width()-1),
1300         y2(r.y()+r.height()-1),
1301         i;
1302     QPen dp(cols[dark], QPENWIDTH1),
1303         lp(cols[0], QPENWIDTH1);
1304 
1305     if(opts.fadeLines && (horiz ? r.width() : r.height())>16)
1306     {
1307         QLinearGradient grad(r.topLeft(), horiz ? r.topRight() : r.bottomLeft());
1308         QColor          fade(cols[dark]);
1309 
1310         fade.setAlphaF(0.0);
1311         grad.setColorAt(0, fade);
1312         grad.setColorAt(0.4, cols[dark]);
1313         grad.setColorAt(0.6, cols[dark]);
1314         grad.setColorAt(1, fade);
1315 
1316         dp=QPen(QBrush(grad), QPENWIDTH1);
1317 
1318         if(LINE_FLAT!=type)
1319         {
1320             fade=QColor(cols[0]);
1321 
1322             fade.setAlphaF(0.0);
1323             grad.setColorAt(0, fade);
1324             grad.setColorAt(0.4, cols[0]);
1325             grad.setColorAt(0.6, cols[0]);
1326             grad.setColorAt(1, fade);
1327             lp=QPen(QBrush(grad), QPENWIDTH1);
1328         }
1329     }
1330 
1331     p->setRenderHint(QPainter::Antialiasing, true);
1332     if(horiz)
1333     {
1334         if(startOffset && y+startOffset>0)
1335             y+=startOffset;
1336 
1337         p->setPen(dp);
1338         for(i=0; i<space; i+=step)
1339             drawAaLine(p, x+offset, y+i, x2-offset, y+i);
1340 
1341         if(LINE_FLAT!=type)
1342         {
1343             p->setPen(lp);
1344             x+=etchedDisp;
1345             x2+=etchedDisp;
1346             for(i=1; i<space; i+=step)
1347                 drawAaLine(p, x+offset, y+i, x2-offset, y+i);
1348         }
1349     }
1350     else
1351     {
1352         if(startOffset && x+startOffset>0)
1353             x+=startOffset;
1354 
1355         p->setPen(dp);
1356         for(i=0; i<space; i+=step)
1357             drawAaLine(p, x+i, y+offset, x+i, y2-offset);
1358 
1359         if(LINE_FLAT!=type)
1360         {
1361             p->setPen(lp);
1362             y+=etchedDisp;
1363             y2+=etchedDisp;
1364             for(i=1; i<space; i+=step)
1365                 drawAaLine(p, x+i, y+offset, x+i, y2-offset);
1366         }
1367     }
1368     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
1369 }
1370 
1371 void Style::drawProgressBevelGradient(QPainter *p, const QRect &origRect, const QStyleOption *option, bool horiz, EAppearance bevApp,
1372                                       const QColor *cols) const
1373 {
1374     bool    vertical(!horiz),
1375         inCache(true);
1376     QRect   r(0, 0, horiz ? PROGRESS_CHUNK_WIDTH*2 : origRect.width(),
1377               horiz ? origRect.height() : PROGRESS_CHUNK_WIDTH*2);
1378     QtcKey  key(createKey(horiz ? r.height() : r.width(), cols[ORIGINAL_SHADE], horiz, bevApp, WIDGET_PROGRESSBAR));
1379     QPixmap *pix(m_pixmapCache.object(key));
1380 
1381     if(!pix)
1382     {
1383         pix=new QPixmap(r.width(), r.height());
1384 
1385         QPainter pixPainter(pix);
1386 
1387         if(qtcIsFlat(bevApp))
1388             pixPainter.fillRect(r, cols[ORIGINAL_SHADE]);
1389         else
1390             drawBevelGradientReal(cols[ORIGINAL_SHADE], &pixPainter, r, horiz, false, bevApp, WIDGET_PROGRESSBAR);
1391 
1392         switch(opts.stripedProgress)
1393         {
1394         default:
1395         case STRIPE_NONE:
1396             break;
1397         case STRIPE_PLAIN:
1398         {
1399             QRect r2(horiz
1400                      ? QRect(r.x(), r.y(), PROGRESS_CHUNK_WIDTH, r.height())
1401                      : QRect(r.x(), r.y(), r.width(), PROGRESS_CHUNK_WIDTH));
1402 
1403             if(qtcIsFlat(bevApp))
1404                 pixPainter.fillRect(r2, cols[1]);
1405             else
1406                 drawBevelGradientReal(cols[1], &pixPainter, r2, horiz, false, bevApp, WIDGET_PROGRESSBAR);
1407             break;
1408         }
1409         case STRIPE_DIAGONAL:
1410         {
1411             QRegion reg;
1412             int     size(vertical ? origRect.width() : origRect.height());
1413 
1414             for(int offset=0; offset<(size*2); offset+=(PROGRESS_CHUNK_WIDTH*2))
1415             {
1416                 QPolygon a;
1417 
1418                 if(vertical)
1419                     a.setPoints(4, r.x(),           r.y()+offset,
1420                                 r.x()+r.width(), (r.y()+offset)-size,
1421                                 r.x()+r.width(), (r.y()+offset+PROGRESS_CHUNK_WIDTH)-size,
1422                                 r.x(),           r.y()+offset+PROGRESS_CHUNK_WIDTH);
1423                 else
1424                     a.setPoints(4, r.x()+offset,                             r.y(),
1425                                 r.x()+offset+PROGRESS_CHUNK_WIDTH,        r.y(),
1426                                 (r.x()+offset+PROGRESS_CHUNK_WIDTH)-size, r.y()+r.height(),
1427                                 (r.x()+offset)-size,                      r.y()+r.height());
1428 
1429                 reg+=QRegion(a);
1430             }
1431 
1432             pixPainter.setClipRegion(reg);
1433             if(qtcIsFlat(bevApp))
1434                 pixPainter.fillRect(r, cols[1]);
1435             else
1436                 drawBevelGradientReal(cols[1], &pixPainter, r, horiz, false, bevApp, WIDGET_PROGRESSBAR);
1437         }
1438         }
1439 
1440         pixPainter.end();
1441         int cost(pix->width()*pix->height()*(pix->depth()/8));
1442 
1443         if(cost<m_pixmapCache.maxCost())
1444             m_pixmapCache.insert(key, pix, cost);
1445         else
1446             inCache=false;
1447     }
1448     QRect fillRect(origRect);
1449 
1450     if(opts.animatedProgress)
1451     {
1452         int animShift=vertical || option->state&STATE_REVERSE ? PROGRESS_CHUNK_WIDTH : -PROGRESS_CHUNK_WIDTH;
1453 
1454         if(vertical || option->state&STATE_REVERSE)
1455             animShift -= (m_animateStep/2) % (PROGRESS_CHUNK_WIDTH*2);
1456         else
1457             animShift += (m_animateStep/2) % (PROGRESS_CHUNK_WIDTH*2);
1458 
1459         if(horiz)
1460             fillRect.adjust(animShift-PROGRESS_CHUNK_WIDTH, 0, PROGRESS_CHUNK_WIDTH, 0);
1461         else
1462             fillRect.adjust(0, animShift-PROGRESS_CHUNK_WIDTH, 0, PROGRESS_CHUNK_WIDTH);
1463     }
1464 
1465     p->save();
1466     p->setClipRect(origRect, Qt::IntersectClip);
1467     p->drawTiledPixmap(fillRect, *pix);
1468     if (opts.stripedProgress == STRIPE_FADE && fillRect.width() > 4 &&
1469         fillRect.height() > 4) {
1470         addStripes(p, QPainterPath(), fillRect, !vertical);
1471     }
1472     p->restore();
1473 
1474     if (!inCache) {
1475         delete pix;
1476     }
1477 }
1478 
1479 void
1480 Style::drawBevelGradient(const QColor &base, QPainter *p, const QRect &origRect,
1481                          const QPainterPath &path, bool horiz, bool sel,
1482                          EAppearance bevApp, EWidget w, bool useCache) const
1483 {
1484     if (origRect.width() < 1 || origRect.height() < 1) {
1485         return;
1486     }
1487     if (qtcIsFlat(bevApp)) {
1488         if (noneOf(w, WIDGET_TAB_TOP, WIDGET_TAB_BOT) ||
1489             !qtcIsCustomBgnd(opts) || opts.tabBgnd || !sel) {
1490             if (path.isEmpty()) {
1491                 p->fillRect(origRect, base);
1492             } else {
1493                 p->fillPath(path, base);
1494             }
1495         }
1496     } else {
1497         bool tab = oneOf(w, WIDGET_TAB_TOP, WIDGET_TAB_BOT);
1498         bool selected = tab ? false : sel;
1499         EAppearance app =
1500             (selected ? opts.sunkenAppearance :
1501              w == WIDGET_LISTVIEW_HEADER && bevApp == APPEARANCE_BEVELLED ?
1502              APPEARANCE_LV_BEVELLED : bevApp != APPEARANCE_BEVELLED ||
1503              WIDGET_BUTTON(w) ||
1504              oneOf(w, WIDGET_LISTVIEW_HEADER, WIDGET_TROUGH,
1505                    WIDGET_NO_ETCH_BTN, WIDGET_MENU_BUTTON) ? bevApp :
1506              APPEARANCE_GRADIENT);
1507 
1508         if (w == WIDGET_PROGRESSBAR || !useCache) {
1509             drawBevelGradientReal(base, p, origRect, path, horiz, sel, app, w);
1510         } else {
1511             QRect r(0, 0, horiz ? PIXMAP_DIMENSION : origRect.width(),
1512                     horiz ? origRect.height() : PIXMAP_DIMENSION);
1513             QtcKey key(createKey(horiz ? r.height() : r.width(),
1514                                  base, horiz, app, w));
1515             QPixmap *pix(m_pixmapCache.object(key));
1516             bool inCache(true);
1517 
1518             if (!pix) {
1519                 pix = new QPixmap(r.width(), r.height());
1520                 pix->fill(Qt::transparent);
1521 
1522                 QPainter pixPainter(pix);
1523 
1524                 drawBevelGradientReal(base, &pixPainter, r, horiz, sel, app, w);
1525                 pixPainter.end();
1526 
1527                 int cost(pix->width()*pix->height()*(pix->depth()/8));
1528 
1529                 if (cost < m_pixmapCache.maxCost()) {
1530                     m_pixmapCache.insert(key, pix, cost);
1531                 } else {
1532                     inCache = false;
1533                 }
1534             }
1535 
1536             if(!path.isEmpty())
1537             {
1538                 p->save();
1539                 p->setClipPath(path, Qt::IntersectClip);
1540             }
1541 
1542             p->drawTiledPixmap(origRect, *pix);
1543             if(!path.isEmpty())
1544                 p->restore();
1545             if(!inCache)
1546                 delete pix;
1547         }
1548     }
1549 }
1550 
1551 void
1552 Style::drawBevelGradientReal(const QColor &base, QPainter *p, const QRect &r,
1553                              const QPainterPath &path, bool horiz, bool sel,
1554                              EAppearance app, EWidget w) const
1555 {
1556     bool topTab = (w == WIDGET_TAB_TOP);
1557     bool botTab = (w == WIDGET_TAB_BOT);
1558     bool dwt = qtcIsCustomBgnd(opts) && (w == WIDGET_DOCK_WIDGET_TITLE);
1559     bool titleBar = (opts.windowBorder & WINDOW_BORDER_BLEND_TITLEBAR &&
1560                      (oneOf(w, WIDGET_MDI_WINDOW, WIDGET_MDI_WINDOW_TITLE) ||
1561                       (opts.dwtSettings & DWT_COLOR_AS_PER_TITLEBAR &&
1562                        w == WIDGET_DOCK_WIDGET_TITLE && !dwt)));
1563     bool reverse = QApplication::layoutDirection() == Qt::RightToLeft;
1564     const Gradient *grad = qtcGetGradient(app, &opts);
1565     QLinearGradient g(r.topLeft(), horiz ? r.bottomLeft() : r.topRight());
1566     GradientStopCont::const_iterator it(grad->stops.begin());
1567     GradientStopCont::const_iterator end(grad->stops.end());
1568     int numStops(grad->stops.size());
1569 
1570     for (int i = 0;it != end;++it, ++i) {
1571         QColor col;
1572 
1573         if ((topTab || botTab || dwt || titleBar) && i == numStops-1) {
1574             if (titleBar) {
1575                 col = m_backgroundCols[ORIGINAL_SHADE];
1576                 col.setAlphaF(0.0);
1577             } else {
1578                 col = base;
1579                 if ((sel && opts.tabBgnd == 0 && !reverse) || dwt) {
1580                     col.setAlphaF(0.0);
1581                 }
1582             }
1583         } else {
1584             shade(base, &col, botTab && opts.invertBotTab ?
1585                   qMax(INVERT_SHADE((*it).val), 0.9) : (*it).val);
1586         }
1587         if (w != WIDGET_TOOLTIP && (*it).alpha < 1.0) {
1588             col.setAlphaF(col.alphaF() * (*it).alpha);
1589         }
1590         g.setColorAt(botTab ? 1.0 - (*it).pos : (*it).pos, col);
1591     }
1592 
1593     if (app == APPEARANCE_AGUA && !(topTab || botTab || dwt) &&
1594         (horiz ? r.height() : r.width()) > AGUA_MAX) {
1595         QColor col;
1596         double pos = AGUA_MAX/((horiz ? r.height() : r.width())*2.0);
1597         shade(base, &col, AGUA_MID_SHADE);
1598         g.setColorAt(pos, col);
1599         g.setColorAt(1.0-pos, col);
1600     }
1601 
1602     //p->fillRect(r, base);
1603     if (path.isEmpty()) {
1604         p->fillRect(r, QBrush(g));
1605     } else {
1606         p->fillPath(path, QBrush(g));
1607     }
1608 }
1609 
1610 void Style::drawSunkenBevel(QPainter *p, const QRect &r, const QColor &col) const
1611 {
1612     double          radius=opts.titlebarButtons&TITLEBAR_BUTTON_ROUND
1613         ? r.height()/2.0
1614         : opts.round>ROUND_FULL
1615         ? 5.0
1616         : opts.round>ROUND_SLIGHT
1617         ? 3.0
1618         : 2.0;
1619     QPainterPath    path(buildPath(QRectF(r), WIDGET_OTHER, ROUNDED_ALL, radius));
1620     QLinearGradient g(r.topLeft(), r.bottomLeft());
1621     QColor          black(Qt::black),
1622         white(Qt::white);
1623 
1624     black.setAlphaF(SUNKEN_BEVEL_DARK_ALPHA(col));
1625     white.setAlphaF(SUNKEN_BEVEL_LIGHT_ALPHA(col));
1626     g.setColorAt(0, black);
1627     g.setColorAt(1, white);
1628     p->save();
1629     p->setRenderHint(QPainter::Antialiasing, true);
1630     p->fillPath(path, QBrush(g));
1631     p->restore();
1632 }
1633 
1634 void
1635 Style::drawLightBevel(QPainter *p, const QRect &r, const QStyleOption *option,
1636                       const QWidget *widget, int round, const QColor &fill,
1637                       const QColor *custom, bool doBorder, EWidget w) const
1638 {
1639     bool onToolbar = (opts.tbarBtnAppearance != APPEARANCE_NONE &&
1640                       (w == WIDGET_TOOLBAR_BUTTON ||
1641                        (WIDGET_BUTTON(w) && isOnToolbar(widget))));
1642 
1643     if (oneOf(w, WIDGET_PROGRESSBAR, WIDGET_SB_BUTTON) ||
1644         (w == WIDGET_SPIN && !opts.unifySpin)/* || !m_usePixmapCache*/) {
1645         drawLightBevelReal(p, r, option, widget, round, fill, custom,
1646                            doBorder, w, true, opts.round, onToolbar);
1647     } else {
1648         static const int constMaxCachePixmap = 128;
1649 
1650         int endSize = 0;
1651         int middleSize = 8;
1652         bool horiz = (CIRCULAR_SLIDER(w) ||
1653                       isHoriz(option, w, opts.tbarBtns == TBTN_JOINED));
1654         bool circular = ((w == WIDGET_MDI_WINDOW_BUTTON &&
1655                           (opts.titlebarButtons & TITLEBAR_BUTTON_ROUND)) ||
1656                          oneOf(w, WIDGET_RADIO_BUTTON, WIDGET_DIAL) ||
1657                          CIRCULAR_SLIDER(w));
1658         double radius = 0;
1659         ERound realRound = qtcGetWidgetRound(&opts, r.width(), r.height(), w);
1660 
1661         if (!circular) {
1662             switch (realRound) {
1663             case ROUND_SLIGHT:
1664             case ROUND_NONE:
1665             case ROUND_FULL:
1666                 endSize = (SLIDER(w) && opts.coloredMouseOver == MO_PLASTIK &&
1667                            option->state&State_MouseOver ? 9 : 5);
1668                 break;
1669             case ROUND_EXTRA:
1670                 endSize = 7;
1671                 break;
1672             case ROUND_MAX:
1673                 radius = qtcGetRadius(&opts, r.width(), r.height(),
1674                                       w, RADIUS_ETCH);
1675                 endSize = (SLIDER(w) ? qMax((opts.sliderWidth / 2) + 1,
1676                                             int(radius + 1.5)) :
1677                            int(radius + 2.5));
1678                 middleSize = MIN_ROUND_MAX_WIDTH - (endSize * 2) + 4;
1679                 if (middleSize < 4)
1680                     middleSize = 4;
1681                 break;
1682             }
1683         }
1684 
1685         int size = 2 * endSize + middleSize;
1686 
1687         if (size > constMaxCachePixmap) {
1688             drawLightBevelReal(p, r, option, widget, round, fill, custom,
1689                                doBorder, w, true, realRound, onToolbar);
1690         } else {
1691             bool small(circular || (horiz ? r.width() : r.height())<(2*endSize));
1692             QPixmap pix;
1693             const QSize pixSize(small ? QSize(r.width(), r.height()) :
1694                                 QSize(horiz ? size : r.width(),
1695                                       horiz ? r.height() : size));
1696             uint state(option->state&(State_Raised|State_Sunken|State_On|State_Horizontal|State_HasFocus|State_MouseOver|
1697                                          (WIDGET_MDI_WINDOW_BUTTON==w ? State_Active : State_None)));
1698 
1699             QString key = QStringLiteral("qtc-%1-%2-%3-%4-%5-%6-%7-%8-%9")
1700                 .arg(w, 0, 16).arg(onToolbar ? 1 : 0, 0, 16).arg(round, 0, 16)
1701                 .arg((int)realRound, 0, 16).arg(pixSize.width(), 0, 16)
1702                 .arg(pixSize.height(), 0, 16)
1703                 .arg(state, 0, 16).arg(fill.rgba(), 0, 16).arg((int)(radius * 100), 0, 16);
1704             if (!m_usePixmapCache || !QPixmapCache::find(key, &pix)) {
1705                 pix = QPixmap(pixSize);
1706                 pix.fill(Qt::transparent);
1707 
1708                 QPainter pixPainter(&pix);
1709                 ERound oldRound = opts.round;
1710                 opts.round = realRound;
1711                 pixPainter.setRenderHint(QPainter::Antialiasing, true);
1712                 drawLightBevelReal(&pixPainter, QRect(0, 0, pixSize.width(),
1713                                                       pixSize.height()), option,
1714                                    widget, round, fill, custom, doBorder, w,
1715                                    false, realRound, onToolbar);
1716                 opts.round = oldRound;
1717                 pixPainter.end();
1718 
1719                 if (m_usePixmapCache) {
1720                     QPixmapCache::insert(key, pix);
1721                 }
1722             }
1723 
1724             if (small) {
1725                 p->drawPixmap(r.topLeft(), pix);
1726             } else if (horiz) {
1727                 int middle(qMin(r.width()-(2*endSize), middleSize));
1728                 if(middle>0)
1729                     p->drawTiledPixmap(r.x()+endSize, r.y(), r.width()-(2*endSize), pix.height(), pix.copy(endSize, 0, middle, pix.height()));
1730                 p->drawPixmap(r.x(), r.y(), pix.copy(0, 0, endSize, pix.height()));
1731                 p->drawPixmap(r.x()+r.width()-endSize, r.y(), pix.copy(pix.width()-endSize, 0, endSize, pix.height()));
1732             } else {
1733                 int middle(qMin(r.height()-(2*endSize), middleSize));
1734                 if (middle > 0) {
1735                     p->drawTiledPixmap(r.x(), r.y() + endSize, pix.width(),
1736                                        r.height() - 2 * endSize,
1737                                        pix.copy(0, endSize,
1738                                                 pix.width(), middle));
1739                 }
1740                 p->drawPixmap(r.x(), r.y(),
1741                               pix.copy(0, 0, pix.width(), endSize));
1742                 p->drawPixmap(r.x(), r.y() + r.height() - endSize,
1743                               pix.copy(0, pix.height() - endSize, pix.width(),
1744                                        endSize));
1745             }
1746 
1747             if (w == WIDGET_SB_SLIDER && opts.stripedSbar) {
1748                 QRect rx(r.adjusted(1, 1, -1, -1));
1749                 addStripes(p, buildPath(rx, WIDGET_SB_SLIDER, realRound,
1750                                         qtcGetRadius(&opts, rx.width() - 1,
1751                                                      rx.height() - 1,
1752                                                      WIDGET_SB_SLIDER,
1753                                                      RADIUS_INTERNAL)),
1754                            rx, horiz);
1755             }
1756         }
1757     }
1758 }
1759 
1760 void
1761 Style::drawLightBevelReal(QPainter *p, const QRect &rOrig,
1762                           const QStyleOption *option, const QWidget *widget,
1763                           int round, const QColor &fill, const QColor *custom,
1764                           bool doBorder, EWidget w, bool useCache,
1765                           ERound realRound, bool onToolbar) const
1766 {
1767     EAppearance app(qtcWidgetApp(onToolbar ? WIDGET_TOOLBAR_BUTTON : w,
1768                                   &opts, option->state&State_Active));
1769     QRect r(rOrig);
1770     bool bevelledButton((WIDGET_BUTTON(w) || WIDGET_NO_ETCH_BTN == w ||
1771                          WIDGET_MENU_BUTTON == w) && APPEARANCE_BEVELLED == app);
1772     bool sunken(option->state &(/*State_Down | */State_On | State_Sunken));
1773     bool flatWidget((WIDGET_MDI_WINDOW_BUTTON==w &&
1774                      (opts.round==ROUND_MAX ||
1775                       opts.titlebarButtons&TITLEBAR_BUTTON_ROUND)) ||
1776                     (WIDGET_PROGRESSBAR==w && !opts.borderProgress));
1777     bool lightBorder(!flatWidget && DRAW_LIGHT_BORDER(sunken, w, app));
1778     bool draw3dfull(!flatWidget && !lightBorder &&
1779                     DRAW_3D_FULL_BORDER(sunken, app));
1780     bool draw3d(!flatWidget && (draw3dfull ||
1781                                 (!lightBorder && DRAW_3D_BORDER(sunken, app))));
1782     bool drawShine(DRAW_SHINE(sunken, app));
1783     bool doColouredMouseOver(doBorder && option->state&State_Enabled &&
1784                              WIDGET_MDI_WINDOW_BUTTON!=w && WIDGET_SPIN!=w &&
1785                              WIDGET_COMBO_BUTTON!=w && WIDGET_SB_BUTTON!=w &&
1786                              (!SLIDER(w) || !opts.colorSliderMouseOver) &&
1787                              !(option->state&STATE_KWIN_BUTTON) &&
1788                              (opts.coloredTbarMo ||
1789                               !(option->state&STATE_TBAR_BUTTON)) &&
1790                              opts.coloredMouseOver &&
1791                              option->state&State_MouseOver &&
1792                              WIDGET_PROGRESSBAR!=w &&
1793                              (option->state&STATE_TOGGLE_BUTTON || !sunken));
1794     bool plastikMouseOver(doColouredMouseOver &&
1795                           MO_PLASTIK==opts.coloredMouseOver);
1796     bool colouredMouseOver(doColouredMouseOver && WIDGET_MENU_BUTTON!=w &&
1797                            (MO_COLORED==opts.coloredMouseOver ||
1798                             MO_COLORED_THICK==opts.coloredMouseOver ||
1799                             (MO_GLOW==opts.coloredMouseOver &&
1800                              !(opts.buttonEffect != EFFECT_NONE)))),
1801         doEtch(doBorder && ETCH_WIDGET(w) && opts.buttonEffect != EFFECT_NONE),
1802         glowFocus(doEtch && USE_GLOW_FOCUS(option->state&State_MouseOver) && option->state&State_HasFocus &&
1803                   option->state&State_Enabled),
1804         horiz(CIRCULAR_SLIDER(w) || isHoriz(option, w, TBTN_JOINED==opts.tbarBtns)),
1805         sunkenToggleMo(sunken && !(option->state&State_Sunken) && option->state&(State_MouseOver|STATE_TOGGLE_BUTTON));
1806     const QColor *cols(custom ? custom : m_backgroundCols),
1807         *border(colouredMouseOver ? borderColors(option, cols) : cols);
1808 
1809     p->save();
1810 
1811     if (doEtch)
1812         r.adjust(1, 1, -1, -1);
1813 
1814     if (WIDGET_TROUGH == w && !opts.borderSbarGroove)
1815         doBorder = false;
1816 
1817     p->setRenderHint(QPainter::Antialiasing, true);
1818 
1819     if (r.width() > 0 && r.height() > 0) {
1820         if (w == WIDGET_PROGRESSBAR && opts.stripedProgress != STRIPE_NONE) {
1821             drawProgressBevelGradient(p, opts.borderProgress ?
1822                                       r.adjusted(1, 1, -1, -1) : r,
1823                                       option, horiz, app, custom);
1824         } else {
1825             drawBevelGradient(fill, p, WIDGET_PROGRESSBAR==w && opts.borderProgress ? r.adjusted(1, 1, -1, -1) : r,
1826                               doBorder
1827                               ? buildPath(r, w, round, qtcGetRadius(&opts, r.width()-2, r.height()-2, w, RADIUS_INTERNAL))
1828                               : buildPath(QRectF(r), w, round, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_EXTERNAL)),
1829                               horiz, sunken, app, w, useCache);
1830 
1831             if(!sunken || sunkenToggleMo)
1832                 if(plastikMouseOver) // && !sunken)
1833                 {
1834                     p->save();
1835                     p->setClipPath(buildPath(r.adjusted(0, 0, 0, -1), w, round,
1836                                              qtcGetRadius(&opts, r.width()-2, r.height()-2, w, RADIUS_INTERNAL)));
1837                     if (SLIDER(w)) {
1838                         int len = sbSliderMOLen(opts, horiz ? r.width() :
1839                                                 r.height()) + 1;
1840                         int so = lightBorder ? SLIDER_MO_PLASTIK_BORDER : 1;
1841                         int eo = len + so;
1842                         int col = SLIDER_MO_SHADE;
1843 
1844                         if (horiz) {
1845                             drawBevelGradient(m_mouseOverCols[col], p, QRect(r.x()+so-1, r.y(), len, r.height()-1), horiz, sunken, app, w, useCache);
1846                             drawBevelGradient(m_mouseOverCols[col], p, QRect(r.x()+r.width()-eo+1, r.y(), len, r.height()-1), horiz, sunken, app, w, useCache);
1847                         }
1848                         else
1849                         {
1850                             drawBevelGradient(m_mouseOverCols[col], p, QRect(r.x(), r.y()+so-1, r.width()-1, len), horiz, sunken, app, w, useCache);
1851                             drawBevelGradient(m_mouseOverCols[col], p, QRect(r.x(), r.y()+r.height()-eo+1, r.width()-1, len), horiz, sunken, app, w, useCache);
1852                         }
1853                     }
1854                     else
1855                     {
1856                         bool horizontal((horiz && WIDGET_SB_BUTTON!=w)|| (!horiz && WIDGET_SB_BUTTON==w)),
1857                             thin(WIDGET_SB_BUTTON==w || WIDGET_SPIN==w || ((horiz ? r.height() : r.width())<16));
1858 
1859                         setPainterPen(p, m_mouseOverCols[MO_PLASTIK_DARK(w)], QPENWIDTH1);
1860                         if(horizontal)
1861                         {
1862                             drawAaLine(p, r.x()+1, r.y()+1, r.x()+r.width()-2, r.y()+1);
1863                             drawAaLine(p, r.x()+1, r.y()+r.height()-2, r.x()+r.width()-2, r.y()+r.height()-2);
1864                         }
1865                         else
1866                         {
1867                             drawAaLine(p, r.x()+1, r.y()+1, r.x()+1, r.y()+r.height()-2);
1868                             drawAaLine(p, r.x()+r.width()-2, r.y()+1, r.x()+r.width()-2, r.y()+r.height()-2);
1869                         }
1870                         if(!thin)
1871                         {
1872                             setPainterPen(p, m_mouseOverCols[MO_PLASTIK_LIGHT(w)], QPENWIDTH1);
1873                             if(horizontal)
1874                             {
1875                                 drawAaLine(p, r.x()+1, r.y()+2, r.x()+r.width()-2, r.y()+2);
1876                                 drawAaLine(p, r.x()+1, r.y()+r.height()-3, r.x()+r.width()-2, r.y()+r.height()-3);
1877                             }
1878                             else
1879                             {
1880                                 drawAaLine(p, r.x()+2, r.y()+1, r.x()+2, r.y()+r.height()-2);
1881                                 drawAaLine(p, r.x()+r.width()-3, r.y()+1, r.x()+r.width()-3, r.y()+r.height()-2);
1882                             }
1883                         }
1884                     }
1885                     p->restore();
1886                 }
1887         }
1888 
1889         if(drawShine)
1890         {
1891             bool   mo(option->state&State_Enabled && option->state&State_MouseOver && opts.highlightFactor);
1892             QColor white(Qt::white);
1893 
1894             if(WIDGET_MDI_WINDOW_BUTTON==w || WIDGET_RADIO_BUTTON==w || CIRCULAR_SLIDER(w))
1895             {
1896                 QRectF          ra(r.x()+0.5, r.y()+0.5, r.width(), r.height());
1897                 double          topSize=(ra.height()*0.4),
1898                     topWidthAdjust=WIDGET_RADIO_BUTTON==w || WIDGET_SLIDER==w ? 4 : 4.75;
1899                 QRectF          topGradRect(ra.x()+topWidthAdjust, ra.y(),
1900                                             ra.width()-(topWidthAdjust*2)-1, topSize-1);
1901                 QLinearGradient topGrad(topGradRect.topLeft(), topGradRect.bottomLeft());
1902 
1903                 white.setAlphaF(mo ? (opts.highlightFactor>0 ? 0.8 : 0.7) : 0.75);
1904                 topGrad.setColorAt(0.0, white);
1905                 white.setAlphaF(/*mo ? (opts.highlightFactor>0 ? 0.3 : 0.1) : */0.2);
1906                 topGrad.setColorAt(1.0, white);
1907                 p->fillPath(buildPath(topGradRect, w, round, topSize), QBrush(topGrad));
1908             }
1909             else
1910             {
1911                 QRectF ra(r.x()+0.5, r.y()+0.5, r.width(), r.height());
1912                 double size = qtcMin((horiz ? ra.height() : ra.width()) / 2.0,
1913                                      16),
1914                     rad=size/2.0;
1915                 int    mod=4;
1916 
1917                 if(horiz)
1918                 {
1919                     if(!(ROUNDED_LEFT&round))
1920                         ra.adjust(-8, 0, 0, 0);
1921                     if(!(ROUNDED_RIGHT&round))
1922                         ra.adjust(0, 0, 8, 0);
1923                 }
1924                 else
1925                 {
1926                     if(!(ROUNDED_TOP&round))
1927                         ra.adjust(0, -8, 0, 0);
1928                     if(!(ROUNDED_BOTTOM&round))
1929                         ra.adjust(0, 0, 0, 8);
1930                 }
1931 
1932                 if (realRound < ROUND_MAX ||
1933                     (!isMaxRoundWidget(w) && !IS_SLIDER(w))) {
1934                     rad /= 2.0;
1935                     mod = mod >> 1;
1936                 }
1937 
1938                 QRectF          gr(horiz ? QRectF(ra.x()+mod, ra.y(), ra.width()-(mod*2)-1, size-1)
1939                                    : QRectF(ra.x(), ra.y()+mod, size-1, ra.height()-(mod*2)-1));
1940                 QLinearGradient g(gr.topLeft(), horiz ? gr.bottomLeft() : gr.topRight());
1941 
1942                 white.setAlphaF(mo ? (opts.highlightFactor>0 ? 0.95 : 0.85) : 0.9);
1943                 g.setColorAt(0.0, white);
1944                 white.setAlphaF(mo ? (opts.highlightFactor>0 ? 0.3 : 0.1) : 0.2);
1945                 g.setColorAt(1.0, white);
1946                 if(WIDGET_SB_BUTTON==w)
1947                 {
1948                     p->save();
1949                     p->setClipRect(r);
1950                 }
1951                 p->fillPath(buildPath(gr, w, round, rad), QBrush(g));
1952                 if(WIDGET_SB_BUTTON==w)
1953                     p->restore();
1954             }
1955         }
1956     }
1957 
1958     r.adjust(1, 1, -1, -1);
1959 
1960     if (plastikMouseOver && (!sunken  || sunkenToggleMo)) {
1961         bool thin = (oneOf(w, WIDGET_SB_BUTTON, WIDGET_SPIN) ||
1962                      (horiz ? r.height() : r.width()) < 16);
1963         bool horizontal = (SLIDER(w) ? !horiz :
1964                            (horiz && w != WIDGET_SB_BUTTON) ||
1965                            (!horiz && w == WIDGET_SB_BUTTON));
1966         int len = SLIDER(w) ? sbSliderMOLen(opts, horiz ? r.width() :
1967                                             r.height()) : (thin ? 1 : 2);
1968 
1969         p->save();
1970         if (horizontal) {
1971             p->setClipRect(r.x(), r.y() + len, r.width(), r.height() - len * 2);
1972         } else {
1973             p->setClipRect(r.x() + len, r.y(), r.width() - len * 2, r.height());
1974         }
1975     }
1976 
1977     if (!colouredMouseOver && lightBorder) {
1978         setPainterPen(p, cols[LIGHT_BORDER(app)], QPENWIDTH1);
1979         p->drawPath(buildPath(r, w, round,
1980                               qtcGetRadius(&opts, r.width(),
1981                                            r.height(), w, RADIUS_INTERNAL)));
1982     } else if (colouredMouseOver || (draw3d && option->state & State_Raised)) {
1983         QPainterPath innerTlPath;
1984         QPainterPath innerBrPath;
1985         int dark(/*bevelledButton ? */2/* : 4*/);
1986 
1987         buildSplitPath(r, round, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_INTERNAL),
1988                        innerTlPath, innerBrPath);
1989 
1990         setPainterPen(p, border[colouredMouseOver ? MO_STD_LIGHT(w, sunken) : (sunken ? dark : 0)], QPENWIDTH1);
1991         p->drawPath(innerTlPath);
1992         if(colouredMouseOver || bevelledButton || draw3dfull)
1993         {
1994             setPainterPen(p, border[colouredMouseOver ? MO_STD_DARK(w) : (sunken ? 0 : dark)], QPENWIDTH1);
1995             p->drawPath(innerBrPath);
1996         }
1997     }
1998     if(plastikMouseOver && (!sunken  || sunkenToggleMo))
1999         p->restore();
2000     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
2001 
2002     if(doEtch || glowFocus)
2003     {
2004         if( !(opts.thin&THIN_FRAMES) && (!sunken || sunkenToggleMo ||
2005                                          (sunken && glowFocus && widget && qobject_cast<const QAbstractButton *>(widget) &&
2006                                           static_cast<const QAbstractButton *>(widget)->isCheckable())) &&
2007             ((WIDGET_OTHER!=w && WIDGET_SLIDER_TROUGH!=w && MO_GLOW==opts.coloredMouseOver && option->state&State_MouseOver) ||
2008              (WIDGET_DEF_BUTTON==w && IND_GLOW==opts.defBtnIndicator) ||
2009              glowFocus) )
2010             drawGlow(p, rOrig, WIDGET_DEF_BUTTON==w && option->state&State_MouseOver ? WIDGET_STD_BUTTON : w,
2011                      glowFocus ? m_focusCols : 0L);
2012         else
2013             drawEtch(p, rOrig, widget, w, EFFECT_SHADOW==opts.buttonEffect && WIDGET_BUTTON(w) && !sunken);
2014     }
2015 
2016     if(doBorder)
2017     {
2018         const QColor *borderCols=glowFocus || ( (WIDGET_COMBO==w || WIDGET_MENU_BUTTON==w || (WIDGET_NO_ETCH_BTN==w && ROUNDED_ALL!=round)) &&
2019                                                 USE_GLOW_FOCUS(option->state&State_MouseOver) &&
2020                                                 option->state&State_HasFocus && option->state&State_Enabled)
2021             ? m_focusCols
2022             : (WIDGET_COMBO==w || WIDGET_COMBO_BUTTON==w) && border==m_comboBtnCols
2023             ? option->state&State_MouseOver && MO_GLOW==opts.coloredMouseOver && !sunken
2024             ? m_mouseOverCols
2025             : m_buttonCols
2026             : cols;
2027 
2028         r.adjust(-1, -1, 1, 1);
2029         if(!sunken && option->state&State_Enabled && !glowFocus &&
2030            ( ( ( (doEtch && WIDGET_OTHER!=w && WIDGET_SLIDER_TROUGH!=w) || SLIDER(w) || WIDGET_COMBO==w || WIDGET_MENU_BUTTON==w ) &&
2031                (MO_GLOW==opts.coloredMouseOver/* || MO_COLORED==opts.colorMenubarMouseOver*/) && option->state&State_MouseOver) ||
2032              glowFocus || (doEtch && WIDGET_DEF_BUTTON==w && IND_GLOW==opts.defBtnIndicator)))
2033             drawBorder(p, r, option, round,
2034                        WIDGET_DEF_BUTTON==w && IND_GLOW==opts.defBtnIndicator && !(option->state&State_MouseOver)
2035                        ? m_defBtnCols : m_mouseOverCols, w);
2036         else
2037             drawBorder(p, r, option, round,
2038                        colouredMouseOver && MO_COLORED_THICK==opts.coloredMouseOver ? m_mouseOverCols : borderCols, w);
2039     }
2040 
2041     p->restore();
2042 }
2043 
2044 void Style::drawGlow(QPainter *p, const QRect &r, EWidget w, const QColor *cols) const
2045 {
2046     bool   def(WIDGET_DEF_BUTTON==w && IND_GLOW==opts.defBtnIndicator),
2047         defShade=def && (!m_defBtnCols ||
2048                          (m_defBtnCols[ORIGINAL_SHADE]==m_mouseOverCols[ORIGINAL_SHADE]));
2049     QColor col(cols ? cols[GLOW_MO]
2050                : def && m_defBtnCols
2051                ? m_defBtnCols[GLOW_DEFBTN] : m_mouseOverCols[GLOW_MO]);
2052 
2053     col.setAlphaF(GLOW_ALPHA(defShade));
2054     p->setBrush(Qt::NoBrush);
2055     p->setRenderHint(QPainter::Antialiasing, true);
2056     setPainterPen(p, col, QPENWIDTH1);
2057     p->drawPath(buildPath(r, w, ROUNDED_ALL, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_ETCH)));
2058     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
2059 }
2060 
2061 void Style::drawEtch(QPainter *p, const QRect &r, const QWidget *widget,  EWidget w, bool raised, int round) const
2062 {
2063     QPainterPath tl,
2064         br;
2065     QColor       col(Qt::black);
2066 
2067     if(WIDGET_TOOLBAR_BUTTON==w && EFFECT_ETCH==opts.tbarBtnEffect)
2068         raised=false;
2069 
2070     buildSplitPath(r, round, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_ETCH), tl, br);
2071 
2072     col.setAlphaF(USE_CUSTOM_ALPHAS(opts) ? opts.customAlphas[ALPHA_ETCH_DARK] : ETCH_TOP_ALPHA);
2073     p->setBrush(Qt::NoBrush);
2074     p->setRenderHint(QPainter::Antialiasing, true);
2075     setPainterPen(p, col, QPENWIDTH1);
2076 
2077     if(!raised && WIDGET_SLIDER!=w)
2078     {
2079         p->drawPath(tl);
2080         if(WIDGET_SLIDER_TROUGH==w && opts.thinSbarGroove && widget && qobject_cast<const QScrollBar *>(widget))
2081         {
2082             QColor col(Qt::white);
2083             col.setAlphaF(USE_CUSTOM_ALPHAS(opts) ? opts.customAlphas[ALPHA_ETCH_LIGHT] : ETCH_BOTTOM_ALPHA); // 0.25);
2084             setPainterPen(p, col, QPENWIDTH1);
2085         }
2086         else
2087             setPainterPen(p, getLowerEtchCol(widget), QPENWIDTH1);
2088     }
2089 
2090     p->drawPath(br);
2091     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
2092 }
2093 
2094 void Style::drawBgndRing(QPainter &painter, int x, int y, int size, int size2, bool isWindow) const
2095 {
2096     double width=(size-size2)/2.0,
2097         width2=width/2.0;
2098     QColor col(Qt::white);
2099 
2100     col.setAlphaF(RINGS_INNER_ALPHA(isWindow ? opts.bgndImage.type : opts.menuBgndImage.type));
2101     if (width == 1) {
2102         width = QPENWIDTH1;
2103     }
2104     painter.setPen(QPen(col, width));
2105     painter.drawEllipse(QRectF(x+width2, y+width2, size-width, size-width));
2106 
2107     if(IMG_BORDERED_RINGS==(isWindow ? opts.bgndImage.type : opts.menuBgndImage.type))
2108     {
2109         col.setAlphaF(RINGS_OUTER_ALPHA);
2110         painter.setPen(QPen(col, QPENWIDTH1));
2111         painter.drawEllipse(QRectF(x, y, size, size));
2112         if(size2)
2113             painter.drawEllipse(QRectF(x+width, y+width, size2, size2));
2114     }
2115 }
2116 
2117 QPixmap Style::drawStripes(const QColor &color, int opacity) const
2118 {
2119     QPixmap pix;
2120     QColor  col(color);
2121 
2122     if(100!=opacity)
2123         col.setAlphaF(opacity/100.0);
2124 
2125     QString key = QStringLiteral("qtc-stripes-%1").arg(col.rgba(), 0, 16);
2126     if(!m_usePixmapCache || !QPixmapCache::find(key, &pix))
2127     {
2128         pix=QPixmap(QSize(64, 64));
2129 
2130         if(100!=opacity)
2131             pix.fill(Qt::transparent);
2132 
2133         QPainter pixPainter(&pix);
2134         QColor   col2(shade(col, BGND_STRIPE_SHADE));
2135 
2136         if(100!=opacity)
2137         {
2138             col2.setAlphaF(opacity/100.0);
2139             pixPainter.setPen(QPen(col, QPENWIDTH1));
2140             for(int i=0; i<pix.height(); i+=4)
2141                 pixPainter.drawLine(0, i, pix.width()-1, i);
2142         }
2143         else
2144             pixPainter.fillRect(pix.rect(), col);
2145         pixPainter.setPen(QPen(QColor((3*col.red()+col2.red())/4,
2146                                  (3*col.green()+col2.green())/4,
2147                                  (3*col.blue()+col2.blue())/4,
2148                                  100!=opacity ? col2.alpha() : 255), QPENWIDTH1));
2149 
2150         for(int i=1; i<pix.height(); i+=4)
2151         {
2152             pixPainter.drawLine(0, i, pix.width()-1, i);
2153             pixPainter.drawLine(0, i+2, pix.width()-1, i+2);
2154         }
2155         pixPainter.setPen(QPen(col2, QPENWIDTH1));
2156         for(int i=2; i<pix.height()-1; i+=4)
2157             pixPainter.drawLine(0, i, pix.width()-1, i);
2158 
2159         if(m_usePixmapCache)
2160             QPixmapCache::insert(key, pix);
2161     }
2162 
2163     return pix;
2164 }
2165 
2166 void
2167 Style::drawBackground(QPainter *p, const QColor &bgnd, const QRect &r,
2168                       int opacity, BackgroundType type, EAppearance app,
2169                       const QPainterPath &path) const
2170 {
2171     bool isWindow = type != BGND_MENU;
2172 
2173     if (!qtcIsFlatBgnd(app)) {
2174         static const int constPixmapWidth  = 16;
2175         static const int constPixmapHeight = 512;
2176 
2177         QColor col(bgnd);
2178         QPixmap pix;
2179         QSize scaledSize;
2180         EGradType grad = isWindow ? opts.bgndGrad : opts.menuBgndGrad;
2181 
2182         if (app == APPEARANCE_STRIPED) {
2183             pix = drawStripes(col, opacity);
2184         } else if (app == APPEARANCE_FILE) {
2185             pix = isWindow ? opts.bgndPixmap.img : opts.menuBgndPixmap.img;
2186         } else {
2187             scaledSize = QSize(grad == GT_HORIZ ? constPixmapWidth : r.width(),
2188                                grad == GT_HORIZ ? r.height() :
2189                                constPixmapWidth);
2190 
2191             if (opacity != 100)
2192                 col.setAlphaF(opacity / 100.0);
2193 
2194             QString key = QStringLiteral("qtc-bgnd-%1-%2-%3")
2195                 .arg(col.rgba(), 0, 16).arg(grad).arg(app);
2196             if (!m_usePixmapCache || !QPixmapCache::find(key, &pix)) {
2197                 pix = QPixmap(QSize(grad == GT_HORIZ ? constPixmapWidth :
2198                                     constPixmapHeight, grad == GT_HORIZ ?
2199                                     constPixmapHeight : constPixmapWidth));
2200                 pix.fill(Qt::transparent);
2201 
2202                 QPainter pixPainter(&pix);
2203                 drawBevelGradientReal(col, &pixPainter,
2204                                       QRect(0, 0, pix.width(), pix.height()),
2205                                       grad == GT_HORIZ, false, app,
2206                                       WIDGET_OTHER);
2207                 pixPainter.end();
2208                 if (m_usePixmapCache) {
2209                     QPixmapCache::insert(key, pix);
2210                 }
2211             }
2212         }
2213 
2214         if (path.isEmpty()) {
2215             p->drawTiledPixmap(r, oneOf(app, APPEARANCE_STRIPED,
2216                                         APPEARANCE_FILE) ||
2217                                scaledSize == pix.size() ? pix :
2218                                pix.scaled(scaledSize, Qt::IgnoreAspectRatio));
2219         } else {
2220             p->save();
2221             p->setBrushOrigin(r.x(), r.y());
2222             p->fillPath(path,
2223                         QBrush(oneOf(app, APPEARANCE_STRIPED,
2224                                      APPEARANCE_FILE) ||
2225                                scaledSize == pix.size() ? pix :
2226                                pix.scaled(scaledSize, Qt::IgnoreAspectRatio)));
2227             p->restore();
2228         }
2229 
2230         if (isWindow && noneOf(app, APPEARANCE_STRIPED, APPEARANCE_FILE) &&
2231             grad == GT_HORIZ &&
2232             qtcGetGradient(app, &opts)->border == GB_SHINE) {
2233             int size = qMin(BGND_SHINE_SIZE, qMin(r.height() * 2, r.width()));
2234             QString key = QStringLiteral("qtc-radial-%1").arg(size / BGND_SHINE_STEPS, 0, 16);
2235             if (!m_usePixmapCache || !QPixmapCache::find(key, &pix)) {
2236                 size /= BGND_SHINE_STEPS;
2237                 size *= BGND_SHINE_STEPS;
2238                 pix = QPixmap(size, size / 2);
2239                 pix.fill(Qt::transparent);
2240                 QRadialGradient gradient(QPointF(pix.width() / 2.0, 0),
2241                                          pix.width() / 2.0,
2242                                          QPointF(pix.width() / 2.0, 0));
2243                 QColor c(Qt::white);
2244                 double alpha = qtcShineAlpha(&col);
2245 
2246                 c.setAlphaF(alpha);
2247                 gradient.setColorAt(0, c);
2248                 c.setAlphaF(alpha * 0.625);
2249                 gradient.setColorAt(0.5, c);
2250                 c.setAlphaF(alpha * 0.175);
2251                 gradient.setColorAt(0.75, c);
2252                 c.setAlphaF(0);
2253                 gradient.setColorAt(1, c);
2254                 QPainter pixPainter(&pix);
2255                 pixPainter.fillRect(QRect(0, 0, pix.width(), pix.height()),
2256                                     gradient);
2257                 pixPainter.end();
2258                 if (m_usePixmapCache) {
2259                     QPixmapCache::insert(key, pix);
2260                 }
2261             }
2262             p->drawPixmap(r.x() + ((r.width() - pix.width()) / 2), r.y(), pix);
2263         }
2264     } else {
2265         QColor col(bgnd);
2266         if (opacity != 100) {
2267             col.setAlphaF(opacity / 100.0);
2268         }
2269         if (path.isEmpty()) {
2270             p->fillRect(r, col);
2271         } else {
2272             p->save();
2273             p->setBrushOrigin(r.x(), r.y());
2274             p->fillPath(path, col);
2275             p->restore();
2276         }
2277     }
2278 }
2279 
2280 void
2281 Style::drawBackgroundImage(QPainter *p, bool isWindow, const QRect &r) const
2282 {
2283     QtCImage &img = isWindow ? opts.bgndImage : opts.menuBgndImage;
2284     int imgWidth = img.type == IMG_FILE ? img.width : RINGS_WIDTH(img.type);
2285     int imgHeight = img.type == IMG_FILE ? img.height : RINGS_HEIGHT(img.type);
2286 
2287     switch (img.type) {
2288     case IMG_NONE:
2289         break;
2290     case IMG_FILE:
2291         qtcLoadBgndImage(&img);
2292         if (!img.pixmap.img.isNull()) {
2293             switch (img.pos) {
2294             case PP_TL:
2295                 p->drawPixmap(r.x(), r.y(), img.pixmap.img);
2296                 break;
2297             case PP_TM:
2298                 p->drawPixmap(r.x() + (r.width() - img.pixmap.img.width()) / 2,
2299                               r.y(), img.pixmap.img);
2300                 break;
2301             default:
2302             case PP_TR:
2303                 p->drawPixmap(r.right() - img.pixmap.img.width(), r.y(),
2304                               img.pixmap.img);
2305                 break;
2306             case PP_BL:
2307                 p->drawPixmap(r.x(), r.bottom() - img.pixmap.img.height(),
2308                               img.pixmap.img);
2309                 break;
2310             case PP_BM:
2311                 p->drawPixmap(r.x() + (r.width() - img.pixmap.img.width()) / 2,
2312                               r.bottom() - img.pixmap.img.height(),
2313                               img.pixmap.img);
2314                 break;
2315             case PP_BR:
2316                 p->drawPixmap(r.right() - img.pixmap.img.width(),
2317                               r.bottom() - img.pixmap.img.height(),
2318                               img.pixmap.img);
2319                 break;
2320             case PP_LM:
2321                 p->drawPixmap(r.left(), r.y() + (r.height() -
2322                                                  img.pixmap.img.height()) / 2,
2323                               img.pixmap.img);
2324                 break;
2325             case PP_RM:
2326                 p->drawPixmap(r.right() - img.pixmap.img.width(),
2327                               r.y() + (r.height() -
2328                                        img.pixmap.img.height()) / 2,
2329                               img.pixmap.img);
2330                 break;
2331             case PP_CENTRED:
2332                 p->drawPixmap(r.x() + (r.width() - img.pixmap.img.width()) / 2,
2333                               r.y() + (r.height() -
2334                                        img.pixmap.img.height()) / 2,
2335                               img.pixmap.img);
2336             }
2337         }
2338         break;
2339     case IMG_PLAIN_RINGS:
2340     case IMG_BORDERED_RINGS:
2341         if (img.pixmap.img.isNull()) {
2342             img.pixmap.img = QPixmap(imgWidth, imgHeight);
2343             img.pixmap.img.fill(Qt::transparent);
2344             QPainter pixPainter(&img.pixmap.img);
2345 
2346             pixPainter.setRenderHint(QPainter::Antialiasing);
2347             drawBgndRing(pixPainter, 0, 0, 200, 140, isWindow);
2348 
2349             drawBgndRing(pixPainter, 210, 10, 230, 214, isWindow);
2350             drawBgndRing(pixPainter, 226, 26, 198, 182, isWindow);
2351             drawBgndRing(pixPainter, 300, 100, 50, 0, isWindow);
2352 
2353             drawBgndRing(pixPainter, 100, 96, 160, 144, isWindow);
2354             drawBgndRing(pixPainter, 116, 112, 128, 112, isWindow);
2355 
2356             drawBgndRing(pixPainter, 250, 160, 200, 140, isWindow);
2357             drawBgndRing(pixPainter, 310, 220, 80, 0, isWindow);
2358             pixPainter.end();
2359         }
2360         p->drawPixmap(r.right() - img.pixmap.img.width(),
2361                       r.y() + 1, img.pixmap.img);
2362         break;
2363     case IMG_SQUARE_RINGS:
2364         if (img.pixmap.img.isNull()) {
2365             img.pixmap.img = QPixmap(imgWidth, imgHeight);
2366             img.pixmap.img.fill(Qt::transparent);
2367             QPainter pixPainter(&img.pixmap.img);
2368             QColor col(Qt::white);
2369             double halfWidth = RINGS_SQUARE_LINE_WIDTH / 2.0;
2370 
2371             col.setAlphaF(RINGS_SQUARE_SMALL_ALPHA);
2372             pixPainter.setRenderHint(QPainter::Antialiasing);
2373             pixPainter.setPen(QPen(col, RINGS_SQUARE_LINE_WIDTH, Qt::SolidLine,
2374                                    Qt::SquareCap, Qt::RoundJoin));
2375             pixPainter.drawPath(buildPath(QRectF(halfWidth + 0.5,
2376                                                  halfWidth + 0.5,
2377                                                  RINGS_SQUARE_SMALL_SIZE,
2378                                                  RINGS_SQUARE_SMALL_SIZE),
2379                                           WIDGET_OTHER, ROUNDED_ALL,
2380                                           RINGS_SQUARE_RADIUS));
2381             pixPainter.drawPath(buildPath(QRectF(halfWidth + 0.5 +
2382                                                  (imgWidth -
2383                                                   (RINGS_SQUARE_SMALL_SIZE +
2384                                                    RINGS_SQUARE_LINE_WIDTH)),
2385                                                  halfWidth + 0.5 +
2386                                                  (imgHeight -
2387                                                   (RINGS_SQUARE_SMALL_SIZE +
2388                                                    RINGS_SQUARE_LINE_WIDTH)),
2389                                                  RINGS_SQUARE_SMALL_SIZE,
2390                                                  RINGS_SQUARE_SMALL_SIZE),
2391                                           WIDGET_OTHER, ROUNDED_ALL,
2392                                           RINGS_SQUARE_RADIUS));
2393             col.setAlphaF(RINGS_SQUARE_LARGE_ALPHA);
2394             pixPainter.setPen(QPen(col, RINGS_SQUARE_LINE_WIDTH, Qt::SolidLine,
2395                                    Qt::SquareCap, Qt::RoundJoin));
2396             pixPainter.drawPath(buildPath(QRectF(halfWidth + 0.5 +
2397                                                  (imgWidth -
2398                                                   RINGS_SQUARE_LARGE_SIZE -
2399                                                   RINGS_SQUARE_LINE_WIDTH) / 2.0,
2400                                                  halfWidth + 0.5 +
2401                                                  (imgHeight -
2402                                                   RINGS_SQUARE_LARGE_SIZE -
2403                                                   RINGS_SQUARE_LINE_WIDTH) / 2.0,
2404                                                  RINGS_SQUARE_LARGE_SIZE,
2405                                                  RINGS_SQUARE_LARGE_SIZE),
2406                                           WIDGET_OTHER, ROUNDED_ALL,
2407                                           RINGS_SQUARE_RADIUS));
2408             pixPainter.end();
2409         }
2410         p->drawPixmap(r.right() - img.pixmap.img.width(),
2411                       r.y() + 1, img.pixmap.img);
2412         break;
2413     }
2414 }
2415 
2416 void
2417 Style::drawBackground(QPainter *p, const QWidget *widget,
2418                       BackgroundType type) const
2419 {
2420     bool isWindow = type != BGND_MENU;
2421     bool previewMdi = (isWindow && m_isPreview &&
2422                        qobject_cast<const QMdiSubWindow*>(widget));
2423     const QWidget *window = m_isPreview ? widget : widget->window();
2424     int opacity = (type == BGND_MENU ? opts.menuBgndOpacity :
2425                    type == BGND_DIALOG ? opts.dlgOpacity : opts.bgndOpacity);
2426     QRect bgndRect = widget->rect();
2427     QRect imgRect = bgndRect;
2428     QtcQWidgetProps props(widget);
2429 
2430     if (opacity != 100 && !(qobject_cast<const QMdiSubWindow*>(widget) ||
2431                             Utils::hasAlphaChannel(window))) {
2432         opacity = 100;
2433     }
2434     if (widget) {
2435         props->opacity = opacity;
2436     }
2437 
2438     p->setClipRegion(widget->rect(), Qt::IntersectClip);
2439 
2440     if (isWindow) {
2441         if (!previewMdi) {
2442             WindowBorders borders = qtcGetWindowBorderSize(false);
2443             bgndRect.adjust(-borders.sides, -borders.titleHeight,
2444                             borders.sides, borders.bottom);
2445         } else {
2446             bgndRect.adjust(0, -pixelMetric(PM_TitleBarHeight,
2447                                             0L, widget), 0, 0);
2448         }
2449         if (opts.bgndImage.type == IMG_FILE && opts.bgndImage.onBorder) {
2450             imgRect = bgndRect;
2451         }
2452     }
2453 
2454     drawBackground(p, (isWindow ? window->palette().window().color() :
2455                        popupMenuCols()[ORIGINAL_SHADE]), bgndRect, opacity,
2456                    type, (type != BGND_MENU ? opts.bgndAppearance :
2457                           opts.menuBgndAppearance));
2458     // FIXME, workaround only, the non transparent part of the image will have
2459     // a different overall opacity.
2460     p->save();
2461     p->setCompositionMode(QPainter::CompositionMode_SourceOver);
2462     drawBackgroundImage(p, isWindow, imgRect);
2463     p->restore();
2464 }
2465 
2466 QPainterPath
2467 Style::buildPath(const QRectF &r, EWidget w, int round, double radius) const
2468 {
2469     QPainterPath path;
2470 
2471     if (oneOf(w, WIDGET_RADIO_BUTTON, WIDGET_DIAL) ||
2472         (w == WIDGET_MDI_WINDOW_BUTTON &&
2473          opts.titlebarButtons & TITLEBAR_BUTTON_ROUND) || CIRCULAR_SLIDER(w)) {
2474         path.addEllipse(r);
2475         return path;
2476     }
2477 
2478     if (opts.round == ROUND_NONE || radius < 0.01) {
2479         round = ROUNDED_NONE;
2480     }
2481 
2482     double diameter = radius * 2;
2483 
2484     if (w != WIDGET_MDI_WINDOW_TITLE && round & CORNER_BR) {
2485         path.moveTo(r.x() + r.width(), r.y() + r.height() - radius);
2486     } else {
2487         path.moveTo(r.x() + r.width(), r.y() + r.height());
2488     }
2489     if (round & CORNER_TR) {
2490         path.arcTo(r.x() + r.width() - diameter, r.y(),
2491                    diameter, diameter, 0, 90);
2492     } else {
2493         path.lineTo(r.x() + r.width(), r.y());
2494     }
2495     if (round & CORNER_TL) {
2496         path.arcTo(r.x(), r.y(), diameter, diameter, 90, 90);
2497     } else {
2498         path.lineTo(r.x(), r.y());
2499     }
2500     if (w != WIDGET_MDI_WINDOW_TITLE && round & CORNER_BL) {
2501         path.arcTo(r.x(), r.y() + r.height() - diameter,
2502                    diameter, diameter, 180, 90);
2503     } else {
2504         path.lineTo(r.x(), r.y() + r.height());
2505     }
2506 
2507     if (w != WIDGET_MDI_WINDOW_TITLE) {
2508         if (round & CORNER_BR) {
2509             path.arcTo(r.x() + r.width() - diameter,
2510                        r.y() + r.height() - diameter,
2511                        diameter, diameter, 270, 90);
2512         } else {
2513             path.lineTo(r.x() + r.width(), r.y() + r.height());
2514         }
2515     }
2516     return path;
2517 }
2518 
2519 QPainterPath
2520 Style::buildPath(const QRect &r, EWidget w, int round, double radius) const
2521 {
2522     return buildPath(QRectF(r.x() + 0.5, r.y() + 0.5,
2523                             r.width() - 1, r.height() - 1), w, round, radius);
2524 }
2525 
2526 void
2527 Style::buildSplitPath(const QRect &r, int round, double radius,
2528                       QPainterPath &tl, QPainterPath &br) const
2529 {
2530     double xd = r.x() + 0.5;
2531     double yd = r.y() + 0.5;
2532     double diameter = radius * 2;
2533     bool rounded = diameter > 0.0;
2534     int width = r.width() - 1;
2535     int height = r.height() - 1;
2536 
2537     if (rounded && round & CORNER_TR) {
2538         tl.arcMoveTo(xd + width - diameter, yd, diameter, diameter, 45);
2539         tl.arcTo(xd + width - diameter, yd, diameter, diameter, 45, 45);
2540         if (width > diameter) {
2541             tl.lineTo(xd + width - diameter, yd);
2542         }
2543     } else {
2544         tl.moveTo(xd + width, yd);
2545     }
2546 
2547     if (rounded && round & CORNER_TL) {
2548         tl.arcTo(xd, yd, diameter, diameter, 90, 90);
2549     } else {
2550         tl.lineTo(xd, yd);
2551     }
2552 
2553     if (rounded && round & CORNER_BL) {
2554         tl.arcTo(xd, yd + height - diameter, diameter, diameter, 180, 45);
2555         br.arcMoveTo(xd, yd + height - diameter, diameter, diameter, 180 + 45);
2556         br.arcTo(xd, yd + height - diameter, diameter, diameter, 180 + 45, 45);
2557     } else {
2558         tl.lineTo(xd, yd + height);
2559         br.moveTo(xd, yd + height);
2560     }
2561 
2562     if (rounded && round & CORNER_BR) {
2563         br.arcTo(xd + width - diameter, yd + height - diameter, diameter,
2564                  diameter, 270, 90);
2565     } else {
2566         br.lineTo(xd + width, yd + height);
2567     }
2568 
2569     if (rounded && round & CORNER_TR) {
2570         br.arcTo(xd + width - diameter, yd, diameter, diameter, 0, 45);
2571     } else {
2572         br.lineTo(xd + width, yd);
2573     }
2574 }
2575 
2576 void
2577 Style::drawBorder(QPainter *p, const QRect &r, const QStyleOption *option,
2578                   int round, const QColor *custom, EWidget w,
2579                   EBorder borderProfile, bool doBlend, int borderVal) const
2580 {
2581     if(ROUND_NONE==opts.round)
2582         round=ROUNDED_NONE;
2583 
2584     State        state(option->state);
2585     bool         enabled(state&State_Enabled),
2586         entry(WIDGET_ENTRY==w || (WIDGET_SCROLLVIEW==w && opts.highlightScrollViews)),
2587         hasFocus(enabled && entry && state&State_HasFocus),
2588         hasMouseOver(enabled && entry && state & State_MouseOver &&
2589                      opts.unifyCombo && opts.unifySpin);
2590     const QColor *cols(enabled && hasMouseOver && opts.coloredMouseOver && entry
2591                        ? m_mouseOverCols
2592                        : enabled && hasFocus && entry
2593                        ? m_focusCols
2594                        : custom
2595                        ? custom
2596                        : APP_KRUNNER==theThemedApp ? m_backgroundCols : backgroundColors(option));
2597     QColor       border(WIDGET_DEF_BUTTON==w && IND_FONT_COLOR==opts.defBtnIndicator && enabled
2598                         ? option->palette.buttonText().color()
2599                         : cols[WIDGET_PROGRESSBAR==w
2600                                ? PBAR_BORDER
2601                                : !enabled && (WIDGET_BUTTON(w) || WIDGET_SLIDER_TROUGH==w)
2602                                ? QTC_STD_BORDER
2603                                : m_mouseOverCols==cols && IS_SLIDER(w)
2604                                ? SLIDER_MO_BORDER_VAL
2605                                : borderVal]);
2606 
2607     p->setRenderHint(QPainter::Antialiasing, true);
2608     p->setBrush(Qt::NoBrush);
2609 
2610     if(WIDGET_TAB_BOT==w || WIDGET_TAB_TOP==w)
2611         cols=m_backgroundCols;
2612 
2613     if(!(opts.thin&THIN_FRAMES) && (WIDGET_SCROLLVIEW!=w || !(opts.square&SQUARE_SCROLLVIEW) || opts.highlightScrollViews))
2614         switch(borderProfile)
2615         {
2616         case BORDER_FLAT:
2617             break;
2618         case BORDER_RAISED:
2619         case BORDER_SUNKEN:
2620         case BORDER_LIGHT:
2621         {
2622             int          dark=FRAME_DARK_SHADOW;
2623             QColor       tl(cols[BORDER_RAISED==borderProfile || BORDER_LIGHT==borderProfile ? 0 : dark]),
2624                 br(cols[BORDER_RAISED==borderProfile ? dark : 0]);
2625             QPainterPath topPath,
2626                 botPath;
2627 
2628             if( ((hasMouseOver || hasFocus) && WIDGET_ENTRY==w) ||
2629                 (hasFocus && WIDGET_SCROLLVIEW==w))
2630             {
2631                 tl.setAlphaF(ENTRY_INNER_ALPHA);
2632                 br.setAlphaF(ENTRY_INNER_ALPHA);
2633             }
2634             else if(doBlend)
2635             {
2636                 tl.setAlphaF(BORDER_BLEND_ALPHA(w));
2637                 br.setAlphaF(BORDER_SUNKEN==borderProfile ? 0.0 : BORDER_BLEND_ALPHA(w));
2638             }
2639 
2640             QRect inner(r.adjusted(1, 1, -1, -1));
2641 
2642             buildSplitPath(inner, round, qtcGetRadius(&opts, inner.width(), inner.height(), w, RADIUS_INTERNAL), topPath, botPath);
2643 
2644             setPainterPen(p, (enabled || BORDER_SUNKEN==borderProfile) /*&&
2645                                                                   (BORDER_RAISED==borderProfile || BORDER_LIGHT==borderProfile || hasFocus || APPEARANCE_FLAT!=app)*/
2646                       ? tl
2647                       : option->palette.window().color(), QPENWIDTH1);
2648             p->drawPath(topPath);
2649             if(WIDGET_SCROLLVIEW==w || // Because of list view headers, need to draw dark line on right!
2650                (! ( (WIDGET_ENTRY==w && !hasFocus && !hasMouseOver) ||
2651                     (WIDGET_ENTRY!=w && doBlend && BORDER_SUNKEN==borderProfile) ) ) )
2652             {
2653                 if(!hasFocus && !hasMouseOver && BORDER_LIGHT!=borderProfile && WIDGET_SCROLLVIEW!=w)
2654                     setPainterPen(p, /*WIDGET_SCROLLVIEW==w && !hasFocus
2655                                 ? checkColour(option, QPalette::Window)
2656                                 : WIDGET_ENTRY==w && !hasFocus
2657                                 ? checkColour(option, QPalette::Base)
2658                                 : */enabled && (BORDER_SUNKEN==borderProfile || hasFocus || /*APPEARANCE_FLAT!=app ||*/
2659                                                 WIDGET_TAB_TOP==w || WIDGET_TAB_BOT==w)
2660                                 ? br
2661                                 : checkColour(option, QPalette::Window), QPENWIDTH1);
2662                 p->drawPath(botPath);
2663             }
2664         }
2665         }
2666 
2667     if(BORDER_SUNKEN==borderProfile &&
2668        (WIDGET_FRAME==w || ((WIDGET_ENTRY==w || WIDGET_SCROLLVIEW==w) && !opts.etchEntry && !hasFocus && !hasMouseOver)))
2669     {
2670         QPainterPath topPath,
2671             botPath;
2672         QColor       col(border);
2673 
2674         col.setAlphaF(LOWER_BORDER_ALPHA);
2675         buildSplitPath(r, round, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_EXTERNAL), topPath, botPath);
2676         p->setPen(QPen(/*enabled ? */border/* : col*/, QPENWIDTH1));
2677         p->drawPath(topPath);
2678 //         if(enabled)
2679         p->setPen(col);
2680         p->drawPath(botPath);
2681     }
2682     else
2683     {
2684         p->setPen(QPen(border, QPENWIDTH1));
2685         p->drawPath(buildPath(r, w, round, qtcGetRadius(&opts, r.width(), r.height(), w, RADIUS_EXTERNAL)));
2686     }
2687 
2688     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
2689 }
2690 
2691 void Style::drawMdiControl(QPainter *p, const QStyleOptionTitleBar *titleBar, SubControl sc, const QWidget *widget,
2692                            ETitleBarButtons btn, const QColor &iconColor, const QColor *btnCols, const QColor *bgndCols,
2693                            int adjust, bool activeWindow) const
2694 {
2695     bool hover((titleBar->activeSubControls&sc) && (titleBar->state&State_MouseOver));
2696 
2697     if(!activeWindow && !hover && opts.titlebarButtons&TITLEBAR_BUTTOM_HIDE_ON_INACTIVE_WINDOW)
2698         return;
2699 
2700     QRect rect(subControlRect(CC_TitleBar, titleBar, sc, widget));
2701 
2702     if (rect.isValid())
2703     {
2704         rect.adjust(adjust, adjust, -adjust, -adjust);
2705 
2706         bool sunken((titleBar->activeSubControls&sc) && (titleBar->state&State_Sunken)),
2707             colored(coloredMdiButtons(titleBar->state&State_Active, hover)),
2708             useBtnCols(opts.titlebarButtons&TITLEBAR_BUTTON_STD_COLOR &&
2709                        (hover ||
2710                         !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_MOUSE_OVER) ||
2711                         opts.titlebarButtons&TITLEBAR_BUTTON_COLOR));
2712         const QColor *buttonColors=colored && !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_SYMBOL)
2713             ? m_titleBarButtonsCols[btn] : (useBtnCols ? btnCols : bgndCols);
2714         const QColor &icnColor=opts.titlebarButtons&TITLEBAR_BUTTON_ICON_COLOR
2715             ? opts.titlebarButtonColors[btn+(NUM_TITLEBAR_BUTTONS*(titleBar->state&State_Active ? 1 : 2))]
2716             : colored && opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_SYMBOL
2717             ? m_titleBarButtonsCols[btn][ORIGINAL_SHADE]
2718             : SC_TitleBarCloseButton==sc && hover && !sunken && !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR)
2719             ? CLOSE_COLOR
2720             : SC_TitleBarCloseButton!=sc && hover && !sunken &&
2721             !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR) &&
2722             opts.titlebarButtons&TITLEBAR_BUTTON_USE_HOVER_COLOR
2723             ? m_mouseOverCols[ORIGINAL_SHADE]
2724             : iconColor;
2725 
2726         bool drewFrame=drawMdiButton(p, rect, hover, sunken, buttonColors);
2727         drawMdiIcon(p, icnColor, (drewFrame ? buttonColors : bgndCols)[ORIGINAL_SHADE],
2728                     rect, hover, sunken, subControlToIcon(sc), true, drewFrame);
2729     }
2730 }
2731 
2732 void Style::drawDwtControl(QPainter *p, const State &state, const QRect &rect, ETitleBarButtons btn, Icon icon,
2733                            const QColor &iconColor, const QColor *btnCols, const QColor *bgndCols) const
2734 {
2735     bool    sunken(state&State_Sunken),
2736         hover(state&State_MouseOver),
2737         colored(coloredMdiButtons(state&State_Active, hover)),
2738         useBtnCols(opts.titlebarButtons&TITLEBAR_BUTTON_STD_COLOR &&
2739                    (hover ||
2740                     !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_MOUSE_OVER) ||
2741                     opts.titlebarButtons&TITLEBAR_BUTTON_COLOR));
2742     const QColor *buttonColors=colored && !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_SYMBOL)
2743         ? m_titleBarButtonsCols[btn] : (useBtnCols ? btnCols : bgndCols);
2744     const QColor &icnColor=opts.dwtSettings&DWT_ICON_COLOR_AS_PER_TITLEBAR && opts.titlebarButtons&TITLEBAR_BUTTON_ICON_COLOR
2745         ? opts.titlebarButtonColors[btn+(NUM_TITLEBAR_BUTTONS/**(titleBar->state&State_Active ? 1 : 2)*/)]
2746         : colored && opts.titlebarButtons&TITLEBAR_BUTTON_COLOR_SYMBOL
2747         ? m_titleBarButtonsCols[btn][ORIGINAL_SHADE]
2748         : (TITLEBAR_CLOSE==btn && !(opts.titlebarButtons&TITLEBAR_BUTTON_COLOR) && (hover || sunken)
2749            ? CLOSE_COLOR
2750            : iconColor);
2751 
2752     bool drewFrame=drawMdiButton(p, rect, hover, sunken, buttonColors);
2753     drawMdiIcon(p, icnColor, (drewFrame ? buttonColors : bgndCols)[ORIGINAL_SHADE], rect, hover, sunken, icon, false, drewFrame);
2754 }
2755 
2756 bool Style::drawMdiButton(QPainter *painter, const QRect &r, bool hover, bool sunken, const QColor *cols) const
2757 {
2758     if(!(opts.titlebarButtons&TITLEBAR_BUTTON_NO_FRAME) &&
2759        (hover || sunken || !(opts.titlebarButtons&TITLEBAR_BUTTON_HOVER_FRAME)))
2760     {
2761         QStyleOption opt;
2762 
2763         opt.rect=r; // .adjusted(1, 1, -1, -1);
2764         if(opts.titlebarButtons&TITLEBAR_BUTTON_ROUND)
2765             opt.rect.adjust(1, 1, -1, -1);
2766         opt.state=State_Enabled|State_Horizontal|State_Raised;
2767         if(hover)
2768             opt.state|=State_MouseOver;
2769         if(sunken)
2770             opt.state|=State_Sunken;
2771 
2772         drawLightBevel(painter, opt.rect, &opt, 0L, ROUNDED_ALL, getFill(&opt, cols), cols, true, WIDGET_MDI_WINDOW_BUTTON);
2773         return true;
2774     }
2775 
2776     return false;
2777 }
2778 
2779 void Style::drawMdiIcon(QPainter *painter, const QColor &color, const QColor &bgnd,  const QRect &r, bool hover, bool sunken, Icon icon,
2780                         bool stdSize, bool drewFrame) const
2781 {
2782     if(!(opts.titlebarButtons&TITLEBAR_BUTTON_HOVER_SYMBOL_FULL) || hover || sunken)
2783     {
2784         bool faded=!sunken && !hover && opts.titlebarButtons&TITLEBAR_BUTTON_HOVER_SYMBOL;
2785 
2786         if(!sunken && !faded && EFFECT_NONE!=opts.titlebarEffect)
2787             //         // && hover && !(opts.titlebarButtons&TITLEBAR_BUTTON_HOVER_SYMBOL) && !customCol)
2788         {
2789             EEffect effect=opts.titlebarEffect;
2790 
2791             if(EFFECT_ETCH==opts.titlebarEffect && drewFrame)
2792                 effect=EFFECT_SHADOW;
2793 
2794             drawIcon(painter, blendColors(WINDOW_SHADOW_COLOR(effect), bgnd, WINDOW_TEXT_SHADOW_ALPHA(effect)),
2795                      EFFECT_SHADOW==effect
2796                      ? r.adjusted(1, 1, 1, 1)
2797                      : r.adjusted(0, 1, 0, 1),
2798                      sunken, icon, stdSize);
2799         }
2800 
2801         QColor col(color);
2802 
2803         if(faded)
2804             col=blendColors(col, bgnd, HOVER_BUTTON_ALPHA(col));
2805 
2806         drawIcon(painter, col, r, sunken, icon, stdSize);
2807     }
2808 }
2809 
2810 void Style::drawIcon(QPainter *painter, const QColor &color, const QRect &r, bool sunken, Icon icon, bool stdSize) const
2811 {
2812     static const int constIconSize=9;
2813     static const int constSmallIconSize=7;
2814 
2815     painter->setPen(color);
2816 
2817     QSize    iconSize(stdSize
2818                       ? constIconSize
2819                       : constSmallIconSize,
2820                       stdSize
2821                       ? constIconSize
2822                       : (ICN_RESTORE==icon && !(opts.titlebarButtons&TITLEBAR_BUTTOM_ARROW_MIN_MAX)
2823                          ? constSmallIconSize+1
2824                          : constSmallIconSize));
2825     QRect    br(r.x()+((r.width()-iconSize.width())>>1),
2826                 r.y()+((r.height()-iconSize.height())>>1),
2827                 iconSize.width(), iconSize.height());
2828     if(sunken)
2829         br.adjust(1, 1, 1, 1);
2830 
2831     switch(icon)
2832     {
2833     case ICN_MIN:
2834         if(opts.titlebarButtons&TITLEBAR_BUTTOM_ARROW_MIN_MAX)
2835             drawArrow(painter, opts.vArrows ? br.adjusted(0, 1, 0, 1) : br, PE_IndicatorArrowDown, color, false);
2836         else
2837             drawRect(painter, QRect(br.left(), br.bottom()-1, br.width(), 2));
2838         break;
2839     case ICN_MAX:
2840         if(opts.titlebarButtons&TITLEBAR_BUTTOM_ARROW_MIN_MAX)
2841             drawArrow(painter, opts.vArrows ? br.adjusted(0, -1, 0, -1) : br, PE_IndicatorArrowUp, color, false);
2842         else
2843         {
2844             drawRect(painter, br);
2845             painter->drawLine(br.left() + 1, br.top() + 1,  br.right() - 1, br.top() + 1);
2846         }
2847         break;
2848     case ICN_CLOSE:
2849         if(stdSize && opts.titlebarButtons&TITLEBAR_BUTTON_SUNKEN_BACKGROUND)
2850             br.adjust(1, 1, -1, -1);
2851         painter->save();
2852         painter->setClipRect(br);
2853         painter->setPen(QPen(color, 2));
2854         painter->drawLine(br.left(), br.top(), br.right(), br.bottom());
2855         painter->drawLine(br.right(), br.top(), br.left(), br.bottom());
2856         painter->restore();
2857         break;
2858     case ICN_RESTORE:
2859         if(opts.titlebarButtons&TITLEBAR_BUTTOM_ARROW_MIN_MAX)
2860         {
2861             painter->drawLine(br.x()+1, br.y(), br.x()+br.width()-2, br.y());
2862             painter->drawLine(br.x()+1, br.y()+br.height()-1, br.x()+br.width()-2, br.y()+br.height()-1);
2863             painter->drawLine(br.x(), br.y()+1, br.x(), br.y()+br.height()-2);
2864             painter->drawLine(br.x()+br.width()-1, br.y()+1, br.x()+br.width()-1, br.y()+br.height()-2);
2865             drawRect(painter, br.adjusted(1, 1, -1, -1));
2866         }
2867         else
2868         {
2869             drawRect(painter, QRect(br.x(), br.y()+3, br.width()-2, br.height()-3));
2870             painter->drawLine(br.x()+1, br.y()+4, br.x()+br.width()-4, br.y()+4);
2871             painter->drawLine(br.x()+2, br.y(), br.x()+br.width()-1, br.y());
2872             painter->drawLine(br.x()+2, br.y()+1, br.x()+br.width()-1, br.y()+1);
2873             painter->drawLine(br.x()+br.width()-1, br.y()+2, br.x()+br.width()-1, br.y()+(stdSize ? 5 : 4));
2874             painter->drawPoint(br.x()+br.width()-2, br.y()+(stdSize ? 5 : 4));
2875             painter->drawPoint(br.x()+2, br.y()+2);
2876         }
2877         break;
2878     case ICN_UP:
2879         drawArrow(painter, br, PE_IndicatorArrowUp, color, false);
2880         break;
2881     case ICN_DOWN:
2882         drawArrow(painter, opts.vArrows ? br.adjusted(0, 1, 0, 1) : br, PE_IndicatorArrowDown, color, false);
2883         break;
2884     case ICN_RIGHT:
2885         drawArrow(painter, br, PE_IndicatorArrowRight, color, false);
2886         break;
2887     case ICN_MENU:
2888         for(int i=1; i<=constIconSize; i+=3)
2889             painter->drawLine(br.left() + 1, br.top() + i,  br.right() - 1, br.top() + i);
2890         break;
2891     case ICN_SHADE:
2892     case ICN_UNSHADE:
2893     {
2894         bool isDwt=opts.dwtSettings&DWT_BUTTONS_AS_PER_TITLEBAR;
2895         br.adjust(0, -2, 0, 0);
2896         drawRect(painter, isDwt ? QRect(br.left(), br.bottom(), br.width(), 2) : QRect(br.left()+1, br.bottom()-1, br.width()-2, 2));
2897         br.adjust(0, ICN_SHADE==icon ? -3 : -5, 0, 0);
2898         drawArrow(painter, opts.vArrows ? br.adjusted(0, 1, 0, 1) : br,
2899                   ICN_SHADE==icon ? PE_IndicatorArrowDown : PE_IndicatorArrowUp, color, false);
2900         break;
2901     }
2902     default:
2903         break;
2904     }
2905 }
2906 
2907 void Style::drawEntryField(QPainter *p, const QRect &rx,  const QWidget *widget, const QStyleOption *option,
2908                            int round, bool fill, bool doEtch, EWidget w) const
2909 {
2910     QRect r(rx);
2911 
2912     if(doEtch && opts.etchEntry)
2913         r.adjust(1, 1, -1, -1);
2914 
2915     p->setRenderHint(QPainter::Antialiasing, true);
2916     if(fill)
2917         p->fillPath(buildPath(QRectF(r).adjusted(1, 1, -1, -1), WIDGET_SCROLLVIEW==w ? w : WIDGET_ENTRY, round,
2918                               qtcGetRadius(&opts, r.width()-2, r.height()-2, WIDGET_SCROLLVIEW==w ? w : WIDGET_ENTRY, RADIUS_INTERNAL)),
2919                     option->palette.brush(QPalette::Base));
2920     else
2921     {
2922         p->setPen(WIDGET_SCROLLVIEW!=w || !(opts.square&SQUARE_SCROLLVIEW) || opts.highlightScrollViews ? checkColour(option, QPalette::Base)
2923                   : backgroundColors(option)[ORIGINAL_SHADE]);
2924         p->drawPath(buildPath(r.adjusted(1, 1, -1, -1), WIDGET_SCROLLVIEW==w ? w : WIDGET_ENTRY, round,
2925                               qtcGetRadius(&opts, r.width()-2, r.height()-2, WIDGET_SCROLLVIEW==w ? w : WIDGET_ENTRY, RADIUS_INTERNAL)));
2926     }
2927     QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
2928 
2929     if(doEtch && opts.etchEntry)
2930         drawEtch(p, rx, widget, WIDGET_SCROLLVIEW==w ? w : WIDGET_ENTRY, false);
2931 
2932     drawBorder(p, r, option, round, 0L, w, BORDER_SUNKEN);
2933 }
2934 
2935 void Style::drawMenuItem(QPainter *p, const QRect &r, const QStyleOption *option, MenuItemType type, int round, const QColor *cols) const
2936 {
2937     QColor altCols[TOTAL_SHADES+1];
2938     if (theThemedApp == APP_KWIN) {
2939         QWidget *w = qobject_cast<QWidget*>(option->styleObject);
2940         QPalette::ColorRole role = (opts.useHighlightForMenu || (option->state & (State_On|State_Sunken))) ?
2941             QPalette::HighlightedText : QPalette::WindowText;
2942         if (w && w->palette().color(QPalette::Active, role)
2943                 != QApplication::palette().color(QPalette::Active, role)) {
2944 //             qWarning() << "drawMenuItem: widget" << w << "bgCol" << w->palette().color(QPalette::Active, role)
2945 //                 << "differs from app bgCol" << QApplication::palette().color(QPalette::Active, role);
2946             shadeColors(w->palette().color(QPalette::Active, role), altCols);
2947             cols = altCols;
2948         }
2949     }
2950 
2951     int fill=opts.useHighlightForMenu && ((MENU_BAR!=type) || m_highlightCols==cols || APP_OPENOFFICE==theThemedApp) ? ORIGINAL_SHADE : 4,
2952         border=opts.borderMenuitems ? 0 : fill;
2953 
2954     if(m_highlightCols!=cols && MENU_BAR==type && !(option->state&(State_On|State_Sunken)) &&
2955        !opts.colorMenubarMouseOver && (opts.borderMenuitems || !qtcIsFlat(opts.menuitemAppearance)))
2956         fill=ORIGINAL_SHADE;
2957 
2958     if(MENU_BAR!=type && APPEARANCE_FADE==opts.menuitemAppearance)
2959     {
2960         bool reverse = Qt::RightToLeft==option->direction;
2961         QColor trans(Qt::white);
2962         QRect r2(opts.round != ROUND_NONE ? r.adjusted(1, 1, -1, -1) : r);
2963         QRectF rf(r2);
2964         double fadePercent = ((double)MENUITEM_FADE_SIZE)/rf.width();
2965         QLinearGradient grad(r2.topLeft(), r2.topRight());
2966 
2967         trans.setAlphaF(0.0);
2968         grad.setColorAt(0, reverse ? trans : cols[fill]);
2969         grad.setColorAt(reverse ? fadePercent : 1.0-fadePercent, cols[fill]);
2970         grad.setColorAt(1, reverse ? cols[fill] : trans);
2971         if (opts.round != ROUND_NONE) {
2972             p->save();
2973             p->setRenderHint(QPainter::Antialiasing, true);
2974             p->fillPath(buildPath(rf, WIDGET_OTHER,
2975                                   reverse ? ROUNDED_RIGHT : ROUNDED_LEFT, 4),
2976                         QBrush(grad));
2977             p->restore();
2978         } else {
2979             p->fillRect(r2, QBrush(grad));
2980         }
2981     } else if (MENU_BAR==type || opts.borderMenuitems) {
2982         bool stdColor(MENU_BAR!=type || (SHADE_BLEND_SELECTED!=opts.shadeMenubars && SHADE_SELECTED!=opts.shadeMenubars));
2983 
2984         QStyleOption opt(*option);
2985 
2986         opt.state|=State_Horizontal|State_Raised;
2987         opt.state&=~(State_Sunken|State_On);
2988 
2989         if(stdColor && opts.borderMenuitems)
2990             drawLightBevel(p, r, &opt, 0L, round, cols[fill], cols, stdColor, WIDGET_MENU_ITEM);
2991         else
2992         {
2993             QRect fr(r);
2994 
2995             fr.adjust(1, 1, -1, -1);
2996 
2997             if(fr.width()>0 && fr.height()>0)
2998                 drawBevelGradient(cols[fill], p, fr, true, false, opts.menuitemAppearance, WIDGET_MENU_ITEM);
2999             drawBorder(p, r, &opt, round, cols, WIDGET_MENU_ITEM, BORDER_FLAT, false, border);
3000         }
3001     }
3002     else
3003     {
3004         // For now dont round combos - getting weird effects with shadow/clipping in Gtk2 style :-(
3005         if (/*MENU_COMBO==type || */opts.square & SQUARE_POPUP_MENUS) {
3006             drawBevelGradient(cols[fill], p, r, true, false,
3007                               opts.menuitemAppearance, WIDGET_MENU_ITEM);
3008         } else {
3009             p->save();
3010             p->setRenderHint(QPainter::Antialiasing, true);
3011             drawBevelGradient(
3012                 cols[fill], p, r,
3013                 buildPath(QRectF(r), WIDGET_OTHER, ROUNDED_ALL,
3014                           (opts.round >= ROUND_FULL ? 5.0 : 2.5) -
3015                           (opts.round > ROUND_SLIGHT ? 1.0 : 0.5)), true, false,
3016                 opts.menuitemAppearance, WIDGET_MENU_ITEM, false);
3017             p->restore();
3018         }
3019     }
3020 }
3021 
3022 void Style::drawProgress(QPainter *p, const QRect &r, const QStyleOption *option, bool vertical, bool reverse) const
3023 {
3024     QStyleOption opt(*option);
3025     QRect        rx(r);
3026 
3027     opt.state|=State_Raised;
3028 
3029     if(vertical)
3030         opt.state&=~State_Horizontal;
3031     else
3032         opt.state|=State_Horizontal;
3033 
3034     if(reverse)
3035         opt.state|=STATE_REVERSE;
3036     else
3037         opt.state&=~STATE_REVERSE;
3038 
3039     if((vertical ? r.height() : r.width())<1)
3040         return;
3041 
3042     if(vertical && r.height()<3)
3043         rx.setHeight(3);
3044 
3045     if(!vertical && rx.width()<3)
3046         rx.setWidth(3);
3047 
3048     // KTorrent's progressbars seem to have state==State_None
3049     const QColor *use=option->state&State_Enabled || State_None==option->state || ECOLOR_BACKGROUND==opts.progressGrooveColor
3050         ? m_progressCols
3051         ? m_progressCols
3052         : highlightColors(option, true)
3053         : m_backgroundCols;
3054 
3055     drawLightBevel(p, rx, &opt, 0L, ROUNDED_ALL, use[ORIGINAL_SHADE], use, opts.borderProgress, WIDGET_PROGRESSBAR);
3056 
3057     if(opts.glowProgress && (vertical ? rx.height() : rx.width())>3)
3058     {
3059         QRect           ri(opts.borderProgress ? rx.adjusted(1, 1, -1, -1) : rx);
3060         QLinearGradient grad(0, 0, vertical ? 0 : 1, vertical ? 1 : 0);
3061         QColor          glow(Qt::white),
3062             blank(Qt::white);
3063 
3064         blank.setAlphaF(0);
3065         glow.setAlphaF(GLOW_PROG_ALPHA);
3066         grad.setCoordinateMode(QGradient::ObjectBoundingMode);
3067         grad.setColorAt(0, (reverse ? GLOW_END : GLOW_START)==opts.glowProgress ? glow : blank);
3068         if(GLOW_MIDDLE==opts.glowProgress)
3069             grad.setColorAt(0.5, glow);
3070         grad.setColorAt(1, (reverse ? GLOW_START : GLOW_END)==opts.glowProgress ? glow : blank);
3071         p->fillRect(ri, grad);
3072     }
3073 
3074     if(!opts.borderProgress)
3075     {
3076         p->setPen(use[PBAR_BORDER]);
3077         if(!vertical)
3078         {
3079             p->drawLine(rx.topLeft(), rx.topRight());
3080             p->drawLine(rx.bottomLeft(), rx.bottomRight());
3081         }
3082         else
3083         {
3084             p->drawLine(rx.topLeft(), rx.bottomLeft());
3085             p->drawLine(rx.topRight(), rx.bottomRight());
3086         }
3087     }
3088 }
3089 
3090 static QPolygon rotate(const QPolygon &p, double angle)
3091 {
3092     QTransform transform;
3093     transform.rotate(angle);
3094     return transform.map(p);
3095 }
3096 
3097 void
3098 Style::drawArrow(QPainter *p, const QRect &rx, PrimitiveElement pe,
3099                  QColor col, bool small, bool kwin) const
3100 {
3101     QPolygon a;
3102     QRect r(rx);
3103     int m = !small && kwin ? ((r.height() - 7) / 2) : 0;
3104 
3105     if(small)
3106         a.setPoints(opts.vArrows ? 6 : 3,  2,0,  0,-2,  -2,0,   -2,1, 0,-1, 2,1);
3107     else
3108         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);
3109 
3110     switch (pe) {
3111     case PE_IndicatorArrowUp:
3112         if(m)
3113             r.adjust(0, -m, 0, -m);
3114         break;
3115     case PE_IndicatorArrowDown:
3116         if(m)
3117             r.adjust(0, m, 0, m);
3118         a=rotate(a, 180);
3119         break;
3120     case PE_IndicatorArrowRight:
3121         a=rotate(a, 90);
3122         break;
3123     case PE_IndicatorArrowLeft:
3124         a=rotate(a, 270);
3125         break;
3126     default:
3127         return;
3128     }
3129     a.translate((r.x()+(r.width()>>1)), (r.y()+(r.height()>>1)));
3130     p->save();
3131     col.setAlpha(255);
3132     p->setPen(col);
3133     p->setBrush(col);
3134     // Qt5 changes how coordinates is calculate for non-AA drawing.
3135     // use QPainter::Qt4CompatiblePainting for now.
3136     // A better solution should be shifting the coordinates by 0.5
3137     // or maybe use QPainterPath
3138     p->setRenderHint(QPainter::Qt4CompatiblePainting, true);
3139     // Qt >= 4.8.5 has problem drawing polygons correctly. Enabling
3140     // antialiasing can work around the problem although it will also make
3141     // the arrow blurry.
3142     // QtCurve issue:
3143     // https://github.com/QtCurve/qtcurve-qt4/issues/3.
3144     // Upstream bug report:
3145     // https://bugreports.qt-project.org/browse/QTBUG-33512
3146     p->setRenderHint(QPainter::Antialiasing, opts.vArrows);
3147     p->drawPolygon(a);
3148     p->restore();
3149 }
3150 
3151 void Style::drawSbSliderHandle(QPainter *p, const QRect &rOrig, const QStyleOption *option, bool slider) const
3152 {
3153     QStyleOption opt(*option);
3154     QRect        r(rOrig);
3155 
3156     if(opt.state&(State_Sunken|State_On))
3157         opt.state|=State_MouseOver;
3158 
3159     if(r.width()>r.height())
3160         opt.state|=State_Horizontal;
3161 
3162     opt.state &= ~(State_Sunken | State_On);
3163     opt.state |= State_Raised;
3164 
3165     if (auto slider = styleOptCast<QStyleOptionSlider>(option)) {
3166         if (slider->minimum == slider->maximum) {
3167             opt.state &= ~(State_MouseOver | State_Enabled);
3168         }
3169     }
3170 
3171     int          min(MIN_SLIDER_SIZE(opts.sliderThumbs));
3172     const QColor *use(sliderColors(&opt));
3173 
3174     drawLightBevel(p, r, &opt, 0L, (slider && (!(opts.square&SQUARE_SLIDER) ||
3175                                                (SLIDER_ROUND==opts.sliderStyle || SLIDER_ROUND_ROTATED==opts.sliderStyle)))
3176 #ifndef SIMPLE_SCROLLBARS
3177                    || (!slider && !(opts.square&SQUARE_SB_SLIDER) && (SCROLLBAR_NONE==opts.scrollbarType || opts.flatSbarButtons))
3178 #endif
3179                    ? ROUNDED_ALL : ROUNDED_NONE,
3180                    getFill(&opt, use, false, SHADE_DARKEN==opts.shadeSliders), use, true,
3181                    slider ? WIDGET_SLIDER : WIDGET_SB_SLIDER);
3182 
3183     if(LINE_NONE!=opts.sliderThumbs && (slider || ((opt.state&State_Horizontal && r.width()>=min)|| r.height()>=min)) &&
3184        (!slider || SLIDER_CIRCULAR!=opts.sliderStyle))
3185     {
3186         const QColor *markers(use);
3187         bool         horiz(opt.state&State_Horizontal);
3188 
3189         if(LINE_SUNKEN==opts.sliderThumbs)
3190             if(horiz)
3191                 r.adjust(0, -1, 0, 0);
3192             else
3193                 r.adjust(-1, 0, 0, 0);
3194         else
3195             r.adjust(horiz ? 1 : 0, horiz ? 0 : 1, 0, 0);
3196 
3197         switch(opts.sliderThumbs)
3198         {
3199         case LINE_1DOT:
3200             p->drawPixmap(r.x()+((r.width()-5)/2), r.y()+((r.height()-5)/2), *getPixmap(markers[QTC_STD_BORDER], PIX_DOT, 1.0));
3201             break;
3202         case LINE_FLAT:
3203             drawLines(p, r, !horiz, 3, 5, markers, 0, 5, opts.sliderThumbs);
3204             break;
3205         case LINE_SUNKEN:
3206             drawLines(p, r, !horiz, 4, 3, markers, 0, 3, opts.sliderThumbs);
3207             break;
3208         case LINE_DOTS:
3209         default:
3210             drawDots(p, r, !horiz, slider ? 3 : 5, slider ? 4 : 2, markers, 0, 5);
3211         }
3212     }
3213 }
3214 
3215 void Style::drawSliderHandle(QPainter *p, const QRect &r, const QStyleOptionSlider *option) const
3216 {
3217     bool         horiz(SLIDER_TRIANGULAR==opts.sliderStyle ? r.height()>r.width() : r.width()>r.height());
3218     QStyleOption opt(*option);
3219 
3220     if(!(option->activeSubControls&SC_SliderHandle) || !(opt.state&State_Enabled))
3221         opt.state&=~State_MouseOver;
3222 
3223     if (opts.sliderStyle == SLIDER_TRIANGULAR) {
3224         if (r.width() > r.height()) {
3225             opt.state |= State_Horizontal;
3226         }
3227         opt.state &= ~(State_Sunken | State_On);
3228         opt.state |= State_Raised;
3229         const QColor *use = sliderColors(&opt);
3230         const QColor *border = (opt.state & State_MouseOver &&
3231                                 oneOf(opts.coloredMouseOver, MO_GLOW,
3232                                       MO_COLORED) ? m_mouseOverCols : use);
3233         const QColor &fill(getFill(&opt, use, false,
3234                                    opts.shadeSliders == SHADE_DARKEN));
3235         int x = r.x();
3236         int y = r.y();
3237         PrimitiveElement direction(horiz ? PE_IndicatorArrowDown :
3238                                    PE_IndicatorArrowRight);
3239         QPolygon clipRegion;
3240         bool drawLight(MO_PLASTIK!=opts.coloredMouseOver || !(opt.state&State_MouseOver));
3241         int size(SLIDER_TRIANGULAR==opts.sliderStyle ? 15 : 13),
3242             borderVal(m_mouseOverCols==border ? SLIDER_MO_BORDER_VAL : BORDER_VAL(opt.state&State_Enabled));
3243 
3244         if(option->tickPosition & QSlider::TicksBelow)
3245             direction=horiz ? PE_IndicatorArrowDown : PE_IndicatorArrowRight;
3246         else if(option->tickPosition & QSlider::TicksAbove)
3247             direction=horiz ? PE_IndicatorArrowUp : PE_IndicatorArrowLeft;
3248 
3249         if (MO_GLOW==opts.coloredMouseOver && opts.buttonEffect != EFFECT_NONE)
3250             x++, y++;
3251 
3252         switch(direction)
3253         {
3254         default:
3255         case PE_IndicatorArrowDown:
3256             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);
3257             break;
3258         case PE_IndicatorArrowUp:
3259             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);
3260             break;
3261         case PE_IndicatorArrowLeft:
3262             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 );
3263             break;
3264         case PE_IndicatorArrowRight:
3265             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);
3266         }
3267 
3268         p->save();
3269         p->setClipRegion(QRegion(clipRegion)); // , QPainter::CoordPainter);
3270         if(qtcIsFlat(opts.sliderAppearance))
3271         {
3272             p->fillRect(r, fill);
3273 
3274             if(MO_PLASTIK==opts.coloredMouseOver && opt.state&State_MouseOver && !opts.colorSliderMouseOver)
3275             {
3276                 int col(SLIDER_MO_SHADE),
3277                     len(SLIDER_MO_LEN);
3278 
3279                 if(horiz)
3280                 {
3281                     p->fillRect(QRect(x+1, y+1, len, size-2), m_mouseOverCols[col]);
3282                     p->fillRect(QRect(x+r.width()-(1+len), y+1, len, r.height()-2), m_mouseOverCols[col]);
3283                 }
3284                 else
3285                 {
3286                     p->fillRect(QRect(x+1, y+1, size-2, len), m_mouseOverCols[col]);
3287                     p->fillRect(QRect(x+1, y+r.height()-(1+len), r.width()-2, len), m_mouseOverCols[col]);
3288                 }
3289             }
3290         }
3291         else
3292         {
3293             drawBevelGradient(fill, p, QRect(x, y, horiz ? r.width()-1 : size, horiz ? size : r.height()-1),
3294                               horiz, false, MODIFY_AGUA(opts.sliderAppearance));
3295 
3296             if(MO_PLASTIK==opts.coloredMouseOver && opt.state&State_MouseOver && !opts.colorSliderMouseOver)
3297             {
3298                 int col(SLIDER_MO_SHADE),
3299                     len(SLIDER_MO_LEN);
3300 
3301                 if(horiz)
3302                 {
3303                     drawBevelGradient(m_mouseOverCols[col], p, QRect(x+1, y+1, len, size-2),
3304                                       horiz, false, MODIFY_AGUA(opts.sliderAppearance));
3305                     drawBevelGradient(m_mouseOverCols[col], p,  QRect(x+r.width()-(1+len), y+1, len, size-2),
3306                                       horiz, false, MODIFY_AGUA(opts.sliderAppearance));
3307                 }
3308                 else
3309                 {
3310                     drawBevelGradient(m_mouseOverCols[col], p, QRect(x+1, y+1, size-2, len),
3311                                       horiz, false, MODIFY_AGUA(opts.sliderAppearance));
3312                     drawBevelGradient(m_mouseOverCols[col], p,QRect(x+1, y+r.height()-(1+len), size-2, len),
3313                                       horiz, false, MODIFY_AGUA(opts.sliderAppearance));
3314                 }
3315             }
3316         }
3317 
3318         p->restore();
3319         p->save();
3320 
3321         QPainterPath path;
3322         double       xd(x+0.5),
3323             yd(y+0.5),
3324             radius(2.5),
3325             diameter(radius*2),
3326             xdg(x-0.5),
3327             ydg(y-0.5),
3328             radiusg(radius+1),
3329             diameterg(radiusg*2);
3330         bool         glowMo(MO_GLOW==opts.coloredMouseOver && opt.state&State_MouseOver);
3331         QColor       glowCol(border[GLOW_MO]);
3332 
3333         glowCol.setAlphaF(GLOW_ALPHA(false));
3334 
3335         p->setPen(glowMo ? glowCol : border[borderVal]);
3336 
3337         switch(direction)
3338         {
3339         default:
3340         case PE_IndicatorArrowDown:
3341             p->setRenderHint(QPainter::Antialiasing, true);
3342             if(glowMo)
3343             {
3344                 path.moveTo(xdg+12-radiusg, ydg);
3345                 path.arcTo(xdg, ydg, diameterg, diameterg, 90, 90);
3346                 path.lineTo(xdg, ydg+10.5);
3347                 path.lineTo(xdg+6, ydg+16.5);
3348                 path.lineTo(xdg+12, ydg+10.5);
3349                 path.arcTo(xdg+12-diameterg, ydg, diameterg, diameterg, 0, 90);
3350                 p->drawPath(path);
3351                 path=QPainterPath();
3352                 p->setPen(border[borderVal]);
3353             }
3354             path.moveTo(xd+10-radius, yd);
3355             path.arcTo(xd, yd, diameter, diameter, 90, 90);
3356             path.lineTo(xd, yd+9);
3357             path.lineTo(xd+5, yd+14);
3358             path.lineTo(xd+10, yd+9);
3359             path.arcTo(xd+10-diameter, yd, diameter, diameter, 0, 90);
3360             p->drawPath(path);
3361             QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
3362             if(drawLight)
3363             {
3364                 p->setPen(use[APPEARANCE_DULL_GLASS==opts.sliderAppearance ? 1 : 0]);
3365                 p->drawLine(x+1, y+2, x+1, y+8);
3366                 p->drawLine(x+2, y+1, x+7, y+1);
3367             }
3368             break;
3369         case PE_IndicatorArrowUp:
3370             p->setRenderHint(QPainter::Antialiasing, true);
3371             if(glowMo)
3372             {
3373                 path.moveTo(xdg, ydg+6);
3374                 path.arcTo(xdg, ydg+16-diameterg, diameterg, diameterg, 180, 90);
3375                 path.arcTo(xdg+12-diameterg, ydg+16-diameterg, diameterg, diameterg, 270, 90);
3376                 path.lineTo(xdg+12, ydg+5.5);
3377                 path.lineTo(xdg+6, ydg-0.5);
3378                 path.lineTo(xdg, ydg+5.5);
3379                 p->drawPath(path);
3380                 path=QPainterPath();
3381                 p->setPen(border[borderVal]);
3382             }
3383             path.moveTo(xd, yd+5);
3384             path.arcTo(xd, yd+14-diameter, diameter, diameter, 180, 90);
3385             path.arcTo(xd+10-diameter, yd+14-diameter, diameter, diameter, 270, 90);
3386             path.lineTo(xd+10, yd+5);
3387             path.lineTo(xd+5, yd);
3388             path.lineTo(xd, yd+5);
3389             p->drawPath(path);
3390             QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
3391             if(drawLight)
3392             {
3393                 p->setPen(use[APPEARANCE_DULL_GLASS==opts.sliderAppearance ? 1 : 0]);
3394                 p->drawLine(x+5, y+1, x+1, y+5);
3395                 p->drawLine(x+1, y+5, x+1, y+11);
3396             }
3397             break;
3398         case PE_IndicatorArrowLeft:
3399             p->setRenderHint(QPainter::Antialiasing, true);
3400             if(glowMo)
3401             {
3402                 path.moveTo(xdg+6, ydg+12);
3403                 path.arcTo(xdg+16-diameterg, ydg+12-diameterg, diameterg, diameterg, 270, 90);
3404                 path.arcTo(xdg+16-diameterg, ydg, diameterg, diameterg, 0, 90);
3405                 path.lineTo(xdg+5.5, ydg);
3406                 path.lineTo(xdg-0.5, ydg+6);
3407                 path.lineTo(xdg+5.5, ydg+12);
3408                 p->drawPath(path);
3409                 path=QPainterPath();
3410                 p->setPen(border[borderVal]);
3411             }
3412             path.moveTo(xd+5, yd+10);
3413             path.arcTo(xd+14-diameter, yd+10-diameter, diameter, diameter, 270, 90);
3414             path.arcTo(xd+14-diameter, yd, diameter, diameter, 0, 90);
3415             path.lineTo(xd+5, yd);
3416             path.lineTo(xd, yd+5);
3417             path.lineTo(xd+5, yd+10);
3418             p->drawPath(path);
3419             QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
3420             if(drawLight)
3421             {
3422                 p->setPen(use[APPEARANCE_DULL_GLASS==opts.sliderAppearance ? 1 : 0]);
3423                 p->drawLine(x+1, y+5, x+5, y+1);
3424                 p->drawLine(x+5, y+1, x+11, y+1);
3425             }
3426             break;
3427         case PE_IndicatorArrowRight:
3428             p->setRenderHint(QPainter::Antialiasing, true);
3429             if(glowMo)
3430             {
3431                 path.moveTo(xdg+11, ydg);
3432                 path.arcTo(xdg, ydg, diameterg, diameterg, 90, 90);
3433                 path.arcTo(xdg, ydg+12-diameterg, diameterg, diameterg, 180, 90);
3434                 path.lineTo(xdg+10.5, ydg+12);
3435                 path.lineTo(xdg+16.5, ydg+6);
3436                 path.lineTo(xdg+10.5, ydg);
3437                 p->drawPath(path);
3438                 path=QPainterPath();
3439                 p->setPen(border[borderVal]);
3440             }
3441             path.moveTo(xd+9, yd);
3442             path.arcTo(xd, yd, diameter, diameter, 90, 90);
3443             path.arcTo(xd, yd+10-diameter, diameter, diameter, 180, 90);
3444             path.lineTo(xd+9, yd+10);
3445             path.lineTo(xd+14, yd+5);
3446             path.lineTo(xd+9, yd);
3447             p->drawPath(path);
3448             QPAINTER_RENDERHINT_AA_MAYBE_OFF(p);
3449             if(drawLight)
3450             {
3451                 p->setPen(use[APPEARANCE_DULL_GLASS==opts.sliderAppearance ? 1 : 0]);
3452                 p->drawLine(x+2, y+1, x+7, y+1);
3453                 p->drawLine(x+1, y+2, x+1, y+8);
3454             }
3455             break;
3456         }
3457         p->restore();
3458     } else {
3459         if (oneOf(opts.sliderStyle, SLIDER_PLAIN_ROTATED,
3460                   SLIDER_ROUND_ROTATED)) {
3461             opt.state ^= State_Horizontal;
3462         }
3463         drawSbSliderHandle(p, r, &opt, true);
3464     }
3465 }
3466 
3467 void Style::drawSliderGroove(QPainter *p, const QRect &groove, const QRect &handle,  const QStyleOptionSlider *slider,
3468                              const QWidget *widget) const
3469 {
3470     bool               horiz(Qt::Horizontal==slider->orientation);
3471     QRect              grv(groove);
3472     QStyleOptionSlider opt(*slider);
3473 
3474     opt.state&=~(State_HasFocus|State_On|State_Sunken|State_MouseOver);
3475 
3476     if(horiz)
3477     {
3478         int dh=(grv.height()-5)>>1;
3479         grv.adjust(0, dh, 0, -dh);
3480         opt.state|=State_Horizontal;
3481 
3482         if (opts.buttonEffect != EFFECT_NONE)
3483             grv.adjust(0, -1, 0, 1);
3484     }
3485     else
3486     {
3487         int dw=(grv.width()-5)>>1;
3488         grv.adjust(dw, 0, -dw, 0);
3489         opt.state&=~State_Horizontal;
3490 
3491         if (opts.buttonEffect != EFFECT_NONE)
3492             grv.adjust(-1, 0, 1, 0);
3493     }
3494 
3495     if(grv.height()>0 && grv.width()>0)
3496     {
3497         drawLightBevel(p, grv, &opt, widget,
3498                        opts.square&SQUARE_SLIDER ? ROUNDED_NONE : ROUNDED_ALL,
3499                        m_backgroundCols[slider->state&State_Enabled ? 2 : ORIGINAL_SHADE],
3500                        m_backgroundCols, true, WIDGET_SLIDER_TROUGH);
3501 
3502         if(opts.fillSlider && slider->maximum!=slider->minimum && slider->state&State_Enabled)
3503         {
3504             const QColor *usedCols=m_sliderCols ? m_sliderCols : m_highlightCols;
3505 
3506             if (horiz)
3507                 if (slider->upsideDown)
3508                     grv=QRect(handle.right()-4, grv.top(), (grv.right()-handle.right())+4, grv.height());
3509                 else
3510                     grv=QRect(grv.left(), grv.top(), handle.left()+4, grv.height());
3511             else
3512                 if (slider->upsideDown)
3513                     grv=QRect(grv.left(), handle.bottom()-4, grv.width(), (grv.height() - handle.bottom())+4);
3514                 else
3515                     grv=QRect(grv.left(), grv.top(), grv.width(), (handle.top() - grv.top())+4);
3516 
3517             if(grv.height()>0 && grv.width()>0)
3518                 drawLightBevel(p, grv, &opt, widget, opts.square&SQUARE_SLIDER ? ROUNDED_NONE : ROUNDED_ALL,
3519                                usedCols[ORIGINAL_SHADE], usedCols, true, WIDGET_FILLED_SLIDER_TROUGH);
3520         }
3521     }
3522 }
3523 
3524 void
3525 Style::drawMenuOrToolBarBackground(const QWidget *widget, QPainter *p,
3526                                    const QRect &r, const QStyleOption *option,
3527                                    bool menu, bool horiz) const
3528 {
3529     // LibreOffice - when drawMenuOrToolBarBackground is called with menuRect,
3530     // this is empty!
3531     if (r.width() < 1 || r.height() < 1)
3532         return;
3533 
3534     EAppearance app = menu ? opts.menubarAppearance : opts.toolbarAppearance;
3535     if (!qtcIsCustomBgnd(opts) || !qtcIsFlat(app) ||
3536         (menu && opts.shadeMenubars != SHADE_NONE)) {
3537         p->save();
3538 #if 0
3539         // Revert for now
3540         // This is necessary for correct opacity on the menubar but may
3541         // break transparent gradient.
3542         p->setCompositionMode(QPainter::CompositionMode_Source);
3543 #endif
3544         QRect rx(r);
3545 #ifdef Q_OS_MACOS
3546         QColor col(menu ?
3547                    menuColors(option, m_active)[ORIGINAL_SHADE] :
3548                    option->palette.window().color());
3549 #else
3550         QColor col(menu && (option->state & State_Enabled ||
3551                             opts.shadeMenubars != SHADE_NONE) ?
3552                    menuColors(option, m_active)[ORIGINAL_SHADE] :
3553                    option->palette.window().color());
3554 #endif
3555         // TODO: QtQuick
3556         int opacity = qtcGetOpacity(widget ? widget : getWidget(p));
3557 
3558         if (menu && BLEND_TITLEBAR) {
3559             rx.adjust(0, -qtcGetWindowBorderSize(false).titleHeight, 0, 0);
3560         }
3561         if (opacity < 100) {
3562             col.setAlphaF(opacity / 100.0);
3563         }
3564         drawBevelGradient(col, p, rx, horiz, false, MODIFY_AGUA(app));
3565         p->restore();
3566     }
3567 }
3568 
3569 void Style::drawHandleMarkers(QPainter *p, const QRect &rx, const QStyleOption *option, bool tb, ELine handles) const
3570 {
3571     if(rx.width()<2 || rx.height()<2)
3572         return;
3573 
3574     QRect r(rx);
3575 
3576     if(APP_OPENOFFICE==theThemedApp)
3577     {
3578         r.setX(r.x()+2);
3579         r.setWidth(10);
3580     }
3581 
3582     // CPD: Mouse over of toolbar handles not working - the whole toolbar seems to be active :-(
3583     QStyleOption opt(*option);
3584 
3585     opt.state&=~State_MouseOver;
3586 
3587     const QColor *border(borderColors(&opt, m_backgroundCols));
3588 
3589     switch(handles)
3590     {
3591     case LINE_NONE:
3592         break;
3593     case LINE_1DOT:
3594         p->drawPixmap(r.x()+((r.width()-5)/2), r.y()+((r.height()-5)/2), *getPixmap(border[QTC_STD_BORDER], PIX_DOT, 1.0));
3595         break;
3596     case LINE_DOTS:
3597         drawDots(p, r, !(option->state&State_Horizontal), 2, tb ? 5 : 3, border, tb ? -2 : 0, 5);
3598         break;
3599     case LINE_DASHES:
3600         if(option->state&State_Horizontal)
3601             drawLines(p, QRect(r.x()+(tb ? 2 : (r.width()-6)/2), r.y(), 3, r.height()), true, (r.height()-8)/2,
3602                       tb ? 0 : (r.width()-5)/2, border, 0, 5, handles);
3603         else
3604             drawLines(p, QRect(r.x(), r.y()+(tb ? 2 : (r.height()-6)/2), r.width(), 3), false, (r.width()-8)/2,
3605                       tb ? 0 : (r.height()-5)/2, border, 0, 5, handles);
3606         break;
3607     case LINE_FLAT:
3608         drawLines(p, r, !(option->state&State_Horizontal), 2, tb ? 4 : 2, border, tb ? -2 : 0, 4, handles);
3609         break;
3610     default:
3611         drawLines(p, r, !(option->state&State_Horizontal), 2, tb ? 4 : 2, border, tb ? -2 : 0, 3, handles);
3612     }
3613 }
3614 
3615 void Style::fillTab(QPainter *p, const QRect &r, const QStyleOption *option, const QColor &fill, bool horiz, EWidget tab,
3616                     bool tabOnly) const
3617 {
3618     bool   invertedSel=option->state&State_Selected && APPEARANCE_INVERTED==opts.appearance;
3619     QColor col(invertedSel ? option->palette.window().color() : fill);
3620 
3621     if(opts.tabBgnd && !tabOnly)
3622         col=shade(col, TO_FACTOR(opts.tabBgnd));
3623 
3624     if(invertedSel)
3625         p->fillRect(r, col);
3626     else
3627     {
3628         bool        selected(option->state&State_Selected);
3629         EAppearance app(selected ? SEL_TAB_APP : NORM_TAB_APP);
3630 
3631         drawBevelGradient(col, p, r, horiz, selected, app, tab);
3632     }
3633 }
3634 
3635 void Style::colorTab(QPainter *p, const QRect &r, bool horiz, EWidget tab, int round) const
3636 {
3637     p->save();
3638     p->setRenderHint(QPainter::Antialiasing, true);
3639     QLinearGradient grad(r.topLeft(), horiz ? r.bottomLeft() : r.topRight());
3640     QColor          start(m_highlightCols[ORIGINAL_SHADE]),
3641         end(m_highlightCols[ORIGINAL_SHADE]);
3642 
3643     start.setAlphaF(TO_ALPHA(opts.colorSelTab));
3644     end.setAlphaF(0.0);
3645     grad.setColorAt(0, WIDGET_TAB_TOP==tab ? start : end);
3646     grad.setColorAt(1, WIDGET_TAB_TOP==tab ? end : start);
3647     p->fillPath(buildPath(r, tab, round, qtcGetRadius(&opts, r.width(), r.height(), tab, RADIUS_EXTERNAL)), grad);
3648     p->restore();
3649 }
3650 
3651 void Style::shadeColors(const QColor &base, QColor *vals) const
3652 {
3653     bool useCustom(USE_CUSTOM_SHADES(opts));
3654     double hl=TO_FACTOR(opts.highlightFactor);
3655 
3656     for(int i=0; i<QTC_NUM_STD_SHADES; ++i)
3657         shade(base, &vals[i], useCustom ? opts.customShades[i] :
3658               qtcShadeGetIntern(opts.contrast, i,
3659                                 opts.darkerBorders, opts.shading));
3660     shade(base, &vals[SHADE_ORIG_HIGHLIGHT], hl);
3661     shade(vals[4], &vals[SHADE_4_HIGHLIGHT], hl);
3662     shade(vals[2], &vals[SHADE_2_HIGHLIGHT], hl);
3663     vals[ORIGINAL_SHADE]=base;
3664 }
3665 
3666 const QColor * Style::buttonColors(const QStyleOption *option) const
3667 {
3668     if(option && option->version>=TBAR_VERSION_HACK &&
3669        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];
3672 
3673     if(option && option->palette.button()!=m_buttonCols[ORIGINAL_SHADE])
3674     {
3675         shadeColors(option->palette.button().color(), m_coloredButtonCols);
3676         return m_coloredButtonCols;
3677     }
3678 
3679     return m_buttonCols;
3680 }
3681 
3682 QColor Style::titlebarIconColor(const QStyleOption *option) const
3683 {
3684     if(option && option->version>=TBAR_VERSION_HACK)
3685     {
3686         if(opts.titlebarButtons&TITLEBAR_BUTTON_ICON_COLOR && option->version<TBAR_VERSION_HACK+(NUM_TITLEBAR_BUTTONS*3))
3687             return opts.titlebarButtonColors[option->version-TBAR_VERSION_HACK];
3688         if(option->version<TBAR_VERSION_HACK+NUM_TITLEBAR_BUTTONS &&
3689            coloredMdiButtons(option->state&State_Active, option->state&(State_MouseOver|State_Sunken)))
3690             return m_titleBarButtonsCols[option->version-TBAR_VERSION_HACK][ORIGINAL_SHADE];
3691     }
3692 
3693     return buttonColors(option)[ORIGINAL_SHADE];
3694 }
3695 
3696 const QColor * Style::popupMenuCols(const QStyleOption *option) const
3697 {
3698     return (opts.lighterPopupMenuBgnd || opts.shadePopupMenu || !option ?
3699             m_popupMenuCols : backgroundColors(option));
3700 }
3701 
3702 const QColor*
3703 Style::checkRadioColors(const QStyleOption *option) const
3704 {
3705     return (opts.crColor && option && option->state & State_Enabled &&
3706             (option->state & State_On || option->state & State_NoChange)
3707             ? m_checkRadioSelCols : buttonColors(option));
3708 }
3709 
3710 const QColor * Style::sliderColors(const QStyleOption *option) const
3711 {
3712     return (option && option->state&State_Enabled)
3713         ? SHADE_NONE!=opts.shadeSliders && m_sliderCols &&
3714         (!opts.colorSliderMouseOver || option->state&State_MouseOver)
3715         ? m_sliderCols
3716         : m_buttonCols //buttonColors(option)
3717         : m_backgroundCols;
3718 }
3719 
3720 const QColor * Style::backgroundColors(const QColor &col) const
3721 {
3722     if(col.alpha()!=0 && col!=m_backgroundCols[ORIGINAL_SHADE])
3723     {
3724         shadeColors(col, m_coloredBackgroundCols);
3725         return m_coloredBackgroundCols;
3726     }
3727 
3728     return m_backgroundCols;
3729 }
3730 
3731 const QColor * Style::highlightColors(const QColor &col) const
3732 {
3733     if(col.alpha()!=0 && col!=m_highlightCols[ORIGINAL_SHADE])
3734     {
3735         shadeColors(col, m_coloredHighlightCols);
3736         return m_coloredHighlightCols;
3737     }
3738 
3739     return m_highlightCols;
3740 }
3741 
3742 const QColor * Style::borderColors(const QStyleOption *option, const QColor *use) const
3743 {
3744     return opts.coloredMouseOver && option && option->state&State_MouseOver && option->state&State_Enabled ? m_mouseOverCols : use;
3745 }
3746 
3747 const QColor * Style::getSidebarButtons() const
3748 {
3749     if(!m_sidebarButtonsCols)
3750     {
3751         if(SHADE_BLEND_SELECTED==opts.shadeSliders)
3752             m_sidebarButtonsCols=m_sliderCols;
3753         else if(IND_COLORED==opts.defBtnIndicator)
3754             m_sidebarButtonsCols=m_defBtnCols;
3755         else
3756         {
3757             m_sidebarButtonsCols=new QColor [TOTAL_SHADES+1];
3758             shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE], m_buttonCols[ORIGINAL_SHADE]),
3759                         m_sidebarButtonsCols);
3760         }
3761     }
3762 
3763     return m_sidebarButtonsCols;
3764 }
3765 
3766 void Style::setMenuColors(const QColor &bgnd)
3767 {
3768     switch (opts.shadeMenubars) {
3769     case SHADE_NONE:
3770         std::copy(m_backgroundCols, m_backgroundCols + TOTAL_SHADES + 1, m_menubarCols);
3771         break;
3772     case SHADE_BLEND_SELECTED:
3773         shadeColors(midColor(m_highlightCols[ORIGINAL_SHADE], m_backgroundCols[ORIGINAL_SHADE]), m_menubarCols);
3774         break;
3775     case SHADE_SELECTED:
3776         shadeColors(IS_GLASS(opts.appearance)
3777                     ? shade(m_highlightCols[ORIGINAL_SHADE], MENUBAR_GLASS_SELECTED_DARK_FACTOR)
3778                     : m_highlightCols[ORIGINAL_SHADE],
3779                     m_menubarCols);
3780         break;
3781     case SHADE_CUSTOM:
3782         shadeColors(opts.customMenubarsColor, m_menubarCols);
3783         break;
3784     case SHADE_DARKEN:
3785         shadeColors(shade(bgnd, MENUBAR_DARK_FACTOR), m_menubarCols);
3786         break;
3787     case SHADE_WINDOW_BORDER:
3788         break;
3789     }
3790 
3791     QColor *base=opts.shadePopupMenu
3792         ? SHADE_WINDOW_BORDER==opts.shadeMenubars
3793         ? (QColor *)getMdiColors(0L, true) // TODO: option!!!
3794         : m_menubarCols
3795         : m_backgroundCols;
3796 
3797     if (opts.lighterPopupMenuBgnd) {
3798         if (!m_popupMenuCols) {
3799             m_popupMenuCols = new QColor[TOTAL_SHADES + 1];
3800         }
3801         shadeColors(shade(base[ORIGINAL_SHADE],
3802                           TO_FACTOR(opts.lighterPopupMenuBgnd)),
3803                     m_popupMenuCols);
3804     } else {
3805         m_popupMenuCols = base;
3806     }
3807 }
3808 
3809 void Style::setMenuTextColors(QWidget *widget, bool isMenuBar) const
3810 {
3811     if(SHADE_WINDOW_BORDER==opts.shadeMenubars)
3812     {
3813         QPalette pal(widget->palette());
3814         QStyleOption opt;
3815 
3816         opt.init(widget);
3817         getMdiColors(&opt, false);
3818 
3819         pal.setBrush(QPalette::Active, QPalette::Foreground, m_activeMdiTextColor);
3820         pal.setBrush(QPalette::Active, QPalette::Text, pal.brush(QPalette::Active, QPalette::Foreground));
3821         if(isMenuBar)
3822         {
3823             pal.setBrush(QPalette::Inactive, QPalette::Foreground,
3824                          opts.shadeMenubarOnlyWhenActive ? m_mdiTextColor : m_activeMdiTextColor);
3825             pal.setBrush(QPalette::Inactive, QPalette::Text, pal.brush(QPalette::Inactive, QPalette::Foreground));
3826         }
3827         else if(opts.shadePopupMenu)
3828         {
3829             pal.setBrush(QPalette::Disabled, QPalette::Foreground, midColor(m_activeMdiTextColor, popupMenuCols()[ORIGINAL_SHADE]));
3830             pal.setBrush(QPalette::Disabled, QPalette::Text, pal.brush(QPalette::Disabled, QPalette::Foreground));
3831         }
3832 
3833         widget->setPalette(pal);
3834     } else if (opts.customMenuTextColor ||
3835                oneOf(opts.shadeMenubars, SHADE_BLEND_SELECTED,
3836                      SHADE_SELECTED) ||
3837                (opts.shadeMenubars == SHADE_CUSTOM &&
3838                 TOO_DARK(m_menubarCols[ORIGINAL_SHADE]))) {
3839         QPalette pal(widget->palette());
3840 
3841         pal.setBrush(QPalette::Active, QPalette::Foreground,
3842                      opts.customMenuTextColor ? opts.customMenuNormTextColor :
3843                      pal.highlightedText().color());
3844         pal.setBrush(QPalette::Active, QPalette::Text, pal.brush(QPalette::Active, QPalette::Foreground));
3845 
3846         if(isMenuBar && !opts.shadeMenubarOnlyWhenActive)
3847         {
3848             pal.setBrush(QPalette::Inactive, QPalette::Foreground, opts.customMenuTextColor
3849                          ? opts.customMenuNormTextColor
3850                          : pal.highlightedText().color());
3851             pal.setBrush(QPalette::Inactive, QPalette::Text, pal.brush(QPalette::Inactive, QPalette::Foreground));
3852         }
3853         else if(!isMenuBar && opts.shadePopupMenu)
3854         {
3855             pal.setBrush(QPalette::Disabled, QPalette::Foreground,
3856                          midColor(pal.brush(QPalette::Active, QPalette::Foreground).color(), popupMenuCols()[ORIGINAL_SHADE]));
3857             pal.setBrush(QPalette::Disabled, QPalette::Text, pal.brush(QPalette::Disabled, QPalette::Foreground));
3858         }
3859         widget->setPalette(pal);
3860     }
3861 }
3862 
3863 const QColor * Style::menuColors(const QStyleOption *option, bool active) const
3864 {
3865     if(SHADE_WINDOW_BORDER == opts.shadeMenubars)
3866     {
3867         return getMdiColors(option, active);
3868     }
3869 #ifdef Q_OS_MACOS
3870     else if(opts.shadeMenubarOnlyWhenActive && !active)
3871 #else
3872     else if(opts.shadeMenubars == SHADE_NONE || (opts.shadeMenubarOnlyWhenActive && !active))
3873 #endif
3874     {
3875         return backgroundColors(option);
3876     }
3877     return m_menubarCols;
3878 }
3879 
3880 bool
3881 Style::coloredMdiButtons(bool active, bool mouseOver) const
3882 {
3883     return (opts.titlebarButtons & TITLEBAR_BUTTON_COLOR &&
3884             (active ?
3885              (mouseOver || !(opts.titlebarButtons &
3886                              TITLEBAR_BUTTON_COLOR_MOUSE_OVER)) :
3887              ((opts.titlebarButtons & TITLEBAR_BUTTON_COLOR_MOUSE_OVER &&
3888                mouseOver) ||
3889               (!(opts.titlebarButtons & TITLEBAR_BUTTON_COLOR_MOUSE_OVER) &&
3890                opts.titlebarButtons & TITLEBAR_BUTTON_COLOR_INACTIVE))));
3891 }
3892 
3893 const QColor*
3894 Style::getMdiColors(const QStyleOption *option, bool active) const
3895 {
3896     if (!m_activeMdiColors) {
3897 #ifndef QTC_QT5_ENABLE_KDE
3898         m_activeMdiTextColor = (option ? option->palette.text().color() :
3899                                  QApplication::palette().text().color());
3900         m_mdiTextColor = (option ? option->palette.text().color() :
3901                            QApplication::palette().text().color());
3902 
3903         QFile f(kdeHome() + "/share/config/kdeglobals");
3904 
3905         if (f.open(QIODevice::ReadOnly)) {
3906             QTextStream in(&f);
3907             bool inPal = false;
3908 
3909             while (!in.atEnd()) {
3910                 QString line(in.readLine());
3911                 if (inPal) {
3912                     if (!m_activeMdiColors &&
3913                         line.indexOf("activeBackground=") == 0) {
3914                         QColor col;
3915                         setRgb(&col, line.mid(17).split(","));
3916                         if (col != m_highlightCols[ORIGINAL_SHADE]) {
3917                             m_activeMdiColors = new QColor[TOTAL_SHADES + 1];
3918                             shadeColors(col, m_activeMdiColors);
3919                         }
3920                     } else if (!m_mdiColors &&
3921                                line.indexOf("inactiveBackground=") == 0) {
3922                         QColor col;
3923                         setRgb(&col, line.mid(19).split(","));
3924                         if (col != m_buttonCols[ORIGINAL_SHADE]) {
3925                             m_mdiColors = new QColor[TOTAL_SHADES+1];
3926                             shadeColors(col, m_mdiColors);
3927                         }
3928                     } else if(line.indexOf("activeForeground=") == 0) {
3929                         setRgb(&m_activeMdiTextColor, line.mid(17).split(","));
3930                     } else if(line.indexOf("inactiveForeground=") == 0) {
3931                         setRgb(&m_mdiTextColor, line.mid(19).split(","));
3932                     } else if (line.indexOf('[') != -1) {
3933                         break;
3934                     }
3935                 } else if(line.indexOf("[WM]") == 0) {
3936                     inPal = true;
3937                 }
3938             }
3939             f.close();
3940         }
3941 #else
3942         Q_UNUSED(option);
3943         KConfigGroup cg(m_kdeGlobals, "WM");
3944 
3945         QColor col = cg.readEntry("activeBackground", QColor(48, 174, 232));
3946 
3947         if (col != m_backgroundCols[ORIGINAL_SHADE]) {
3948             m_activeMdiColors = new QColor[TOTAL_SHADES + 1];
3949             shadeColors(col, m_activeMdiColors);
3950         }
3951 
3952         col = cg.readEntry("inactiveBackground", QColor(224, 223, 222));;
3953         if (col != m_backgroundCols[ORIGINAL_SHADE]) {
3954             m_mdiColors = new QColor[TOTAL_SHADES+1];
3955             shadeColors(col, m_mdiColors);
3956         }
3957 
3958         m_activeMdiTextColor = cg.readEntry("activeForeground", QColor(255, 255, 255));
3959         m_mdiTextColor = cg.readEntry("inactiveForeground", QColor(75, 71, 67));
3960 #endif
3961 
3962         if(!m_activeMdiColors)
3963             m_activeMdiColors=(QColor *)m_backgroundCols;
3964         if(!m_mdiColors)
3965             m_mdiColors=(QColor *)m_backgroundCols;
3966 
3967         if(opts.shadeMenubarOnlyWhenActive && SHADE_WINDOW_BORDER==opts.shadeMenubars &&
3968            m_activeMdiColors[ORIGINAL_SHADE]==m_mdiColors[ORIGINAL_SHADE])
3969             opts.shadeMenubarOnlyWhenActive=false;
3970     }
3971 
3972     return active ? m_activeMdiColors : m_mdiColors;
3973 }
3974 
3975 void Style::readMdiPositions() const
3976 {
3977     if (0==m_mdiButtons[0].size() && 0==m_mdiButtons[1].size()) {
3978 #ifdef Q_OS_MACOS
3979         // no control over where the system menu appears, so we have little choice
3980         // but to keep it at its default position. The user can still override this.
3981         m_mdiButtons[0].append(SC_TitleBarSysMenu);
3982         m_mdiButtons[0].append(SC_TitleBarCloseButton);
3983         m_mdiButtons[0].append(SC_TitleBarMinButton);
3984         m_mdiButtons[0].append(SC_TitleBarMaxButton);
3985 
3986         m_mdiButtons[1].append(SC_TitleBarShadeButton);
3987         m_mdiButtons[1].append(SC_TitleBarContextHelpButton);
3988 #else
3989         // Set defaults...
3990         m_mdiButtons[0].append(SC_TitleBarSysMenu);
3991         m_mdiButtons[0].append(SC_TitleBarShadeButton);
3992 
3993         m_mdiButtons[1].append(SC_TitleBarContextHelpButton);
3994         m_mdiButtons[1].append(SC_TitleBarMinButton);
3995         m_mdiButtons[1].append(SC_TitleBarMaxButton);
3996         m_mdiButtons[1].append(WINDOWTITLE_SPACER);
3997         m_mdiButtons[1].append(SC_TitleBarCloseButton);
3998 #endif
3999 
4000 #ifdef QTC_QT5_ENABLE_KDE
4001         KSharedConfigPtr cfg = KSharedConfig::openConfig("kwinrc");
4002         KConfigGroup grp = cfg->group("org.kde.kdecoration2");
4003 
4004         QString left=grp.readEntry("ButtonsOnLeft", QString()),
4005             right=grp.readEntry("ButtonsOnRight", QString());
4006 
4007         if(!left.isEmpty() || !right.isEmpty())
4008             m_mdiButtons[0].clear(), m_mdiButtons[1].clear();
4009 
4010         if(!left.isEmpty())
4011             parseWindowLine(left, m_mdiButtons[0]);
4012 
4013         if(!right.isEmpty())
4014             parseWindowLine(right, m_mdiButtons[1]);
4015 
4016         // Designer uses shade buttons, not min/max - so if we don't have shade in our kwin config. 
4017         // then add this button near the max button...
4018         if (-1==m_mdiButtons[0].indexOf(SC_TitleBarShadeButton) && -1==m_mdiButtons[1].indexOf(SC_TitleBarShadeButton)) {
4019             int maxPos=m_mdiButtons[0].indexOf(SC_TitleBarMaxButton);
4020 
4021             if(-1==maxPos) // Left doesnt have max button, assume right does and add shade there
4022             {
4023                 int minPos=m_mdiButtons[1].indexOf(SC_TitleBarMinButton);
4024                 maxPos=m_mdiButtons[1].indexOf(SC_TitleBarMaxButton);
4025 
4026                 m_mdiButtons[1].insert(minPos<maxPos ? (minPos==-1 ? 0 : minPos)
4027                                         : (maxPos==-1 ? 0 : maxPos), SC_TitleBarShadeButton);
4028             }
4029             else // Add to left button
4030             {
4031                 int minPos=m_mdiButtons[0].indexOf(SC_TitleBarMinButton);
4032 
4033                 m_mdiButtons[1].insert(minPos>maxPos ? (minPos==-1 ? 0 : minPos)
4034                                         : (maxPos==-1 ? 0 : maxPos), SC_TitleBarShadeButton);
4035             }
4036         }
4037 #endif
4038     }
4039 }
4040 
4041 const QColor & Style::getFill(const QStyleOption *option, const QColor *use, bool cr, bool darker) const
4042 {
4043     return !option || !(option->state&State_Enabled)
4044         ? use[darker ? 2 : ORIGINAL_SHADE]
4045         : option->state&State_Sunken  // State_Down ????
4046         ? use[darker ? 5 : 4]
4047         : option->state&State_MouseOver
4048         ? !cr && option->state&State_On
4049         ? use[darker ? 3 : SHADE_4_HIGHLIGHT]
4050         : use[darker ? SHADE_2_HIGHLIGHT : SHADE_ORIG_HIGHLIGHT]
4051         : !cr && option->state&State_On
4052         ? use[darker ? 5 : 4]
4053         : use[darker ? 2 : ORIGINAL_SHADE];
4054 }
4055 
4056 QPixmap * Style::getPixmap(const QColor col, EPixmap p, double shade) const
4057 {
4058     QtcKey  key(createKey(col, p));
4059     QPixmap *pix=m_pixmapCache.object(key);
4060 
4061     if (!pix) {
4062         if (p == PIX_DOT) {
4063             pix=new QPixmap(5, 5);
4064             pix->fill(Qt::transparent);
4065 
4066             QColor          c(col);
4067             QPainter        p(pix);
4068             QLinearGradient g1(0, 0, 5, 5),
4069                 g2(0, 0, 3, 3);
4070 
4071             g1.setColorAt(0.0, c);
4072             c.setAlphaF(0.4);
4073             g1.setColorAt(1.0, c);
4074             c=Qt::white;
4075             c.setAlphaF(0.9);
4076             g2.setColorAt(0.0, c);
4077             c.setAlphaF(0.7);
4078             g2.setColorAt(1.0, c);
4079             p.setRenderHint(QPainter::Antialiasing, true);
4080             p.setPen(Qt::NoPen);
4081             p.setBrush(g1);
4082             p.drawEllipse(0, 0, 5, 5);
4083             p.setBrush(g2);
4084             p.drawEllipse(1, 1, 4, 4);
4085             p.end();
4086         }
4087         else
4088         {
4089             pix=new QPixmap();
4090 
4091             QImage img;
4092 
4093             switch(p)
4094             {
4095             case PIX_CHECK:
4096                 if(opts.xCheck) {
4097                     img = qtc_check_x_on;
4098                 } else {
4099                     img = qtc_check_on;
4100                 }
4101                 break;
4102             default:
4103                 break;
4104             }
4105 
4106             if (img.depth()<32)
4107                 img=img.convertToFormat(QImage::Format_ARGB32);
4108 
4109             qtcAdjustPix(img.bits(), 4, img.width(), img.height(),
4110                          img.bytesPerLine(), col.red(), col.green(),
4111                          col.blue(), shade, QTC_PIXEL_QT);
4112             *pix=QPixmap::fromImage(img);
4113         }
4114         m_pixmapCache.insert(key, pix, pix->depth()/8);
4115     }
4116 
4117     return pix;
4118 }
4119 
4120 const QColor & Style::getTabFill(bool current, bool highlight, const QColor *use) const
4121 {
4122     return (current ? use[ORIGINAL_SHADE] : highlight ?
4123             use[SHADE_2_HIGHLIGHT] : use[2]);
4124 }
4125 
4126 QColor Style::menuStripeCol() const
4127 {
4128     switch(opts.menuStripe)
4129     {
4130     default:
4131     case SHADE_NONE:
4132         return m_backgroundCols[ORIGINAL_SHADE];
4133     case SHADE_CUSTOM:
4134         return opts.customMenuStripeColor;
4135     case SHADE_BLEND_SELECTED:
4136         // Hack! Use opts.customMenuStripeColor to store this setting!
4137         if (isBlack(opts.customMenuStripeColor)) {
4138             opts.customMenuStripeColor =
4139                 midColor(m_highlightCols[ORIGINAL_SHADE],
4140                          popupMenuCols()[ORIGINAL_SHADE]);
4141         }
4142         return opts.customMenuStripeColor;
4143     case SHADE_SELECTED:
4144         return m_highlightCols[MENU_STRIPE_SHADE];
4145     case SHADE_DARKEN:
4146         return popupMenuCols()[MENU_STRIPE_SHADE];
4147     }
4148 }
4149 
4150 const QColor & Style::checkRadioCol(const QStyleOption *opt) const
4151 {
4152     return opt->state&State_Enabled
4153         ? m_checkRadioCol
4154         : opts.crButton
4155         ? opt->palette.buttonText().color()
4156         : opt->palette.text().color();
4157 }
4158 
4159 QColor Style::shade(const QColor &a, double k) const
4160 {
4161     QColor mod;
4162     qtcShade(&a, &mod, k, opts.shading);
4163     return mod;
4164 }
4165 
4166 void Style::shade(const QColor &ca, QColor *cb, double k) const
4167 {
4168     qtcShade(&ca, cb, k, opts.shading);
4169 }
4170 
4171 QColor Style::getLowerEtchCol(const QWidget *widget) const
4172 {
4173     if(USE_CUSTOM_ALPHAS(opts))
4174     {
4175         QColor col(Qt::white);
4176         col.setAlphaF(opts.customAlphas[ALPHA_ETCH_LIGHT]);
4177         return col;
4178     }
4179 
4180     if (qtcIsFlatBgnd(opts.bgndAppearance)) {
4181         QtcQWidgetProps props(widget);
4182         bool doEtch = widget && widget->parentWidget() && !props->noEtch;
4183         // CPD: Don't really want to check here for every widget, when
4184         // (so far) on problem seems to be in KPackageKit, and thats with
4185         // its KTextBrowser - so just check when we draw scrollviews...
4186         // if (doEtch && isInQAbstractItemView(widget->parentWidget())) {
4187         //     doEtch = false;
4188         //     props->noEtch = true;
4189         // }
4190 
4191         if(doEtch)
4192         {
4193             QColor bgnd(widget->parentWidget()->palette().color(widget->parentWidget()->backgroundRole()));
4194 
4195             if(bgnd.alpha()>0)
4196                 return shade(bgnd, 1.06);
4197         }
4198     }
4199 
4200     QColor col(Qt::white);
4201     col.setAlphaF(0.1); // qtcIsFlatBgnd(opts.bgndAppearance) ? 0.25 : 0.4);
4202 
4203     return col;
4204 }
4205 
4206 int
4207 Style::getFrameRound(const QWidget *widget) const
4208 {
4209     if (opts.square & SQUARE_FRAME) {
4210         return ROUNDED_NONE;
4211     }
4212     const QWidget *window = widget ? widget->window() : nullptr;
4213 
4214     if (window) {
4215         if (widget->rect() == window->rect()) {
4216             return ROUNDED_NONE;
4217         }
4218     }
4219 
4220     if ((opts.square & SQUARE_ENTRY) && widget &&
4221         qobject_cast<const QLabel*>(widget)) {
4222         return ROUNDED_NONE;
4223     }
4224     return ROUNDED_ALL;
4225 }
4226 
4227 void
4228 Style::widgetDestroyed(QObject *o)
4229 {
4230     QWidget *w = static_cast<QWidget*>(o);
4231     if (theThemedApp == APP_KONTACT) {
4232         m_sViewContainers.remove(w);
4233         QMap<QWidget*, QSet<QWidget*> >::Iterator it(m_sViewContainers.begin());
4234         QMap<QWidget*, QSet<QWidget*> >::Iterator end(m_sViewContainers.end());
4235         QSet<QWidget*> rem;
4236 
4237         for (;it != end;++it) {
4238             (*it).remove(w);
4239             if ((*it).isEmpty()) {
4240                 rem.insert(it.key());
4241             }
4242         }
4243         for (QWidget *widget: const_(rem)) {
4244             m_sViewContainers.remove(widget);
4245         }
4246     }
4247 }
4248 
4249 #ifdef QTC_QT5_ENABLE_KDE
4250 // void Style::setupKde4()
4251 // {
4252 //     if(kapp) {
4253 //         setDecorationColors();
4254 //     } else {
4255 //         applyKdeSettings(true);
4256 //         applyKdeSettings(false);
4257 //     }
4258 // }
4259 
4260 void
4261 Style::setDecorationColors()
4262 {
4263     KColorScheme kcs(QPalette::Active);
4264     if (opts.coloredMouseOver) {
4265         shadeColors(kcs.decoration(KColorScheme::HoverColor).color(),
4266                     m_mouseOverCols);
4267     }
4268     shadeColors(kcs.decoration(KColorScheme::FocusColor).color(), m_focusCols);
4269 }
4270 
4271 // void Style::applyKdeSettings(bool pal)
4272 // {
4273 //     if(pal)
4274 //     {
4275 //         if(!kapp)
4276 //             QApplication::setPalette(standardPalette());
4277 //         setDecorationColors();
4278 //     }
4279 //     else
4280 //     {
4281 //         KConfigGroup g(m_configFile, "General");
4282 //         QFont        mnu=g.readEntry("menuFont", QApplication::font());
4283 
4284 //         QApplication::setFont(g.readEntry("font", QApplication::font()));
4285 //         QApplication::setFont(mnu, "QMenuBar");
4286 //         QApplication::setFont(mnu, "QMenu");
4287 //         QApplication::setFont(mnu, "KPopupTitle");
4288 //         QApplication::setFont(g.readEntry("toolBarFont", QApplication::font()), "QToolBar");
4289 //     }
4290 // }
4291 #endif
4292 
4293 void Style::kdeGlobalSettingsChange(int type, int)
4294 {
4295     // TODO
4296     // KDE5 is not emitting this anymore.
4297     // We need our own signal from the configure UI
4298     Q_UNUSED(type);
4299     // switch(type) {
4300     // case KGlobalSettings::StyleChanged: {
4301     //     m_configFile->reparseConfiguration();
4302     //     if (m_usePixmapCache)
4303     //         QPixmapCache::clear();
4304     //     init(false);
4305 
4306     //     for (QWidget *widget: QApplication::topLevelWidgets()) {
4307     //         widget->update();
4308     //     }
4309     //     break;
4310     // }
4311     // case KGlobalSettings::PaletteChanged:
4312     //     m_configFile->reparseConfiguration();
4313     //     applyKdeSettings(true);
4314     //     if (m_usePixmapCache)
4315     //         QPixmapCache::clear();
4316     //     break;
4317     // case KGlobalSettings::FontChanged:
4318     //     m_configFile->reparseConfiguration();
4319     //     applyKdeSettings(false);
4320     //     break;
4321     // }
4322 
4323     m_blurHelper->setEnabled(Utils::compositingActive());
4324     m_windowManager->initialize(opts.windowDrag);
4325 }
4326 
4327 void Style::borderSizesChanged()
4328 {
4329 #ifdef QTC_QT5_ENABLE_KDE
4330     int old = qtcGetWindowBorderSize(false).titleHeight;
4331 
4332     if (old != qtcGetWindowBorderSize(true).titleHeight) {
4333         for (QWidget *widget: QApplication::topLevelWidgets()) {
4334             if (qobject_cast<QMainWindow*>(widget) &&
4335                 static_cast<QMainWindow*>(widget)->menuBar()) {
4336                 static_cast<QMainWindow*>(widget)->menuBar()->update();
4337             }
4338         }
4339     }
4340 #endif
4341 }
4342 
4343 static QMainWindow*
4344 getWindow(unsigned int xid)
4345 {
4346     QTC_RET_IF_FAIL(xid, nullptr);
4347     for (QWidget *widget: QApplication::topLevelWidgets()) {
4348         if (qobject_cast<QMainWindow*>(widget) && qtcGetWid(widget) == xid) {
4349             return static_cast<QMainWindow*>(widget);
4350         }
4351     }
4352     return nullptr;
4353 }
4354 
4355 static bool
4356 diffTime(struct timeval *lastTime)
4357 {
4358     struct timeval now, diff;
4359 
4360     gettimeofday(&now, nullptr);
4361     timersub(&now, lastTime, &diff);
4362     *lastTime = now;
4363     return diff.tv_sec > 0 || diff.tv_usec > 500000;
4364 }
4365 
4366 void
4367 Style::toggleMenuBar(unsigned int xid)
4368 {
4369     static unsigned int lastXid = 0;
4370     static struct timeval lastTime = {0, 0};
4371 
4372     if (diffTime(&lastTime) || lastXid != xid) {
4373         QMainWindow *win = getWindow(xid);
4374         if (win) {
4375             toggleMenuBar(win);
4376         }
4377     }
4378     lastXid = xid;
4379 }
4380 
4381 void
4382 Style::toggleStatusBar(unsigned int xid)
4383 {
4384     static unsigned int lastXid = 0;
4385     static struct timeval lastTime = {0, 0};
4386 
4387     if (diffTime(&lastTime) || lastXid != xid) {
4388         QMainWindow *win = getWindow(xid);
4389         if (win) {
4390             toggleStatusBar(win);
4391         }
4392     }
4393     lastXid = xid;
4394 }
4395 
4396 void Style::compositingToggled()
4397 {
4398     for (QWidget *widget: QApplication::topLevelWidgets()) {
4399         widget->update();
4400     }
4401 }
4402 
4403 void Style::toggleMenuBar(QMainWindow *window)
4404 {
4405     bool triggeredAction(false);
4406 
4407 #ifdef QTC_QT5_ENABLE_KDE
4408     if (qobject_cast<KXmlGuiWindow*>(window)) {
4409         KActionCollection *collection=static_cast<KXmlGuiWindow *>(window)->actionCollection();
4410         QAction           *act=collection ? collection->action(KStandardAction::name(KStandardAction::ShowMenubar)) : 0L;
4411         if(act)
4412         {
4413             act->trigger();
4414             triggeredAction=true;
4415         }
4416     }
4417 #endif
4418     if(!triggeredAction)
4419     {
4420         QWidget *menubar=window->menuWidget();
4421         if(m_saveMenuBarStatus)
4422             qtcSetMenuBarHidden(appName, menubar->isVisible());
4423 
4424         window->menuWidget()->setHidden(menubar->isVisible());
4425     }
4426 }
4427 
4428 void Style::toggleStatusBar(QMainWindow *window)
4429 {
4430     bool triggeredAction(false);
4431 
4432 #ifdef QTC_QT5_ENABLE_KDE
4433     if (qobject_cast<KXmlGuiWindow*>(window)) {
4434         KActionCollection *collection=static_cast<KXmlGuiWindow *>(window)->actionCollection();
4435         QAction           *act=collection ? collection->action(KStandardAction::name(KStandardAction::ShowStatusbar)) : 0L;
4436         if(act)
4437         {
4438             act->trigger();
4439             triggeredAction=true;
4440             //emitStatusBarState(true); // TODO: ???
4441         }
4442     }
4443 #endif
4444     if (!triggeredAction) {
4445         QList<QStatusBar*> sb = getStatusBars(window);
4446 
4447         if (sb.count()) {
4448             if (m_saveStatusBarStatus) {
4449                 qtcSetStatusBarHidden(appName, sb.first()->isVisible());
4450             }
4451             for (QStatusBar *statusBar: const_(sb)) {
4452                 statusBar->setHidden(statusBar->isVisible());
4453             }
4454             emitStatusBarState(sb.first());
4455         }
4456     }
4457 }
4458 
4459 void Style::emitMenuSize(QWidget *w, unsigned short size, bool force)
4460 {
4461     // DO NOT condition compile on QTC_ENABLE_X11.
4462     // There's no direct linkage on X11 and the following code will just do
4463     // nothing if X11 is not enabled (either at compile time or at run time).
4464     QTC_RET_IF_FAIL(qtcX11Enabled());
4465 
4466     if (WId wid = qtcGetWid(w->window())) {
4467         static const char *constMenuSizeProperty = "qtcMenuSize";
4468         unsigned short oldSize = 2000;
4469 
4470         if (!force) {
4471             QVariant prop(w->property(constMenuSizeProperty));
4472             if (prop.isValid()) {
4473                 bool ok;
4474                 oldSize = prop.toUInt(&ok);
4475                 if (!ok) {
4476                     oldSize = 2000;
4477                 }
4478             }
4479         }
4480 
4481         if (oldSize != size) {
4482             w->setProperty(constMenuSizeProperty, size);
4483             qtcX11SetMenubarSize(wid, size);
4484             if(!m_dBusHelper->m_dBus)
4485                 m_dBusHelper->m_dBus = new QDBusInterface("org.kde.kwin", "/QtCurve",
4486                                              "org.kde.QtCurve");
4487             m_dBusHelper->m_dBus->call(QDBus::NoBlock, "menuBarSize",
4488                           (unsigned int)wid, (int)size);
4489         }
4490     }
4491 }
4492 
4493 void Style::emitStatusBarState(QStatusBar *sb)
4494 {
4495     if (opts.statusbarHiding & HIDE_KWIN) {
4496         if (!m_dBusHelper->m_dBus)
4497             m_dBusHelper->m_dBus = new QDBusInterface("org.kde.kwin", "/QtCurve",
4498                                         "org.kde.QtCurve");
4499         m_dBusHelper->m_dBus->call(QDBus::NoBlock, "statusBarState",
4500                      (unsigned int)qtcGetWid(sb->window()),
4501                      sb->isVisible());
4502     }
4503 }
4504 }