1212#include < QtGui/QPainter>
1313#include < QtWidgets/QApplication>
1414#include < QtWidgets/QComboBox>
15+ #include < QtWidgets/QProxyStyle>
1516#include < QtWidgets/QStyleFactory>
16- #include < QtWidgets/QStyledItemDelegate>
17- #include < unordered_map>
1817
1918#include < QtCore/QtDebug>
2019
20+ #include < memory>
21+ #include < unordered_map>
22+
2123namespace Mayo {
2224
2325namespace {
@@ -28,95 +30,61 @@ const QIcon& nullQIcon()
2830 return null;
2931}
3032
31- class QComboBoxItemViewDelegate : public QStyledItemDelegate {
33+ // Provides a specific style for "flat" QComboBox behavior
34+ // This kind of QComboBox is used in toolbar just below Mayo's main menubar
35+ class FlatComboBoxStyle : public QProxyStyle {
3236public:
33- QComboBoxItemViewDelegate (QObject* parent = nullptr )
34- : QStyledItemDelegate(parent)
35- {}
36-
37- void paint (
38- QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index
39- ) const override
37+ FlatComboBoxStyle (QStyle* style)
38+ : QProxyStyle(style)
4039 {
41- QStyleOptionViewItem opts = option;
42- this ->initStyleOption (&opts, index);
43- #if 1
44- qDebug () << " opts.state: " << opts.state << " text=" << opts.text ;
45- QBrush rectBrush;
46- if (opts.state .testFlag (QStyle::State_Enabled)
47- && opts.state .testFlag (QStyle::State_Active)
48- && opts.state .testFlag (QStyle::State_HasFocus))
49- {
50- rectBrush = opts.widget ->palette ().color (QPalette::Window).lighter (200 );
51- }
52- else {
53- rectBrush = opts.widget ->palette ().color (QPalette::Window);
54- }
40+ }
5541
56- const QWidget* widget = opts.widget ;
57- painter->setBrush (widget->palette ().color (QPalette::Window));
58- painter->fillRect (opts.rect , rectBrush);
42+ void setArrowPixmap (const QPixmap& pixmap)
43+ {
44+ m_arrowPixmap = pixmap;
45+ }
5946
60- painter->setPen (opts.widget ->palette ().color (QPalette::Text));
61- painter->drawText (opts.rect , Qt::AlignLeft | Qt::AlignVCenter, opts.text );
62- #else
63- const QWidget* widget = opts.widget;
64- const QStyle* style = widget ? widget->style() : QApplication::style();
65- const QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &opts, widget);
47+ void drawComplexControl (
48+ QStyle::ComplexControl control,
49+ const QStyleOptionComplex* option,
50+ QPainter* painter,
51+ const QWidget* widget
52+ ) const override
53+ {
6654
67- style->drawControl(QStyle::CE_ItemViewItem, &opts, painter, widget);
55+ auto opt = qstyleoption_cast<const QStyleOptionComboBox*>(option);
56+ if (control != QStyle::CC_ComboBox || !opt) {
57+ QProxyStyle::drawComplexControl (control, option, painter, widget);
58+ return ;
59+ }
6860
69- painter->setPen(opts.widget->palette().color(QPalette::Text));
70- style->drawItemText(painter, textRect, opts.displayAlignment, opts.palette, opts.state & QStyle::State_Enabled, opts.text, QPalette::Text);
61+ if (
62+ option->state .testFlag (QStyle::State_Enabled)
63+ && option->state .testFlag (QStyle::State_Active)
64+ && option->state .testFlag (QStyle::State_MouseOver)
65+ )
66+ {
67+ QStyleOptionToolButton optsBtn;
68+ optsBtn.initFrom (widget);
69+ optsBtn.features = QStyleOptionToolButton::None;
70+ optsBtn.toolButtonStyle = Qt::ToolButtonIconOnly;
71+ this ->drawPrimitive (QStyle::PE_PanelButtonTool, &optsBtn, painter, widget);
72+ }
7173
72- painter->drawText(opts.rect, Qt::AlignLeft | Qt::AlignVCenter, opts.text);
73- #endif
74+ const QRect arrowRect = this ->subControlRect (QStyle::CC_ComboBox, opt, QStyle::SC_ComboBoxArrow, widget);
75+ const QRect arrowPixmapRect (
76+ arrowRect.left () + arrowRect.width () / 2 - (m_arrowPixmap.width () / 2 ),
77+ arrowRect.top () + arrowRect.height () / 2 - (m_arrowPixmap.height () / 2 ),
78+ m_arrowPixmap.width (),
79+ m_arrowPixmap.height ()
80+ );
81+ painter->drawPixmap (arrowPixmapRect, m_arrowPixmap);
7482 }
7583
76- QSize sizeHint (const QStyleOptionViewItem& option, const QModelIndex& index) const override
77- {
78- QSize size = QStyledItemDelegate::sizeHint (option, index);
79- size.setHeight (size.height () * 1.5 );
80- return size;
81- }
84+ private:
85+ QPixmap m_arrowPixmap;
8286};
8387
84- QString cssFlatComboBox (
85- const QString& urlPixDownArrow,
86- const QString& urlPixDownArrowDisabled
87- )
88- {
89- const QPalette appPalette = qApp->palette ();
90- const QString css = QString (
91- R"(
92- QComboBox {
93- border-style: solid;
94- background: %1;
95- padding: 2px 15px 2px 10px;
96- }
97- QComboBox:hover {
98- border-style: solid;
99- background: %2;
100- padding: 2px 15px 2px 10px;
101- }
102- QComboBox::drop-down {
103- subcontrol-origin: padding;
104- subcontrol-position: top right;
105- width: 15px;
106- border-left-width: 0px;
107- border-top-right-radius: 3px;
108- border-bottom-right-radius: 3px;
109- }
110- QComboBox::down-arrow { image: url(%3); }
111- QComboBox::down-arrow:disabled { image: url(%4); }
112- )"
113- ).arg (appPalette.color (QPalette::Window).name (),
114- appPalette.color (QPalette::Window).darker (110 ).name (),
115- urlPixDownArrow,
116- urlPixDownArrowDisabled);
117- return css;
118- }
119-
12088QPixmap invertedPixmap (const QPixmap& pix)
12189{
12290 QImage img = pix.toImage ();
@@ -230,17 +198,19 @@ class ThemeClassic : public Theme {
230198 const QString icnFileName = iconFileName (icn);
231199 m_mapIcon.emplace (icn, QIcon (QPixmap (icnBasePath + icnFileName)));
232200 }
201+
202+ m_flatComboBoxStyle.reset (new FlatComboBoxStyle (nullptr ));
203+ m_flatComboBoxStyle->setArrowPixmap (QPixmap (" :/images/themes/classic/indicator-down_8.png" ));
233204 }
234205
235206 void setupHeaderComboBox (QComboBox* cb) override
236207 {
237- const QString urlDown (" :/images/themes/classic/indicator-down_8.png" );
238- const QString urlDownDisabled (" :/images/themes/classic/indicator-down-disabled_8.png" );
239- cb->setStyleSheet (cssFlatComboBox (urlDown, urlDownDisabled));
208+ cb->setStyle (m_flatComboBoxStyle.get ());
240209 }
241210
242211private:
243212 std::unordered_map<Theme::Icon, QIcon> m_mapIcon;
213+ std::unique_ptr<FlatComboBoxStyle> m_flatComboBoxStyle;
244214};
245215
246216class ThemeDark : public Theme {
@@ -314,11 +284,15 @@ class ThemeDark : public Theme {
314284 m_mapIcon.emplace (icn, pix);
315285 }
316286
317- qApp->setStyle (QStyleFactory::create (" Fusion" ));
287+ auto fusionStyle = QStyleFactory::create (" Fusion" );
288+ qApp->setStyle (fusionStyle);
289+ m_flatComboBoxStyle.reset (new FlatComboBoxStyle (fusionStyle));
290+ m_flatComboBoxStyle->setArrowPixmap (QPixmap (" :/images/themes/dark/indicator-down_8.png" ));
291+
318292 QPalette p = qApp->palette ();
319- p.setColor (QPalette::Base, QColor (80 , 80 , 80 ));
320- p.setColor (QPalette::Window, QColor (37 , 37 , 37 ));
321- p.setColor (QPalette::Button, QColor (73 , 73 , 73 ));
293+ p.setColor (QPalette::Base, QColor (50 , 50 , 50 )); // #323232
294+ p.setColor (QPalette::Window, QColor (37 , 37 , 37 )); // #252525
295+ p.setColor (QPalette::Button, QColor (73 , 73 , 73 )); // #494949
322296 p.setColor (QPalette::Text, Qt::white);
323297 p.setColor (QPalette::ButtonText, Qt::white);
324298 p.setColor (QPalette::WindowText, Qt::white);
@@ -327,8 +301,8 @@ class ThemeDark : public Theme {
327301 p.setColor (QPalette::Link, linkColor);
328302 p.setColor (QPalette::LinkVisited, linkColor);
329303
330- const QColor disabledGray (40 , 40 , 40 );
331- const QColor disabledTextGray (128 , 128 , 128 );
304+ const QColor disabledGray (40 , 40 , 40 ); // #282828
305+ const QColor disabledTextGray (128 , 128 , 128 ); // #808080
332306 p.setColor (QPalette::Disabled, QPalette::Window, disabledGray);
333307 p.setColor (QPalette::Disabled, QPalette::Base, disabledGray);
334308 p.setColor (QPalette::Disabled, QPalette::AlternateBase, disabledGray);
@@ -338,7 +312,7 @@ class ThemeDark : public Theme {
338312 p.setColor (QPalette::Disabled, QPalette::WindowText, disabledTextGray);
339313 qApp->setPalette (p);
340314
341- const QString css =
315+ QString css =
342316 R"(
343317 QFrame[frameShape="5"] {
344318 color: gray;
@@ -347,48 +321,54 @@ class ThemeDark : public Theme {
347321 }
348322 QAbstractItemView {
349323 show-decoration-selected: 1;
350- background: #252525 ;
351- selection-background-color: #505050 ;
324+ background: mayo_PaletteWindowColor ;
325+ selection-background-color: mayo_MenuItemSelectedColor ;
352326 }
353- QAbstractItemView::item:hover { background: #383838; }
327+ QAbstractItemView::item:hover { background: mayo_MenuItemSelectedColor; }
328+ QMenuBar::item:selected { background: mayo_PaletteButtonColor; }
329+ QMenuBar::item:pressed { background: mayo_PaletteHighlightColor; }
354330 QMenu {
355- background: #252525 ;
331+ background: mayo_PaletteBaseColor ;
356332 border: 1px solid rgb(100,100,100);
357333 }
358334 QMenu::item:selected { background: rgb(110,110,110); }
359335 QMenu::separator {
360336 background: rgb(110,110,110);
361337 height: 1px;
362338 }
363- QLineEdit { background: #505050 ; }
364- QTextEdit { background: #505050 ; }
365- QSpinBox { background: #505050 ; }
366- QDoubleSpinBox { background: #505050 ; }
339+ QLineEdit { background: mayo_PaletteBaseColor ; }
340+ QTextEdit { background: mayo_PaletteBaseColor ; }
341+ QSpinBox { background: mayo_PaletteBaseColor ; }
342+ QDoubleSpinBox { background: mayo_PaletteBaseColor ; }
367343 QToolButton:checked { background: #383838; }
368344 QToolButton:pressed { background: #383838; }
369- QComboBox { background: #505050; }
370345 QGroupBox {
371346 border: 1px solid #808080;
372347 margin-top: 4ex;
373348 }
374- QFileDialog { background: #505050; }
375- QComboBox:editable { background: #505050; }
376- QComboBox:disabled { background: rgb(40,40,40); }
377- QProgressBar { background: #505050; }
349+ QFileDialog { background: mayo_PaletteBaseColor; }
350+ QComboBox { background: mayo_PaletteButtonColor; }
351+ QComboBox:editable { background: mayo_PaletteButtonColor; }
352+ QComboBox:disabled { background: mayo_PaletteBaseColor_Disabled; }
353+ QProgressBar { background: mayo_PaletteBaseColor; }
378354 )" ;
355+ css.replace (" mayo_MenuItemSelectedColor" , QColor{80 , 80 , 80 }.name ());
356+ css.replace (" mayo_PaletteBaseColor_Disabled" , p.color (QPalette::Disabled, QPalette::Base).name ());
357+ css.replace (" mayo_PaletteBaseColor" , p.color (QPalette::Base).name ());
358+ css.replace (" mayo_PaletteWindowColor" , p.color (QPalette::Window).name ());
359+ css.replace (" mayo_PaletteButtonColor" , p.color (QPalette::Button).name ());
360+ css.replace (" mayo_PaletteHighlightColor" , p.color (QPalette::Highlight).name ());
379361 qApp->setStyleSheet (css);
380362 }
381363
382364 void setupHeaderComboBox (QComboBox* cb) override
383365 {
384- const QString urlDown (" :/images/themes/dark/indicator-down_8.png" );
385- const QString urlDownDisabled (" :/images/themes/classic/indicator-down-disabled_8.png" );
386- cb->setStyleSheet (cssFlatComboBox (urlDown, urlDownDisabled));
387- cb->setItemDelegate (new QComboBoxItemViewDelegate (cb));
366+ cb->setStyle (m_flatComboBoxStyle.get ());
388367 }
389368
390369private:
391370 std::unordered_map<Theme::Icon, QIcon> m_mapIcon;
371+ std::unique_ptr<FlatComboBoxStyle> m_flatComboBoxStyle;
392372};
393373
394374} // namespace
0 commit comments