3
3
4
4
#include " DockMenuBar.h"
5
5
6
+ #include < QtCore/QTimer>
6
7
#include < QtGui/QPainter>
7
8
#include < QtGui/QPaintEvent>
8
9
#include < QtWidgets/QBoxLayout>
10
+ #include < QtWidgets/QStyleFactory>
9
11
#include < QtWidgets/QStyleOption>
10
12
13
+ static const int OUTER_MENU_MARGIN = 2 ;
14
+ static const int INNER_MENU_MARGIN = 4 ;
15
+
11
16
DockMenuBar::DockMenuBar (QWidget* original_menu_bar, QWidget* parent)
12
17
: QWidget(parent)
18
+ , m_original_menu_bar(original_menu_bar)
13
19
{
20
+ setSizePolicy (QSizePolicy::MinimumExpanding, QSizePolicy::Minimum);
21
+
14
22
QHBoxLayout* layout = new QHBoxLayout;
15
- layout->setContentsMargins (0 , 2 , 2 , 0 );
23
+ layout->setContentsMargins (0 , OUTER_MENU_MARGIN, OUTER_MENU_MARGIN , 0 );
16
24
setLayout (layout);
17
25
18
26
QWidget* menu_wrapper = new QWidget;
19
27
menu_wrapper->setSizePolicy (QSizePolicy::Fixed , QSizePolicy::Preferred);
20
28
layout->addWidget (menu_wrapper);
21
29
22
30
QHBoxLayout* menu_layout = new QHBoxLayout;
23
- menu_layout->setContentsMargins (0 , 4 , 0 , 4 );
31
+ menu_layout->setContentsMargins (0 , INNER_MENU_MARGIN , 0 , INNER_MENU_MARGIN );
24
32
menu_wrapper->setLayout (menu_layout);
25
33
26
34
menu_layout->addWidget (original_menu_bar);
27
35
28
36
m_layout_switcher = new QTabBar;
29
37
m_layout_switcher->setContentsMargins (0 , 0 , 0 , 0 );
30
- m_layout_switcher->setSizePolicy (QSizePolicy::Fixed , QSizePolicy::Preferred);
38
+ m_layout_switcher->setSizePolicy (QSizePolicy::Expanding , QSizePolicy::Preferred);
31
39
m_layout_switcher->setContextMenuPolicy (Qt::CustomContextMenu);
40
+ m_layout_switcher->setDrawBase (false );
41
+ m_layout_switcher->setExpanding (false );
32
42
m_layout_switcher->setMovable (true );
33
43
layout->addWidget (m_layout_switcher);
34
44
35
- QWidget* spacer = new QWidget;
36
- spacer->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Preferred);
37
- layout->addWidget (spacer);
38
-
39
45
connect (m_layout_switcher, &QTabBar::tabMoved, this , [this ](int from, int to) {
40
46
DockLayout::Index from_index = static_cast <DockLayout::Index>(from);
41
47
DockLayout::Index to_index = static_cast <DockLayout::Index>(to);
@@ -59,6 +65,26 @@ DockMenuBar::DockMenuBar(QWidget* original_menu_bar, QWidget* parent)
59
65
emit lockButtonToggled (checked);
60
66
});
61
67
layout->addWidget (m_layout_locked_toggle);
68
+
69
+ updateTheme ();
70
+ }
71
+
72
+ void DockMenuBar::updateTheme ()
73
+ {
74
+ bool needs_new_style = false ;
75
+
76
+ if (!m_style)
77
+ {
78
+ m_style = new DockLayoutSwitcherStyle (m_layout_switcher);
79
+ m_layout_switcher->setStyle (m_style);
80
+
81
+ needs_new_style = true ;
82
+ }
83
+
84
+ if (needs_new_style || m_style->baseStyle ()->name () != qApp->style ()->name ())
85
+ m_style->setBaseStyle (QStyleFactory::create (qApp->style ()->name ()));
86
+
87
+ m_layout_locked_toggle->setStyleSheet (" color: palette(text)" );
62
88
}
63
89
64
90
void DockMenuBar::updateLayoutSwitcher (DockLayout::Index current_index, const std::vector<DockLayout>& layouts)
@@ -166,6 +192,32 @@ void DockMenuBar::stopBlink()
166
192
}
167
193
}
168
194
195
+ int DockMenuBar::innerHeight () const
196
+ {
197
+ return m_original_menu_bar->sizeHint ().height () + INNER_MENU_MARGIN * 2 ;
198
+ }
199
+
200
+ QSize DockMenuBar::sizeHint () const
201
+ {
202
+ return QSize (m_original_menu_bar->sizeHint ().width (), innerHeight () + OUTER_MENU_MARGIN);
203
+ }
204
+
205
+ void DockMenuBar::paintEvent (QPaintEvent* event)
206
+ {
207
+ QPainter painter (this );
208
+
209
+ // This fixes the background colour of the menu bar when using the WIndows
210
+ // classic theme.
211
+ QStyleOptionMenuItem menu_option;
212
+ menu_option.palette = palette ();
213
+ menu_option.state = QStyle::State_None;
214
+ menu_option.menuItemType = QStyleOptionMenuItem::EmptyArea;
215
+ menu_option.checkType = QStyleOptionMenuItem::NotCheckable;
216
+ menu_option.rect = rect ();
217
+ menu_option.menuRect = rect ();
218
+ style ()->drawControl (QStyle::CE_MenuBarEmptyArea, &menu_option, &painter, this );
219
+ }
220
+
169
221
void DockMenuBar::tabChanged (int index)
170
222
{
171
223
// Prevent recursion.
@@ -182,3 +234,58 @@ void DockMenuBar::tabChanged(int index)
182
234
emit newButtonClicked ();
183
235
}
184
236
}
237
+
238
+ // *****************************************************************************
239
+
240
+ DockLayoutSwitcherStyle::DockLayoutSwitcherStyle (QObject* parent)
241
+ : QProxyStyle(nullptr )
242
+ {
243
+ setParent (parent);
244
+ }
245
+
246
+ void DockLayoutSwitcherStyle::drawControl (
247
+ ControlElement element,
248
+ const QStyleOption* option,
249
+ QPainter* painter,
250
+ const QWidget* widget) const
251
+ {
252
+ QProxyStyle::drawControl (element, option, painter, widget);
253
+
254
+ // Draw a slick-looking highlight under the currently selected tab.
255
+ if (element == CE_TabBarTab && baseStyle ()->name () == " fusion" )
256
+ {
257
+ const QStyleOptionTab* tab = qstyleoption_cast<const QStyleOptionTab*>(option);
258
+ if (tab && (tab->state & State_Selected))
259
+ {
260
+ painter->setPen (tab->palette .highlight ().color ());
261
+ painter->drawLine (tab->rect .bottomLeft (), tab->rect .bottomRight ());
262
+ }
263
+ }
264
+ }
265
+
266
+ QSize DockLayoutSwitcherStyle::sizeFromContents (
267
+ QStyle::ContentsType type, const QStyleOption* option, const QSize& contents_size, const QWidget* widget) const
268
+ {
269
+ QSize size = QProxyStyle::sizeFromContents (type, option, contents_size, widget);
270
+
271
+ DockMenuBar* menu_bar = qobject_cast<DockMenuBar*>(widget->parent ());
272
+ if (!menu_bar)
273
+ return size;
274
+
275
+ // Adjust the size of the layout switcher tabs depending on the theme.
276
+ if (type == CT_TabBarTab)
277
+ {
278
+ if (baseStyle ()->name () == " fusion" || baseStyle ()->name () == " windowsvista" )
279
+ {
280
+ // Make sure the tab extends to the bottom of the widget.
281
+ size.setHeight (menu_bar->innerHeight () - option->rect .top ());
282
+ }
283
+ else if (baseStyle ()->name () == " windows11" )
284
+ {
285
+ // Make sure the tab is centred vertically.
286
+ size.setHeight (menu_bar->innerHeight () - option->rect .top () * 2 );
287
+ }
288
+ }
289
+
290
+ return size;
291
+ }
0 commit comments