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