Mercurial > hg > svapp
comparison style/ThornStyle.cpp @ 668:dac3781826da thorn-cpp
Experimental branch based on Thorn C++ code from RG
author | Chris Cannam |
---|---|
date | Tue, 30 Apr 2019 11:36:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
667:31ea416fea3c | 668:dac3781826da |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Vect | |
5 An experimental audio player for plural recordings of a work | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 | |
8 This file is based on Rosegarden, a MIDI and audio sequencer and | |
9 musical notation editor. Copyright 2000-2018 the Rosegarden | |
10 development team. Thorn style developed in stylesheet form by | |
11 D. Michael McIntyre and reimplemented as a class by David Faure. | |
12 | |
13 This program is free software; you can redistribute it and/or | |
14 modify it under the terms of the GNU General Public License as | |
15 published by the Free Software Foundation; either version 2 of the | |
16 License, or (at your option) any later version. See the file | |
17 COPYING included with this distribution for more information. | |
18 */ | |
19 | |
20 #include "ThornStyle.h" | |
21 #include "AppEventFilter.h" | |
22 | |
23 #include "base/ResourceFinder.h" | |
24 #include "widgets/IconLoader.h" | |
25 | |
26 #include <QApplication> | |
27 #include <QAbstractItemView> | |
28 #include <QCheckBox> | |
29 #include <QDebug> | |
30 #include <qdrawutil.h> | |
31 #include <QEvent> | |
32 #include <QFile> | |
33 #include <QFileDialog> | |
34 #include <QLabel> | |
35 #include <QLayout> | |
36 #include <QPainter> | |
37 #include <QRadioButton> | |
38 #include <QStyleFactory> | |
39 #include <QStyleOption> | |
40 #include <QToolBar> | |
41 #include <QWidget> | |
42 #include <QDialogButtonBox> | |
43 #include <QPushButton> | |
44 #include <QComboBox> | |
45 #include <QSpinBox> | |
46 #include <QScrollBar> | |
47 #include <QAbstractScrollArea> | |
48 | |
49 // Silence gcc compiler warnings due to the switches below not covering all cases, on purpose | |
50 #pragma GCC diagnostic push | |
51 #pragma GCC diagnostic ignored "-Wswitch-enum" | |
52 | |
53 static QPixmap loadPix(const QString &name) | |
54 { | |
55 QPixmap pix(name); | |
56 if (pix.isNull()) { | |
57 qWarning() << "Pixmap not found:" << name; | |
58 Q_ASSERT(0); | |
59 } | |
60 return pix; | |
61 } | |
62 | |
63 Q_GLOBAL_STATIC(AppEventFilter, s_eventFilter) // created on demand in setEnabled | |
64 | |
65 //////////////////////////////////////////////////////////////////////////////////////////////////////// | |
66 | |
67 ThornStyle::ThornStyle() | |
68 // We could load these on demand, but the mainwindow needs most of them already anyway | |
69 : m_horizontalToolbarSeparatorPixmap(loadPix(":/icons/style/htoolbar-separator.png")), | |
70 m_verticalToolbarSeparatorPixmap(loadPix(":/icons/style/vtoolbar-separator.png")), | |
71 m_checkboxUncheckedPixmap(loadPix(":/icons/style/checkbox_unchecked.png")), | |
72 m_checkboxUncheckedHoverPixmap(loadPix(":/icons/style/checkbox_unchecked_hover.png")), | |
73 m_checkboxUncheckedDisabledPixmap(loadPix(":/icons/style/checkbox_disabled.png")), | |
74 m_checkboxUncheckedPressedPixmap(loadPix(":/icons/style/checkbox_unchecked_pressed.png")), | |
75 m_checkboxCheckedPixmap(loadPix(":/icons/style/checkbox_checked.png")), | |
76 m_checkboxCheckedHoverPixmap(loadPix(":/icons/style/checkbox_checked_hover.png")), | |
77 m_checkboxCheckedDisabledPixmap(loadPix(":/icons/style/checkbox_checked_disabled.png")), | |
78 m_checkboxCheckedPressedPixmap(loadPix(":/icons/style/checkbox_checked_pressed.png")), | |
79 m_checkboxIndeterminatePixmap(loadPix(":/icons/style/checkbox_indeterminate.png")), | |
80 m_checkboxIndeterminateHoverPixmap(loadPix(":/icons/style/checkbox_indeterminate_hover.png")), | |
81 //m_checkboxIndeterminateDisabledPixmap(loadPix(":/icons/style/checkbox_indeterminate_disabled.png")), | |
82 m_checkboxIndeterminatePressedPixmap(loadPix(":/icons/style/checkbox_indeterminate_pressed.png")), | |
83 m_radiobuttonUncheckedPixmap(loadPix(":/icons/style/radiobutton_unchecked.png")), | |
84 m_radiobuttonUncheckedHoverPixmap(loadPix(":/icons/style/radiobutton_unchecked_hover.png")), | |
85 m_radiobuttonUncheckedDisabledPixmap(loadPix(":/icons/style/radiobutton_unchecked_disabled.png")), | |
86 m_radiobuttonUncheckedPressedPixmap(loadPix(":/icons/style/radiobutton_unchecked_pressed.png")), | |
87 m_radiobuttonCheckedPixmap(loadPix(":/icons/style/radiobutton_checked.png")), | |
88 m_radiobuttonCheckedHoverPixmap(loadPix(":/icons/style/radiobutton_checked_hover.png")), | |
89 m_radiobuttonCheckedDisabledPixmap(loadPix(":/icons/style/radiobutton_checked_disabled.png")), | |
90 m_radiobuttonCheckedPressedPixmap(loadPix(":/icons/style/radiobutton_checked_pressed.png")), | |
91 m_arrowDownSmallPixmap(loadPix(":/icons/style/arrow-down-small.png")), | |
92 m_arrowDownSmallInvertedPixmap(loadPix(":/icons/style/arrow-down-small-inverted.png")), | |
93 m_arrowUpSmallPixmap(loadPix(":/icons/style/arrow-up-small.png")), | |
94 m_arrowUpSmallInvertedPixmap(loadPix(":/icons/style/arrow-up-small-inverted.png")), | |
95 m_arrowLeftPixmap(":/icons/style/arrow-left.png"), | |
96 m_arrowRightPixmap(":/icons/style/arrow-right.png"), | |
97 m_arrowUpPixmap(":/icons/style/arrow-up.png"), | |
98 m_arrowDownPixmap(":/icons/style/arrow-down.png"), | |
99 m_spinupPixmap(":/icons/style/spinup.png"), | |
100 m_spinupHoverPixmap(":/icons/style/spinup_hover.png"), | |
101 m_spinupOffPixmap(":/icons/style/spinup_off.png"), | |
102 m_spinupPressedPixmap(":/icons/style/spinup_pressed.png"), | |
103 m_spindownPixmap(":/icons/style/spindown.png"), | |
104 m_spindownHoverPixmap(":/icons/style/spindown_hover.png"), | |
105 m_spindownOffPixmap(":/icons/style/spindown_off.png"), | |
106 m_spindownPressedPixmap(":/icons/style/spindown_pressed.png"), | |
107 m_titleClosePixmap(":/icons/style/title-close.png"), | |
108 m_titleUndockPixmap(":/icons/style/title-undock.png") | |
109 { | |
110 // Qt 5 removes QPlastiqueStyle and defaults to a new style called "Fusion." | |
111 // This style forces combo boxes to do bad things. | |
112 // I concluded that using "windows" as a base style causes an acceptable amount | |
113 // of damage while leaving things largely intact. | |
114 setBaseStyle(QStyleFactory::create("windows")); | |
115 | |
116 m_standardPalette.setColor(QPalette::Window, QColor(0x30, 0x30, 0x30)); | |
117 | |
118 // QLabel { color: white } | |
119 m_standardPalette.setColor(QPalette::WindowText, Qt::white); | |
120 | |
121 // QListView, QTableView, QTreeView, QLineEdit... : | |
122 // background-color: #FFFFFF; | |
123 // color: #000000; | |
124 // selection-background-color: #80AFFF; | |
125 // selection-color: #FFFFFF; | |
126 m_standardPalette.setColor(QPalette::Base, Qt::white); | |
127 m_standardPalette.setColor(QPalette::Text, Qt::black); | |
128 m_standardPalette.setColor(QPalette::Highlight, QColor(0x80, 0xAF, 0xFF)); | |
129 m_standardPalette.setColor(QPalette::HighlightedText, Qt::white); | |
130 | |
131 // for QPushButton but also QMenu | |
132 const QColor buttonColor = QColor(0xEE, 0xEE, 0xEE); | |
133 m_standardPalette.setColor(QPalette::Button, buttonColor); | |
134 m_standardPalette.setColor(QPalette::ButtonText, Qt::black); // enabled button texts and menu items | |
135 | |
136 // alternate-background-color: #EEEEFF; | |
137 m_standardPalette.setColor(QPalette::AlternateBase, QColor(0xEE, 0xEE, 0xFF)); | |
138 | |
139 // QToolTip { background-color: #fffbd4; color: #000000; + some awful pixmap hack } | |
140 m_standardPalette.setColor(QPalette::ToolTipBase, QColor(0xFF, 0xFB, 0xD4)); | |
141 m_standardPalette.setColor(QPalette::ToolTipText, Qt::black); | |
142 } | |
143 | |
144 ThornStyle::~ThornStyle() | |
145 { | |
146 } | |
147 | |
148 QIcon ThornStyle::standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *parent) const | |
149 { | |
150 IconLoader loader; | |
151 | |
152 // NOTE: see src/gui/styles/qcommonstyle.cpp in the Qt source for examples | |
153 // of how to extend this whenever more custom icons are called for | |
154 switch (standardIcon) { | |
155 | |
156 // custom icons for QMessageBox | |
157 case SP_MessageBoxInformation: | |
158 return loader.load("style/messagebox-information"); | |
159 | |
160 case SP_MessageBoxWarning: | |
161 return loader.load("style/warning"); | |
162 | |
163 case SP_MessageBoxCritical: | |
164 return loader.load("style/messagebox-critical"); | |
165 | |
166 case SP_MessageBoxQuestion: | |
167 return loader.load("style/messagebox-question"); | |
168 | |
169 case SP_TitleBarNormalButton: | |
170 return m_titleUndockPixmap; | |
171 | |
172 case SP_DockWidgetCloseButton: | |
173 case SP_TitleBarCloseButton: | |
174 return m_titleClosePixmap; | |
175 | |
176 default: | |
177 // let the base class handle the rest | |
178 return QProxyStyle::standardPixmap(standardIcon, option, parent); | |
179 } | |
180 } | |
181 | |
182 QSize ThornStyle::pixmapSize(const QPixmap &pixmap) const | |
183 { | |
184 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | |
185 return QSize(int(round(pixmap.width() / pixmap.devicePixelRatio())), | |
186 int(round(pixmap.height() / pixmap.devicePixelRatio()))); | |
187 #else | |
188 return pixmap.size(); | |
189 #endif | |
190 } | |
191 | |
192 static bool s_thornStyleEnabled = false; | |
193 | |
194 // This method currently only supports being called once | |
195 void ThornStyle::setEnabled(bool b) | |
196 { | |
197 s_thornStyleEnabled = b; | |
198 if (b) { | |
199 qApp->installEventFilter(s_eventFilter()); | |
200 } | |
201 } | |
202 | |
203 bool ThornStyle::isEnabled() | |
204 { | |
205 return s_thornStyleEnabled; | |
206 } | |
207 | |
208 QPalette ThornStyle::standardPalette() const | |
209 { | |
210 return m_standardPalette; | |
211 } | |
212 | |
213 int ThornStyle::styleHint(QStyle::StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const | |
214 { | |
215 switch (hint) { | |
216 case SH_EtchDisabledText: | |
217 return 0; | |
218 case SH_Table_GridLineColor: | |
219 // QTableView { gridline-color: #202020; } | |
220 return qRgb(0x20, 0x20, 0x20); | |
221 case SH_GroupBox_TextLabelColor: | |
222 // QGroupBox::title { color: #FFFFFF; } | |
223 // QGroupBox::title:!enabled { color: #000000; } | |
224 // but it was etched; plain black is unreadable, so let's use another color now | |
225 return option->state & State_Enabled ? qRgb(0xFF, 0xFF, 0xFF) : qRgb(0xAA, 0xAA, 0xAA); | |
226 case SH_DialogButtonBox_ButtonsHaveIcons: | |
227 return 0; | |
228 case SH_DockWidget_ButtonsHaveFrame: | |
229 return 1; | |
230 default: | |
231 break; | |
232 } | |
233 return QProxyStyle::styleHint(hint, option, widget, returnData); | |
234 } | |
235 | |
236 int ThornStyle::pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option, const QWidget *widget) const | |
237 { | |
238 switch (metric) { | |
239 case PM_SplitterWidth: //fall-through | |
240 case PM_DockWidgetSeparatorExtent: | |
241 // QMainWindow::separator { height: 5px; } | |
242 return 5; | |
243 case PM_TabBarScrollButtonWidth: | |
244 // QTabBar::scroller { /* the width of the scroll buttons */ width: 13px; } | |
245 return 13; | |
246 case PM_TabBarBaseOverlap: | |
247 return 0; | |
248 case PM_ToolBarHandleExtent: // Horizontal toolbar: width of the handle. Vertical toolbar: height of the handle | |
249 if (option->state & State_Horizontal) | |
250 return m_horizontalToolbarSeparatorPixmap.width(); | |
251 else | |
252 return m_verticalToolbarSeparatorPixmap.height(); | |
253 case PM_ExclusiveIndicatorWidth: | |
254 return m_radiobuttonUncheckedPixmap.width(); | |
255 case PM_ExclusiveIndicatorHeight: | |
256 return m_radiobuttonUncheckedPixmap.height(); | |
257 case PM_IndicatorWidth: | |
258 return m_checkboxUncheckedPixmap.width(); | |
259 case PM_IndicatorHeight: | |
260 return m_checkboxUncheckedPixmap.height(); | |
261 case PM_MenuPanelWidth: | |
262 return 1; | |
263 case PM_MenuBarHMargin: | |
264 // QMenuBar { padding: 4px; } | |
265 return 4; | |
266 case PM_MenuBarItemSpacing: | |
267 // QMenuBar::item { spacing: 3px; padding: 1px 4px; } | |
268 return 4; | |
269 case PM_ScrollBarExtent: { | |
270 QWidget *parent = widget ? widget->parentWidget() : nullptr; | |
271 QWidget *combo = parent ? parent->parentWidget() : nullptr; | |
272 if (qobject_cast<QComboBox *>(combo)) { | |
273 // QComboBox QAbstractItemView QScrollBar:vertical { width: 12px; } | |
274 return 12; | |
275 } | |
276 // QScrollBar:horizontal { height: 16px; } | |
277 // QScrollBar:vertical { width: 16px; } | |
278 return 16; | |
279 } | |
280 case PM_ToolBarItemSpacing: | |
281 return 0; | |
282 case PM_ToolBarItemMargin: | |
283 case PM_ToolBarFrameWidth: | |
284 return 0; | |
285 case PM_DefaultFrameWidth: | |
286 return 2; | |
287 case PM_SpinBoxFrameWidth: | |
288 return 2; | |
289 case PM_DockWidgetTitleBarButtonMargin: | |
290 // icon size is 16x16 but somehow the buttons ended up 13x13 | |
291 return -1; | |
292 case PM_DockWidgetTitleMargin: // space above and below the title | |
293 return 0; | |
294 case PM_DockWidgetFrameWidth: | |
295 // QDockWidget { border: none; } | |
296 return 0; | |
297 case PM_SmallIconSize: | |
298 return 16; | |
299 default: | |
300 return QProxyStyle::pixelMetric(metric, option, widget); | |
301 } | |
302 } | |
303 | |
304 void ThornStyle::drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const | |
305 { | |
306 switch (element) { | |
307 case PE_IndicatorDockWidgetResizeHandle: | |
308 // QMainWindow::separator:hover { background-color: #CCDFFF; } | |
309 if (option->state & QStyle::State_MouseOver) { | |
310 painter->fillRect(option->rect, QColor(0xCC, 0xDF, 0xFF)); | |
311 return; | |
312 } | |
313 break; | |
314 case PE_FrameTabWidget: // The tab widget frame | |
315 // QTabWidget::pane { border: 2px solid #BBBBBB; border-radius: 4px; padding: 2px; // and background: #404040; | |
316 painter->save(); | |
317 painter->setPen(QPen(QColor(0xBB, 0xBB, 0xBB), 2)); | |
318 painter->setBrush(QColor(0x40, 0x40, 0x40)); | |
319 painter->setRenderHint(QPainter::Antialiasing); | |
320 painter->drawRoundedRect(option->rect.adjusted(2, 2, -2, -2), 4, 4); | |
321 painter->restore(); | |
322 return; | |
323 case PE_FrameGroupBox: // same as above but not the background, already done | |
324 // QGroupBox { background: #404040; color: #FFFFFF; border: 2px solid #BBBBBB; border-radius: 4px; } | |
325 painter->save(); | |
326 painter->setPen(QPen(QColor(0xBB, 0xBB, 0xBB), 2)); | |
327 painter->setRenderHint(QPainter::Antialiasing); | |
328 painter->drawRoundedRect(option->rect.adjusted(2, 2, -2, -2), 4, 4); | |
329 painter->restore(); | |
330 return; | |
331 case PE_IndicatorToolBarHandle: { | |
332 // top or bottom: image: url(:/icons/style/htoolbar-separator.png); | |
333 // left or right: image: url(:icons/style/vtoolbar-separator.png); | |
334 QPixmap pixmap = option->state & State_Horizontal ? m_horizontalToolbarSeparatorPixmap : m_verticalToolbarSeparatorPixmap; | |
335 const QRect rect = alignedRect(Qt::LayoutDirectionAuto, Qt::AlignCenter, option->rect.size(), option->rect); | |
336 painter->drawPixmap(rect, pixmap); | |
337 return; | |
338 } | |
339 case PE_PanelMenu: | |
340 // QMenu { background-color: #EEEEEE; border: 1px solid black; } | |
341 painter->fillRect(option->rect, QColor(0xEE, 0xEE, 0xEE)); | |
342 return; | |
343 case PE_FrameMenu: | |
344 painter->setPen(Qt::black); | |
345 painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); | |
346 return; | |
347 case PE_FrameDockWidget: // only called when the dockwidget is floating | |
348 // QDockWidget { border: none; } | |
349 return; | |
350 case PE_PanelStatusBar: // no frame around the statusbar | |
351 case PE_FrameStatusBarItem: // no frame around the statusbar items | |
352 return; | |
353 case PE_PanelLineEdit: | |
354 // QLineEdit { border: 1px solid #AAAAAA; background-color: #FFFFFF; } | |
355 if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) { | |
356 if (frame->lineWidth > 0) // i.e. not inside QSpinBox | |
357 painter->setPen(QColor(0xAA, 0xAA, 0xAA)); | |
358 else | |
359 painter->setPen(Qt::NoPen); | |
360 painter->setBrush(Qt::white); | |
361 painter->drawRect(option->rect.adjusted(0, 0, -1, -1)); | |
362 } | |
363 return; | |
364 case PE_IndicatorMenuCheckMark: | |
365 return; // done in CE_MenuItem | |
366 case PE_IndicatorCheckBox: | |
367 case PE_IndicatorRadioButton: { | |
368 const bool checked = !(option->state & State_Off); | |
369 const bool disabled = !(option->state & State_Enabled); | |
370 const bool pressed = option->state & State_Sunken; | |
371 const bool hover = option->state & State_MouseOver; | |
372 QPixmap pixmap; | |
373 if (element == PE_IndicatorCheckBox) { | |
374 if (option->state & State_NoChange) { | |
375 // missing icon for disabled | |
376 if (pressed) | |
377 pixmap = m_checkboxIndeterminatePressedPixmap; | |
378 else if (hover) | |
379 pixmap = m_checkboxIndeterminateHoverPixmap; | |
380 else | |
381 pixmap = m_checkboxIndeterminatePixmap; | |
382 } else { | |
383 if (disabled) { | |
384 pixmap = checked ? m_checkboxCheckedDisabledPixmap : m_checkboxUncheckedDisabledPixmap; | |
385 } else { | |
386 if (pressed) | |
387 pixmap = checked ? m_checkboxCheckedPressedPixmap : m_checkboxUncheckedPressedPixmap; | |
388 else if (hover) | |
389 pixmap = checked ? m_checkboxCheckedHoverPixmap : m_checkboxUncheckedHoverPixmap; | |
390 else | |
391 pixmap = checked ? m_checkboxCheckedPixmap : m_checkboxUncheckedPixmap; | |
392 } | |
393 } | |
394 } else { | |
395 if (disabled) { | |
396 pixmap = checked ? m_radiobuttonCheckedDisabledPixmap : m_radiobuttonUncheckedDisabledPixmap; | |
397 } else { | |
398 if (pressed) | |
399 pixmap = checked ? m_radiobuttonCheckedPressedPixmap : m_radiobuttonUncheckedPressedPixmap; | |
400 else if (hover) | |
401 pixmap = checked ? m_radiobuttonCheckedHoverPixmap : m_radiobuttonUncheckedHoverPixmap; | |
402 else | |
403 pixmap = checked ? m_radiobuttonCheckedPixmap : m_radiobuttonUncheckedPixmap; | |
404 } | |
405 } | |
406 QRect pmr(QPoint(0, 0), pixmapSize(pixmap)); | |
407 pmr.moveCenter(option->rect.center()); | |
408 painter->drawPixmap(pmr.topLeft(), pixmap); | |
409 return; | |
410 } | |
411 case PE_IndicatorHeaderArrow: | |
412 // QHeaderView::down-arrow / QHeaderView::up-arrow | |
413 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { | |
414 const bool up = (header->sortIndicator & QStyleOptionHeader::SortUp); | |
415 const QPixmap pixmap = up ? m_arrowUpSmallInvertedPixmap : m_arrowDownSmallInvertedPixmap; | |
416 painter->drawPixmap(option->rect.topLeft(), pixmap); | |
417 } | |
418 return; | |
419 case PE_IndicatorArrowUp: | |
420 case PE_IndicatorArrowDown: | |
421 case PE_IndicatorArrowLeft: | |
422 case PE_IndicatorArrowRight: { | |
423 QPixmap pixmap; | |
424 if (element == PE_IndicatorArrowLeft) | |
425 pixmap = m_arrowLeftPixmap; | |
426 else if (element == PE_IndicatorArrowRight) | |
427 pixmap = m_arrowRightPixmap; | |
428 else if (element == PE_IndicatorArrowUp) | |
429 pixmap = m_arrowUpPixmap; | |
430 else if (element == PE_IndicatorArrowDown) | |
431 pixmap = m_arrowDownPixmap; | |
432 // Scale the pixmap to the desired rect (for scrollbars the pixmap is 12x12 but the rect is 8x8) | |
433 pixmap = pixmap.scaled(option->rect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); | |
434 // In case the scaling didn't occupy the full height (due to aspect ratio), center the resulting pixmap (eg: toolbutton menu indicator) | |
435 const QRect drawRect = alignedRect(option->direction, Qt::AlignCenter, pixmap.size(), option->rect); | |
436 painter->drawPixmap(drawRect.topLeft(), pixmap); | |
437 } | |
438 return; | |
439 case PE_PanelButtonTool: | |
440 if (widget && widget->inherits("QDockWidgetTitleButton")) { | |
441 // QDockWidget::close-button, QDockWidget::float-button { | |
442 // border: 1px solid #AAAAAA; | |
443 // border-radius: 3px; | |
444 // background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD); | |
445 //} | |
446 painter->save(); | |
447 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA))); | |
448 QLinearGradient gradient; | |
449 gradient.setStart(0, 0); | |
450 gradient.setFinalStop(0, option->rect.height()); | |
451 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD)); | |
452 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99)); | |
453 painter->setBrush(gradient); | |
454 painter->setRenderHint(QPainter::Antialiasing); | |
455 painter->drawRoundedRect(option->rect.adjusted(1, 1, -1, -1), 3, 3); | |
456 painter->restore(); | |
457 } | |
458 else if ((option->state & State_On) || (option->state & State_Sunken)) { | |
459 // QToolButton::pressed, QToolButton::checked { border: 1px solid #AAAAAA; border-radius: 2px; | |
460 // background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #E0E0E0, stop:1 #EEEEEE); } | |
461 painter->save(); | |
462 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA))); | |
463 QLinearGradient gradient; | |
464 gradient.setStart(0, 0); | |
465 gradient.setFinalStop(0, option->rect.height()); | |
466 gradient.setColorAt(0, QColor(0xEE, 0xEE, 0xEE)); | |
467 gradient.setColorAt(1, QColor(0xE0, 0xE0, 0xE0)); | |
468 painter->setBrush(gradient); | |
469 painter->setRenderHint(QPainter::Antialiasing); | |
470 painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 2, 2); | |
471 painter->restore(); | |
472 } | |
473 else if ((option->state & State_MouseOver) && (option->state & State_Enabled)) { | |
474 // QToolButton::enabled:hover { border: 1px solid #AAAAAA; border-radius: 2px; background-color: #CCDFFF; } | |
475 painter->save(); | |
476 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA))); | |
477 painter->setBrush(QColor(0xCC, 0xDF, 0xFF)); | |
478 painter->setRenderHint(QPainter::Antialiasing); | |
479 painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 2, 2); | |
480 painter->restore(); | |
481 } | |
482 return; | |
483 case PE_IndicatorProgressChunk: | |
484 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { | |
485 QStyleOptionProgressBar copy = *pb; | |
486 // QProgressBar::chunk { background-color: #D6E8FB; } | |
487 copy.palette.setColor(QPalette::Highlight, QColor(0xD6, 0xE8, 0xFB)); // qwindowsstyle.cpp uses Highlight | |
488 QProxyStyle::drawPrimitive(element, ©, painter, widget); | |
489 } | |
490 return; | |
491 default: | |
492 break; | |
493 } | |
494 QProxyStyle::drawPrimitive(element, option, painter, widget); | |
495 } | |
496 | |
497 void ThornStyle::drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const | |
498 { | |
499 switch (element) { | |
500 case CE_Splitter: // currently unused, but consistent with PE_IndicatorDockWidgetResizeHandle | |
501 if (option->state & QStyle::State_MouseOver) { | |
502 painter->fillRect(option->rect, QColor(0xCC, 0xDF, 0xFF)); | |
503 return; | |
504 } | |
505 break; | |
506 case CE_TabBarTab: | |
507 /* border: 1px solid #AAAAAA; | |
508 background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD); | |
509 color: #000000; | |
510 border-bottom-color: #BBBBBB; // same as the pane color | |
511 border-top-left-radius: 4px; | |
512 border-top-right-radius: 4px; | |
513 */ | |
514 if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) { | |
515 QRect tabRect = tab->rect; | |
516 QColor borderColor; | |
517 QLinearGradient gradient(0, 0, 0, tab->rect.height()); | |
518 const bool selected = tab->state & State_Selected; | |
519 if (selected) { | |
520 // QTabBar::tab:top:selected said | |
521 // background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #E0E0E0, stop:1 #EEEEEE); | |
522 gradient.setColorAt(0, QColor(0xE0, 0xE0, 0xE0)); | |
523 gradient.setColorAt(1, QColor(0xEE, 0xEE, 0xEE)); | |
524 // border: 1px solid #E0E0E0; | |
525 borderColor = QColor(0xE0, 0xE0, 0xE0); | |
526 } else { | |
527 gradient.setColorAt(0, QColor(0x99, 0x99, 0x99)); | |
528 gradient.setColorAt(1, QColor(0xDD, 0xDD, 0xDD)); | |
529 borderColor = QColor(0xAA, 0xAA, 0xAA); | |
530 } | |
531 | |
532 QRect roundedRect; | |
533 // Ruse: we draw a rounded rect that is too big at the bottom (or top, for South), but clipped, so that it looks square | |
534 switch (tab->shape) { | |
535 case QTabBar::RoundedNorth: | |
536 case QTabBar::TriangularNorth: | |
537 if (!selected) { | |
538 // QTabBar::tab:top:!selected { margin-top: 2px; } | |
539 tabRect.adjust(0, 2, 0, 0); | |
540 } | |
541 roundedRect = tabRect.adjusted(0, 0, 0, 5); | |
542 break; | |
543 case QTabBar::RoundedSouth: | |
544 case QTabBar::TriangularSouth: | |
545 if (!selected) { | |
546 // QTabBar::tab:bottom:!selected { margin-bottom: 2px } | |
547 tabRect.adjust(0, 0, 0, -2); | |
548 } | |
549 roundedRect = tabRect.adjusted(0, -5, 0, 0); | |
550 break; | |
551 default: | |
552 qWarning() << "Vertical tabbars not implemented yet, call David"; | |
553 } | |
554 | |
555 // Draw tab shape | |
556 painter->save(); | |
557 painter->setClipRect(tabRect); | |
558 painter->setPen(borderColor); | |
559 painter->setBrush(gradient); | |
560 painter->setRenderHint(QPainter::Antialiasing); | |
561 painter->drawRoundedRect(roundedRect, 4, 4); | |
562 painter->restore(); | |
563 | |
564 // Draw tab text | |
565 QStyleOptionTab modifiedOption = *tab; | |
566 modifiedOption.palette.setColor(QPalette::WindowText, Qt::black); | |
567 QProxyStyle::drawControl(CE_TabBarTabLabel, &modifiedOption, painter, widget); | |
568 } | |
569 return; | |
570 case CE_ToolBar: | |
571 { | |
572 /* | |
573 top or bottom: background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD) | |
574 left or right: background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #DDDDDD, stop:1 #999999) | |
575 */ | |
576 QLinearGradient gradient; | |
577 if (option->state & State_Horizontal) { | |
578 gradient.setStart(0, 0); | |
579 gradient.setFinalStop(0, option->rect.height()); | |
580 } else { | |
581 gradient.setStart(0, 0); | |
582 gradient.setFinalStop(option->rect.width(), 0); | |
583 } | |
584 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD)); | |
585 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99)); | |
586 painter->fillRect(option->rect, gradient); | |
587 } | |
588 return; | |
589 case CE_PushButtonBevel: | |
590 painter->save(); | |
591 painter->setRenderHint(QPainter::Antialiasing); | |
592 if (option->state & State_MouseOver) { | |
593 // QPushButton:hover { border: 1px solid #AAAAAA; border-radius: 3px; background-color: #DDEFFF; } | |
594 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA))); | |
595 painter->setBrush(QColor(0xDD, 0xEF, 0xFF)); | |
596 } else if ((option->state & State_On) || (option->state & State_Sunken)) { | |
597 // QPushButton::checked, QPushButton::pressed { border: 1px solid #AAAAAA; border-radius: 2px; background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #E0E0EA, stop:1 #BBCFFF); } | |
598 QLinearGradient gradient; | |
599 gradient.setStart(0, 0); | |
600 gradient.setFinalStop(0, option->rect.height()); | |
601 gradient.setColorAt(0, QColor(0xE0, 0xE0, 0xEA)); | |
602 gradient.setColorAt(1, QColor(0xBB, 0xCF, 0xFF)); | |
603 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA))); | |
604 painter->setBrush(gradient); | |
605 } else { | |
606 // QPushButton::enabled { border: 1px solid #AAAAAA; border-radius: 3px; background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD); } | |
607 // QPushButton::!enabled { border: 1px solid #808080; + same background as Qt does the sunken effect on these, and that looks fine. } | |
608 QLinearGradient gradient; | |
609 gradient.setStart(0, 0); | |
610 gradient.setFinalStop(0, option->rect.height()); | |
611 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD)); | |
612 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99)); | |
613 if (option->state & State_Enabled) | |
614 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA))); | |
615 else | |
616 painter->setPen(QPen(QColor(0x80, 0x80, 0x80))); | |
617 painter->setBrush(gradient); | |
618 } | |
619 painter->drawRoundedRect(option->rect.adjusted(0, 0, -1, -1), 3, 3); | |
620 painter->restore(); | |
621 return; | |
622 case CE_MenuItem: | |
623 if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { | |
624 int x, y, w, h; | |
625 menuitem->rect.getRect(&x, &y, &w, &h); | |
626 const bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable ? menuitem->checked : false; | |
627 const bool selected = menuitem->state & State_Selected; | |
628 const bool disabled = !(menuitem->state & State_Enabled); | |
629 | |
630 QColor textColor; | |
631 if (selected) { | |
632 // QMenu::item:selected { background-color: #80AFFF; } | |
633 const QColor fill(0x80, 0xAF, 0xFF); | |
634 painter->fillRect(menuitem->rect.adjusted(0, 0, -1, 0), fill); | |
635 | |
636 // QMenu::item:selected { color: #FFFFFF; } | |
637 textColor = QColor(0xFF, 0xFF, 0xFF); | |
638 } else { | |
639 if (disabled) { | |
640 // QMenu::item:!enabled { color: #AAAAAA; } | |
641 textColor = QColor(0xAA, 0xAA, 0xAA); | |
642 } else { | |
643 // QMenu::item:enabled { color: #000000; } | |
644 textColor = Qt::black; | |
645 } | |
646 } | |
647 | |
648 if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { | |
649 /* QMenu::separator { | |
650 height: 2px; | |
651 background: #AAAAAA; | |
652 margin-left: 10px; | |
653 margin-right: 5px; | |
654 } */ | |
655 const int yoff = y-1 + h / 2; | |
656 painter->fillRect(x + 10, yoff, w - 15, 2, QColor(0xAA, 0xAA, 0xAA)); | |
657 return; | |
658 } | |
659 | |
660 // taken from qwindowsstyle.cpp, and modified (due to the width of the checkmarks) | |
661 | |
662 const bool checkable = menuitem->checkType != QStyleOptionMenuItem::NotCheckable; | |
663 const int checkcol = qMax<int>(menuitem->maxIconWidth, m_checkboxCheckedPixmap.width() + 4); | |
664 const QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(), menuitem->rect.y(), checkcol, menuitem->rect.height())); | |
665 | |
666 // Draw icon or checkmark | |
667 QPixmap pixmap; | |
668 if (!menuitem->icon.isNull()) { | |
669 QIcon::Mode mode = disabled ? QIcon::Disabled : QIcon::Normal; | |
670 if (selected && !disabled) | |
671 mode = QIcon::Active; | |
672 if (checked) | |
673 pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On); | |
674 else | |
675 pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode); | |
676 } else if (checkable) { | |
677 if (!selected) { | |
678 if (menuitem->checkType & QStyleOptionMenuItem::Exclusive) { | |
679 pixmap = menuitem->checked ? m_radiobuttonCheckedPixmap : m_radiobuttonUncheckedPixmap; | |
680 } else { | |
681 pixmap = menuitem->checked ? m_checkboxCheckedPixmap : m_checkboxUncheckedPixmap; | |
682 } | |
683 } else { | |
684 if (menuitem->checkType & QStyleOptionMenuItem::Exclusive) { | |
685 pixmap = menuitem->checked ? m_radiobuttonCheckedHoverPixmap : m_radiobuttonUncheckedHoverPixmap; | |
686 } else { | |
687 pixmap = menuitem->checked ? m_checkboxCheckedHoverPixmap : m_checkboxUncheckedHoverPixmap; | |
688 } | |
689 } | |
690 } | |
691 QRect pmr(QPoint(0, 0), pixmapSize(pixmap)); | |
692 pmr.moveCenter(vCheckRect.center()); | |
693 painter->setPen(menuitem->palette.text().color()); | |
694 painter->drawPixmap(pmr.topLeft(), pixmap); | |
695 | |
696 const int itemFrame = 2; | |
697 const int itemHMargin = 2; | |
698 const int itemVMargin = 2; | |
699 const int rightBorder = 15; | |
700 const int arrowHMargin = 6; | |
701 const int xm = itemFrame + checkcol + itemHMargin; | |
702 const int xpos = menuitem->rect.x() + xm; | |
703 painter->setPen(textColor); | |
704 QRect textRect(xpos, y + itemVMargin, | |
705 w - xm - rightBorder - menuitem->tabWidth + 1, h - 2 * itemVMargin); | |
706 QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect); | |
707 QString s(menuitem->text); | |
708 if (!s.isEmpty()) { // draw text | |
709 int t = s.indexOf(QLatin1Char('\t')); | |
710 int text_flags = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; | |
711 if (!styleHint(SH_UnderlineShortcut, menuitem, widget)) | |
712 text_flags |= Qt::TextHideMnemonic; | |
713 if (t >= 0) { | |
714 QRect vShortcutRect = visualRect(option->direction, menuitem->rect, | |
715 QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom()))); | |
716 const QString textToDraw = s.mid(t + 1); | |
717 painter->drawText(vShortcutRect, text_flags, textToDraw); | |
718 s = s.left(t); | |
719 } | |
720 QFont font = menuitem->font; | |
721 if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem) | |
722 font.setBold(true); | |
723 painter->setFont(font); | |
724 const QString textToDraw = s.left(t); | |
725 painter->drawText(vTextRect, text_flags, textToDraw); | |
726 } | |
727 if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) { // draw sub menu arrow | |
728 const int dim = (h - 2 * itemFrame) / 2; | |
729 const PrimitiveElement arrow = (option->direction == Qt::RightToLeft) ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; | |
730 const int submenuXPos = x + w - arrowHMargin - itemFrame - dim; | |
731 const QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(submenuXPos, y + h / 2 - dim / 2, dim, dim)); | |
732 QStyleOptionMenuItem newMI = *menuitem; | |
733 newMI.rect = vSubMenuRect; | |
734 newMI.state = disabled ? State_None : State_Enabled; | |
735 if (selected) { | |
736 newMI.palette.setColor(QPalette::ButtonText, textColor); | |
737 } | |
738 QProxyStyle::drawPrimitive(arrow, &newMI, painter, widget); | |
739 } | |
740 } | |
741 return; | |
742 case CE_CheckBoxLabel: | |
743 case CE_RadioButtonLabel: | |
744 if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { | |
745 QStyleOptionButton modifiedOption = *btn; | |
746 const bool disabled = !(option->state & State_Enabled); | |
747 // QCheckBox:!enabled { color: #000000; } | |
748 // QCheckBox:enabled { color: #FFFFFF } | |
749 modifiedOption.palette.setColor(QPalette::WindowText, disabled ? Qt::black : Qt::white); | |
750 QProxyStyle::drawControl(element, &modifiedOption, painter, widget); | |
751 } | |
752 return; | |
753 case CE_ComboBoxLabel: | |
754 if (option->state & State_Enabled) { | |
755 painter->setPen(Qt::black); | |
756 } else { | |
757 // disabled text light enough to be legible but not as stark as white | |
758 painter->setPen(QColor(0xEE, 0xEE, 0xEE)); | |
759 } | |
760 QCommonStyle::drawControl(element, option, painter, widget); | |
761 return; | |
762 case CE_Header: | |
763 // Copied straight from qwindowsstyle.cpp because the subElementRect calls don't use proxy()->. | |
764 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { | |
765 QRegion clipRegion = painter->clipRegion(); | |
766 painter->setClipRect(option->rect); | |
767 drawControl(CE_HeaderSection, header, painter, widget); | |
768 QStyleOptionHeader subopt = *header; | |
769 subopt.rect = subElementRect(SE_HeaderLabel, header, widget); | |
770 if (subopt.rect.isValid()) { | |
771 subopt.palette.setColor(QPalette::ButtonText, Qt::white); // QHeaderView::section { color: #FFFFFF; } | |
772 drawControl(CE_HeaderLabel, &subopt, painter, widget); | |
773 } | |
774 if (header->sortIndicator != QStyleOptionHeader::None) { | |
775 subopt.rect = subElementRect(SE_HeaderArrow, option, widget); | |
776 drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget); | |
777 } | |
778 painter->setClipRegion(clipRegion); | |
779 } | |
780 return; | |
781 case CE_HeaderSection: | |
782 if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { | |
783 // QHeaderView::section { background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #707070, stop:1 #808080); } | |
784 QLinearGradient gradient; | |
785 gradient.setStart(0, 0); | |
786 gradient.setFinalStop(0, option->rect.height()); | |
787 gradient.setColorAt(0, QColor(0x80, 0x80, 0x80)); | |
788 gradient.setColorAt(1, QColor(0x70, 0x70, 0x70)); | |
789 painter->setBrush(gradient); | |
790 // border: 1px solid #AAAAAA; | |
791 painter->setPen(QPen(QColor(0xAA, 0xAA, 0xAA))); | |
792 painter->drawRect(header->rect); | |
793 // Not converted, not sure what it did: padding-left: 4px; padding-right: 1em; | |
794 } | |
795 return; | |
796 case CE_MenuBarItem: | |
797 if (const QStyleOptionMenuItem *m = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { | |
798 QStyleOptionMenuItem modifiedOption(*m); | |
799 if (option->state & State_Selected) { | |
800 // QMenuBar::item:selected { background-color: #80AFFF; } | |
801 modifiedOption.palette.setColor(QPalette::Button, QColor(0x80, 0xAF, 0xFF)); | |
802 } else if (option->state & State_Sunken) { | |
803 // QMenuBar::item:pressed { background-color: #BBCEFF; } | |
804 modifiedOption.palette.setColor(QPalette::Button, QColor(0xBB, 0xCE, 0xFF)); | |
805 } else { | |
806 // QMenuBar { background-color: #404040; } | |
807 modifiedOption.palette.setColor(QPalette::Button, QColor(0x40, 0x40, 0x40)); | |
808 } | |
809 // QMenuBar::item:selected { color: #FFFFFF; } | |
810 // QMenuBar::item { color: #FFFFFF; } | |
811 modifiedOption.palette.setColor(QPalette::ButtonText, Qt::white); | |
812 | |
813 QProxyStyle::drawControl(element, &modifiedOption, painter, widget); | |
814 } | |
815 return; | |
816 case CE_MenuBarEmptyArea: | |
817 // QMenuBar { background-color: #404040; } | |
818 painter->fillRect(option->rect, QColor(0x40, 0x40, 0x40)); | |
819 return; | |
820 case CE_ScrollBarSubLine: | |
821 case CE_ScrollBarAddLine: | |
822 { | |
823 // QScrollBar::add-line:horizontal { border: 2px solid #404040; background: #808080; } but the 2px border didn't appear | |
824 painter->fillRect(option->rect, QColor(0x80, 0x80, 0x80)); | |
825 // taken from qwindowsstyle.cpp | |
826 PrimitiveElement arrow; | |
827 if (option->state & State_Horizontal) { | |
828 if (element == CE_ScrollBarAddLine) | |
829 arrow = option->direction == Qt::LeftToRight ? PE_IndicatorArrowRight : PE_IndicatorArrowLeft; | |
830 else | |
831 arrow = option->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight; | |
832 } else { | |
833 if (element == CE_ScrollBarAddLine) | |
834 arrow = PE_IndicatorArrowDown; | |
835 else | |
836 arrow = PE_IndicatorArrowUp; | |
837 } | |
838 QStyleOption arrowOpt = *option; | |
839 // QScrollBar:*-arrow { width: 8px; height 8px; } | |
840 arrowOpt.rect = alignedRect(option->direction, Qt::AlignCenter, QSize(8, 8), option->rect); | |
841 drawPrimitive(arrow, &arrowOpt, painter, widget); | |
842 } | |
843 return; | |
844 case CE_ScrollBarSubPage: | |
845 case CE_ScrollBarAddPage: | |
846 // Nothing to be done, CC_ScrollBar did the full fillRect() | |
847 return; | |
848 case CE_ScrollBarSlider: | |
849 { | |
850 // QScrollBar::handle:horizontal { background-color: qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD); } | |
851 // QScrollBar::handle:vertical { background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 #DDDDDD, stop:1 #999999); } | |
852 QLinearGradient gradient; | |
853 gradient.setStart(0, 0); | |
854 if (option->state & State_Horizontal) | |
855 gradient.setFinalStop(0, option->rect.height()); | |
856 else | |
857 gradient.setFinalStop(option->rect.width(), 0); | |
858 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD)); | |
859 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99)); | |
860 painter->fillRect(option->rect, gradient); | |
861 } | |
862 return; | |
863 case CE_DockWidgetTitle: // titlebar on floating dock widgets | |
864 if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option)) { | |
865 const bool active = dwOpt->state & State_Active; | |
866 const bool floating = dwOpt->movable && (dwOpt->state & State_Window); | |
867 QStyleOptionDockWidget copy = *dwOpt; | |
868 copy.palette.setColor(QPalette::Dark, Qt::transparent); // QCommonStyle draws a border around the title with this color, we don't want it | |
869 if (floating && !active) | |
870 copy.palette.setColor(QPalette::WindowText, QColor(0xAA, 0xAA, 0xAA)); | |
871 else | |
872 copy.palette.setColor(QPalette::WindowText, Qt::white); | |
873 // Don't use QWindowsStyle for this, it uses black for the floating && !active case, cached from the initial app palette. | |
874 QCommonStyle::drawControl(element, ©, painter, widget); | |
875 } | |
876 return; | |
877 case CE_ProgressBarGroove: | |
878 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { | |
879 // QProgressBar { background: #FFFFFF; border: 1px solid #AAAAAA; border-radius: 3px; } | |
880 painter->save(); | |
881 painter->setBrush(Qt::white); | |
882 painter->setPen(QColor(0xAA, 0xAA, 0xAA)); | |
883 painter->drawRoundedRect(pb->rect.adjusted(0, 0, -1, -1), 3, 3); | |
884 painter->restore(); | |
885 } | |
886 return; | |
887 case CE_ProgressBarLabel: | |
888 if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(option)) { | |
889 // QProgressBar { color: #000000; text-align: center; } | |
890 QStyleOptionProgressBar copy = *pb; | |
891 copy.palette.setColor(QPalette::HighlightedText, Qt::black); | |
892 QProxyStyle::drawControl(element, ©, painter, widget); | |
893 } | |
894 return; | |
895 default: | |
896 break; | |
897 } | |
898 QProxyStyle::drawControl(element, option, painter, widget); | |
899 } | |
900 | |
901 void ThornStyle::drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const | |
902 { | |
903 switch (control) { | |
904 case CC_ScrollBar: | |
905 if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) { | |
906 // QScrollBar { border: 2px solid #404040; background-color: none; } | |
907 // QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { background: #404040; } | |
908 // Done here by filling the whole scrollbar, and moving the subcontrols by 2 pixels, then drawing nothing for AddPage/SubPage | |
909 painter->fillRect(scrollBar->rect, QColor(0x40, 0x40, 0x40)); | |
910 } | |
911 break; // let the base class do the rest | |
912 case CC_Slider: | |
913 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) { | |
914 const QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, widget); | |
915 const QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, widget); | |
916 if ((slider->subControls & SC_SliderGroove) && groove.isValid()) { | |
917 // QSlider::groove:horizontal { background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #E0E0E0, stop:1 #EEEEEE); } | |
918 QLinearGradient gradient; | |
919 gradient.setStart(0, 0); | |
920 if (option->state & State_Horizontal) | |
921 gradient.setFinalStop(0, option->rect.height()); | |
922 else | |
923 gradient.setFinalStop(option->rect.width(), 0); | |
924 gradient.setColorAt(0, QColor(0xE0, 0xE0, 0xE0)); | |
925 gradient.setColorAt(1, QColor(0xEE, 0xEE, 0xEE)); | |
926 painter->fillRect(groove, gradient); | |
927 } | |
928 #if 0 // no tickmarks | |
929 if (slider->subControls & SC_SliderTickmarks) { | |
930 QStyleOptionSlider tmpSlider = *slider; | |
931 tmpSlider.subControls = SC_SliderTickmarks; | |
932 QCommonStyle::drawComplexControl(control, &tmpSlider, painter, widget); | |
933 } | |
934 #endif | |
935 if (slider->subControls & SC_SliderHandle) { | |
936 // QSlider::handle:horizontal { background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #8f8f8f); | |
937 // border: 1px solid #5c5c5c; border-radius: 3px; } | |
938 QLinearGradient gradient; | |
939 gradient.setStart(0, 0); | |
940 gradient.setFinalStop(option->rect.width(), option->rect.height()); | |
941 gradient.setColorAt(0, QColor(0xB4, 0xB4, 0xB4)); | |
942 gradient.setColorAt(1, QColor(0x8F, 0x8F, 0x8F)); | |
943 painter->setPen(QColor(0x5C, 0x5C, 0x5C)); | |
944 painter->setBrush(gradient); | |
945 painter->setRenderHint(QPainter::Antialiasing); | |
946 painter->drawRoundedRect(handle, 3, 3); | |
947 } | |
948 } | |
949 return; | |
950 case CC_GroupBox: | |
951 if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) { | |
952 QStyleOptionGroupBox copy = *groupBox; | |
953 // QGroupBox::title { subcontrol-position: top center; } | |
954 copy.textAlignment = Qt::AlignHCenter; | |
955 | |
956 // Draw frame | |
957 QRect textRect = subControlRect(CC_GroupBox, ©, SC_GroupBoxLabel, widget); | |
958 QRect checkBoxRect = subControlRect(CC_GroupBox, ©, SC_GroupBoxCheckBox, widget); | |
959 if (groupBox->subControls & QStyle::SC_GroupBoxFrame) { | |
960 QStyleOptionFrame frame; | |
961 frame.QStyleOption::operator=(*groupBox); | |
962 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | |
963 frame.features = groupBox->features; | |
964 #endif | |
965 frame.lineWidth = groupBox->lineWidth; | |
966 frame.midLineWidth = groupBox->midLineWidth; | |
967 frame.rect = subControlRect(CC_GroupBox, ©, SC_GroupBoxFrame, widget); | |
968 painter->save(); | |
969 | |
970 QRegion region(groupBox->rect); | |
971 if (!groupBox->text.isEmpty()) { | |
972 bool ltr = groupBox->direction == Qt::LeftToRight; | |
973 QRect finalRect; | |
974 if (groupBox->subControls & QStyle::SC_GroupBoxCheckBox) { | |
975 finalRect = checkBoxRect.united(textRect); | |
976 finalRect.adjust(ltr ? -4 : 0, 0, ltr ? 0 : 4, 0); | |
977 } else { | |
978 finalRect = textRect; | |
979 } | |
980 region -= finalRect; | |
981 } | |
982 | |
983 // Draw background without clipping | |
984 painter->setPen(Qt::NoPen); | |
985 painter->setBrush(QColor(0x40, 0x40, 0x40)); | |
986 painter->drawRoundedRect(frame.rect.adjusted(2, 2, -2, -2), 4, 4); | |
987 | |
988 painter->setClipRegion(region); | |
989 // Draw frame with clipping | |
990 drawPrimitive(PE_FrameGroupBox, &frame, painter, widget); | |
991 painter->restore(); | |
992 } | |
993 | |
994 copy.subControls &= ~SC_GroupBoxFrame; | |
995 QProxyStyle::drawComplexControl(control, ©, painter, widget); | |
996 } | |
997 return; | |
998 case CC_ToolButton: | |
999 if (const QStyleOptionToolButton *toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) { | |
1000 QRect button = subControlRect(control, toolbutton, SC_ToolButton, widget); | |
1001 QRect menuarea = subControlRect(control, toolbutton, SC_ToolButtonMenu, widget); | |
1002 State bflags = toolbutton->state & ~State_Sunken; | |
1003 | |
1004 /*if (bflags & State_AutoRaise) { | |
1005 if (!(bflags & State_MouseOver) || !(bflags & State_Enabled)) { | |
1006 bflags &= ~State_Raised; | |
1007 } | |
1008 }*/ | |
1009 State mflags = bflags; | |
1010 if (toolbutton->state & State_Sunken) { | |
1011 if (toolbutton->activeSubControls & SC_ToolButton) | |
1012 bflags |= State_Sunken; | |
1013 else // added this "else" so that the down arrow only shifts by +1,+1 when actually clicking on it, not when clicking on the main toolbutton | |
1014 mflags |= State_Sunken; | |
1015 } | |
1016 | |
1017 QStyleOption tool = *toolbutton; | |
1018 if (toolbutton->subControls & SC_ToolButton) { | |
1019 tool.rect = button; | |
1020 tool.state = bflags; | |
1021 drawPrimitive(PE_PanelButtonTool, &tool, painter, widget); | |
1022 } | |
1023 QStyleOptionToolButton label = *toolbutton; | |
1024 label.state = bflags; | |
1025 int fw = pixelMetric(PM_DefaultFrameWidth, option, widget); | |
1026 label.rect = button.adjusted(fw, fw, -fw, -fw); | |
1027 // QToolButton { color: #FFFFFF; } | |
1028 label.palette.setColor(QPalette::ButtonText, Qt::white); | |
1029 drawControl(CE_ToolButtonLabel, &label, painter, widget); | |
1030 | |
1031 if (mflags & State_Sunken) { | |
1032 // QToolButton::menu-arrow:open { top: 1px; left: 1px; /* shift it a bit */ } | |
1033 painter->translate(1, 1); | |
1034 } | |
1035 if (toolbutton->subControls & SC_ToolButtonMenu) { // popupMode == QToolButton::MenuButtonPopup | |
1036 tool.rect = menuarea; | |
1037 tool.state = mflags; | |
1038 drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget); | |
1039 } else if (toolbutton->features & QStyleOptionToolButton::HasMenu) { // InstantPopup, like QPushButton menu | |
1040 // "the arrow on tool buttons with menus in InstantPopup mode is intentionally styled out of existence" | |
1041 } | |
1042 } | |
1043 return; | |
1044 case CC_ComboBox: | |
1045 if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { | |
1046 if ((cmb->subControls & SC_ComboBoxFrame)) { | |
1047 // QComboBox { border: 1px solid #AAAAAA; border-radius: 3px; } | |
1048 // QComboBox::!enabled { border: 1px solid #808080; border-radius: 3px; } | |
1049 if (option->state & State_Enabled) | |
1050 painter->setPen(QColor(0xAA, 0xAA, 0xAA)); | |
1051 else | |
1052 painter->setPen(QColor(0x80, 0x80, 0x80)); | |
1053 | |
1054 if (option->state & State_MouseOver) { | |
1055 // QComboBox:hover { background-color: #CCDFFF; } | |
1056 painter->setBrush(QColor(0xCC, 0xDF, 0xFF)); | |
1057 } else if (cmb->editable) { | |
1058 // QComboBox::editable { background-color: #FFFFFF; } | |
1059 painter->setBrush(Qt::white); | |
1060 } else { | |
1061 // QComboBox::!editable { background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #999999, stop:1 #DDDDDD); } | |
1062 // QComboBox::!editable::on { background-color: qlineargradient(x1:0, y1:1, x2:0, y2:0, stop:0 #E0E0E0, stop:1 #EEEEEE); } | |
1063 QLinearGradient gradient; | |
1064 gradient.setStart(0, 0); | |
1065 gradient.setFinalStop(0, option->rect.height()); | |
1066 if (option->state & State_On) { | |
1067 gradient.setColorAt(0, QColor(0xEE, 0xEE, 0xEE)); | |
1068 gradient.setColorAt(1, QColor(0xE0, 0xE0, 0xE0)); | |
1069 } else { | |
1070 if (qobject_cast<QToolBar*>(widget->parentWidget())) { | |
1071 gradient.setColorAt(0, QColor(0xEE, 0xEE, 0xEE)); | |
1072 gradient.setColorAt(1, QColor(0xDD, 0xDD, 0xDD)); | |
1073 } else { | |
1074 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD)); | |
1075 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99)); | |
1076 } | |
1077 } | |
1078 painter->setBrush(gradient); | |
1079 } | |
1080 painter->setRenderHint(QPainter::Antialiasing); | |
1081 painter->drawRoundedRect(option->rect, 3, 3); | |
1082 } | |
1083 if (cmb->subControls & SC_ComboBoxArrow) { | |
1084 // from qwindowsstyle.cpp, without the rect around the arrow | |
1085 State flags = State_None; | |
1086 QRect ar = subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget); | |
1087 bool sunkenArrow = cmb->activeSubControls == SC_ComboBoxArrow | |
1088 && cmb->state & State_Sunken; | |
1089 ar.adjust(2, 2, -2, -2); | |
1090 if (option->state & State_Enabled) | |
1091 flags |= State_Enabled; | |
1092 if (option->state & State_HasFocus) | |
1093 flags |= State_HasFocus; | |
1094 | |
1095 if (sunkenArrow) | |
1096 flags |= State_Sunken; | |
1097 QStyleOption arrowOpt = *cmb; | |
1098 arrowOpt.rect = ar.adjusted(1, 1, -1, -1); | |
1099 arrowOpt.state = flags; | |
1100 drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget); | |
1101 } | |
1102 #if 0 | |
1103 if (cmb->subControls & SC_ComboBoxEditField) { | |
1104 QRect re = subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget); | |
1105 if (cmb->state & State_HasFocus && !cmb->editable) | |
1106 p->fillRect(re.x(), re.y(), re.width(), re.height(), | |
1107 cmb->palette.brush(QPalette::Highlight)); | |
1108 } | |
1109 #endif | |
1110 } | |
1111 return; | |
1112 case CC_SpinBox: | |
1113 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { | |
1114 bool enabled = option->state & State_Enabled; | |
1115 painter->setRenderHint(QPainter::Antialiasing); | |
1116 QPainterPath framePath; | |
1117 // Draw background color (white), clipped to the rounded rect frame, | |
1118 // without drawing that frame yet (we'll do that last). | |
1119 // That same clipping will be useful for the round corner of the up/down buttons | |
1120 QRect frameRect = subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget).adjusted(2, 2, -2, -2); | |
1121 framePath.addRoundedRect(frameRect, 4, 4); | |
1122 painter->setClipPath(framePath); | |
1123 painter->fillRect(frameRect, sb->palette.brush(QPalette::Base)); | |
1124 const QRect spinupRect = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget); | |
1125 QLinearGradient gradient; | |
1126 gradient.setColorAt(0, QColor(0xDD, 0xDD, 0xDD)); | |
1127 gradient.setColorAt(1, QColor(0x99, 0x99, 0x99)); | |
1128 painter->setPen(QColor(0xAA, 0xAA, 0xAA)); | |
1129 if (sb->subControls & SC_SpinBoxUp) { | |
1130 gradient.setStart(spinupRect.topLeft()); | |
1131 gradient.setFinalStop(spinupRect.bottomLeft()); | |
1132 if (sb->activeSubControls == SC_SpinBoxUp && !(option->state & State_Sunken)) | |
1133 painter->setBrush(QColor(0xDD, 0xEF, 0xFF)); | |
1134 else | |
1135 painter->setBrush(gradient); | |
1136 painter->drawRect(spinupRect); | |
1137 | |
1138 QPixmap pixmap = enabled ? m_arrowUpSmallPixmap | |
1139 : m_arrowUpSmallInvertedPixmap; // off state when value is max | |
1140 pixmap = pixmap.scaled(QSize(7, 7), Qt::KeepAspectRatio, Qt::SmoothTransformation); // TODO: edit the PNGs instead, would be faster | |
1141 const QRect drawRect = alignedRect(option->direction, Qt::AlignCenter, pixmap.size(), spinupRect); | |
1142 painter->drawPixmap(drawRect.topLeft(), pixmap); | |
1143 } | |
1144 if (sb->subControls & SC_SpinBoxDown) { | |
1145 const QRect spindownRect = subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); | |
1146 gradient.setStart(spindownRect.topLeft()); | |
1147 gradient.setFinalStop(spindownRect.bottomLeft()); | |
1148 if (sb->activeSubControls == SC_SpinBoxDown && (option->state & State_MouseOver)) | |
1149 painter->setBrush(QColor(0xDD, 0xEF, 0xFF)); | |
1150 else | |
1151 painter->setBrush(gradient); | |
1152 painter->drawRect(spindownRect); | |
1153 | |
1154 QPixmap pixmap = enabled ? m_arrowDownSmallPixmap | |
1155 : m_arrowDownSmallInvertedPixmap; // off state when value is max | |
1156 pixmap = pixmap.scaled(QSize(7, 7), Qt::KeepAspectRatio, Qt::SmoothTransformation); // TODO: edit the PNGs instead, would be faster | |
1157 const QRect drawRect = alignedRect(option->direction, Qt::AlignCenter, pixmap.size(), spindownRect); | |
1158 painter->drawPixmap(drawRect.topLeft(), pixmap); | |
1159 } | |
1160 painter->setClipping(false); | |
1161 painter->setBrush(Qt::NoBrush); | |
1162 painter->setPen(QColor(0xB0, 0xB0, 0xB0)); // grabbed in frame.png | |
1163 painter->drawRoundedRect(frameRect, 4, 4); | |
1164 } | |
1165 return; | |
1166 default: | |
1167 break; | |
1168 } | |
1169 QProxyStyle::drawComplexControl(control, option, painter, widget); | |
1170 } | |
1171 | |
1172 QSize ThornStyle::sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const | |
1173 { | |
1174 QSize sz = QProxyStyle::sizeFromContents(type, option, size, widget); | |
1175 switch (type) { | |
1176 case CT_LineEdit: | |
1177 // Reduce size of lineedits, to make the NameSetEditor more compact (in the BankEditorDialog) | |
1178 sz -= QSize(2, 2); | |
1179 break; | |
1180 case CT_SpinBox: | |
1181 if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { | |
1182 // Add button + frame widths | |
1183 const int buttonWidth = m_spinupPixmap.width(); | |
1184 const int fw = vopt->frame ? pixelMetric(PM_SpinBoxFrameWidth, vopt, widget) : 0; | |
1185 sz += QSize(buttonWidth + 2*fw, 2*fw); | |
1186 } | |
1187 break; | |
1188 default: | |
1189 break; | |
1190 } | |
1191 return sz; | |
1192 } | |
1193 | |
1194 QRect ThornStyle::subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget) const | |
1195 { | |
1196 QRect rect = QProxyStyle::subElementRect(element, option, widget); | |
1197 switch (element) { | |
1198 case SE_TabWidgetTabBar: | |
1199 // QTabWidget::tab-bar { left: 5px; /* move to the right by 5px */ } | |
1200 return rect.translated(5, 0); | |
1201 case SE_TabWidgetTabPane: | |
1202 return rect; | |
1203 case SE_TabWidgetTabContents: | |
1204 return rect.adjusted(2, 2, -2, -2); | |
1205 case SE_HeaderArrow: { | |
1206 const QSize size = pixmapSize(m_arrowUpSmallInvertedPixmap); | |
1207 QRect sectionRect = option->rect.adjusted(0, 0, -5, 0); | |
1208 const QRect ret = alignedRect(option->direction, Qt::AlignRight | Qt::AlignVCenter, size, sectionRect); | |
1209 return ret; | |
1210 } | |
1211 case SE_ToolBarHandle: | |
1212 if (const QStyleOptionToolBar *tbopt = qstyleoption_cast<const QStyleOptionToolBar *>(option)) { | |
1213 // initially from qcommonstyle.cpp | |
1214 if (tbopt->features & QStyleOptionToolBar::Movable) { | |
1215 const QToolBar *tb = qobject_cast<const QToolBar*>(widget); | |
1216 const int margin = 1; | |
1217 const int handleExtent = pixelMetric(QStyle::PM_ToolBarHandleExtent, option, tb); | |
1218 QRect ret; | |
1219 if (tbopt->state & QStyle::State_Horizontal) { | |
1220 ret = QRect(margin, margin, handleExtent, tbopt->rect.height() - 2*margin); | |
1221 ret = QStyle::visualRect(tbopt->direction, tbopt->rect, ret); | |
1222 } else { | |
1223 ret = QRect(margin, margin, tbopt->rect.width() - 2*margin, handleExtent); | |
1224 } | |
1225 return ret; | |
1226 } | |
1227 } | |
1228 break; | |
1229 default: | |
1230 break; | |
1231 } | |
1232 | |
1233 return rect; | |
1234 } | |
1235 | |
1236 QRect ThornStyle::subControlRect(QStyle::ComplexControl cc, const QStyleOptionComplex *option, QStyle::SubControl sc, const QWidget *widget) const | |
1237 { | |
1238 switch (cc) { | |
1239 case CC_ScrollBar: | |
1240 if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) { | |
1241 QStyleOptionSlider copy = *scrollBar; | |
1242 // QScrollBar said { border: 2px solid #404040; } | |
1243 // We draw that border by filling everything and reducing the available size for contents | |
1244 copy.rect.adjust(2, 2, -2, -2); | |
1245 return QProxyStyle::subControlRect(cc, ©, sc, widget).adjusted(2, 2, 2, 2); | |
1246 } | |
1247 break; | |
1248 case CC_Slider: | |
1249 if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) { | |
1250 //QSlider::groove:horizontal { height: 5px; } | |
1251 const int grooveThickness = 5; | |
1252 QRect ret; | |
1253 | |
1254 switch (sc) { | |
1255 case SC_SliderHandle: { | |
1256 int sliderPos = 0; | |
1257 // QSlider::handle:horizontal { width: 8px; }, but this needs to be 9 to look like the old qss for some reason | |
1258 int len = 9; | |
1259 bool horizontal = slider->orientation == Qt::Horizontal; | |
1260 sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, | |
1261 slider->sliderPosition, | |
1262 (horizontal ? slider->rect.width() | |
1263 : slider->rect.height()) - len, | |
1264 slider->upsideDown); | |
1265 if (horizontal) { | |
1266 ret.setRect(slider->rect.x() + sliderPos, slider->rect.y() + 1, len, slider->rect.height() - 2); | |
1267 } else { | |
1268 ret.setRect(slider->rect.x() + 1, slider->rect.y() + sliderPos, slider->rect.width() - 2, len); | |
1269 } | |
1270 //qDebug() << "ret=" << ret; | |
1271 break; | |
1272 } | |
1273 case SC_SliderGroove: | |
1274 if (slider->orientation == Qt::Horizontal) { | |
1275 const int yOff = (slider->rect.height() - grooveThickness ) / 2; | |
1276 ret.setRect(slider->rect.x(), slider->rect.y() + yOff, | |
1277 slider->rect.width(), grooveThickness); | |
1278 } else { | |
1279 const int xOff = (slider->rect.width() - grooveThickness ) / 2; | |
1280 ret.setRect(slider->rect.x() + xOff, slider->rect.y(), | |
1281 grooveThickness, slider->rect.height()); | |
1282 } | |
1283 break; | |
1284 default: | |
1285 break; | |
1286 } | |
1287 return visualRect(slider->direction, slider->rect, ret); | |
1288 } | |
1289 break; | |
1290 case CC_SpinBox: | |
1291 if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { | |
1292 const int fw = 3; // frame width | |
1293 const int buttonTopBottomMargin = fw - 1; | |
1294 const QSize buttonSize(18, (sb->rect.height() - buttonTopBottomMargin) / 2 - 1); | |
1295 const int x = sb->rect.x() + sb->rect.width() - fw - buttonSize.width(); | |
1296 const int y = sb->rect.y() + buttonTopBottomMargin; | |
1297 QRect ret; | |
1298 switch (sc) { | |
1299 case SC_SpinBoxFrame: | |
1300 return sb->rect; | |
1301 case SC_SpinBoxUp: | |
1302 if (sb->buttonSymbols == QAbstractSpinBox::NoButtons) | |
1303 return QRect(); | |
1304 ret = QRect(x, y, buttonSize.width(), buttonSize.height()); | |
1305 break; | |
1306 case SC_SpinBoxDown: | |
1307 if (sb->buttonSymbols == QAbstractSpinBox::NoButtons) | |
1308 return QRect(); | |
1309 ret = QRect(x, sb->rect.height() - buttonTopBottomMargin - buttonSize.height(), buttonSize.width(), buttonSize.height()); | |
1310 break; | |
1311 case SC_SpinBoxEditField: | |
1312 if (sb->buttonSymbols == QAbstractSpinBox::NoButtons) { | |
1313 ret = QRect(sb->rect.x() + fw, fw, sb->rect.width() - 2*fw, sb->rect.height() - 2*fw); | |
1314 } else { | |
1315 ret = QRect(sb->rect.x() + fw, fw, x - fw, sb->rect.height() - 2*fw); | |
1316 } | |
1317 break; | |
1318 default: | |
1319 break; | |
1320 } | |
1321 return visualRect(sb->direction, sb->rect, ret); | |
1322 } | |
1323 break; | |
1324 default: | |
1325 break; | |
1326 } | |
1327 | |
1328 return QProxyStyle::subControlRect(cc, option, sc, widget); | |
1329 } | |
1330 | |
1331 #pragma GCC diagnostic pop |