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