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 <QActionGroup> |
56 | #include <QMainWindow> |
57 | #include <QMenu> |
58 | #include <QPainter> |
59 | #include <QPainterPath> |
60 | #include <QSpinBox> |
61 | #include <QLabel> |
62 | #include <QToolTip> |
63 | |
64 | #include <stdlib.h> |
65 | |
66 | static QPixmap genIcon(const QSize &iconSize, const QString &, const QColor &color, qreal pixelRatio) |
67 | { |
68 | int w = qRound(iconSize.width() * pixelRatio); |
69 | int h = qRound(iconSize.height() * pixelRatio); |
70 | |
71 | QImage image(w, h, QImage::Format_ARGB32_Premultiplied); |
72 | image.fill(0); |
73 | |
74 | QPainter p(&image); |
75 | |
76 | extern void render_qt_text(QPainter *, int, int, const QColor &); |
77 | render_qt_text(&p, w, h, color); |
78 | |
79 | QPixmap pm = QPixmap::fromImage(image, Qt::DiffuseDither | Qt::DiffuseAlphaDither); |
80 | pm.setDevicePixelRatio(pixelRatio); |
81 | return pm; |
82 | } |
83 | |
84 | static QPixmap genIcon(const QSize &iconSize, int number, const QColor &color, qreal pixelRatio) |
85 | { return genIcon(iconSize, QString::number(number), color, pixelRatio); } |
86 | |
87 | ToolBar::ToolBar(const QString &title, QWidget *parent) |
88 | : QToolBar(parent) |
89 | , spinbox(nullptr) |
90 | , spinboxAction(nullptr) |
91 | { |
92 | setWindowTitle(title); |
93 | setObjectName(title); |
94 | |
95 | setIconSize(QSize(32, 32)); |
96 | |
97 | qreal dpr = devicePixelRatio(); |
98 | menu = new QMenu("One" , this); |
99 | menu->setIcon(genIcon(iconSize(), 1, Qt::black, dpr)); |
100 | menu->addAction(genIcon(iconSize(), "A" , Qt::blue, dpr), "A" ); |
101 | menu->addAction(genIcon(iconSize(), "B" , Qt::blue, dpr), "B" ); |
102 | menu->addAction(genIcon(iconSize(), "C" , Qt::blue, dpr), "C" ); |
103 | addAction(menu->menuAction()); |
104 | |
105 | QAction *two = addAction(genIcon(iconSize(), 2, Qt::white, dpr), "Two" ); |
106 | QFont boldFont; |
107 | boldFont.setBold(true); |
108 | two->setFont(boldFont); |
109 | |
110 | addAction(genIcon(iconSize(), 3, Qt::red, dpr), "Three" ); |
111 | addAction(genIcon(iconSize(), 4, Qt::green, dpr), "Four" ); |
112 | addAction(genIcon(iconSize(), 5, Qt::blue, dpr), "Five" ); |
113 | addAction(genIcon(iconSize(), 6, Qt::yellow, dpr), "Six" ); |
114 | orderAction = new QAction(this); |
115 | orderAction->setText(tr("Order Items in Tool Bar" )); |
116 | connect(orderAction, &QAction::triggered, this, &ToolBar::order); |
117 | |
118 | randomizeAction = new QAction(this); |
119 | randomizeAction->setText(tr("Randomize Items in Tool Bar" )); |
120 | connect(randomizeAction, &QAction::triggered, this, &ToolBar::randomize); |
121 | |
122 | addSpinBoxAction = new QAction(this); |
123 | addSpinBoxAction->setText(tr("Add Spin Box" )); |
124 | connect(addSpinBoxAction, &QAction::triggered, this, &ToolBar::addSpinBox); |
125 | |
126 | removeSpinBoxAction = new QAction(this); |
127 | removeSpinBoxAction->setText(tr("Remove Spin Box" )); |
128 | removeSpinBoxAction->setEnabled(false); |
129 | connect(removeSpinBoxAction, &QAction::triggered, this, &ToolBar::removeSpinBox); |
130 | |
131 | movableAction = new QAction(tr("Movable" ), this); |
132 | movableAction->setCheckable(true); |
133 | connect(movableAction, &QAction::triggered, this, &ToolBar::changeMovable); |
134 | |
135 | allowedAreasActions = new QActionGroup(this); |
136 | allowedAreasActions->setExclusive(false); |
137 | |
138 | allowLeftAction = new QAction(tr("Allow on Left" ), this); |
139 | allowLeftAction->setCheckable(true); |
140 | connect(allowLeftAction, &QAction::triggered, this, &ToolBar::allowLeft); |
141 | |
142 | allowRightAction = new QAction(tr("Allow on Right" ), this); |
143 | allowRightAction->setCheckable(true); |
144 | connect(allowRightAction, &QAction::triggered, this, &ToolBar::allowRight); |
145 | |
146 | allowTopAction = new QAction(tr("Allow on Top" ), this); |
147 | allowTopAction->setCheckable(true); |
148 | connect(allowTopAction, &QAction::triggered, this, &ToolBar::allowTop); |
149 | |
150 | allowBottomAction = new QAction(tr("Allow on Bottom" ), this); |
151 | allowBottomAction->setCheckable(true); |
152 | connect(allowBottomAction, &QAction::triggered, this, &ToolBar::allowBottom); |
153 | |
154 | allowedAreasActions->addAction(allowLeftAction); |
155 | allowedAreasActions->addAction(allowRightAction); |
156 | allowedAreasActions->addAction(allowTopAction); |
157 | allowedAreasActions->addAction(allowBottomAction); |
158 | |
159 | areaActions = new QActionGroup(this); |
160 | areaActions->setExclusive(true); |
161 | |
162 | leftAction = new QAction(tr("Place on Left" ) , this); |
163 | leftAction->setCheckable(true); |
164 | connect(leftAction, &QAction::triggered, this, &ToolBar::placeLeft); |
165 | |
166 | rightAction = new QAction(tr("Place on Right" ) , this); |
167 | rightAction->setCheckable(true); |
168 | connect(rightAction, &QAction::triggered, this, &ToolBar::placeRight); |
169 | |
170 | topAction = new QAction(tr("Place on Top" ) , this); |
171 | topAction->setCheckable(true); |
172 | connect(topAction, &QAction::triggered, this, &ToolBar::placeTop); |
173 | |
174 | bottomAction = new QAction(tr("Place on Bottom" ) , this); |
175 | bottomAction->setCheckable(true); |
176 | connect(bottomAction, &QAction::triggered, this, &ToolBar::placeBottom); |
177 | |
178 | areaActions->addAction(leftAction); |
179 | areaActions->addAction(rightAction); |
180 | areaActions->addAction(topAction); |
181 | areaActions->addAction(bottomAction); |
182 | |
183 | connect(movableAction, &QAction::triggered, areaActions, &QActionGroup::setEnabled); |
184 | |
185 | connect(movableAction, &QAction::triggered, allowedAreasActions, &QActionGroup::setEnabled); |
186 | |
187 | menu = new QMenu(title, this); |
188 | menu->addAction(toggleViewAction()); |
189 | menu->addSeparator(); |
190 | menu->addAction(orderAction); |
191 | menu->addAction(randomizeAction); |
192 | menu->addSeparator(); |
193 | menu->addAction(addSpinBoxAction); |
194 | menu->addAction(removeSpinBoxAction); |
195 | menu->addSeparator(); |
196 | menu->addAction(movableAction); |
197 | menu->addSeparator(); |
198 | menu->addActions(allowedAreasActions->actions()); |
199 | menu->addSeparator(); |
200 | menu->addActions(areaActions->actions()); |
201 | menu->addSeparator(); |
202 | menu->addAction(tr("Insert break" ), this, &ToolBar::insertToolBarBreak); |
203 | |
204 | connect(menu, &QMenu::aboutToShow, this, &ToolBar::updateMenu); |
205 | |
206 | randomize(); |
207 | } |
208 | |
209 | void ToolBar::() |
210 | { |
211 | QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget()); |
212 | Q_ASSERT(mainWindow); |
213 | |
214 | const Qt::ToolBarArea area = mainWindow->toolBarArea(this); |
215 | const Qt::ToolBarAreas areas = allowedAreas(); |
216 | |
217 | movableAction->setChecked(isMovable()); |
218 | |
219 | allowLeftAction->setChecked(isAreaAllowed(Qt::LeftToolBarArea)); |
220 | allowRightAction->setChecked(isAreaAllowed(Qt::RightToolBarArea)); |
221 | allowTopAction->setChecked(isAreaAllowed(Qt::TopToolBarArea)); |
222 | allowBottomAction->setChecked(isAreaAllowed(Qt::BottomToolBarArea)); |
223 | |
224 | if (allowedAreasActions->isEnabled()) { |
225 | allowLeftAction->setEnabled(area != Qt::LeftToolBarArea); |
226 | allowRightAction->setEnabled(area != Qt::RightToolBarArea); |
227 | allowTopAction->setEnabled(area != Qt::TopToolBarArea); |
228 | allowBottomAction->setEnabled(area != Qt::BottomToolBarArea); |
229 | } |
230 | |
231 | leftAction->setChecked(area == Qt::LeftToolBarArea); |
232 | rightAction->setChecked(area == Qt::RightToolBarArea); |
233 | topAction->setChecked(area == Qt::TopToolBarArea); |
234 | bottomAction->setChecked(area == Qt::BottomToolBarArea); |
235 | |
236 | if (areaActions->isEnabled()) { |
237 | leftAction->setEnabled(areas & Qt::LeftToolBarArea); |
238 | rightAction->setEnabled(areas & Qt::RightToolBarArea); |
239 | topAction->setEnabled(areas & Qt::TopToolBarArea); |
240 | bottomAction->setEnabled(areas & Qt::BottomToolBarArea); |
241 | } |
242 | } |
243 | |
244 | void ToolBar::order() |
245 | { |
246 | QList<QAction *> ordered; |
247 | QList<QAction *> actions1 = actions(); |
248 | const QList<QAction *> childActions = findChildren<QAction *>(); |
249 | for (QAction *action : childActions) { |
250 | if (!actions1.contains(action)) |
251 | continue; |
252 | actions1.removeAll(action); |
253 | ordered.append(action); |
254 | } |
255 | |
256 | clear(); |
257 | addActions(ordered); |
258 | |
259 | orderAction->setEnabled(false); |
260 | } |
261 | |
262 | void ToolBar::randomize() |
263 | { |
264 | QList<QAction *> randomized; |
265 | QList<QAction *> actions = this->actions(); |
266 | while (!actions.isEmpty()) { |
267 | QAction *action = actions.takeAt(QRandomGenerator::global()->bounded(int(actions.size()))); |
268 | randomized.append(action); |
269 | } |
270 | clear(); |
271 | addActions(randomized); |
272 | |
273 | orderAction->setEnabled(true); |
274 | } |
275 | |
276 | void ToolBar::addSpinBox() |
277 | { |
278 | if (!spinbox) |
279 | spinbox = new QSpinBox(this); |
280 | if (!spinboxAction) |
281 | spinboxAction = addWidget(spinbox); |
282 | else |
283 | addAction(spinboxAction); |
284 | |
285 | addSpinBoxAction->setEnabled(false); |
286 | removeSpinBoxAction->setEnabled(true); |
287 | } |
288 | |
289 | void ToolBar::removeSpinBox() |
290 | { |
291 | if (spinboxAction) |
292 | removeAction(spinboxAction); |
293 | |
294 | addSpinBoxAction->setEnabled(true); |
295 | removeSpinBoxAction->setEnabled(false); |
296 | } |
297 | |
298 | void ToolBar::allow(Qt::ToolBarArea area, bool a) |
299 | { |
300 | Qt::ToolBarAreas areas = allowedAreas(); |
301 | areas = a ? areas | area : areas & ~area; |
302 | setAllowedAreas(areas); |
303 | |
304 | if (areaActions->isEnabled()) { |
305 | leftAction->setEnabled(areas & Qt::LeftToolBarArea); |
306 | rightAction->setEnabled(areas & Qt::RightToolBarArea); |
307 | topAction->setEnabled(areas & Qt::TopToolBarArea); |
308 | bottomAction->setEnabled(areas & Qt::BottomToolBarArea); |
309 | } |
310 | } |
311 | |
312 | void ToolBar::place(Qt::ToolBarArea area, bool p) |
313 | { |
314 | if (!p) |
315 | return; |
316 | |
317 | QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget()); |
318 | Q_ASSERT(mainWindow); |
319 | |
320 | mainWindow->addToolBar(area, this); |
321 | |
322 | if (allowedAreasActions->isEnabled()) { |
323 | allowLeftAction->setEnabled(area != Qt::LeftToolBarArea); |
324 | allowRightAction->setEnabled(area != Qt::RightToolBarArea); |
325 | allowTopAction->setEnabled(area != Qt::TopToolBarArea); |
326 | allowBottomAction->setEnabled(area != Qt::BottomToolBarArea); |
327 | } |
328 | } |
329 | |
330 | void ToolBar::changeMovable(bool movable) |
331 | { setMovable(movable); } |
332 | |
333 | void ToolBar::allowLeft(bool a) |
334 | { allow(Qt::LeftToolBarArea, a); } |
335 | |
336 | void ToolBar::allowRight(bool a) |
337 | { allow(Qt::RightToolBarArea, a); } |
338 | |
339 | void ToolBar::allowTop(bool a) |
340 | { allow(Qt::TopToolBarArea, a); } |
341 | |
342 | void ToolBar::allowBottom(bool a) |
343 | { allow(Qt::BottomToolBarArea, a); } |
344 | |
345 | void ToolBar::placeLeft(bool p) |
346 | { place(Qt::LeftToolBarArea, p); } |
347 | |
348 | void ToolBar::placeRight(bool p) |
349 | { place(Qt::RightToolBarArea, p); } |
350 | |
351 | void ToolBar::placeTop(bool p) |
352 | { place(Qt::TopToolBarArea, p); } |
353 | |
354 | void ToolBar::placeBottom(bool p) |
355 | { place(Qt::BottomToolBarArea, p); } |
356 | |
357 | void ToolBar::insertToolBarBreak() |
358 | { |
359 | QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parentWidget()); |
360 | Q_ASSERT(mainWindow); |
361 | |
362 | mainWindow->insertToolBarBreak(this); |
363 | } |
364 | |