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

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

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