1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the demonstration applications of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:BSD$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** BSD License Usage |
18 | ** Alternatively, you may use this file under the terms of the BSD license |
19 | ** as follows: |
20 | ** |
21 | ** "Redistribution and use in source and binary forms, with or without |
22 | ** modification, are permitted provided that the following conditions are |
23 | ** met: |
24 | ** * Redistributions of source code must retain the above copyright |
25 | ** notice, this list of conditions and the following disclaimer. |
26 | ** * Redistributions in binary form must reproduce the above copyright |
27 | ** notice, this list of conditions and the following disclaimer in |
28 | ** the documentation and/or other materials provided with the |
29 | ** distribution. |
30 | ** * Neither the name of The Qt Company Ltd nor the names of its |
31 | ** contributors may be used to endorse or promote products derived |
32 | ** from this software without specific prior written permission. |
33 | ** |
34 | ** |
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
46 | ** |
47 | ** $QT_END_LICENSE$ |
48 | ** |
49 | ****************************************************************************/ |
50 | |
51 | #include "toolbar.h" |
52 | |
53 | #include <QRandomGenerator> |
54 | |
55 | #include <QMainWindow> |
56 | #include <QMenu> |
57 | #include <QPainter> |
58 | #include <QPainterPath> |
59 | #include <QSpinBox> |
60 | #include <QLabel> |
61 | #include <QToolTip> |
62 | |
63 | #include <stdlib.h> |
64 | |
65 | static QPixmap genIcon(const QSize &iconSize, const QString &, const QColor &color, qreal pixelRatio) |
66 | { |
67 | int w = qRound(d: iconSize.width() * pixelRatio); |
68 | int h = qRound(d: iconSize.height() * pixelRatio); |
69 | |
70 | QImage image(w, h, QImage::Format_ARGB32_Premultiplied); |
71 | image.fill(pixel: 0); |
72 | |
73 | QPainter p(&image); |
74 | |
75 | extern void render_qt_text(QPainter *, int, int, const QColor &); |
76 | render_qt_text(&p, w, h, color); |
77 | |
78 | QPixmap pm = QPixmap::fromImage(image, flags: Qt::DiffuseDither | Qt::DiffuseAlphaDither); |
79 | pm.setDevicePixelRatio(pixelRatio); |
80 | return pm; |
81 | } |
82 | |
83 | static QPixmap genIcon(const QSize &iconSize, int number, const QColor &color, qreal pixelRatio) |
84 | { return genIcon(iconSize, QString::number(number), color, pixelRatio); } |
85 | |
86 | ToolBar::ToolBar(const QString &title, QWidget *parent) |
87 | : QToolBar(parent) |
88 | , spinbox(nullptr) |
89 | , spinboxAction(nullptr) |
90 | { |
91 | setWindowTitle(title); |
92 | setObjectName(title); |
93 | |
94 | setIconSize(QSize(32, 32)); |
95 | |
96 | qreal dpr = devicePixelRatioF(); |
97 | menu = new QMenu("One" , this); |
98 | menu->setIcon(genIcon(iconSize: iconSize(), number: 1, color: Qt::black, pixelRatio: dpr)); |
99 | menu->addAction(icon: genIcon(iconSize: iconSize(), "A" , color: Qt::blue, pixelRatio: dpr), text: "A" ); |
100 | menu->addAction(icon: genIcon(iconSize: iconSize(), "B" , color: Qt::blue, pixelRatio: dpr), text: "B" ); |
101 | menu->addAction(icon: genIcon(iconSize: iconSize(), "C" , color: Qt::blue, pixelRatio: dpr), text: "C" ); |
102 | addAction(action: menu->menuAction()); |
103 | |
104 | QAction *two = addAction(icon: genIcon(iconSize: iconSize(), number: 2, color: Qt::white, pixelRatio: dpr), text: "Two" ); |
105 | QFont boldFont; |
106 | boldFont.setBold(true); |
107 | two->setFont(boldFont); |
108 | |
109 | addAction(icon: genIcon(iconSize: iconSize(), number: 3, color: Qt::red, pixelRatio: dpr), text: "Three" ); |
110 | addAction(icon: genIcon(iconSize: iconSize(), number: 4, color: Qt::green, pixelRatio: dpr), text: "Four" ); |
111 | addAction(icon: genIcon(iconSize: iconSize(), number: 5, color: Qt::blue, pixelRatio: dpr), text: "Five" ); |
112 | addAction(icon: genIcon(iconSize: iconSize(), number: 6, color: Qt::yellow, pixelRatio: dpr), text: "Six" ); |
113 | orderAction = new QAction(this); |
114 | orderAction->setText(tr(s: "Order Items in Tool Bar" )); |
115 | connect(sender: orderAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::order); |
116 | |
117 | randomizeAction = new QAction(this); |
118 | randomizeAction->setText(tr(s: "Randomize Items in Tool Bar" )); |
119 | connect(sender: randomizeAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::randomize); |
120 | |
121 | addSpinBoxAction = new QAction(this); |
122 | addSpinBoxAction->setText(tr(s: "Add Spin Box" )); |
123 | connect(sender: addSpinBoxAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::addSpinBox); |
124 | |
125 | removeSpinBoxAction = new QAction(this); |
126 | removeSpinBoxAction->setText(tr(s: "Remove Spin Box" )); |
127 | removeSpinBoxAction->setEnabled(false); |
128 | connect(sender: removeSpinBoxAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::removeSpinBox); |
129 | |
130 | movableAction = new QAction(tr(s: "Movable" ), this); |
131 | movableAction->setCheckable(true); |
132 | connect(sender: movableAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::changeMovable); |
133 | |
134 | allowedAreasActions = new QActionGroup(this); |
135 | allowedAreasActions->setExclusive(false); |
136 | |
137 | allowLeftAction = new QAction(tr(s: "Allow on Left" ), this); |
138 | allowLeftAction->setCheckable(true); |
139 | connect(sender: allowLeftAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::allowLeft); |
140 | |
141 | allowRightAction = new QAction(tr(s: "Allow on Right" ), this); |
142 | allowRightAction->setCheckable(true); |
143 | connect(sender: allowRightAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::allowRight); |
144 | |
145 | allowTopAction = new QAction(tr(s: "Allow on Top" ), this); |
146 | allowTopAction->setCheckable(true); |
147 | connect(sender: allowTopAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::allowTop); |
148 | |
149 | allowBottomAction = new QAction(tr(s: "Allow on Bottom" ), this); |
150 | allowBottomAction->setCheckable(true); |
151 | connect(sender: allowBottomAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::allowBottom); |
152 | |
153 | allowedAreasActions->addAction(a: allowLeftAction); |
154 | allowedAreasActions->addAction(a: allowRightAction); |
155 | allowedAreasActions->addAction(a: allowTopAction); |
156 | allowedAreasActions->addAction(a: allowBottomAction); |
157 | |
158 | areaActions = new QActionGroup(this); |
159 | areaActions->setExclusive(true); |
160 | |
161 | leftAction = new QAction(tr(s: "Place on Left" ) , this); |
162 | leftAction->setCheckable(true); |
163 | connect(sender: leftAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::placeLeft); |
164 | |
165 | rightAction = new QAction(tr(s: "Place on Right" ) , this); |
166 | rightAction->setCheckable(true); |
167 | connect(sender: rightAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::placeRight); |
168 | |
169 | topAction = new QAction(tr(s: "Place on Top" ) , this); |
170 | topAction->setCheckable(true); |
171 | connect(sender: topAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::placeTop); |
172 | |
173 | bottomAction = new QAction(tr(s: "Place on Bottom" ) , this); |
174 | bottomAction->setCheckable(true); |
175 | connect(sender: bottomAction, signal: &QAction::triggered, receiver: this, slot: &ToolBar::placeBottom); |
176 | |
177 | areaActions->addAction(a: leftAction); |
178 | areaActions->addAction(a: rightAction); |
179 | areaActions->addAction(a: topAction); |
180 | areaActions->addAction(a: bottomAction); |
181 | |
182 | connect(sender: movableAction, signal: &QAction::triggered, receiver: areaActions, slot: &QActionGroup::setEnabled); |
183 | |
184 | connect(sender: movableAction, signal: &QAction::triggered, receiver: allowedAreasActions, slot: &QActionGroup::setEnabled); |
185 | |
186 | menu = new QMenu(title, this); |
187 | menu->addAction(action: toggleViewAction()); |
188 | menu->addSeparator(); |
189 | menu->addAction(action: orderAction); |
190 | menu->addAction(action: randomizeAction); |
191 | menu->addSeparator(); |
192 | menu->addAction(action: addSpinBoxAction); |
193 | menu->addAction(action: removeSpinBoxAction); |
194 | menu->addSeparator(); |
195 | menu->addAction(action: movableAction); |
196 | menu->addSeparator(); |
197 | menu->addActions(actions: allowedAreasActions->actions()); |
198 | menu->addSeparator(); |
199 | menu->addActions(actions: areaActions->actions()); |
200 | menu->addSeparator(); |
201 | menu->addAction(text: tr(s: "Insert break" ), object: this, slot: &ToolBar::insertToolBarBreak); |
202 | |
203 | connect(sender: menu, signal: &QMenu::aboutToShow, receiver: this, slot: &ToolBar::updateMenu); |
204 | |
205 | randomize(); |
206 | } |
207 | |
208 | void ToolBar::() |
209 | { |
210 | QMainWindow *mainWindow = qobject_cast<QMainWindow *>(object: parentWidget()); |
211 | Q_ASSERT(mainWindow); |
212 | |
213 | const Qt::ToolBarArea area = mainWindow->toolBarArea(toolbar: this); |
214 | const Qt::ToolBarAreas areas = allowedAreas(); |
215 | |
216 | movableAction->setChecked(isMovable()); |
217 | |
218 | allowLeftAction->setChecked(isAreaAllowed(area: Qt::LeftToolBarArea)); |
219 | allowRightAction->setChecked(isAreaAllowed(area: Qt::RightToolBarArea)); |
220 | allowTopAction->setChecked(isAreaAllowed(area: Qt::TopToolBarArea)); |
221 | allowBottomAction->setChecked(isAreaAllowed(area: Qt::BottomToolBarArea)); |
222 | |
223 | if (allowedAreasActions->isEnabled()) { |
224 | allowLeftAction->setEnabled(area != Qt::LeftToolBarArea); |
225 | allowRightAction->setEnabled(area != Qt::RightToolBarArea); |
226 | allowTopAction->setEnabled(area != Qt::TopToolBarArea); |
227 | allowBottomAction->setEnabled(area != Qt::BottomToolBarArea); |
228 | } |
229 | |
230 | leftAction->setChecked(area == Qt::LeftToolBarArea); |
231 | rightAction->setChecked(area == Qt::RightToolBarArea); |
232 | topAction->setChecked(area == Qt::TopToolBarArea); |
233 | bottomAction->setChecked(area == Qt::BottomToolBarArea); |
234 | |
235 | if (areaActions->isEnabled()) { |
236 | leftAction->setEnabled(areas & Qt::LeftToolBarArea); |
237 | rightAction->setEnabled(areas & Qt::RightToolBarArea); |
238 | topAction->setEnabled(areas & Qt::TopToolBarArea); |
239 | bottomAction->setEnabled(areas & Qt::BottomToolBarArea); |
240 | } |
241 | } |
242 | |
243 | void ToolBar::order() |
244 | { |
245 | QList<QAction *> ordered; |
246 | QList<QAction *> actions1 = actions(); |
247 | const QList<QAction *> childActions = findChildren<QAction *>(); |
248 | for (QAction *action : childActions) { |
249 | if (!actions1.contains(t: action)) |
250 | continue; |
251 | actions1.removeAll(t: action); |
252 | ordered.append(t: action); |
253 | } |
254 | |
255 | clear(); |
256 | addActions(actions: ordered); |
257 | |
258 | orderAction->setEnabled(false); |
259 | } |
260 | |
261 | void ToolBar::randomize() |
262 | { |
263 | QList<QAction *> randomized; |
264 | QList<QAction *> actions = this->actions(); |
265 | while (!actions.isEmpty()) { |
266 | QAction *action = actions.takeAt(i: QRandomGenerator::global()->bounded(highest: actions.size())); |
267 | randomized.append(t: action); |
268 | } |
269 | clear(); |
270 | addActions(actions: randomized); |
271 | |
272 | orderAction->setEnabled(true); |
273 | } |
274 | |
275 | void ToolBar::addSpinBox() |
276 | { |
277 | if (!spinbox) |
278 | spinbox = new QSpinBox(this); |
279 | if (!spinboxAction) |
280 | spinboxAction = addWidget(widget: spinbox); |
281 | else |
282 | addAction(action: spinboxAction); |
283 | |
284 | addSpinBoxAction->setEnabled(false); |
285 | removeSpinBoxAction->setEnabled(true); |
286 | } |
287 | |
288 | void ToolBar::removeSpinBox() |
289 | { |
290 | if (spinboxAction) |
291 | removeAction(action: spinboxAction); |
292 | |
293 | addSpinBoxAction->setEnabled(true); |
294 | removeSpinBoxAction->setEnabled(false); |
295 | } |
296 | |
297 | void ToolBar::allow(Qt::ToolBarArea area, bool a) |
298 | { |
299 | Qt::ToolBarAreas areas = allowedAreas(); |
300 | areas = a ? areas | area : areas & ~area; |
301 | setAllowedAreas(areas); |
302 | |
303 | if (areaActions->isEnabled()) { |
304 | leftAction->setEnabled(areas & Qt::LeftToolBarArea); |
305 | rightAction->setEnabled(areas & Qt::RightToolBarArea); |
306 | topAction->setEnabled(areas & Qt::TopToolBarArea); |
307 | bottomAction->setEnabled(areas & Qt::BottomToolBarArea); |
308 | } |
309 | } |
310 | |
311 | void ToolBar::place(Qt::ToolBarArea area, bool p) |
312 | { |
313 | if (!p) |
314 | return; |
315 | |
316 | QMainWindow *mainWindow = qobject_cast<QMainWindow *>(object: parentWidget()); |
317 | Q_ASSERT(mainWindow); |
318 | |
319 | mainWindow->addToolBar(area, toolbar: this); |
320 | |
321 | if (allowedAreasActions->isEnabled()) { |
322 | allowLeftAction->setEnabled(area != Qt::LeftToolBarArea); |
323 | allowRightAction->setEnabled(area != Qt::RightToolBarArea); |
324 | allowTopAction->setEnabled(area != Qt::TopToolBarArea); |
325 | allowBottomAction->setEnabled(area != Qt::BottomToolBarArea); |
326 | } |
327 | } |
328 | |
329 | void ToolBar::changeMovable(bool movable) |
330 | { setMovable(movable); } |
331 | |
332 | void ToolBar::allowLeft(bool a) |
333 | { allow(area: Qt::LeftToolBarArea, a); } |
334 | |
335 | void ToolBar::allowRight(bool a) |
336 | { allow(area: Qt::RightToolBarArea, a); } |
337 | |
338 | void ToolBar::allowTop(bool a) |
339 | { allow(area: Qt::TopToolBarArea, a); } |
340 | |
341 | void ToolBar::allowBottom(bool a) |
342 | { allow(area: Qt::BottomToolBarArea, a); } |
343 | |
344 | void ToolBar::placeLeft(bool p) |
345 | { place(area: Qt::LeftToolBarArea, p); } |
346 | |
347 | void ToolBar::placeRight(bool p) |
348 | { place(area: Qt::RightToolBarArea, p); } |
349 | |
350 | void ToolBar::placeTop(bool p) |
351 | { place(area: Qt::TopToolBarArea, p); } |
352 | |
353 | void ToolBar::placeBottom(bool p) |
354 | { place(area: Qt::BottomToolBarArea, p); } |
355 | |
356 | void ToolBar::insertToolBarBreak() |
357 | { |
358 | QMainWindow *mainWindow = qobject_cast<QMainWindow *>(object: parentWidget()); |
359 | Q_ASSERT(mainWindow); |
360 | |
361 | mainWindow->insertToolBarBreak(before: this); |
362 | } |
363 | |