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//#define QT_EXPERIMENTAL_CLIENT_DECORATIONS
5
6#include "qmainwindow.h"
7#include "qmainwindowlayout_p.h"
8
9#if QT_CONFIG(dockwidget)
10#include "qdockwidget.h"
11#endif
12#if QT_CONFIG(toolbar)
13#include "qtoolbar.h"
14#endif
15
16#include <qapplication.h>
17#include <qmenu.h>
18#if QT_CONFIG(menubar)
19#include <qmenubar.h>
20#endif
21#if QT_CONFIG(statusbar)
22#include <qstatusbar.h>
23#endif
24#include <qevent.h>
25#include <qstyle.h>
26#include <qdebug.h>
27#include <qpainter.h>
28#include <qmimedata.h>
29
30#include <private/qwidget_p.h>
31#if QT_CONFIG(toolbar)
32#include "qtoolbar_p.h"
33#endif
34#include "qwidgetanimator_p.h"
35#include <QtGui/qpa/qplatformwindow.h>
36#include <QtGui/qpa/qplatformwindow_p.h>
37
38QT_BEGIN_NAMESPACE
39
40using namespace Qt::StringLiterals;
41
42class QMainWindowPrivate : public QWidgetPrivate
43{
44 Q_DECLARE_PUBLIC(QMainWindow)
45public:
46 inline QMainWindowPrivate()
47 : layout(nullptr), explicitIconSize(false), toolButtonStyle(Qt::ToolButtonIconOnly)
48#ifdef Q_OS_MACOS
49 , useUnifiedToolBar(false)
50#endif
51 { }
52 QPointer<QMainWindowLayout> layout;
53 QSize iconSize;
54 bool explicitIconSize;
55 Qt::ToolButtonStyle toolButtonStyle;
56#ifdef Q_OS_MACOS
57 bool useUnifiedToolBar;
58#endif
59 void init();
60
61 static inline QMainWindowLayout *mainWindowLayout(const QMainWindow *mainWindow)
62 {
63 return mainWindow ? mainWindow->d_func()->layout.data() : static_cast<QMainWindowLayout *>(nullptr);
64 }
65};
66
67QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *mainWindow)
68{
69 return QMainWindowPrivate::mainWindowLayout(mainWindow);
70}
71
72#ifdef QT_EXPERIMENTAL_CLIENT_DECORATIONS
73Q_WIDGETS_EXPORT void qt_setMainWindowTitleWidget(QMainWindow *mainWindow, Qt::DockWidgetArea area, QWidget *widget)
74{
75 QGridLayout *topLayout = qobject_cast<QGridLayout *>(mainWindow->layout());
76 Q_ASSERT(topLayout);
77
78 int row = 0;
79 int column = 0;
80
81 switch (area) {
82 case Qt::LeftDockWidgetArea:
83 row = 1;
84 column = 0;
85 break;
86 case Qt::TopDockWidgetArea:
87 row = 0;
88 column = 1;
89 break;
90 case Qt::BottomDockWidgetArea:
91 row = 2;
92 column = 1;
93 break;
94 case Qt::RightDockWidgetArea:
95 row = 1;
96 column = 2;
97 break;
98 default:
99 Q_ASSERT_X(false, "qt_setMainWindowTitleWidget", "Unknown area");
100 return;
101 }
102
103 if (QLayoutItem *oldItem = topLayout->itemAtPosition(row, column))
104 delete oldItem->widget();
105 topLayout->addWidget(widget, row, column);
106}
107#endif
108
109void QMainWindowPrivate::init()
110{
111 Q_Q(QMainWindow);
112
113#ifdef QT_EXPERIMENTAL_CLIENT_DECORATIONS
114 QGridLayout *topLayout = new QGridLayout(q);
115 topLayout->setContentsMargins(0, 0, 0, 0);
116
117 layout = new QMainWindowLayout(q, topLayout);
118
119 topLayout->addItem(layout, 1, 1);
120#else
121 layout = new QMainWindowLayout(q, nullptr);
122#endif
123
124 const int metric = q->style()->pixelMetric(metric: QStyle::PM_ToolBarIconSize, option: nullptr, widget: q);
125 iconSize = QSize(metric, metric);
126 q->setAttribute(Qt::WA_Hover);
127 q->setAcceptDrops(true);
128}
129
130/*
131 The Main Window:
132
133 +----------------------------------------------------------+
134 | Menu Bar |
135 +----------------------------------------------------------+
136 | Tool Bar Area |
137 | +--------------------------------------------------+ |
138 | | Dock Window Area | |
139 | | +------------------------------------------+ | |
140 | | | | | |
141 | | | Central Widget | | |
142 | | | | | |
143 | | | | | |
144 | | | | | |
145 | | | | | |
146 | | | | | |
147 | | | | | |
148 | | | | | |
149 | | | | | |
150 | | | | | |
151 | | | | | |
152 | | +------------------------------------------+ | |
153 | | | |
154 | +--------------------------------------------------+ |
155 | |
156 +----------------------------------------------------------+
157 | Status Bar |
158 +----------------------------------------------------------+
159
160*/
161
162/*!
163 \class QMainWindow
164 \brief The QMainWindow class provides a main application
165 window.
166 \ingroup mainwindow-classes
167 \inmodule QtWidgets
168
169 \section1 Qt Main Window Framework
170
171 A main window provides a framework for building an
172 application's user interface. Qt has QMainWindow and its \l{Main
173 Window and Related Classes}{related classes} for main window
174 management. QMainWindow has its own layout to which you can add
175 \l{QToolBar}s, \l{QDockWidget}s, a
176 QMenuBar, and a QStatusBar. The layout has a center area that can
177 be occupied by any kind of widget. You can see an image of the
178 layout below.
179
180 \image mainwindowlayout.png
181
182 \section1 Creating Main Window Components
183
184 A central widget will typically be a standard Qt widget such
185 as a QTextEdit or a QGraphicsView. Custom widgets can also be
186 used for advanced applications. You set the central widget with \c
187 setCentralWidget().
188
189 Main windows have either a single (SDI) or multiple (MDI)
190 document interface. You create MDI applications in Qt by using a
191 QMdiArea as the central widget.
192
193 We will now examine each of the other widgets that can be
194 added to a main window. We give examples on how to create and add
195 them.
196
197 \section2 Creating Menus
198
199 Qt implements menus in QMenu and QMainWindow keeps them in a
200 QMenuBar. \l{QAction}{QAction}s are added to the menus, which
201 display them as menu items.
202
203 You can add new menus to the main window's menu bar by calling
204 \c menuBar(), which returns the QMenuBar for the window, and then
205 add a menu with QMenuBar::addMenu().
206
207 QMainWindow comes with a default menu bar, but you can also
208 set one yourself with \c setMenuBar(). If you wish to implement a
209 custom menu bar (i.e., not use the QMenuBar widget), you can set it
210 with \c setMenuWidget().
211
212 An example of how to create menus follows:
213
214 \snippet code/src_widgets_widgets_qmainwindow.cpp 0
215
216 The \c createPopupMenu() function creates popup menus when the
217 main window receives context menu events. The default
218 implementation generates a menu with the checkable actions from
219 the dock widgets and toolbars. You can reimplement \c
220 createPopupMenu() for a custom menu.
221
222 \section2 Creating Toolbars
223
224 Toolbars are implemented in the QToolBar class. You add a
225 toolbar to a main window with \c addToolBar().
226
227 You control the initial position of toolbars by assigning them
228 to a specific Qt::ToolBarArea. You can split an area by inserting
229 a toolbar break - think of this as a line break in text editing -
230 with \c addToolBarBreak() or \c insertToolBarBreak(). You can also
231 restrict placement by the user with QToolBar::setAllowedAreas()
232 and QToolBar::setMovable().
233
234 The size of toolbar icons can be retrieved with \c iconSize().
235 The sizes are platform dependent; you can set a fixed size with \c
236 setIconSize(). You can alter the appearance of all tool buttons in
237 the toolbars with \c setToolButtonStyle().
238
239 An example of toolbar creation follows:
240
241 \snippet code/src_widgets_widgets_qmainwindow.cpp 1
242
243 \section2 Creating Dock Widgets
244
245 Dock widgets are implemented in the QDockWidget class. A dock
246 widget is a window that can be docked into the main window. You
247 add dock widgets to a main window with \c addDockWidget().
248
249 There are four dock widget areas as given by the
250 Qt::DockWidgetArea enum: left, right, top, and bottom. You can
251 specify which dock widget area that should occupy the corners
252 where the areas overlap with \c setCorner(). By default
253 each area can only contain one row (vertical or horizontal) of
254 dock widgets, but if you enable nesting with \c
255 setDockNestingEnabled(), dock widgets can be added in either
256 direction.
257
258 Two dock widgets may also be stacked on top of each other. A
259 QTabBar is then used to select which of the widgets should be
260 displayed.
261
262 We give an example of how to create and add dock widgets to a
263 main window:
264
265 \snippet mainwindowsnippet.cpp 0
266
267 \section2 The Status Bar
268
269 You can set a status bar with \c setStatusBar(), but one is
270 created the first time \c statusBar() (which returns the main
271 window's status bar) is called. See QStatusBar for information on
272 how to use it.
273
274 \section1 Storing State
275
276 QMainWindow can store the state of its layout with \c
277 saveState(); it can later be retrieved with \c restoreState(). It
278 is the position and size (relative to the size of the main window)
279 of the toolbars and dock widgets that are stored.
280
281 \sa QMenuBar, QToolBar, QStatusBar, QDockWidget, {Menus Example}
282*/
283
284/*!
285 \fn void QMainWindow::iconSizeChanged(const QSize &iconSize)
286
287 This signal is emitted when the size of the icons used in the
288 window is changed. The new icon size is passed in \a iconSize.
289
290 You can connect this signal to other components to help maintain
291 a consistent appearance for your application.
292
293 \sa setIconSize()
294*/
295
296/*!
297 \fn void QMainWindow::toolButtonStyleChanged(Qt::ToolButtonStyle toolButtonStyle)
298
299 This signal is emitted when the style used for tool buttons in the
300 window is changed. The new style is passed in \a toolButtonStyle.
301
302 You can connect this signal to other components to help maintain
303 a consistent appearance for your application.
304
305 \sa setToolButtonStyle()
306*/
307
308#if QT_CONFIG(dockwidget)
309/*!
310 \fn void QMainWindow::tabifiedDockWidgetActivated(QDockWidget *dockWidget)
311
312 This signal is emitted when the tabified dock widget is activated by
313 selecting the tab. The activated dock widget is passed in \a dockWidget.
314
315 \since 5.8
316 \sa tabifyDockWidget(), tabifiedDockWidgets()
317*/
318#endif
319
320/*!
321 Constructs a QMainWindow with the given \a parent and the specified
322 widget \a flags.
323
324 QMainWindow sets the Qt::Window flag itself, and will hence
325 always be created as a top-level widget.
326 */
327QMainWindow::QMainWindow(QWidget *parent, Qt::WindowFlags flags)
328 : QWidget(*(new QMainWindowPrivate()), parent, flags | Qt::Window)
329{
330 d_func()->init();
331}
332
333
334/*!
335 Destroys the main window.
336 */
337QMainWindow::~QMainWindow()
338{ }
339
340/*! \property QMainWindow::iconSize
341 \brief size of toolbar icons in this mainwindow.
342
343 The default is the default tool bar icon size of the GUI style.
344 Note that the icons used must be at least of this size as the
345 icons are only scaled down.
346*/
347
348/*!
349 \property QMainWindow::dockOptions
350 \brief the docking behavior of QMainWindow
351 \since 4.3
352
353 The default value is AnimatedDocks | AllowTabbedDocks.
354*/
355
356/*!
357 \enum QMainWindow::DockOption
358 \since 4.3
359
360 This enum contains flags that specify the docking behavior of QMainWindow.
361
362 \value AnimatedDocks Identical to the \l animated property.
363
364 \value AllowNestedDocks Identical to the \l dockNestingEnabled property.
365
366 \value AllowTabbedDocks The user can drop one dock widget "on top" of
367 another. The two widgets are stacked and a tab
368 bar appears for selecting which one is visible.
369
370 \value ForceTabbedDocks Each dock area contains a single stack of tabbed
371 dock widgets. In other words, dock widgets cannot
372 be placed next to each other in a dock area. If
373 this option is set, AllowNestedDocks has no effect.
374
375 \value VerticalTabs The two vertical dock areas on the sides of the
376 main window show their tabs vertically. If this
377 option is not set, all dock areas show their tabs
378 at the bottom. Implies AllowTabbedDocks. See also
379 \l setTabPosition().
380
381 \value GroupedDragging When dragging the titlebar of a dock, all the tabs
382 that are tabbed with it are going to be dragged.
383 Implies AllowTabbedDocks. Does not work well if
384 some QDockWidgets have restrictions in which area
385 they are allowed. (This enum value was added in Qt
386 5.6.)
387
388 These options only control how dock widgets may be dropped in a QMainWindow.
389 They do not re-arrange the dock widgets to conform with the specified
390 options. For this reason they should be set before any dock widgets
391 are added to the main window. Exceptions to this are the AnimatedDocks and
392 VerticalTabs options, which may be set at any time.
393*/
394
395void QMainWindow::setDockOptions(DockOptions opt)
396{
397 Q_D(QMainWindow);
398 d->layout->setDockOptions(opt);
399}
400
401QMainWindow::DockOptions QMainWindow::dockOptions() const
402{
403 Q_D(const QMainWindow);
404 return d->layout->dockOptions;
405}
406
407QSize QMainWindow::iconSize() const
408{ return d_func()->iconSize; }
409
410void QMainWindow::setIconSize(const QSize &iconSize)
411{
412 Q_D(QMainWindow);
413 QSize sz = iconSize;
414 if (!sz.isValid()) {
415 const int metric = style()->pixelMetric(metric: QStyle::PM_ToolBarIconSize, option: nullptr, widget: this);
416 sz = QSize(metric, metric);
417 }
418 if (d->iconSize != sz) {
419 d->iconSize = sz;
420 emit iconSizeChanged(iconSize: d->iconSize);
421 }
422 d->explicitIconSize = iconSize.isValid();
423}
424
425/*! \property QMainWindow::toolButtonStyle
426 \brief style of toolbar buttons in this mainwindow.
427
428 To have the style of toolbuttons follow the system settings, set this property to Qt::ToolButtonFollowStyle.
429 On Unix, the user settings from the desktop environment will be used.
430 On other platforms, Qt::ToolButtonFollowStyle means icon only.
431
432 The default is Qt::ToolButtonIconOnly.
433*/
434
435Qt::ToolButtonStyle QMainWindow::toolButtonStyle() const
436{ return d_func()->toolButtonStyle; }
437
438void QMainWindow::setToolButtonStyle(Qt::ToolButtonStyle toolButtonStyle)
439{
440 Q_D(QMainWindow);
441 if (d->toolButtonStyle == toolButtonStyle)
442 return;
443 d->toolButtonStyle = toolButtonStyle;
444 emit toolButtonStyleChanged(toolButtonStyle: d->toolButtonStyle);
445}
446
447#if QT_CONFIG(menubar)
448/*!
449 Returns the menu bar for the main window. This function creates
450 and returns an empty menu bar if the menu bar does not exist.
451
452 If you want all windows in a Mac application to share one menu
453 bar, don't use this function to create it, because the menu bar
454 created here will have this QMainWindow as its parent. Instead,
455 you must create a menu bar that does not have a parent, which you
456 can then share among all the Mac windows. Create a parent-less
457 menu bar this way:
458
459 \snippet code/src_gui_widgets_qmenubar.cpp 1
460
461 \sa setMenuBar()
462*/
463QMenuBar *QMainWindow::menuBar() const
464{
465 QMenuBar *menuBar = qobject_cast<QMenuBar *>(object: layout()->menuBar());
466 if (!menuBar) {
467 QMainWindow *self = const_cast<QMainWindow *>(this);
468 menuBar = new QMenuBar(self);
469 self->setMenuBar(menuBar);
470 }
471 return menuBar;
472}
473
474/*!
475 Sets the menu bar for the main window to \a menuBar.
476
477 Note: QMainWindow takes ownership of the \a menuBar pointer and
478 deletes it at the appropriate time.
479
480 \sa menuBar()
481*/
482void QMainWindow::setMenuBar(QMenuBar *menuBar)
483{
484 QLayout *topLayout = layout();
485
486 if (QWidget *existingMenuBar = topLayout->menuBar(); existingMenuBar && existingMenuBar != menuBar) {
487 // Reparent corner widgets before we delete the old menu bar.
488 QMenuBar *oldMenuBar = qobject_cast<QMenuBar *>(object: existingMenuBar);
489 if (oldMenuBar && menuBar) {
490 // TopLeftCorner widget.
491 QWidget *cornerWidget = oldMenuBar->cornerWidget(corner: Qt::TopLeftCorner);
492 if (cornerWidget)
493 menuBar->setCornerWidget(w: cornerWidget, corner: Qt::TopLeftCorner);
494 // TopRightCorner widget.
495 cornerWidget = oldMenuBar->cornerWidget(corner: Qt::TopRightCorner);
496 if (cornerWidget)
497 menuBar->setCornerWidget(w: cornerWidget, corner: Qt::TopRightCorner);
498 }
499
500 existingMenuBar->hide();
501 existingMenuBar->setParent(nullptr);
502 existingMenuBar->deleteLater();
503 }
504 topLayout->setMenuBar(menuBar);
505}
506
507/*!
508 \since 4.2
509
510 Returns the menu bar for the main window. This function returns
511 null if a menu bar hasn't been constructed yet.
512*/
513QWidget *QMainWindow::menuWidget() const
514{
515 QWidget *menuBar = d_func()->layout->menuBar();
516 return menuBar;
517}
518
519/*!
520 \since 4.2
521
522 Sets the menu bar for the main window to \a menuBar.
523
524 QMainWindow takes ownership of the \a menuBar pointer and
525 deletes it at the appropriate time.
526*/
527void QMainWindow::setMenuWidget(QWidget *menuBar)
528{
529 Q_D(QMainWindow);
530 if (d->layout->menuBar() && d->layout->menuBar() != menuBar) {
531 d->layout->menuBar()->hide();
532 d->layout->menuBar()->deleteLater();
533 }
534 d->layout->setMenuBar(menuBar);
535}
536#endif // QT_CONFIG(menubar)
537
538#if QT_CONFIG(statusbar)
539/*!
540 Returns the status bar for the main window. This function creates
541 and returns an empty status bar if the status bar does not exist.
542
543 \sa setStatusBar()
544*/
545QStatusBar *QMainWindow::statusBar() const
546{
547 QStatusBar *statusbar = d_func()->layout->statusBar();
548 if (!statusbar) {
549 QMainWindow *self = const_cast<QMainWindow *>(this);
550 statusbar = new QStatusBar(self);
551 statusbar->setSizePolicy(hor: QSizePolicy::Ignored, ver: QSizePolicy::Fixed);
552 self->setStatusBar(statusbar);
553 }
554 return statusbar;
555}
556
557/*!
558 Sets the status bar for the main window to \a statusbar.
559
560 Setting the status bar to \nullptr will remove it from the main window.
561 Note that QMainWindow takes ownership of the \a statusbar pointer
562 and deletes it at the appropriate time.
563
564 \sa statusBar()
565*/
566void QMainWindow::setStatusBar(QStatusBar *statusbar)
567{
568 Q_D(QMainWindow);
569 if (d->layout->statusBar() && d->layout->statusBar() != statusbar) {
570 d->layout->statusBar()->hide();
571 d->layout->statusBar()->deleteLater();
572 }
573 d->layout->setStatusBar(statusbar);
574}
575#endif // QT_CONFIG(statusbar)
576
577/*!
578 Returns the central widget for the main window. This function
579 returns \nullptr if the central widget has not been set.
580
581 \sa setCentralWidget()
582*/
583QWidget *QMainWindow::centralWidget() const
584{ return d_func()->layout->centralWidget(); }
585
586/*!
587 Sets the given \a widget to be the main window's central widget.
588
589 Note: QMainWindow takes ownership of the \a widget pointer and
590 deletes it at the appropriate time.
591
592 \sa centralWidget()
593*/
594void QMainWindow::setCentralWidget(QWidget *widget)
595{
596 Q_D(QMainWindow);
597 if (d->layout->centralWidget() && d->layout->centralWidget() != widget) {
598 d->layout->centralWidget()->hide();
599 d->layout->centralWidget()->deleteLater();
600 }
601 d->layout->setCentralWidget(widget);
602}
603
604/*!
605 Removes the central widget from this main window.
606
607 The ownership of the removed widget is passed to the caller.
608
609 \since 5.2
610*/
611QWidget *QMainWindow::takeCentralWidget()
612{
613 Q_D(QMainWindow);
614 QWidget *oldcentralwidget = d->layout->centralWidget();
615 if (oldcentralwidget) {
616 oldcentralwidget->setParent(nullptr);
617 d->layout->setCentralWidget(nullptr);
618 }
619 return oldcentralwidget;
620}
621
622#if QT_CONFIG(dockwidget)
623/*!
624 Sets the given dock widget \a area to occupy the specified \a
625 corner.
626
627 \sa corner()
628*/
629void QMainWindow::setCorner(Qt::Corner corner, Qt::DockWidgetArea area)
630{
631 bool valid = false;
632 switch (corner) {
633 case Qt::TopLeftCorner:
634 valid = (area == Qt::TopDockWidgetArea || area == Qt::LeftDockWidgetArea);
635 break;
636 case Qt::TopRightCorner:
637 valid = (area == Qt::TopDockWidgetArea || area == Qt::RightDockWidgetArea);
638 break;
639 case Qt::BottomLeftCorner:
640 valid = (area == Qt::BottomDockWidgetArea || area == Qt::LeftDockWidgetArea);
641 break;
642 case Qt::BottomRightCorner:
643 valid = (area == Qt::BottomDockWidgetArea || area == Qt::RightDockWidgetArea);
644 break;
645 }
646 if (Q_UNLIKELY(!valid))
647 qWarning(msg: "QMainWindow::setCorner(): 'area' is not valid for 'corner'");
648 else
649 d_func()->layout->setCorner(corner, area);
650}
651
652/*!
653 Returns the dock widget area that occupies the specified \a
654 corner.
655
656 \sa setCorner()
657*/
658Qt::DockWidgetArea QMainWindow::corner(Qt::Corner corner) const
659{ return d_func()->layout->corner(corner); }
660#endif
661
662#if QT_CONFIG(toolbar)
663
664static bool checkToolBarArea(Qt::ToolBarArea area, const char *where)
665{
666 switch (area) {
667 case Qt::LeftToolBarArea:
668 case Qt::RightToolBarArea:
669 case Qt::TopToolBarArea:
670 case Qt::BottomToolBarArea:
671 return true;
672 default:
673 break;
674 }
675 qWarning(msg: "%s: invalid 'area' argument", where);
676 return false;
677}
678
679/*!
680 Adds a toolbar break to the given \a area after all the other
681 objects that are present.
682*/
683void QMainWindow::addToolBarBreak(Qt::ToolBarArea area)
684{
685 if (!checkToolBarArea(area, where: "QMainWindow::addToolBarBreak"))
686 return;
687 d_func()->layout->addToolBarBreak(area);
688}
689
690/*!
691 Inserts a toolbar break before the toolbar specified by \a before.
692*/
693void QMainWindow::insertToolBarBreak(QToolBar *before)
694{ d_func()->layout->insertToolBarBreak(before); }
695
696/*!
697 Removes a toolbar break previously inserted before the toolbar specified by \a before.
698*/
699
700void QMainWindow::removeToolBarBreak(QToolBar *before)
701{
702 Q_D(QMainWindow);
703 d->layout->removeToolBarBreak(before);
704}
705
706/*!
707 Adds the \a toolbar into the specified \a area in this main
708 window. The \a toolbar is placed at the end of the current tool
709 bar block (i.e. line). If the main window already manages \a toolbar
710 then it will only move the toolbar to \a area.
711
712 \sa insertToolBar(), addToolBarBreak(), insertToolBarBreak()
713*/
714void QMainWindow::addToolBar(Qt::ToolBarArea area, QToolBar *toolbar)
715{
716 if (!checkToolBarArea(area, where: "QMainWindow::addToolBar"))
717 return;
718
719 Q_D(QMainWindow);
720
721 disconnect(sender: this, SIGNAL(iconSizeChanged(QSize)),
722 receiver: toolbar, SLOT(_q_updateIconSize(QSize)));
723 disconnect(sender: this, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
724 receiver: toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
725
726 if (toolbar->d_func()->state && toolbar->d_func()->state->dragging) {
727 //removing a toolbar which is dragging will cause crash
728#if QT_CONFIG(dockwidget)
729 bool animated = isAnimated();
730 setAnimated(false);
731#endif
732 toolbar->d_func()->endDrag();
733#if QT_CONFIG(dockwidget)
734 setAnimated(animated);
735#endif
736 }
737
738 d->layout->removeToolBar(toolbar);
739
740 toolbar->d_func()->_q_updateIconSize(sz: d->iconSize);
741 toolbar->d_func()->_q_updateToolButtonStyle(style: d->toolButtonStyle);
742 connect(sender: this, SIGNAL(iconSizeChanged(QSize)),
743 receiver: toolbar, SLOT(_q_updateIconSize(QSize)));
744 connect(sender: this, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
745 receiver: toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
746
747 d->layout->addToolBar(area, toolbar);
748}
749
750/*! \overload
751 Equivalent of calling addToolBar(Qt::TopToolBarArea, \a toolbar)
752*/
753void QMainWindow::addToolBar(QToolBar *toolbar)
754{ addToolBar(area: Qt::TopToolBarArea, toolbar); }
755
756/*!
757 \overload
758
759 Creates a QToolBar object, setting its window title to \a title,
760 and inserts it into the top toolbar area.
761
762 \sa setWindowTitle()
763*/
764QToolBar *QMainWindow::addToolBar(const QString &title)
765{
766 QToolBar *toolBar = new QToolBar(this);
767 toolBar->setWindowTitle(title);
768 addToolBar(toolbar: toolBar);
769 return toolBar;
770}
771
772/*!
773 Inserts the \a toolbar into the area occupied by the \a before toolbar
774 so that it appears before it. For example, in normal left-to-right
775 layout operation, this means that \a toolbar will appear to the left
776 of the toolbar specified by \a before in a horizontal toolbar area.
777
778 \sa insertToolBarBreak(), addToolBar(), addToolBarBreak()
779*/
780void QMainWindow::insertToolBar(QToolBar *before, QToolBar *toolbar)
781{
782 Q_D(QMainWindow);
783
784 d->layout->removeToolBar(toolbar);
785
786 toolbar->d_func()->_q_updateIconSize(sz: d->iconSize);
787 toolbar->d_func()->_q_updateToolButtonStyle(style: d->toolButtonStyle);
788 connect(sender: this, SIGNAL(iconSizeChanged(QSize)),
789 receiver: toolbar, SLOT(_q_updateIconSize(QSize)));
790 connect(sender: this, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
791 receiver: toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
792
793 d->layout->insertToolBar(before, toolbar);
794}
795
796/*!
797 Removes the \a toolbar from the main window layout and hides
798 it. Note that the \a toolbar is \e not deleted.
799*/
800void QMainWindow::removeToolBar(QToolBar *toolbar)
801{
802 if (toolbar) {
803 d_func()->layout->removeToolBar(toolbar);
804 toolbar->hide();
805 }
806}
807
808/*!
809 Returns the Qt::ToolBarArea for \a toolbar. If \a toolbar has not
810 been added to the main window, this function returns \c
811 Qt::NoToolBarArea.
812
813 \sa addToolBar(), addToolBarBreak(), Qt::ToolBarArea
814*/
815Qt::ToolBarArea QMainWindow::toolBarArea(const QToolBar *toolbar) const
816{ return d_func()->layout->toolBarArea(toolbar); }
817
818/*!
819
820 Returns whether there is a toolbar
821 break before the \a toolbar.
822
823 \sa addToolBarBreak(), insertToolBarBreak()
824*/
825bool QMainWindow::toolBarBreak(QToolBar *toolbar) const
826{
827 return d_func()->layout->toolBarBreak(toolBar: toolbar);
828}
829
830#endif // QT_CONFIG(toolbar)
831
832#if QT_CONFIG(dockwidget)
833
834/*! \property QMainWindow::animated
835 \brief whether manipulating dock widgets and tool bars is animated
836 \since 4.2
837
838 When a dock widget or tool bar is dragged over the
839 main window, the main window adjusts its contents
840 to indicate where the dock widget or tool bar will
841 be docked if it is dropped. Setting this property
842 causes QMainWindow to move its contents in a smooth
843 animation. Clearing this property causes the contents
844 to snap into their new positions.
845
846 By default, this property is set. It may be cleared if
847 the main window contains widgets which are slow at resizing
848 or repainting themselves.
849
850 Setting this property is identical to setting the AnimatedDocks
851 option using setDockOptions().
852*/
853
854bool QMainWindow::isAnimated() const
855{
856 Q_D(const QMainWindow);
857 return d->layout->dockOptions & AnimatedDocks;
858}
859
860void QMainWindow::setAnimated(bool enabled)
861{
862 Q_D(QMainWindow);
863
864 DockOptions opts = d->layout->dockOptions;
865 opts.setFlag(flag: AnimatedDocks, on: enabled);
866
867 d->layout->setDockOptions(opts);
868}
869
870/*! \property QMainWindow::dockNestingEnabled
871 \brief whether docks can be nested
872 \since 4.2
873
874 If this property is \c false, dock areas can only contain a single row
875 (horizontal or vertical) of dock widgets. If this property is \c true,
876 the area occupied by a dock widget can be split in either direction to contain
877 more dock widgets.
878
879 Dock nesting is only necessary in applications that contain a lot of
880 dock widgets. It gives the user greater freedom in organizing their
881 main window. However, dock nesting leads to more complex
882 (and less intuitive) behavior when a dock widget is dragged over the
883 main window, since there are more ways in which a dropped dock widget
884 may be placed in the dock area.
885
886 Setting this property is identical to setting the AllowNestedDocks option
887 using setDockOptions().
888*/
889
890bool QMainWindow::isDockNestingEnabled() const
891{
892 Q_D(const QMainWindow);
893 return d->layout->dockOptions & AllowNestedDocks;
894}
895
896void QMainWindow::setDockNestingEnabled(bool enabled)
897{
898 Q_D(QMainWindow);
899
900 DockOptions opts = d->layout->dockOptions;
901 opts.setFlag(flag: AllowNestedDocks, on: enabled);
902
903 d->layout->setDockOptions(opts);
904}
905
906#if 0
907// If added back in, add the '!' to the qdoc comment marker as well.
908/*
909 \property QMainWindow::verticalTabsEnabled
910 \brief whether left and right dock areas use vertical tabs
911 \since 4.2
912
913 If this property is set to false, dock areas containing tabbed dock widgets
914 display horizontal tabs, similar to Visual Studio.
915
916 If this property is set to true, then the right and left dock areas display vertical
917 tabs, similar to KDevelop.
918
919 This property should be set before any dock widgets are added to the main window.
920*/
921
922bool QMainWindow::verticalTabsEnabled() const
923{
924 return d_func()->layout->verticalTabsEnabled();
925}
926
927void QMainWindow::setVerticalTabsEnabled(bool enabled)
928{
929 d_func()->layout->setVerticalTabsEnabled(enabled);
930}
931#endif
932
933static bool checkDockWidgetArea(Qt::DockWidgetArea area, const char *where)
934{
935 switch (area) {
936 case Qt::LeftDockWidgetArea:
937 case Qt::RightDockWidgetArea:
938 case Qt::TopDockWidgetArea:
939 case Qt::BottomDockWidgetArea:
940 return true;
941 default:
942 break;
943 }
944 qWarning(msg: "%s: invalid 'area' argument", where);
945 return false;
946}
947
948#if QT_CONFIG(tabbar)
949/*!
950 \property QMainWindow::documentMode
951 \brief whether the tab bar for tabbed dockwidgets is set to document mode.
952 \since 4.5
953
954 The default is false.
955
956 \sa QTabBar::documentMode
957*/
958bool QMainWindow::documentMode() const
959{
960 return d_func()->layout->documentMode();
961}
962
963void QMainWindow::setDocumentMode(bool enabled)
964{
965 d_func()->layout->setDocumentMode(enabled);
966}
967#endif // QT_CONFIG(tabbar)
968
969#if QT_CONFIG(tabwidget)
970/*!
971 \property QMainWindow::tabShape
972 \brief the tab shape used for tabbed dock widgets.
973 \since 4.5
974
975 The default is \l QTabWidget::Rounded.
976
977 \sa setTabPosition()
978*/
979QTabWidget::TabShape QMainWindow::tabShape() const
980{
981 return d_func()->layout->tabShape();
982}
983
984void QMainWindow::setTabShape(QTabWidget::TabShape tabShape)
985{
986 d_func()->layout->setTabShape(tabShape);
987}
988
989/*!
990 \since 4.5
991
992 Returns the tab position for \a area.
993
994 \note The \l VerticalTabs dock option overrides the tab positions returned
995 by this function.
996
997 \sa setTabPosition(), tabShape()
998*/
999QTabWidget::TabPosition QMainWindow::tabPosition(Qt::DockWidgetArea area) const
1000{
1001 if (!checkDockWidgetArea(area, where: "QMainWindow::tabPosition"))
1002 return QTabWidget::South;
1003 return d_func()->layout->tabPosition(area);
1004}
1005
1006/*!
1007 \since 4.5
1008
1009 Sets the tab position for the given dock widget \a areas to the specified
1010 \a tabPosition. By default, all dock areas show their tabs at the bottom.
1011
1012 \note The \l VerticalTabs dock option overrides the tab positions set by
1013 this method.
1014
1015 \sa tabPosition(), setTabShape()
1016*/
1017void QMainWindow::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition)
1018{
1019 d_func()->layout->setTabPosition(areas, tabPosition);
1020}
1021#endif // QT_CONFIG(tabwidget)
1022
1023/*!
1024 Adds the given \a dockwidget to the specified \a area.
1025*/
1026void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget)
1027{
1028 if (!checkDockWidgetArea(area, where: "QMainWindow::addDockWidget"))
1029 return;
1030
1031 Qt::Orientation orientation = Qt::Vertical;
1032 switch (area) {
1033 case Qt::TopDockWidgetArea:
1034 case Qt::BottomDockWidgetArea:
1035 orientation = Qt::Horizontal;
1036 break;
1037 default:
1038 break;
1039 }
1040 d_func()->layout->removeWidget(w: dockwidget); // in case it was already in here
1041 addDockWidget(area, dockwidget, orientation);
1042}
1043
1044/*!
1045 Restores the state of \a dockwidget if it is created after the call
1046 to restoreState(). Returns \c true if the state was restored; otherwise
1047 returns \c false.
1048
1049 \sa restoreState(), saveState()
1050*/
1051
1052bool QMainWindow::restoreDockWidget(QDockWidget *dockwidget)
1053{
1054 return d_func()->layout->restoreDockWidget(dockwidget);
1055}
1056
1057/*!
1058 Adds \a dockwidget into the given \a area in the direction
1059 specified by the \a orientation.
1060*/
1061void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget,
1062 Qt::Orientation orientation)
1063{
1064 if (!checkDockWidgetArea(area, where: "QMainWindow::addDockWidget"))
1065 return;
1066
1067 // add a window to an area, placing done relative to the previous
1068 d_func()->layout->addDockWidget(area, dockwidget, orientation);
1069}
1070
1071/*!
1072 \fn void QMainWindow::splitDockWidget(QDockWidget *first, QDockWidget *second, Qt::Orientation orientation)
1073
1074 Splits the space covered by the \a first dock widget into two parts,
1075 moves the \a first dock widget into the first part, and moves the
1076 \a second dock widget into the second part.
1077
1078 The \a orientation specifies how the space is divided: A Qt::Horizontal
1079 split places the second dock widget to the right of the first; a
1080 Qt::Vertical split places the second dock widget below the first.
1081
1082 \e Note: if \a first is currently in a tabbed docked area, \a second will
1083 be added as a new tab, not as a neighbor of \a first. This is because a
1084 single tab can contain only one dock widget.
1085
1086 \e Note: The Qt::LayoutDirection influences the order of the dock widgets
1087 in the two parts of the divided area. When right-to-left layout direction
1088 is enabled, the placing of the dock widgets will be reversed.
1089
1090 \sa tabifyDockWidget(), addDockWidget(), removeDockWidget()
1091*/
1092void QMainWindow::splitDockWidget(QDockWidget *after, QDockWidget *dockwidget,
1093 Qt::Orientation orientation)
1094{
1095 d_func()->layout->splitDockWidget(after, dockwidget, orientation);
1096}
1097
1098#if QT_CONFIG(tabbar)
1099/*!
1100 \fn void QMainWindow::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
1101
1102 Moves \a second dock widget on top of \a first dock widget, creating a tabbed
1103 docked area in the main window.
1104
1105 \sa tabifiedDockWidgets()
1106*/
1107void QMainWindow::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
1108{
1109 d_func()->layout->tabifyDockWidget(first, second);
1110}
1111
1112
1113/*!
1114 \fn QList<QDockWidget*> QMainWindow::tabifiedDockWidgets(QDockWidget *dockwidget) const
1115
1116 Returns the dock widgets that are tabified together with \a dockwidget.
1117
1118 \since 4.5
1119 \sa tabifyDockWidget()
1120*/
1121
1122QList<QDockWidget*> QMainWindow::tabifiedDockWidgets(QDockWidget *dockwidget) const
1123{
1124 Q_D(const QMainWindow);
1125 return d->layout ? d->layout->tabifiedDockWidgets(dockWidget: dockwidget) : QList<QDockWidget *>();
1126}
1127#endif // QT_CONFIG(tabbar)
1128
1129
1130/*!
1131 Removes the \a dockwidget from the main window layout and hides
1132 it. Note that the \a dockwidget is \e not deleted.
1133*/
1134void QMainWindow::removeDockWidget(QDockWidget *dockwidget)
1135{
1136 if (dockwidget) {
1137 d_func()->layout->removeWidget(w: dockwidget);
1138 dockwidget->hide();
1139 }
1140}
1141
1142/*!
1143 Returns the Qt::DockWidgetArea for \a dockwidget. If \a dockwidget
1144 has not been added to the main window, this function returns \c
1145 Qt::NoDockWidgetArea.
1146
1147 \sa addDockWidget(), splitDockWidget(), Qt::DockWidgetArea
1148*/
1149Qt::DockWidgetArea QMainWindow::dockWidgetArea(QDockWidget *dockwidget) const
1150{ return d_func()->layout->dockWidgetArea(widget: dockwidget); }
1151
1152
1153/*!
1154 \since 5.6
1155 Resizes the dock widgets in the list \a docks to the corresponding size in
1156 pixels from the list \a sizes. If \a orientation is Qt::Horizontal, adjusts
1157 the width, otherwise adjusts the height of the dock widgets.
1158 The sizes will be adjusted such that the maximum and the minimum sizes are
1159 respected and the QMainWindow itself will not be resized.
1160 Any additional/missing space is distributed amongst the widgets according
1161 to the relative weight of the sizes.
1162
1163 Example:
1164 \snippet code/src_widgets_widgets_qmainwindow.cpp 2
1165
1166 If the blue and the yellow widget are nested on the same level they will be
1167 resized such that the yellowWidget is twice as big as the blueWidget
1168
1169 If some widgets are grouped in tabs, only one widget per group should be
1170 specified. Widgets not in the list might be changed to respect the constraints.
1171*/
1172void QMainWindow::resizeDocks(const QList<QDockWidget *> &docks,
1173 const QList<int> &sizes, Qt::Orientation orientation)
1174{
1175 d_func()->layout->layoutState.dockAreaLayout.resizeDocks(docks, sizes, o: orientation);
1176 d_func()->layout->invalidate();
1177}
1178
1179
1180#endif // QT_CONFIG(dockwidget)
1181
1182/*!
1183 Saves the current state of this mainwindow's toolbars and
1184 dockwidgets. This includes the corner settings which can
1185 be set with setCorner(). The \a version number is stored
1186 as part of the data.
1187
1188 The \l{QObject::objectName}{objectName} property is used
1189 to identify each QToolBar and QDockWidget. You should make sure
1190 that this property is unique for each QToolBar and QDockWidget you
1191 add to the QMainWindow
1192
1193 To restore the saved state, pass the return value and \a version
1194 number to restoreState().
1195
1196 To save the geometry when the window closes, you can
1197 implement a close event like this:
1198
1199 \snippet code/src_gui_widgets_qmainwindow.cpp 0
1200
1201 \sa restoreState(), QWidget::saveGeometry(), QWidget::restoreGeometry()
1202*/
1203QByteArray QMainWindow::saveState(int version) const
1204{
1205 QByteArray data;
1206 QDataStream stream(&data, QIODevice::WriteOnly);
1207 stream.setVersion(QDataStream::Qt_5_0);
1208 stream << QMainWindowLayout::VersionMarker;
1209 stream << version;
1210 d_func()->layout->saveState(stream);
1211 return data;
1212}
1213
1214/*!
1215 Restores the \a state of this mainwindow's toolbars and
1216 dockwidgets. Also restores the corner settings too. The
1217 \a version number is compared with that stored in \a state.
1218 If they do not match, the mainwindow's state is left
1219 unchanged, and this function returns \c false; otherwise, the state
1220 is restored, and this function returns \c true.
1221
1222 To restore geometry saved using QSettings, you can use code like
1223 this:
1224
1225 \snippet code/src_gui_widgets_qmainwindow.cpp 1
1226
1227 \sa saveState(), QWidget::saveGeometry(),
1228 QWidget::restoreGeometry(), restoreDockWidget()
1229*/
1230bool QMainWindow::restoreState(const QByteArray &state, int version)
1231{
1232 if (state.isEmpty())
1233 return false;
1234 QByteArray sd = state;
1235 QDataStream stream(&sd, QIODevice::ReadOnly);
1236 stream.setVersion(QDataStream::Qt_5_0);
1237 int marker, v;
1238 stream >> marker;
1239 stream >> v;
1240 if (stream.status() != QDataStream::Ok || marker != QMainWindowLayout::VersionMarker || v != version)
1241 return false;
1242 bool restored = d_func()->layout->restoreState(stream);
1243 return restored;
1244}
1245
1246/*! \reimp */
1247bool QMainWindow::event(QEvent *event)
1248{
1249 Q_D(QMainWindow);
1250
1251#if QT_CONFIG(dockwidget)
1252 if (d->layout && d->layout->windowEvent(e: event))
1253 return true;
1254#endif
1255
1256 switch (event->type()) {
1257
1258#if QT_CONFIG(toolbar)
1259 case QEvent::ToolBarChange: {
1260 Q_ASSERT(d->layout);
1261 d->layout->toggleToolBarsVisible();
1262 return true;
1263 }
1264#endif
1265
1266#if QT_CONFIG(statustip)
1267 case QEvent::StatusTip:
1268#if QT_CONFIG(statusbar)
1269 Q_ASSERT(d->layout);
1270 if (QStatusBar *sb = d->layout->statusBar())
1271 sb->showMessage(text: static_cast<QStatusTipEvent*>(event)->tip());
1272 else
1273#endif
1274 static_cast<QStatusTipEvent*>(event)->ignore();
1275 return true;
1276#endif // QT_CONFIG(statustip)
1277
1278 case QEvent::StyleChange:
1279#if QT_CONFIG(dockwidget)
1280 Q_ASSERT(d->layout);
1281 d->layout->layoutState.dockAreaLayout.styleChangedEvent();
1282#endif
1283 if (!d->explicitIconSize)
1284 setIconSize(QSize());
1285 break;
1286#if QT_CONFIG(draganddrop)
1287 case QEvent::DragEnter:
1288 case QEvent::Drop:
1289 if (!d->layout->draggingWidget)
1290 break;
1291 event->accept();
1292 return true;
1293 case QEvent::DragMove: {
1294 if (!d->layout->draggingWidget)
1295 break;
1296 auto dragMoveEvent = static_cast<QDragMoveEvent *>(event);
1297 d->layout->hover(hoverTarget: d->layout->draggingWidget,
1298 mousePos: mapToGlobal(dragMoveEvent->position()).toPoint());
1299 event->accept();
1300 return true;
1301 }
1302 case QEvent::DragLeave:
1303 if (!d->layout->draggingWidget)
1304 break;
1305 d->layout->hover(hoverTarget: d->layout->draggingWidget, mousePos: pos() - QPoint(-1, -1));
1306 return true;
1307#endif
1308 default:
1309 break;
1310 }
1311
1312 return QWidget::event(event);
1313}
1314
1315#if QT_CONFIG(toolbar)
1316
1317/*!
1318 \property QMainWindow::unifiedTitleAndToolBarOnMac
1319 \brief whether the window uses the unified title and toolbar look on \macos
1320
1321 Note that the Qt 5 implementation has several limitations compared to Qt 4:
1322 \list
1323 \li Use in windows with OpenGL content is not supported. This includes QOpenGLWidget.
1324 \li Using dockable or movable toolbars may result in painting errors and is not recommended
1325 \endlist
1326
1327 \since 5.2
1328*/
1329void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool enabled)
1330{
1331#ifdef Q_OS_MACOS
1332 if (!isWindow())
1333 return;
1334
1335 Q_D(QMainWindow);
1336 d->useUnifiedToolBar = enabled;
1337
1338 // The unified toolbar is drawn by the macOS style with a transparent background.
1339 // To ensure a suitable surface format is used we need to first create backing
1340 // QWindow so we have something to update the surface format on, and then let
1341 // QWidget know about the translucency, which it will propagate to the surface.
1342 setAttribute(Qt::WA_NativeWindow);
1343 setAttribute(Qt::WA_TranslucentBackground, enabled);
1344
1345 d->create(); // Create first, before querying the platform window
1346 using namespace QNativeInterface::Private;
1347 if (auto *platformWindow = dynamic_cast<QCocoaWindow*>(window()->windowHandle()->handle()))
1348 platformWindow->setContentBorderEnabled(enabled);
1349
1350 update();
1351#else
1352 Q_UNUSED(enabled);
1353#endif
1354}
1355
1356bool QMainWindow::unifiedTitleAndToolBarOnMac() const
1357{
1358#ifdef Q_OS_MACOS
1359 return d_func()->useUnifiedToolBar;
1360#endif
1361 return false;
1362}
1363
1364#endif // QT_CONFIG(toolbar)
1365
1366/*!
1367 \internal
1368*/
1369bool QMainWindow::isSeparator(const QPoint &pos) const
1370{
1371#if QT_CONFIG(dockwidget)
1372 Q_D(const QMainWindow);
1373 return !d->layout->layoutState.dockAreaLayout.findSeparator(pos).isEmpty();
1374#else
1375 Q_UNUSED(pos);
1376 return false;
1377#endif
1378}
1379
1380#ifndef QT_NO_CONTEXTMENU
1381/*!
1382 \reimp
1383*/
1384void QMainWindow::contextMenuEvent(QContextMenuEvent *event)
1385{
1386 event->ignore();
1387 // only show the context menu for direct QDockWidget and QToolBar
1388 // children and for the menu bar as well
1389 QWidget *child = childAt(p: event->pos());
1390 while (child && child != this) {
1391#if QT_CONFIG(menubar)
1392 if (QMenuBar *mb = qobject_cast<QMenuBar *>(object: child)) {
1393 if (mb->parentWidget() != this)
1394 return;
1395 break;
1396 }
1397#endif
1398#if QT_CONFIG(dockwidget)
1399 if (QDockWidget *dw = qobject_cast<QDockWidget *>(object: child)) {
1400 if (dw->parentWidget() != this)
1401 return;
1402 if (dw->widget()
1403 && dw->widget()->geometry().contains(p: child->mapFrom(this, event->pos()))) {
1404 // ignore the event if the mouse is over the QDockWidget contents
1405 return;
1406 }
1407 break;
1408 }
1409#endif // QT_CONFIG(dockwidget)
1410#if QT_CONFIG(toolbar)
1411 if (QToolBar *tb = qobject_cast<QToolBar *>(object: child)) {
1412 if (tb->parentWidget() != this)
1413 return;
1414 break;
1415 }
1416#endif
1417 child = child->parentWidget();
1418 }
1419 if (child == this)
1420 return;
1421
1422#if QT_CONFIG(menu)
1423 QMenu *popup = createPopupMenu();
1424 if (popup) {
1425 if (!popup->isEmpty()) {
1426 popup->setAttribute(Qt::WA_DeleteOnClose);
1427 popup->popup(pos: event->globalPos());
1428 event->accept();
1429 } else {
1430 delete popup;
1431 }
1432 }
1433#endif
1434}
1435#endif // QT_NO_CONTEXTMENU
1436
1437#if QT_CONFIG(menu)
1438/*!
1439 Returns a popup menu containing checkable entries for the toolbars and
1440 dock widgets present in the main window. If there are no toolbars and
1441 dock widgets present, this function returns \nullptr.
1442
1443 By default, this function is called by the main window when the user
1444 activates a context menu, typically by right-clicking on a toolbar or a dock
1445 widget.
1446
1447 If you want to create a custom popup menu, reimplement this function and
1448 return a newly-created popup menu. Ownership of the popup menu is transferred
1449 to the caller.
1450
1451 \sa addDockWidget(), addToolBar(), menuBar()
1452*/
1453QMenu *QMainWindow::createPopupMenu()
1454{
1455 Q_D(QMainWindow);
1456 QMenu *menu = nullptr;
1457#if QT_CONFIG(dockwidget)
1458 QList<QDockWidget *> dockwidgets = findChildren<QDockWidget *>();
1459 if (dockwidgets.size()) {
1460 menu = new QMenu(this);
1461 for (int i = 0; i < dockwidgets.size(); ++i) {
1462 QDockWidget *dockWidget = dockwidgets.at(i);
1463 // filter to find out if we own this QDockWidget
1464 if (dockWidget->parentWidget() == this) {
1465 if (d->layout->layoutState.dockAreaLayout.indexOf(dockWidget).isEmpty())
1466 continue;
1467 } else if (QDockWidgetGroupWindow *dwgw =
1468 qobject_cast<QDockWidgetGroupWindow *>(object: dockWidget->parentWidget())) {
1469 if (dwgw->parentWidget() != this)
1470 continue;
1471 if (dwgw->layoutInfo()->indexOf(widget: dockWidget).isEmpty())
1472 continue;
1473 } else {
1474 continue;
1475 }
1476 menu->addAction(action: dockwidgets.at(i)->toggleViewAction());
1477 }
1478 menu->addSeparator();
1479 }
1480#endif // QT_CONFIG(dockwidget)
1481#if QT_CONFIG(toolbar)
1482 QList<QToolBar *> toolbars = findChildren<QToolBar *>();
1483 if (toolbars.size()) {
1484 if (!menu)
1485 menu = new QMenu(this);
1486 for (int i = 0; i < toolbars.size(); ++i) {
1487 QToolBar *toolBar = toolbars.at(i);
1488 if (toolBar->parentWidget() == this
1489 && (!d->layout->layoutState.toolBarAreaLayout.indexOf(toolBar).isEmpty())) {
1490 menu->addAction(action: toolbars.at(i)->toggleViewAction());
1491 }
1492 }
1493 }
1494#endif
1495 Q_UNUSED(d);
1496 return menu;
1497}
1498#endif // QT_CONFIG(menu)
1499
1500QT_END_NAMESPACE
1501
1502#include "moc_qmainwindow.cpp"
1503

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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