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

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