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