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>(QFunctionPointer(function)))(
340 tb->window()->windowHandle(), tb, upper.y(), lower.y());
341 } else {
342 (reinterpret_cast<RegisterContentBorderAreaFunction>(QFunctionPointer(function)))(
343 tb->window()->windowHandle(), tb, 0, 0);
344 }
345#endif
346}
347
348void QToolBarLayout::setGeometry(const QRect &rect)
349{
350 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
351 if (!tb)
352 return;
353 QStyle *style = tb->style();
354 QStyleOptionToolBar opt;
355 tb->initStyleOption(option: &opt);
356 const QMargins margins = contentsMargins();
357 const int extensionExtent = style->pixelMetric(metric: QStyle::PM_ToolBarExtensionExtent, option: &opt, widget: tb);
358 Qt::Orientation o = tb->orientation();
359
360 QLayout::setGeometry(rect);
361
362 updateMacBorderMetrics();
363
364 bool ranOutOfSpace = false;
365 if (!animating)
366 ranOutOfSpace = layoutActions(size: rect.size());
367
368 if (expanded || animating || ranOutOfSpace) {
369 Qt::ToolBarArea area = Qt::TopToolBarArea;
370 if (QMainWindow *win = qobject_cast<QMainWindow*>(object: tb->parentWidget()))
371 area = win->toolBarArea(toolbar: tb);
372 QSize hint = sizeHint();
373
374 QPoint pos;
375 rpick(o, pos) = pick(o, pos: rect.bottomRight()) -
376 pick(o, size: QSize(margins.bottom(), margins.right())) - extensionExtent + 2;
377 if (area == Qt::LeftToolBarArea || area == Qt::TopToolBarArea)
378 rperp(o, pos) = perp(o, pos: rect.topLeft()) +
379 perp(o, size: QSize(margins.top(), margins.left()));
380 else
381 rperp(o, pos) = perp(o, pos: rect.bottomRight()) -
382 perp(o, size: QSize(margins.bottom(), margins.right())) -
383 (perp(o, size: hint) - perp(o, m: margins)) + 1;
384 QSize size;
385 rpick(o, size) = extensionExtent;
386 rperp(o, size) = perp(o, size: hint) - perp(o, m: margins);
387 QRect r(pos, size);
388
389 if (o == Qt::Horizontal)
390 r = QStyle::visualRect(direction: parentWidget()->layoutDirection(), boundingRect: rect, logicalRect: r);
391
392 extension->setGeometry(r);
393
394 if (extension->isHidden())
395 extension->show();
396 } else {
397 if (!extension->isHidden())
398 extension->hide();
399 }
400}
401
402bool QToolBarLayout::layoutActions(const QSize &size)
403{
404 if (dirty)
405 updateGeomArray();
406
407 QRect rect(0, 0, size.width(), size.height());
408
409 QList<QWidget*> showWidgets, hideWidgets;
410
411 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
412 if (!tb)
413 return false;
414 QStyle *style = tb->style();
415 QStyleOptionToolBar opt;
416 tb->initStyleOption(option: &opt);
417 const int handleExtent = movable()
418 ? style->pixelMetric(metric: QStyle::PM_ToolBarHandleExtent, option: &opt, widget: tb) : 0;
419 const QMargins margins = contentsMargins();
420 const int spacing = this->spacing();
421 const int extensionExtent = style->pixelMetric(metric: QStyle::PM_ToolBarExtensionExtent, option: &opt, widget: tb);
422 Qt::Orientation o = tb->orientation();
423 bool extensionMenuContainsOnlyWidgetActions = true;
424
425 int space = pick(o, size: rect.size()) - pick(o, m: margins) - handleExtent;
426 if (space <= 0)
427 return false; // nothing to do.
428
429 if (popupMenu)
430 popupMenu->clear();
431
432 bool ranOutOfSpace = false;
433 int rows = 0;
434 int rowPos = perp(o, pos: rect.topLeft()) + perp(o, size: QSize(margins.top(), margins.left()));
435 int i = 0;
436 while (i < items.size()) {
437 QList<QLayoutStruct> a = geomArray;
438
439 int start = i;
440 int size = 0;
441 int prev = -1;
442 int rowHeight = 0;
443 int count = 0;
444 int maximumSize = 0;
445 bool expansiveRow = false;
446 for (; i < items.size(); ++i) {
447 if (a[i].empty)
448 continue;
449
450 int newSize = size + (count == 0 ? 0 : spacing) + a[i].minimumSize;
451 if (prev != -1 && newSize > space) {
452 if (rows == 0)
453 ranOutOfSpace = true;
454 // do we have to move the previous item to the next line to make space for
455 // the extension button?
456 if (count > 1 && size + spacing + extensionExtent > space)
457 i = prev;
458 break;
459 }
460
461 if (expanded)
462 rowHeight = qMax(a: rowHeight, b: perp(o, size: items.at(i)->sizeHint()));
463 expansiveRow = expansiveRow || a[i].expansive;
464 size = newSize;
465 maximumSize += spacing + (a[i].expansive ? a[i].maximumSize : a[i].smartSizeHint());
466 prev = i;
467 ++count;
468 }
469
470 // stretch at the end
471 a[i].sizeHint = 0;
472 a[i].maximumSize = QWIDGETSIZE_MAX;
473 a[i].minimumSize = 0;
474 a[i].expansive = true;
475 a[i].stretch = 0;
476 a[i].empty = true;
477
478 if (expansiveRow && maximumSize < space) {
479 expansiveRow = false;
480 a[i].maximumSize = space - maximumSize;
481 }
482
483 qGeomCalc(chain&: a, start, count: i - start + (expansiveRow ? 0 : 1), pos: 0,
484 space: space - (ranOutOfSpace ? (extensionExtent + spacing) : 0),
485 spacer: spacing);
486
487 for (int j = start; j < i; ++j) {
488 QToolBarItem *item = items.at(i: j);
489
490 if (a[j].empty) {
491 if (!item->widget()->isHidden())
492 hideWidgets << item->widget();
493 continue;
494 }
495
496 QPoint pos;
497 rpick(o, pos) = pick(o, size: QSize(margins.top(), margins.left())) + handleExtent + a[j].pos;
498 rperp(o, pos) = rowPos;
499 QSize size;
500 rpick(o, size) = a[j].size;
501 if (expanded)
502 rperp(o, size) = rowHeight;
503 else
504 rperp(o, size) = perp(o, size: rect.size()) - perp(o, m: margins);
505 QRect r(pos, size);
506
507 if (o == Qt::Horizontal)
508 r = QStyle::visualRect(direction: parentWidget()->layoutDirection(), boundingRect: rect, logicalRect: r);
509
510 item->setGeometry(r);
511
512 if (item->widget()->isHidden())
513 showWidgets << item->widget();
514 }
515
516 if (!expanded) {
517 for (int j = i; j < items.size(); ++j) {
518 QToolBarItem *item = items.at(i: j);
519 if (!item->widget()->isHidden())
520 hideWidgets << item->widget();
521 if (popupMenu) {
522 if (!defaultWidgetAction(item)) {
523 popupMenu->addAction(action: item->action);
524 extensionMenuContainsOnlyWidgetActions = false;
525 }
526 }
527 }
528 break;
529 }
530
531 rowPos += rowHeight + spacing;
532 ++rows;
533 }
534
535 // if we are using a popup menu, not the expadning toolbar effect, we cannot move custom
536 // widgets into the menu. If only custom widget actions are chopped off, the popup menu
537 // is empty. So we show the little extension button to show something is chopped off,
538 // but we make it disabled.
539 extension->setEnabled(popupMenu == nullptr || !extensionMenuContainsOnlyWidgetActions);
540
541 // we have to do the show/hide here, because it triggers more calls to setGeometry :(
542 for (int i = 0; i < showWidgets.size(); ++i)
543 showWidgets.at(i)->show();
544 for (int i = 0; i < hideWidgets.size(); ++i)
545 hideWidgets.at(i)->hide();
546
547 return ranOutOfSpace;
548}
549
550QSize QToolBarLayout::expandedSize(const QSize &size) const
551{
552 if (dirty)
553 updateGeomArray();
554
555 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
556 if (!tb)
557 return QSize(0, 0);
558 QMainWindow *win = qobject_cast<QMainWindow*>(object: tb->parentWidget());
559 Qt::Orientation o = tb->orientation();
560 QStyle *style = tb->style();
561 QStyleOptionToolBar opt;
562 tb->initStyleOption(option: &opt);
563 const int handleExtent = movable()
564 ? style->pixelMetric(metric: QStyle::PM_ToolBarHandleExtent, option: &opt, widget: tb) : 0;
565 const QMargins margins = contentsMargins();
566 const int spacing = this->spacing();
567 const int extensionExtent = style->pixelMetric(metric: QStyle::PM_ToolBarExtensionExtent, option: &opt, widget: tb);
568
569 int total_w = 0;
570 int count = 0;
571 for (int x = 0; x < items.size(); ++x) {
572 if (!geomArray[x].empty) {
573 total_w += (count == 0 ? 0 : spacing) + geomArray[x].minimumSize;
574 ++count;
575 }
576 }
577 if (count == 0)
578 return QSize(0, 0);
579
580 int min_w = pick(o, size);
581 int rows = (int)qSqrt(v: qreal(count));
582 if (rows == 1)
583 ++rows; // we want to expand to at least two rows
584 int space = total_w/rows + spacing + extensionExtent;
585 space = qMax(a: space, b: min_w - pick(o, m: margins) - handleExtent);
586 if (win != nullptr)
587 space = qMin(a: space, b: pick(o, size: win->size()) - pick(o, m: margins) - handleExtent);
588
589 int w = 0;
590 int h = 0;
591 int i = 0;
592 while (i < items.size()) {
593 int count = 0;
594 int size = 0;
595 int prev = -1;
596 int rowHeight = 0;
597 for (; i < items.size(); ++i) {
598 if (geomArray[i].empty)
599 continue;
600
601 int newSize = size + (count == 0 ? 0 : spacing) + geomArray[i].minimumSize;
602 rowHeight = qMax(a: rowHeight, b: perp(o, size: items.at(i)->sizeHint()));
603 if (prev != -1 && newSize > space) {
604 if (count > 1 && size + spacing + extensionExtent > space) {
605 size -= spacing + geomArray[prev].minimumSize;
606 i = prev;
607 }
608 break;
609 }
610
611 size = newSize;
612 prev = i;
613 ++count;
614 }
615
616 w = qMax(a: size, b: w);
617 h += rowHeight + spacing;
618 }
619
620 w += pick(o: Qt::Horizontal, m: margins) + handleExtent + spacing + extensionExtent;
621 w = qMax(a: w, b: min_w);
622 if (win != nullptr)
623 w = qMin(a: w, b: pick(o, size: win->size()));
624 h += pick(o: Qt::Vertical, m: margins) - spacing; //there is no spacing before the first row
625
626 QSize result;
627 rpick(o, size&: result) = w;
628 rperp(o, size&: result) = h;
629 return result;
630}
631
632void QToolBarLayout::setExpanded(bool exp)
633{
634 QWidget *tb = qobject_cast<QToolBar*>(object: parentWidget());
635 if (!tb)
636 return;
637 if (exp == expanded && !tb->isWindow())
638 return;
639
640 expanded = exp;
641 extension->setChecked(expanded);
642
643 if (QMainWindow *win = qobject_cast<QMainWindow*>(object: tb->parentWidget())) {
644#if !QT_CONFIG(dockwidget)
645 animating = false;
646#else
647 animating = !tb->isWindow() && win->isAnimated();
648#endif
649 QMainWindowLayout *layout = qt_mainwindow_layout(window: win);
650 if (expanded) {
651 tb->raise();
652 } else {
653 QList<int> path = layout->layoutState.indexOf(widget: tb);
654 if (!path.isEmpty()) {
655 QRect rect = layout->layoutState.itemRect(path);
656 layoutActions(size: rect.size());
657 }
658 }
659 layout->layoutState.toolBarAreaLayout.apply(animate: animating);
660 }
661}
662
663QSize QToolBarLayout::minimumSize() const
664{
665 if (dirty)
666 updateGeomArray();
667 return minSize;
668}
669
670QSize QToolBarLayout::sizeHint() const
671{
672 if (dirty)
673 updateGeomArray();
674 return hint;
675}
676
677QToolBarItem *QToolBarLayout::createItem(QAction *action)
678{
679 bool customWidget = false;
680 bool standardButtonWidget = false;
681 QWidget *widget = nullptr;
682 QToolBar *tb = qobject_cast<QToolBar*>(object: parentWidget());
683 if (!tb)
684 return (QToolBarItem *)nullptr;
685
686 if (QWidgetAction *widgetAction = qobject_cast<QWidgetAction *>(object: action)) {
687 widget = widgetAction->requestWidget(parent: tb);
688 if (widget != nullptr) {
689 widget->setAttribute(Qt::WA_LayoutUsesWidgetRect);
690 customWidget = true;
691 }
692 } else if (action->isSeparator()) {
693 QToolBarSeparator *sep = new QToolBarSeparator(tb);
694 connect(sender: tb, SIGNAL(orientationChanged(Qt::Orientation)),
695 receiver: sep, SLOT(setOrientation(Qt::Orientation)));
696 widget = sep;
697 }
698
699 if (!widget) {
700 QToolButton *button = new QToolButton(tb);
701 button->setAutoRaise(true);
702 button->setFocusPolicy(Qt::NoFocus);
703 button->setIconSize(tb->iconSize());
704 button->setToolButtonStyle(tb->toolButtonStyle());
705 QObject::connect(sender: tb, SIGNAL(iconSizeChanged(QSize)),
706 receiver: button, SLOT(setIconSize(QSize)));
707 QObject::connect(sender: tb, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
708 receiver: button, SLOT(setToolButtonStyle(Qt::ToolButtonStyle)));
709 button->setDefaultAction(action);
710 QObject::connect(sender: button, SIGNAL(triggered(QAction*)), receiver: tb, SIGNAL(actionTriggered(QAction*)));
711 widget = button;
712 standardButtonWidget = true;
713 }
714
715 widget->hide();
716 QToolBarItem *result = new QToolBarItem(widget);
717 if (standardButtonWidget)
718 result->setAlignment(Qt::AlignJustify);
719 result->customWidget = customWidget;
720 result->action = action;
721 return result;
722}
723
724QT_END_NAMESPACE
725
726#include "moc_qtoolbarlayout_p.cpp"
727

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