source: trunk/src/gui/widgets/qmainwindow.cpp@ 883

Last change on this file since 883 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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