VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/extensions/QIToolBar.cpp@ 102269

Last change on this file since 102269 was 102269, checked in by vboxsync, 11 months ago

FE/Qt: bugref:10450: macOS: No need to QIToolBar layout/paint hacks since Qt6.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.1 KB
Line 
1/* $Id: QIToolBar.cpp 102269 2023-11-22 18:50:08Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - QIToolBar class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QLayout>
30#include <QMainWindow>
31#include <QResizeEvent>
32#ifdef VBOX_WS_MAC
33# include <QApplication>
34# include <QPainter>
35# include <QPainterPath>
36#endif
37
38/* GUI includes: */
39#include "QIToolBar.h"
40#ifdef VBOX_WS_MAC
41# include "VBoxUtils.h"
42#endif
43
44
45QIToolBar::QIToolBar(QWidget *pParent /* = 0 */)
46 : QToolBar(pParent)
47 , m_pMainWindow(qobject_cast<QMainWindow*>(pParent))
48#ifdef VBOX_WS_MAC
49 , m_fEmulateUnifiedToolbar(false)
50 , m_iOverallContentsWidth(0)
51 , m_iBrandingWidth(0)
52#endif
53{
54 prepare();
55}
56
57void QIToolBar::setUseTextLabels(bool fEnable)
58{
59 /* Determine tool-button style on the basis of passed flag: */
60 Qt::ToolButtonStyle tbs = fEnable ? Qt::ToolButtonTextUnderIcon : Qt::ToolButtonIconOnly;
61
62 /* Depending on parent, assign this style: */
63 if (m_pMainWindow)
64 m_pMainWindow->setToolButtonStyle(tbs);
65 else
66 setToolButtonStyle(tbs);
67}
68
69bool QIToolBar::useTextLabels() const
70{
71 /* Depending on parent, return the style: */
72 if (m_pMainWindow)
73 return m_pMainWindow->toolButtonStyle() == Qt::ToolButtonTextUnderIcon;
74 else
75 return toolButtonStyle() == Qt::ToolButtonTextUnderIcon;
76}
77
78#ifdef VBOX_WS_MAC
79void QIToolBar::enableMacToolbar()
80{
81 /* Depending on parent, enable unified title/tool-bar: */
82 if (m_pMainWindow)
83 m_pMainWindow->setUnifiedTitleAndToolBarOnMac(true);
84}
85
86void QIToolBar::emulateMacToolbar()
87{
88 /* Remember request, to be used in paintEvent: */
89 m_fEmulateUnifiedToolbar = true;
90}
91
92void QIToolBar::setShowToolBarButton(bool fShow)
93{
94 ::darwinSetShowsToolbarButton(this, fShow);
95}
96
97void QIToolBar::enableBranding(const QIcon &icnBranding,
98 const QString &strBranding,
99 const QColor &clrBranding,
100 int iBrandingWidth)
101{
102 m_icnBranding = icnBranding;
103 m_strBranding = strBranding;
104 m_clrBranding = clrBranding;
105 m_iBrandingWidth = iBrandingWidth;
106 update();
107}
108#endif /* VBOX_WS_MAC */
109
110bool QIToolBar::event(QEvent *pEvent)
111{
112 /* Sanity check: */
113 if (!pEvent)
114 return QToolBar::event(pEvent);
115
116 /* Handle required event types: */
117 switch (pEvent->type())
118 {
119#ifdef VBOX_WS_MAC
120 case QEvent::LayoutRequest:
121 {
122 /* Recalculate overall contents width on layout
123 * request if we have branding stuff: */
124 if (!m_icnBranding.isNull())
125 recalculateOverallContentsWidth();
126 break;
127 }
128#endif /* VBOX_WS_MAC */
129 default:
130 break;
131 }
132
133 /* Call to base-class: */
134 return QToolBar::event(pEvent);
135}
136
137void QIToolBar::resizeEvent(QResizeEvent *pEvent)
138{
139 /* Call to base-class: */
140 QToolBar::resizeEvent(pEvent);
141
142 /* Notify listeners about new size: */
143 emit sigResized(pEvent->size());
144}
145
146#ifdef VBOX_WS_MAC
147void QIToolBar::paintEvent(QPaintEvent *pEvent)
148{
149 /* Call to base-class: */
150 QToolBar::paintEvent(pEvent);
151
152 /* If we have request to emulate unified tool-bar: */
153 if (m_fEmulateUnifiedToolbar)
154 {
155 /* Limit painting with incoming rectangle: */
156 QPainter painter(this);
157 painter.setClipRect(pEvent->rect());
158
159 /* Acquire full rectangle: */
160 const QRect rectangle = rect();
161
162 /* Prepare gradient: */
163 const QColor backgroundColor = QApplication::palette().color(QPalette::Active, QPalette::Window);
164 QLinearGradient gradient(rectangle.topLeft(), rectangle.bottomLeft());
165 gradient.setColorAt(0, backgroundColor.darker(105));
166 gradient.setColorAt(1, backgroundColor.darker(115));
167
168 /* Fill background: */
169 painter.fillRect(rectangle, gradient);
170
171 /* Do we have branding stuff and a place for it? */
172 if ( !m_icnBranding.isNull()
173 && width() >= m_iOverallContentsWidth + m_iBrandingWidth)
174 {
175 /* A bit of common stuff: */
176 QFont fnt = font();
177 int iTextWidth = 0;
178 int iTextHeight = 0;
179
180 /* Configure font to fit width (m_iBrandingWidth - 2 * 4): */
181 if (useTextLabels())
182 {
183 for (int i = 0; i <= 10; ++i) // no more than 10 tries ..
184 {
185 if (fnt.pixelSize() == -1)
186 fnt.setPointSize(fnt.pointSize() - i);
187 else
188 fnt.setPixelSize(fnt.pixelSize() - i);
189 iTextWidth = QFontMetrics(fnt).size(0, m_strBranding).width();
190 if (iTextWidth <= m_iBrandingWidth - 2 * 4)
191 break;
192 }
193 iTextHeight = QFontMetrics(fnt).height();
194 }
195
196 /* Draw pixmap: */
197 const int iIconSize = qMin(rectangle.height(), 32 /* default */);
198 const int iIconMarginH = (m_iBrandingWidth - iIconSize) / 2;
199 const int iIconMarginV = (rectangle.height() - iIconSize - iTextHeight) / 2;
200 const int iIconX = rectangle.width() - iIconSize - iIconMarginH;
201 const int iIconY = iIconMarginV;
202 painter.drawPixmap(iIconX, iIconY, m_icnBranding.pixmap(QSize(iIconSize, iIconSize)));
203
204 /* Draw text path: */
205 if (useTextLabels())
206 {
207 const int iTextMargingH = (m_iBrandingWidth - iTextWidth) / 2;
208 const int iTextX = rectangle.width() - iTextWidth - iTextMargingH;
209 const int iTextY = iIconY + iIconSize + iTextHeight;
210 QPainterPath textPath;
211 textPath.addText(0, 0, fnt, m_strBranding);
212 textPath.translate(iTextX, iTextY);
213 painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
214 painter.setPen(QPen(m_clrBranding.darker(80), 2, Qt::SolidLine, Qt::RoundCap));
215 painter.drawPath(QPainterPathStroker().createStroke(textPath));
216 painter.setBrush(Qt::black);
217 painter.setPen(Qt::NoPen);
218 painter.drawPath(textPath);
219 }
220 }
221 }
222}
223#endif /* VBOX_WS_MAC */
224
225void QIToolBar::prepare()
226{
227 /* Configure tool-bar: */
228 setFloatable(false);
229 setMovable(false);
230
231#ifdef VBOX_WS_MAC
232 setStyleSheet("QToolBar { border: 0px none black; }");
233#endif
234
235 /* Configure tool-bar' layout: */
236 if (layout())
237 layout()->setContentsMargins(0, 0, 0, 0);
238
239 /* Configure tool-bar' context-menu policy: */
240 setContextMenuPolicy(Qt::PreventContextMenu);
241}
242
243#ifdef VBOX_WS_MAC
244void QIToolBar::recalculateOverallContentsWidth()
245{
246 /* Reset contents width: */
247 m_iOverallContentsWidth = 0;
248
249 /* Caclulate new value: */
250 if (!layout())
251 return;
252 int iResult = 0;
253 const int iSpacing = layout()->spacing();
254 foreach (QAction *pAction, actions())
255 {
256 if (!pAction || !pAction->isVisible())
257 continue;
258 QWidget *pWidget = widgetForAction(pAction);
259 if (!pWidget)
260 continue;
261 /* Add each widget width and spacing: */
262 const int iWidth = pWidget->width() + iSpacing;
263 iResult += iWidth;
264 }
265 /* Subtract last spacing: */
266 iResult -= iSpacing;
267
268 /* Update result: */
269 m_iOverallContentsWidth = qMax(m_iOverallContentsWidth, iResult);
270}
271#endif /* VBOX_WS_MAC */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette