1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qapplication.h>
5#include <qaction.h>
6#include <qwidgetaction.h>
7#include <qtoolbar.h>
8#include <qstyleoption.h>
9#if QT_CONFIG(toolbutton)
10#include <qtoolbutton.h>
11#endif
12#include <qmenu.h>
13#include <qdebug.h>
14#include <qmath.h>
15#ifdef Q_OS_MACOS
16#include <qpa/qplatformnativeinterface.h>
17#endif
18
19#include "qmainwindowlayout_p.h"
20#if QT_CONFIG(toolbutton)
21#include "qtoolbarextension_p.h"
22#endif
23#include "qtoolbarlayout_p.h"
24#include "qtoolbarseparator_p.h"
25
26QT_BEGIN_NAMESPACE
27
28// qmainwindow.cpp
29extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
30
31/******************************************************************************
32** QToolBarItem
33*/
34
35QToolBarItem::QToolBarItem(QWidget *widget)
36 : QWidgetItem(widget), action(nullptr), customWidget(false)
37{
38}
39
40bool QToolBarItem::isEmpty() const
41{
42 return action == nullptr || !action->isVisible();
43}
44
45/******************************************************************************
46** QToolBarLayout
47*/
48
49QToolBarLayout::QToolBarLayout(QWidget *parent)
50 : QLayout(parent), expanded(false), animating(false), dirty(true),
51 expanding(false), empty(true), expandFlag(false), popupMenu(nullptr)
52{
53 QToolBar *tb = qobject_cast<QToolBar*>(object: parent);
54 if (!tb)
55 return;
56
57 extension = new QToolBarExtension(tb);
58 extension->setFocusPolicy(Qt::NoFocus);
59 extension->hide();
60 QObject::connect(sender: tb, SIGNAL(orientationChanged(Qt::Orientation)),
61 receiver: extension, SLOT(setOrientation(Qt::Orientation)));
62
63 setUsePopupMenu(qobject_cast<QMainWindow*>(object: tb->parentWidget()) == 0);
64}
65
66QToolBarLayout::~QToolBarLayout()
67{
68 while (!items.isEmpty()) {
69 QToolBarItem *item = items.takeFirst();
70 if (QWidgetAction *widgetAction = qobject_cast<QWidgetAction*>(object: item->action)) {
71 if (item->customWidget)
72 widgetAction->releaseWidget(widget: item->widget());
73 }
74 delete item;
75 }
76}
77
78void QToolBarLayout::updateMarginAndSpacing()
79{
80 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
81 if (!tb)
82 return;
83 QStyle *style = tb->style();
84 QStyleOptionToolBar opt;
85 tb->initStyleOption(option: &opt);
86 const int margin = style->pixelMetric(metric: QStyle::PM_ToolBarItemMargin, option: &opt, widget: tb)
87 + style->pixelMetric(metric: QStyle::PM_ToolBarFrameWidth, option: &opt, widget: tb);
88 setContentsMargins(left: margin, top: margin, right: margin, bottom: margin);
89 setSpacing(style->pixelMetric(metric: QStyle::PM_ToolBarItemSpacing, option: &opt, widget: tb));
90}
91
92bool QToolBarLayout::hasExpandFlag() const
93{
94 return expandFlag;
95}
96
97void QToolBarLayout::setUsePopupMenu(bool set)
98{
99 if (!dirty && ((popupMenu == nullptr) == set))
100 invalidate();
101 if (!set) {
102 QObject::connect(sender: extension, SIGNAL(clicked(bool)),
103 receiver: this, SLOT(setExpanded(bool)), Qt::UniqueConnection);
104 extension->setPopupMode(QToolButton::DelayedPopup);
105 extension->setMenu(nullptr);
106 delete popupMenu;
107 popupMenu = nullptr;
108 } else {
109 QObject::disconnect(sender: extension, SIGNAL(clicked(bool)),
110 receiver: this, SLOT(setExpanded(bool)));
111 extension->setPopupMode(QToolButton::InstantPopup);
112 if (!popupMenu) {
113 popupMenu = new QMenu(extension);
114 }
115 extension->setMenu(popupMenu);
116 }
117}
118
119void QToolBarLayout::checkUsePopupMenu()
120{
121 QToolBar *tb = static_cast<QToolBar *>(parent());
122 QMainWindow *mw = qobject_cast<QMainWindow *>(object: tb->parent());
123 Qt::Orientation o = tb->orientation();
124 setUsePopupMenu(!mw || tb->isFloating() || perp(o, size: expandedSize(size: mw->size())) >= perp(o, size: mw->size()));
125}
126
127void QToolBarLayout::addItem(QLayoutItem*)
128{
129 qWarning(msg: "QToolBarLayout::addItem(): please use addAction() instead");
130 return;
131}
132
133QLayoutItem *QToolBarLayout::itemAt(int index) const
134{
135 if (index < 0 || index >= items.size())
136 return nullptr;
137 return items.at(i: index);
138}
139
140QLayoutItem *QToolBarLayout::takeAt(int index)
141{
142 if (index < 0 || index >= items.size())
143 return nullptr;
144 QToolBarItem *item = items.takeAt(i: index);
145
146 if (popupMenu)
147 popupMenu->removeAction(action: item->action);
148
149 QWidgetAction *widgetAction = qobject_cast<QWidgetAction*>(object: item->action);
150 if (widgetAction != nullptr && item->customWidget) {
151 widgetAction->releaseWidget(widget: item->widget());
152 } else {
153 // destroy the QToolButton/QToolBarSeparator
154 item->widget()->hide();
155 item->widget()->deleteLater();
156 }
157
158 invalidate();
159 return item;
160}
161
162void QToolBarLayout::insertAction(int index, QAction *action)
163{
164 index = qMax(a: 0, b: index);
165 index = qMin(a: items.size(), b: index);
166
167 QToolBarItem *item = createItem(action);
168 if (item) {
169 items.insert(i: index, t: item);
170 invalidate();
171 }
172}
173
174int QToolBarLayout::indexOf(const QAction *action) const
175{
176 for (int i = 0; i < items.size(); ++i) {
177 if (items.at(i)->action == action)
178 return i;
179 }
180 return -1;
181}
182
183int QToolBarLayout::count() const
184{
185 return items.size();
186}
187
188bool QToolBarLayout::isEmpty() const
189{
190 if (dirty)
191 updateGeomArray();
192 return empty;
193}
194
195void QToolBarLayout::invalidate()
196{
197 dirty = true;
198 QLayout::invalidate();
199}
200
201Qt::Orientations QToolBarLayout::expandingDirections() const
202{
203 if (dirty)
204 updateGeomArray();
205 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
206 if (!tb)
207 return {};
208 Qt::Orientation o = tb->orientation();
209 return expanding ? Qt::Orientations(o) : Qt::Orientations{};
210}
211
212bool QToolBarLayout::movable() const
213{
214 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
215 if (!tb)
216 return false;
217 QMainWindow *win = qobject_cast<QMainWindow*>(object: tb->parentWidget());
218 return tb->isMovable() && win != nullptr;
219}
220
221void QToolBarLayout::updateGeomArray() const
222{
223 if (!dirty)
224 return;
225
226 QToolBarLayout *that = const_cast<QToolBarLayout*>(this);
227
228 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
229 if (!tb)
230 return;
231 QStyle *style = tb->style();
232 QStyleOptionToolBar opt;
233 tb->initStyleOption(option: &opt);
234 const int handleExtent = movable()
235 ? style->pixelMetric(metric: QStyle::PM_ToolBarHandleExtent, option: &opt, widget: tb) : 0;
236 const QMargins margins = contentsMargins();
237 const int spacing = this->spacing();
238 const int extensionExtent = style->pixelMetric(metric: QStyle::PM_ToolBarExtensionExtent, option: &opt, widget: tb);
239 Qt::Orientation o = tb->orientation();
240
241 that->minSize = QSize(0, 0);
242 that->hint = QSize(0, 0);
243 rperp(o, size&: that->minSize) = style->pixelMetric(metric: QStyle::PM_ToolBarHandleExtent, option: &opt, widget: tb);
244 rperp(o, size&: that->hint) = style->pixelMetric(metric: QStyle::PM_ToolBarHandleExtent, option: &opt, widget: tb);
245
246 that->expanding = false;
247 that->empty = false;
248
249 QList<QLayoutStruct> a(items.size() + 1); // + 1 for the stretch
250
251 int count = 0;
252 for (int i = 0; i < items.size(); ++i) {
253 QToolBarItem *item = items.at(i);
254
255 QSize max = item->maximumSize();
256 QSize min = item->minimumSize();
257 QSize hint = item->sizeHint();
258 Qt::Orientations exp = item->expandingDirections();
259 bool empty = item->isEmpty();
260
261 that->expanding = expanding || exp & o;
262
263
264 if (item->widget()) {
265 if ((item->widget()->sizePolicy().horizontalPolicy() & QSizePolicy::ExpandFlag)) {
266 that->expandFlag = true;
267 }
268 }
269
270 if (!empty) {
271 if (count == 0) // the minimum size only displays one widget
272 rpick(o, size&: that->minSize) += pick(o, size: min);
273 int s = perp(o, size: minSize);
274 rperp(o, size&: that->minSize) = qMax(a: s, b: perp(o, size: min));
275
276 //we only add spacing before item (ie never before the first one)
277 rpick(o, size&: that->hint) += (count == 0 ? 0 : spacing) + pick(o, size: hint);
278 s = perp(o, size: that->hint);
279 rperp(o, size&: that->hint) = qMax(a: s, b: perp(o, size: hint));
280 ++count;
281 }
282
283 a[i].sizeHint = pick(o, size: hint);
284 a[i].maximumSize = pick(o, size: max);
285 a[i].minimumSize = pick(o, size: min);
286 a[i].expansive = exp & o;
287 if (o == Qt::Horizontal)
288 a[i].stretch = item->widget()->sizePolicy().horizontalStretch();
289 else
290 a[i].stretch = item->widget()->sizePolicy().verticalStretch();
291 a[i].empty = empty;
292 }
293
294 that->geomArray = a;
295 that->empty = count == 0;
296
297 rpick(o, size&: that->minSize) += handleExtent;
298 that->minSize += QSize(pick(o: Qt::Horizontal, m: margins), pick(o: Qt::Vertical, m: margins));
299 if (items.size() > 1)
300 rpick(o, size&: that->minSize) += spacing + extensionExtent;
301
302 rpick(o, size&: that->hint) += handleExtent;
303 that->hint += QSize(pick(o: Qt::Horizontal, m: margins), pick(o: Qt::Vertical, m: margins));
304 that->dirty = false;
305}
306
307static bool defaultWidgetAction(QToolBarItem *item)
308{
309 QWidgetAction *a = qobject_cast<QWidgetAction*>(object: item->action);
310 return a != nullptr && a->defaultWidget() == item->widget();
311}
312
313void QToolBarLayout::updateMacBorderMetrics()
314{
315#ifdef Q_OS_MACOS
316 QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
317 if (!tb)
318 return;
319
320 QRect rect = geometry();
321
322 QMainWindow *mainWindow = qobject_cast<QMainWindow*>(tb->parentWidget());
323 if (!mainWindow || !mainWindow->isWindow() || !mainWindow->unifiedTitleAndToolBarOnMac())
324 return;
325
326 QPlatformNativeInterface *nativeInterface = QApplication::platformNativeInterface();
327 if (!nativeInterface)
328 return; // Not Cocoa platform plugin.
329 QPlatformNativeInterface::NativeResourceForIntegrationFunction function =
330 nativeInterface->nativeResourceFunctionForIntegration("registerContentBorderArea");
331 if (!function)
332 return; // Not Cocoa platform plugin.
333
334 QPoint upper = tb->mapToParent(rect.topLeft());
335 QPoint lower = tb->mapToParent(rect.bottomLeft() + QPoint(0, 1));
336
337 typedef void (*RegisterContentBorderAreaFunction)(QWindow *window, void *identifier, int upper, int lower);
338 if (mainWindow->toolBarArea(tb) == Qt::TopToolBarArea) {
339 (reinterpret_cast<RegisterContentBorderAreaFunction>(function))(tb->window()->windowHandle(), tb, upper.y(), lower.y());
340 } else {
341 (reinterpret_cast<RegisterContentBorderAreaFunction>(function))(tb->window()->windowHandle(), tb, 0, 0);
342 }
343#endif
344}
345
346void QToolBarLayout::setGeometry(const QRect &rect)
347{
348 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
349 if (!tb)
350 return;
351 QStyle *style = tb->style();
352 QStyleOptionToolBar opt;
353 tb->initStyleOption(option: &opt);
354 const QMargins margins = contentsMargins();
355 const int extensionExtent = style->pixelMetric(metric: QStyle::PM_ToolBarExtensionExtent, option: &opt, widget: tb);
356 Qt::Orientation o = tb->orientation();
357
358 QLayout::setGeometry(rect);
359
360 updateMacBorderMetrics();
361
362 bool ranOutOfSpace = false;
363 if (!animating)
364 ranOutOfSpace = layoutActions(size: rect.size());
365
366 if (expanded || animating || ranOutOfSpace) {
367 Qt::ToolBarArea area = Qt::TopToolBarArea;
368 if (QMainWindow *win = qobject_cast<QMainWindow*>(object: tb->parentWidget()))
369 area = win->toolBarArea(toolbar: tb);
370 QSize hint = sizeHint();
371
372 QPoint pos;
373 rpick(o, pos) = pick(o, pos: rect.bottomRight()) -
374 pick(o, size: QSize(margins.bottom(), margins.right())) - extensionExtent + 2;
375 if (area == Qt::LeftToolBarArea || area == Qt::TopToolBarArea)
376 rperp(o, pos) = perp(o, pos: rect.topLeft()) +
377 perp(o, size: QSize(margins.top(), margins.left()));
378 else
379 rperp(o, pos) = perp(o, pos: rect.bottomRight()) -
380 perp(o, size: QSize(margins.bottom(), margins.right())) -
381 (perp(o, size: hint) - perp(o, m: margins)) + 1;
382 QSize size;
383 rpick(o, size) = extensionExtent;
384 rperp(o, size) = perp(o, size: hint) - perp(o, m: margins);
385 QRect r(pos, size);
386
387 if (o == Qt::Horizontal)
388 r = QStyle::visualRect(direction: parentWidget()->layoutDirection(), boundingRect: rect, logicalRect: r);
389
390 extension->setGeometry(r);
391
392 if (extension->isHidden())
393 extension->show();
394 } else {
395 if (!extension->isHidden())
396 extension->hide();
397 }
398}
399
400bool QToolBarLayout::layoutActions(const QSize &size)
401{
402 if (dirty)
403 updateGeomArray();
404
405 QRect rect(0, 0, size.width(), size.height());
406
407 QList<QWidget*> showWidgets, hideWidgets;
408
409 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
410 if (!tb)
411 return false;
412 QStyle *style = tb->style();
413 QStyleOptionToolBar opt;
414 tb->initStyleOption(option: &opt);
415 const int handleExtent = movable()
416 ? style->pixelMetric(metric: QStyle::PM_ToolBarHandleExtent, option: &opt, widget: tb) : 0;
417 const QMargins margins = contentsMargins();
418 const int spacing = this->spacing();
419 const int extensionExtent = style->pixelMetric(metric: QStyle::PM_ToolBarExtensionExtent, option: &opt, widget: tb);
420 Qt::Orientation o = tb->orientation();
421 bool extensionMenuContainsOnlyWidgetActions = true;
422
423 int space = pick(o, size: rect.size()) - pick(o, m: margins) - handleExtent;
424 if (space <= 0)
425 return false; // nothing to do.
426
427 if (popupMenu)
428 popupMenu->clear();
429
430 bool ranOutOfSpace = false;
431 int rows = 0;
432 int rowPos = perp(o, pos: rect.topLeft()) + perp(o, size: QSize(margins.top(), margins.left()));
433 int i = 0;
434 while (i < items.size()) {
435 QList<QLayoutStruct> a = geomArray;
436
437 int start = i;
438 int size = 0;
439 int prev = -1;
440 int rowHeight = 0;
441 int count = 0;
442 int maximumSize = 0;
443 bool expansiveRow = false;
444 for (; i < items.size(); ++i) {
445 if (a[i].empty)
446 continue;
447
448 int newSize = size + (count == 0 ? 0 : spacing) + a[i].minimumSize;
449 if (prev != -1 && newSize > space) {
450 if (rows == 0)
451 ranOutOfSpace = true;
452 // do we have to move the previous item to the next line to make space for
453 // the extension button?
454 if (count > 1 && size + spacing + extensionExtent > space)
455 i = prev;
456 break;
457 }
458
459 if (expanded)
460 rowHeight = qMax(a: rowHeight, b: perp(o, size: items.at(i)->sizeHint()));
461 expansiveRow = expansiveRow || a[i].expansive;
462 size = newSize;
463 maximumSize += spacing + (a[i].expansive ? a[i].maximumSize : a[i].smartSizeHint());
464 prev = i;
465 ++count;
466 }
467
468 // stretch at the end
469 a[i].sizeHint = 0;
470 a[i].maximumSize = QWIDGETSIZE_MAX;
471 a[i].minimumSize = 0;
472 a[i].expansive = true;
473 a[i].stretch = 0;
474 a[i].empty = true;
475
476 if (expansiveRow && maximumSize < space) {
477 expansiveRow = false;
478 a[i].maximumSize = space - maximumSize;
479 }
480
481 qGeomCalc(chain&: a, start, count: i - start + (expansiveRow ? 0 : 1), pos: 0,
482 space: space - (ranOutOfSpace ? (extensionExtent + spacing) : 0),
483 spacer: spacing);
484
485 for (int j = start; j < i; ++j) {
486 QToolBarItem *item = items.at(i: j);
487
488 if (a[j].empty) {
489 if (!item->widget()->isHidden())
490 hideWidgets << item->widget();
491 continue;
492 }
493
494 QPoint pos;
495 rpick(o, pos) = pick(o, size: QSize(margins.top(), margins.left())) + handleExtent + a[j].pos;
496 rperp(o, pos) = rowPos;
497 QSize size;
498 rpick(o, size) = a[j].size;
499 if (expanded)
500 rperp(o, size) = rowHeight;
501 else
502 rperp(o, size) = perp(o, size: rect.size()) - perp(o, m: margins);
503 QRect r(pos, size);
504
505 if (o == Qt::Horizontal)
506 r = QStyle::visualRect(direction: parentWidget()->layoutDirection(), boundingRect: rect, logicalRect: r);
507
508 item->setGeometry(r);
509
510 if (item->widget()->isHidden())
511 showWidgets << item->widget();
512 }
513
514 if (!expanded) {
515 for (int j = i; j < items.size(); ++j) {
516 QToolBarItem *item = items.at(i: j);
517 if (!item->widget()->isHidden())
518 hideWidgets << item->widget();
519 if (popupMenu) {
520 if (!defaultWidgetAction(item)) {
521 popupMenu->addAction(action: item->action);
522 extensionMenuContainsOnlyWidgetActions = false;
523 }
524 }
525 }
526 break;
527 }
528
529 rowPos += rowHeight + spacing;
530 ++rows;
531 }
532
533 // if we are using a popup menu, not the expadning toolbar effect, we cannot move custom
534 // widgets into the menu. If only custom widget actions are chopped off, the popup menu
535 // is empty. So we show the little extension button to show something is chopped off,
536 // but we make it disabled.
537 extension->setEnabled(popupMenu == nullptr || !extensionMenuContainsOnlyWidgetActions);
538
539 // we have to do the show/hide here, because it triggers more calls to setGeometry :(
540 for (int i = 0; i < showWidgets.size(); ++i)
541 showWidgets.at(i)->show();
542 for (int i = 0; i < hideWidgets.size(); ++i)
543 hideWidgets.at(i)->hide();
544
545 return ranOutOfSpace;
546}
547
548QSize QToolBarLayout::expandedSize(const QSize &size) const
549{
550 if (dirty)
551 updateGeomArray();
552
553 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
554 if (!tb)
555 return QSize(0, 0);
556 QMainWindow *win = qobject_cast<QMainWindow*>(object: tb->parentWidget());
557 Qt::Orientation o = tb->orientation();
558 QStyle *style = tb->style();
559 QStyleOptionToolBar opt;
560 tb->initStyleOption(option: &opt);
561 const int handleExtent = movable()
562 ? style->pixelMetric(metric: QStyle::PM_ToolBarHandleExtent, option: &opt, widget: tb) : 0;
563 const QMargins margins = contentsMargins();
564 const int spacing = this->spacing();
565 const int extensionExtent = style->pixelMetric(metric: QStyle::PM_ToolBarExtensionExtent, option: &opt, widget: tb);
566
567 int total_w = 0;
568 int count = 0;
569 for (int x = 0; x < items.size(); ++x) {
570 if (!geomArray[x].empty) {
571 total_w += (count == 0 ? 0 : spacing) + geomArray[x].minimumSize;
572 ++count;
573 }
574 }
575 if (count == 0)
576 return QSize(0, 0);
577
578 int min_w = pick(o, size);
579 int rows = (int)qSqrt(v: qreal(count));
580 if (rows == 1)
581 ++rows; // we want to expand to at least two rows
582 int space = total_w/rows + spacing + extensionExtent;
583 space = qMax(a: space, b: min_w - pick(o, m: margins) - handleExtent);
584 if (win != nullptr)
585 space = qMin(a: space, b: pick(o, size: win->size()) - pick(o, m: margins) - handleExtent);
586
587 int w = 0;
588 int h = 0;
589 int i = 0;
590 while (i < items.size()) {
591 int count = 0;
592 int size = 0;
593 int prev = -1;
594 int rowHeight = 0;
595 for (; i < items.size(); ++i) {
596 if (geomArray[i].empty)
597 continue;
598
599 int newSize = size + (count == 0 ? 0 : spacing) + geomArray[i].minimumSize;
600 rowHeight = qMax(a: rowHeight, b: perp(o, size: items.at(i)->sizeHint()));
601 if (prev != -1 && newSize > space) {
602 if (count > 1 && size + spacing + extensionExtent > space) {
603 size -= spacing + geomArray[prev].minimumSize;
604 i = prev;
605 }
606 break;
607 }
608
609 size = newSize;
610 prev = i;
611 ++count;
612 }
613
614 w = qMax(a: size, b: w);
615 h += rowHeight + spacing;
616 }
617
618 w += pick(o: Qt::Horizontal, m: margins) + handleExtent + spacing + extensionExtent;
619 w = qMax(a: w, b: min_w);
620 if (win != nullptr)
621 w = qMin(a: w, b: pick(o, size: win->size()));
622 h += pick(o: Qt::Vertical, m: margins) - spacing; //there is no spacing before the first row
623
624 QSize result;
625 rpick(o, size&: result) = w;
626 rperp(o, size&: result) = h;
627 return result;
628}
629
630void QToolBarLayout::setExpanded(bool exp)
631{
632 QWidget *tb = qobject_cast<QToolBar*>(object: parentWidget());
633 if (!tb)
634 return;
635 if (exp == expanded && !tb->isWindow())
636 return;
637
638 expanded = exp;
639 extension->setChecked(expanded);
640
641 if (QMainWindow *win = qobject_cast<QMainWindow*>(object: tb->parentWidget())) {
642#if !QT_CONFIG(dockwidget)
643 animating = false;
644#else
645 animating = !tb->isWindow() && win->isAnimated();
646#endif
647 QMainWindowLayout *layout = qt_mainwindow_layout(window: win);
648 if (expanded) {
649 tb->raise();
650 } else {
651 QList<int> path = layout->layoutState.indexOf(widget: tb);
652 if (!path.isEmpty()) {
653 QRect rect = layout->layoutState.itemRect(path);
654 layoutActions(size: rect.size());
655 }
656 }
657 layout->layoutState.toolBarAreaLayout.apply(animate: animating);
658 }
659}
660
661QSize QToolBarLayout::minimumSize() const
662{
663 if (dirty)
664 updateGeomArray();
665 return minSize;
666}
667
668QSize QToolBarLayout::sizeHint() const
669{
670 if (dirty)
671 updateGeomArray();
672 return hint;
673}
674
675QToolBarItem *QToolBarLayout::createItem(QAction *action)
676{
677 bool customWidget = false;
678 bool standardButtonWidget = false;
679 QWidget *widget = nullptr;
680 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
681 if (!tb)
682 return (QToolBarItem *)nullptr;
683
684 if (QWidgetAction *widgetAction = qobject_cast<QWidgetAction *>(object: action)) {
685 widget = widgetAction->requestWidget(parent: tb);
686 if (widget != nullptr) {
687 widget->setAttribute(Qt::WA_LayoutUsesWidgetRect);
688 customWidget = true;
689 }
690 } else if (action->isSeparator()) {
691 QToolBarSeparator *sep = new QToolBarSeparator(tb);
692 connect(sender: tb, SIGNAL(orientationChanged(Qt::Orientation)),
693 receiver: sep, SLOT(setOrientation(Qt::Orientation)));
694 widget = sep;
695 }
696
697 if (!widget) {
698 QToolButton *button = new QToolButton(tb);
699 button->setAutoRaise(true);
700 button->setFocusPolicy(Qt::NoFocus);
701 button->setIconSize(tb->iconSize());
702 button->setToolButtonStyle(tb->toolButtonStyle());
703 QObject::connect(sender: tb, SIGNAL(iconSizeChanged(QSize)),
704 receiver: button, SLOT(setIconSize(QSize)));
705 QObject::connect(sender: tb, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
706 receiver: button, SLOT(setToolButtonStyle(Qt::ToolButtonStyle)));
707 button->setDefaultAction(action);
708 QObject::connect(sender: button, SIGNAL(triggered(QAction*)), receiver: tb, SIGNAL(actionTriggered(QAction*)));
709 widget = button;
710 standardButtonWidget = true;
711 }
712
713 widget->hide();
714 QToolBarItem *result = new QToolBarItem(widget);
715 if (standardButtonWidget)
716 result->setAlignment(Qt::AlignJustify);
717 result->customWidget = customWidget;
718 result->action = action;
719 return result;
720}
721
722QT_END_NAMESPACE
723
724#include "moc_qtoolbarlayout_p.cpp"
725

source code of qtbase/src/widgets/widgets/qtoolbarlayout.cpp