Merge remote branch 'origin/4.6' into integration-master-from-4.6
[qt:kenya888s-qt-palm-pre.git] / src / gui / widgets / qmainwindow.cpp
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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
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 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
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>
64 QT_BEGIN_NAMESPACE
65 extern OSWindowRef qt_mac_window_for(const QWidget *); // qwidget_mac.cpp
66 QT_END_NAMESPACE
67 #endif
68 #ifdef QT_SOFTKEYS_ENABLED
69 #include <private/qsoftkeymanager_p.h>
70 #endif
71
72 QT_BEGIN_NAMESPACE
73
74 class QMainWindowPrivate : public QWidgetPrivate
75 {
76     Q_DECLARE_PUBLIC(QMainWindow)
77 public:
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
113 void 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  */
317 QMainWindow::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  */
329 QMainWindow::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  */
340 QMainWindow::~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
391 void QMainWindow::setDockOptions(DockOptions opt)
392 {
393     Q_D(QMainWindow);
394     d->layout->setDockOptions(opt);
395 }
396
397 QMainWindow::DockOptions QMainWindow::dockOptions() const
398 {
399     Q_D(const QMainWindow);
400     return d->layout->dockOptions;
401 }
402
403 QSize QMainWindow::iconSize() const
404 { return d_func()->iconSize; }
405
406 void 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
427 Qt::ToolButtonStyle QMainWindow::toolButtonStyle() const
428 { return d_func()->toolButtonStyle; }
429
430 void 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 */
455 QMenuBar *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 */
474 void 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 */
509 QWidget *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 */
523 void 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 */
541 QStatusBar *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 */
562 void 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 */
579 QWidget *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 */
590 void 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 */
607 void 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 */
636 Qt::DockWidgetArea QMainWindow::corner(Qt::Corner corner) const
637 { return d_func()->layout->corner(corner); }
638 #endif
639
640 #ifndef QT_NO_TOOLBAR
641
642 static 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 */
661 void 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 */
671 void 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
678 void 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 */
692 void 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 */
735 void 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 */
746 QToolBar *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 */
762 void 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 */
782 void 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 */
797 Qt::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 */
807 bool 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
836 bool QMainWindow::isAnimated() const
837 {
838     Q_D(const QMainWindow);
839     return d->layout->dockOptions & AnimatedDocks;
840 }
841
842 void 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
875 bool QMainWindow::isDockNestingEnabled() const
876 {
877     Q_D(const QMainWindow);
878     return d->layout->dockOptions & AllowNestedDocks;
879 }
880
881 void 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
908 bool QMainWindow::verticalTabsEnabled() const
909 {
910     return d_func()->layout->verticalTabsEnabled();
911 }
912
913 void QMainWindow::setVerticalTabsEnabled(bool enabled)
914 {
915     d_func()->layout->setVerticalTabsEnabled(enabled);
916 }
917 #endif
918
919 static 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 */
944 bool QMainWindow::documentMode() const
945 {
946     return d_func()->layout->documentMode();
947 }
948
949 void 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 */
965 QTabWidget::TabShape QMainWindow::tabShape() const
966 {
967     return d_func()->layout->tabShape();
968 }
969
970 void 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 */
985 QTabWidget::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 */
1003 void 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 */
1012 void 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
1053 bool 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 */
1062 void 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 */
1093 void 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 */
1107 void 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
1122 QList<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 */
1150 void 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 */
1165 Qt::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 */
1189 QByteArray 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 */
1214 bool 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)
1230 QCursor 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
1254 void 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 */
1307 bool 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             d->layout->layoutState.dockAreaLayout.styleChangedEvent();
1397             if (!d->explicitIconSize)
1398                 setIconSize(QSize());
1399             break;
1400 #ifdef Q_WS_MAC
1401         case QEvent::Show:
1402             if (unifiedTitleAndToolBarOnMac())
1403                 d->layout->syncUnifiedToolbarVisibility();
1404             d->layout->blockVisiblityCheck = false;
1405             break;
1406        case QEvent::WindowStateChange:
1407             {
1408                 if (isHidden()) {
1409                     // We are coming out of a minimize, leave things as is.
1410                     d->layout->blockVisiblityCheck = true;
1411                 }
1412 #  ifdef QT_MAC_USE_COCOA
1413                 // We need to update the HIToolbar status when we go out of or into fullscreen.
1414                 QWindowStateChangeEvent *wce = static_cast<QWindowStateChangeEvent *>(event);
1415                 if ((windowState() & Qt::WindowFullScreen) || (wce->oldState() & Qt::WindowFullScreen)) {
1416                     d->layout->updateHIToolBarStatus();
1417                 }
1418 #  endif // Cocoa
1419             }
1420             break;
1421 #endif // Q_WS_MAC
1422 #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
1423        case QEvent::CursorChange:
1424            if (d->cursorAdjusted) {
1425                d->oldCursor = cursor();
1426                d->hasOldCursor = testAttribute(Qt::WA_SetCursor);
1427            }
1428            break;
1429 #endif
1430 #ifdef QT_SOFTKEYS_ENABLED
1431     case QEvent::LanguageChange:
1432         d->menuBarAction->setText(QSoftKeyManager::standardSoftKeyText(QSoftKeyManager::MenuSoftKey));
1433         break;
1434 #endif
1435         default:
1436             break;
1437     }
1438
1439     return QWidget::event(event);
1440 }
1441
1442 #ifndef QT_NO_TOOLBAR
1443
1444 /*!
1445     \property QMainWindow::unifiedTitleAndToolBarOnMac
1446     \brief whether the window uses the unified title and toolbar look on Mac OS X
1447     \since 4.3
1448
1449     This property is false by default and only has any effect on Mac OS X 10.4 or higher.
1450
1451     If set to true, then the top toolbar area is replaced with a Carbon HIToolbar
1452     or a Cocoa NSToolbar (depending on whether Qt was built with Carbon or Cocoa).
1453     All toolbars in the top toolbar area and any toolbars added afterwards are
1454     moved to that. This means a couple of things.
1455
1456     \list
1457     \i QToolBars in this toolbar area are not movable and you cannot drag other
1458         toolbars to it
1459     \i Toolbar breaks are not respected or preserved
1460     \i Any custom widgets in the toolbar will not be shown if the toolbar
1461         becomes too small (only actions will be shown)
1462     \i Before Qt 4.5, if you called showFullScreen() on the main window, the QToolbar would
1463         disappear since it is considered to be part of the title bar. Qt 4.5 and up will now work around this by pulling
1464         the toolbars out and back into the regular toolbar and vice versa when you swap out.
1465         However, a good practice would be that turning off the unified toolbar before you call
1466         showFullScreen() and restoring it after you call showNormal().
1467     \endlist
1468
1469     Setting this back to false will remove these restrictions.
1470
1471     The Qt::WA_MacBrushedMetal attribute takes precedence over this property.
1472 */
1473 void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set)
1474 {
1475 #ifdef Q_WS_MAC
1476     Q_D(QMainWindow);
1477     if (!isWindow() || d->useHIToolBar == set || QSysInfo::MacintoshVersion < QSysInfo::MV_10_3)
1478         return;
1479
1480     // ### Disable the unified toolbar when using anything but the native graphics system.
1481     if (windowSurface())
1482         return;
1483
1484     d->useHIToolBar = set;
1485     createWinId(); // We need the hiview for down below.
1486
1487     d->layout->updateHIToolBarStatus();
1488     // Enabling the unified toolbar clears the opaque size grip setting, update it.
1489     d->macUpdateOpaqueSizeGrip();
1490 #else
1491     Q_UNUSED(set)
1492 #endif
1493 }
1494
1495 bool QMainWindow::unifiedTitleAndToolBarOnMac() const
1496 {
1497 #ifdef Q_WS_MAC
1498     return d_func()->useHIToolBar && !testAttribute(Qt::WA_MacBrushedMetal) && !(windowFlags() & Qt::FramelessWindowHint);
1499 #endif
1500     return false;
1501 }
1502
1503 #endif // QT_NO_TOOLBAR
1504
1505 /*!
1506     \internal
1507 */
1508 bool QMainWindow::isSeparator(const QPoint &pos) const
1509 {
1510 #ifndef QT_NO_DOCKWIDGET
1511     Q_D(const QMainWindow);
1512     return !d->layout->layoutState.dockAreaLayout.findSeparator(pos).isEmpty();
1513 #else
1514     Q_UNUSED(pos);
1515     return false;
1516 #endif
1517 }
1518
1519 #ifndef QT_NO_CONTEXTMENU
1520 /*!
1521     \reimp
1522 */
1523 void QMainWindow::contextMenuEvent(QContextMenuEvent *event)
1524 {
1525     event->ignore();
1526     // only show the context menu for direct QDockWidget and QToolBar
1527     // children and for the menu bar as well
1528     QWidget *child = childAt(event->pos());
1529     while (child && child != this) {
1530 #ifndef QT_NO_MENUBAR
1531         if (QMenuBar *mb = qobject_cast<QMenuBar *>(child)) {
1532             if (mb->parentWidget() != this)
1533                 return;
1534             break;
1535         }
1536 #endif
1537 #ifndef QT_NO_DOCKWIDGET
1538         if (QDockWidget *dw = qobject_cast<QDockWidget *>(child)) {
1539             if (dw->parentWidget() != this)
1540                 return;
1541             if (dw->widget()
1542                 && dw->widget()->geometry().contains(child->mapFrom(this, event->pos()))) {
1543                 // ignore the event if the mouse is over the QDockWidget contents
1544                 return;
1545             }
1546             break;
1547         }
1548 #endif // QT_NO_DOCKWIDGET
1549 #ifndef QT_NO_TOOLBAR
1550         if (QToolBar *tb = qobject_cast<QToolBar *>(child)) {
1551             if (tb->parentWidget() != this)
1552                 return;
1553             break;
1554         }
1555 #endif
1556         child = child->parentWidget();
1557     }
1558     if (child == this)
1559         return;
1560
1561 #ifndef QT_NO_MENU
1562     QMenu *popup = createPopupMenu();
1563     if (popup) {
1564         if (!popup->isEmpty()) {
1565             popup->setAttribute(Qt::WA_DeleteOnClose);
1566             popup->popup(event->globalPos());
1567             event->accept();
1568         } else {
1569             delete popup;
1570         }
1571     }
1572 #endif
1573 }
1574 #endif // QT_NO_CONTEXTMENU
1575
1576 #ifndef QT_NO_MENU
1577 /*!
1578     Returns a popup menu containing checkable entries for the toolbars and
1579     dock widgets present in the main window. If  there are no toolbars and
1580     dock widgets present, this function returns a null pointer.
1581
1582     By default, this function is called by the main window when the user
1583     activates a context menu, typically by right-clicking on a toolbar or a dock
1584     widget.
1585
1586     If you want to create a custom popup menu, reimplement this function and
1587     return a newly-created popup menu. Ownership of the popup menu is transferred
1588     to the caller.
1589
1590     \sa addDockWidget(), addToolBar(), menuBar()
1591 */
1592 QMenu *QMainWindow::createPopupMenu()
1593 {
1594     Q_D(QMainWindow);
1595     QMenu *menu = 0;
1596 #ifndef QT_NO_DOCKWIDGET
1597     QList<QDockWidget *> dockwidgets = qFindChildren<QDockWidget *>(this);
1598     if (dockwidgets.size()) {
1599         menu = new QMenu(this);
1600         for (int i = 0; i < dockwidgets.size(); ++i) {
1601             QDockWidget *dockWidget = dockwidgets.at(i);
1602             if (dockWidget->parentWidget() == this
1603                 && !d->layout->layoutState.dockAreaLayout.indexOf(dockWidget).isEmpty()) {
1604                 menu->addAction(dockwidgets.at(i)->toggleViewAction());
1605             }
1606         }
1607         menu->addSeparator();
1608     }
1609 #endif // QT_NO_DOCKWIDGET
1610 #ifndef QT_NO_TOOLBAR
1611     QList<QToolBar *> toolbars = qFindChildren<QToolBar *>(this);
1612     if (toolbars.size()) {
1613         if (!menu)
1614             menu = new QMenu(this);
1615         for (int i = 0; i < toolbars.size(); ++i) {
1616             QToolBar *toolBar = toolbars.at(i);
1617             if (toolBar->parentWidget() == this
1618                 && (!d->layout->layoutState.toolBarAreaLayout.indexOf(toolBar).isEmpty()
1619                     || (unifiedTitleAndToolBarOnMac()
1620                         && toolBarArea(toolBar) == Qt::TopToolBarArea))) {
1621                 menu->addAction(toolbars.at(i)->toggleViewAction());
1622             }
1623         }
1624     }
1625 #endif
1626     Q_UNUSED(d);
1627     return menu;
1628 }
1629 #endif // QT_NO_MENU
1630
1631 QT_END_NAMESPACE
1632
1633 #endif // QT_NO_MAINWINDOW