src/gui/widgets/qmainwindowlayout.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 "qmainwindowlayout_p.h"
       
    43 #include "qdockarealayout_p.h"
       
    44 
       
    45 #ifndef QT_NO_MAINWINDOW
       
    46 #include "qdockwidget.h"
       
    47 #include "qdockwidget_p.h"
       
    48 #include "qtoolbar_p.h"
       
    49 #include "qmainwindow.h"
       
    50 #include "qmainwindowlayout_p.h"
       
    51 #include "qtoolbar.h"
       
    52 #include "qtoolbarlayout_p.h"
       
    53 #include "qwidgetanimator_p.h"
       
    54 #include "qrubberband.h"
       
    55 #include "qdockwidget_p.h"
       
    56 #include "qtabbar_p.h"
       
    57 
       
    58 #include <qapplication.h>
       
    59 #include <qstatusbar.h>
       
    60 #include <qstring.h>
       
    61 #include <qstyle.h>
       
    62 #include <qvarlengtharray.h>
       
    63 #include <qstack.h>
       
    64 #include <qmap.h>
       
    65 #include <qtimer.h>
       
    66 
       
    67 #include <qdebug.h>
       
    68 
       
    69 #include <private/qapplication_p.h>
       
    70 #include <private/qlayoutengine_p.h>
       
    71 #ifdef Q_WS_MAC
       
    72 #   include <private/qcore_mac_p.h>
       
    73 #   include <private/qt_cocoa_helpers_mac_p.h>
       
    74 #endif
       
    75 
       
    76 #ifdef Q_DEBUG_MAINWINDOW_LAYOUT
       
    77 #   include <QTextStream>
       
    78 #endif
       
    79 
       
    80 QT_BEGIN_NAMESPACE
       
    81 
       
    82 /******************************************************************************
       
    83 ** debug
       
    84 */
       
    85 
       
    86 #if defined(Q_DEBUG_MAINWINDOW_LAYOUT) && !defined(QT_NO_DOCKWIDGET)
       
    87 
       
    88 static QTextStream qout(stderr, QIODevice::WriteOnly);
       
    89 
       
    90 static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent);
       
    91 
       
    92 static void dumpLayout(QTextStream &qout, const QDockAreaLayoutItem &item, QString indent)
       
    93 {
       
    94     qout << indent << "QDockAreaLayoutItem: "
       
    95             << "pos: " << item.pos << " size:" << item.size
       
    96             << " gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
       
    97             << " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize) << '\n';
       
    98     indent += QLatin1String("  ");
       
    99     if (item.widgetItem != 0) {
       
   100         qout << indent << "widget: "
       
   101             << item.widgetItem->widget()->metaObject()->className()
       
   102             << ' ' << item.widgetItem->widget()->windowTitle() << '\n';
       
   103     } else if (item.subinfo != 0) {
       
   104         qout << indent << "subinfo:\n";
       
   105         dumpLayout(qout, *item.subinfo, indent + QLatin1String("  "));
       
   106     } else if (item.placeHolderItem != 0) {
       
   107         QRect r = item.placeHolderItem->topLevelRect;
       
   108         qout << indent << "placeHolder: "
       
   109             << "pos: " << item.pos << " size:" << item.size
       
   110             << " gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
       
   111             << " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize)
       
   112             << " objectName:" << item.placeHolderItem->objectName
       
   113             << " hidden:" << item.placeHolderItem->hidden
       
   114             << " window:" << item.placeHolderItem->window
       
   115             << " rect:" << r.x() << ',' << r.y() << ' '
       
   116             << r.width() << 'x' << r.height() << '\n';
       
   117     }
       
   118     qout.flush();
       
   119 }
       
   120 
       
   121 static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent)
       
   122 {
       
   123     qout << indent << "QDockAreaLayoutInfo: "
       
   124             << layout.rect.left() << ','
       
   125             << layout.rect.top() << ' '
       
   126             << layout.rect.width() << 'x'
       
   127             << layout.rect.height()
       
   128             << " orient:" << layout.o
       
   129             << " tabbed:" << layout.tabbed
       
   130             << " tbshape:" << layout.tabBarShape << '\n';
       
   131 
       
   132     indent += QLatin1String("  ");
       
   133 
       
   134     for (int i = 0; i < layout.item_list.count(); ++i) {
       
   135         qout << indent << "Item: " << i << '\n';
       
   136         dumpLayout(qout, layout.item_list.at(i), indent + QLatin1String("  "));
       
   137     }
       
   138     qout.flush();
       
   139 };
       
   140 
       
   141 static void dumpLayout(QTextStream &qout, const QDockAreaLayout &layout, QString indent)
       
   142 {
       
   143     qout << indent << "QDockAreaLayout: "
       
   144             << layout.rect.left() << ','
       
   145             << layout.rect.top() << ' '
       
   146             << layout.rect.width() << 'x'
       
   147             << layout.rect.height() << '\n';
       
   148 
       
   149     qout << indent << "TopDockArea:\n";
       
   150     dumpLayout(qout, layout.docks[QInternal::TopDock], indent + QLatin1String("  "));
       
   151     qout << indent << "LeftDockArea:\n";
       
   152     dumpLayout(qout, layout.docks[QInternal::LeftDock], indent + QLatin1String("  "));
       
   153     qout << indent << "RightDockArea:\n";
       
   154     dumpLayout(qout, layout.docks[QInternal::RightDock], indent + QLatin1String("  "));
       
   155     qout << indent << "BottomDockArea:\n";
       
   156     dumpLayout(qout, layout.docks[QInternal::BottomDock], indent + QLatin1String("  "));
       
   157 
       
   158     qout.flush();
       
   159 };
       
   160 
       
   161 void qt_dumpLayout(QTextStream &qout, QMainWindow *window)
       
   162 {
       
   163     QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(window->layout());
       
   164     dumpLayout(qout, layout->layoutState.dockAreaLayout, QString());
       
   165 }
       
   166 
       
   167 #endif // Q_DEBUG_MAINWINDOW_LAYOUT && !QT_NO_DOCKWIDGET
       
   168 
       
   169 /******************************************************************************
       
   170 ** QMainWindowLayoutState
       
   171 */
       
   172 
       
   173 // we deal with all the #ifndefferry here so QMainWindowLayout code is clean
       
   174 
       
   175 QMainWindowLayoutState::QMainWindowLayoutState(QMainWindow *win)
       
   176     :
       
   177 #ifndef QT_NO_TOOLBAR
       
   178     toolBarAreaLayout(win),
       
   179 #endif
       
   180 #ifndef QT_NO_DOCKWIDGET
       
   181     dockAreaLayout(win)
       
   182 #else
       
   183     centralWidgetItem(0)
       
   184 #endif
       
   185 
       
   186 {
       
   187     mainWindow = win;
       
   188 }
       
   189 
       
   190 QSize QMainWindowLayoutState::sizeHint() const
       
   191 {
       
   192 
       
   193     QSize result(0, 0);
       
   194 
       
   195 #ifndef QT_NO_DOCKWIDGET
       
   196     result = dockAreaLayout.sizeHint();
       
   197 #else
       
   198     if (centralWidgetItem != 0)
       
   199         result = centralWidgetItem->sizeHint();
       
   200 #endif
       
   201 
       
   202 #ifndef QT_NO_TOOLBAR
       
   203     result = toolBarAreaLayout.sizeHint(result);
       
   204 #endif // QT_NO_TOOLBAR
       
   205 
       
   206     return result;
       
   207 }
       
   208 
       
   209 QSize QMainWindowLayoutState::minimumSize() const
       
   210 {
       
   211     QSize result(0, 0);
       
   212 
       
   213 #ifndef QT_NO_DOCKWIDGET
       
   214     result = dockAreaLayout.minimumSize();
       
   215 #else
       
   216     if (centralWidgetItem != 0)
       
   217         result = centralWidgetItem->minimumSize();
       
   218 #endif
       
   219 
       
   220 #ifndef QT_NO_TOOLBAR
       
   221     result = toolBarAreaLayout.minimumSize(result);
       
   222 #endif // QT_NO_TOOLBAR
       
   223 
       
   224     return result;
       
   225 }
       
   226 
       
   227 void QMainWindowLayoutState::apply(bool animated)
       
   228 {
       
   229 #ifndef QT_NO_TOOLBAR
       
   230     toolBarAreaLayout.apply(animated);
       
   231 #endif
       
   232 
       
   233 #ifndef QT_NO_DOCKWIDGET
       
   234 //    dumpLayout(dockAreaLayout, QString());
       
   235     dockAreaLayout.apply(animated);
       
   236 #else
       
   237     if (centralWidgetItem != 0) {
       
   238         QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
       
   239         Q_ASSERT(layout != 0);
       
   240         layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animated);
       
   241     }
       
   242 #endif
       
   243 }
       
   244 
       
   245 void QMainWindowLayoutState::fitLayout()
       
   246 {
       
   247     QRect r;
       
   248 #ifdef QT_NO_TOOLBAR
       
   249     r = rect;
       
   250 #else
       
   251     toolBarAreaLayout.rect = rect;
       
   252     r = toolBarAreaLayout.fitLayout();
       
   253 #endif // QT_NO_TOOLBAR
       
   254 
       
   255 #ifndef QT_NO_DOCKWIDGET
       
   256     dockAreaLayout.rect = r;
       
   257     dockAreaLayout.fitLayout();
       
   258 #else
       
   259     centralWidgetRect = r;
       
   260 #endif
       
   261 }
       
   262 
       
   263 void QMainWindowLayoutState::deleteAllLayoutItems()
       
   264 {
       
   265 #ifndef QT_NO_TOOLBAR
       
   266     toolBarAreaLayout.deleteAllLayoutItems();
       
   267 #endif
       
   268 
       
   269 #ifndef QT_NO_DOCKWIDGET
       
   270     dockAreaLayout.deleteAllLayoutItems();
       
   271 #endif
       
   272 }
       
   273 
       
   274 void QMainWindowLayoutState::deleteCentralWidgetItem()
       
   275 {
       
   276 #ifndef QT_NO_DOCKWIDGET
       
   277     delete dockAreaLayout.centralWidgetItem;
       
   278     dockAreaLayout.centralWidgetItem = 0;
       
   279 #else
       
   280     delete centralWidgetItem;
       
   281     centralWidgetItem = 0;
       
   282 #endif
       
   283 }
       
   284 
       
   285 QLayoutItem *QMainWindowLayoutState::itemAt(int index, int *x) const
       
   286 {
       
   287 #ifndef QT_NO_TOOLBAR
       
   288     if (QLayoutItem *ret = toolBarAreaLayout.itemAt(x, index))
       
   289         return ret;
       
   290 #endif
       
   291 
       
   292 #ifndef QT_NO_DOCKWIDGET
       
   293     if (QLayoutItem *ret = dockAreaLayout.itemAt(x, index))
       
   294         return ret;
       
   295 #else
       
   296     if (centralWidgetItem != 0 && (*x)++ == index)
       
   297         return centralWidgetItem;
       
   298 #endif
       
   299 
       
   300     return 0;
       
   301 }
       
   302 
       
   303 QLayoutItem *QMainWindowLayoutState::takeAt(int index, int *x)
       
   304 {
       
   305 #ifndef QT_NO_TOOLBAR
       
   306     if (QLayoutItem *ret = toolBarAreaLayout.takeAt(x, index))
       
   307         return ret;
       
   308 #endif
       
   309 
       
   310 #ifndef QT_NO_DOCKWIDGET
       
   311     if (QLayoutItem *ret = dockAreaLayout.takeAt(x, index))
       
   312         return ret;
       
   313 #else
       
   314     if (centralWidgetItem != 0 && (*x)++ == index) {
       
   315         QLayoutItem *ret = centralWidgetItem;
       
   316         centralWidgetItem = 0;
       
   317         return ret;
       
   318     }
       
   319 #endif
       
   320 
       
   321     return 0;
       
   322 }
       
   323 
       
   324 QList<int> QMainWindowLayoutState::indexOf(QWidget *widget) const
       
   325 {
       
   326     QList<int> result;
       
   327 
       
   328 #ifndef QT_NO_TOOLBAR
       
   329     // is it a toolbar?
       
   330     if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
       
   331         result = toolBarAreaLayout.indexOf(toolBar);
       
   332         if (!result.isEmpty())
       
   333             result.prepend(0);
       
   334         return result;
       
   335     }
       
   336 #endif
       
   337 
       
   338 #ifndef QT_NO_DOCKWIDGET
       
   339     // is it a dock widget?
       
   340     if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget)) {
       
   341         result = dockAreaLayout.indexOf(dockWidget);
       
   342         if (!result.isEmpty())
       
   343             result.prepend(1);
       
   344         return result;
       
   345     }
       
   346 #endif //QT_NO_DOCKWIDGET
       
   347 
       
   348     return result;
       
   349 }
       
   350 
       
   351 bool QMainWindowLayoutState::contains(QWidget *widget) const
       
   352 {
       
   353 #ifndef QT_NO_DOCKWIDGET
       
   354     if (dockAreaLayout.centralWidgetItem != 0 && dockAreaLayout.centralWidgetItem->widget() == widget)
       
   355         return true;
       
   356     if (!dockAreaLayout.indexOf(widget).isEmpty())
       
   357         return true;
       
   358 #else
       
   359     if (centralWidgetItem != 0 && centralWidgetItem->widget() == widget)
       
   360         return true;
       
   361 #endif
       
   362 
       
   363 #ifndef QT_NO_TOOLBAR
       
   364     if (!toolBarAreaLayout.indexOf(widget).isEmpty())
       
   365         return true;
       
   366 #endif
       
   367     return false;
       
   368 }
       
   369 
       
   370 void QMainWindowLayoutState::setCentralWidget(QWidget *widget)
       
   371 {
       
   372     QLayoutItem *item = 0;
       
   373     //make sure we remove the widget
       
   374     deleteCentralWidgetItem();
       
   375 
       
   376     if (widget != 0)
       
   377         item = new QWidgetItemV2(widget);
       
   378 
       
   379 #ifndef QT_NO_DOCKWIDGET
       
   380     dockAreaLayout.centralWidgetItem = item;
       
   381 #else
       
   382     centralWidgetItem = item;
       
   383 #endif
       
   384 }
       
   385 
       
   386 QWidget *QMainWindowLayoutState::centralWidget() const
       
   387 {
       
   388     QLayoutItem *item = 0;
       
   389 
       
   390 #ifndef QT_NO_DOCKWIDGET
       
   391     item = dockAreaLayout.centralWidgetItem;
       
   392 #else
       
   393     item = centralWidgetItem;
       
   394 #endif
       
   395 
       
   396     if (item != 0)
       
   397         return item->widget();
       
   398     return 0;
       
   399 }
       
   400 
       
   401 QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget,
       
   402                                             const QPoint &pos) const
       
   403 {
       
   404     QList<int> result;
       
   405 
       
   406 #ifndef QT_NO_TOOLBAR
       
   407     // is it a toolbar?
       
   408     if (qobject_cast<QToolBar*>(widget) != 0) {
       
   409         result = toolBarAreaLayout.gapIndex(pos);
       
   410         if (!result.isEmpty())
       
   411             result.prepend(0);
       
   412         return result;
       
   413     }
       
   414 #endif
       
   415 
       
   416 #ifndef QT_NO_DOCKWIDGET
       
   417     // is it a dock widget?
       
   418     if (qobject_cast<QDockWidget *>(widget) != 0) {
       
   419         result = dockAreaLayout.gapIndex(pos);
       
   420         if (!result.isEmpty())
       
   421             result.prepend(1);
       
   422         return result;
       
   423     }
       
   424 #endif //QT_NO_DOCKWIDGET
       
   425 
       
   426     return result;
       
   427 }
       
   428 
       
   429 bool QMainWindowLayoutState::insertGap(const QList<int> &path, QLayoutItem *item)
       
   430 {
       
   431     if (path.isEmpty())
       
   432         return false;
       
   433 
       
   434     int i = path.first();
       
   435 
       
   436 #ifndef QT_NO_TOOLBAR
       
   437     if (i == 0) {
       
   438         Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) != 0);
       
   439         return toolBarAreaLayout.insertGap(path.mid(1), item);
       
   440     }
       
   441 #endif
       
   442 
       
   443 #ifndef QT_NO_DOCKWIDGET
       
   444     if (i == 1) {
       
   445         Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) != 0);
       
   446         return dockAreaLayout.insertGap(path.mid(1), item);
       
   447     }
       
   448 #endif //QT_NO_DOCKWIDGET
       
   449 
       
   450     return false;
       
   451 }
       
   452 
       
   453 void QMainWindowLayoutState::remove(const QList<int> &path)
       
   454 {
       
   455     int i = path.first();
       
   456 
       
   457 #ifndef QT_NO_TOOLBAR
       
   458     if (i == 0)
       
   459         toolBarAreaLayout.remove(path.mid(1));
       
   460 #endif
       
   461 
       
   462 #ifndef QT_NO_DOCKWIDGET
       
   463     if (i == 1)
       
   464         dockAreaLayout.remove(path.mid(1));
       
   465 #endif //QT_NO_DOCKWIDGET
       
   466 }
       
   467 
       
   468 void QMainWindowLayoutState::remove(QLayoutItem *item)
       
   469 {
       
   470 #ifndef QT_NO_TOOLBAR
       
   471     toolBarAreaLayout.remove(item);
       
   472 #endif
       
   473 
       
   474 #ifndef QT_NO_DOCKWIDGET
       
   475     // is it a dock widget?
       
   476     if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(item->widget())) {
       
   477         QList<int> path = dockAreaLayout.indexOf(dockWidget);
       
   478         if (!path.isEmpty())
       
   479             dockAreaLayout.remove(path);
       
   480     }
       
   481 #endif //QT_NO_DOCKWIDGET
       
   482 }
       
   483 
       
   484 void QMainWindowLayoutState::clear()
       
   485 {
       
   486 #ifndef QT_NO_TOOLBAR
       
   487     toolBarAreaLayout.clear();
       
   488 #endif
       
   489 
       
   490 #ifndef QT_NO_DOCKWIDGET
       
   491     dockAreaLayout.clear();
       
   492 #else
       
   493     centralWidgetRect = QRect();
       
   494 #endif
       
   495 
       
   496     rect = QRect();
       
   497 }
       
   498 
       
   499 bool QMainWindowLayoutState::isValid() const
       
   500 {
       
   501     return rect.isValid();
       
   502 }
       
   503 
       
   504 QLayoutItem *QMainWindowLayoutState::item(const QList<int> &path)
       
   505 {
       
   506     int i = path.first();
       
   507 
       
   508 #ifndef QT_NO_TOOLBAR
       
   509     if (i == 0)
       
   510         return toolBarAreaLayout.item(path.mid(1)).widgetItem;
       
   511 #endif
       
   512 
       
   513 #ifndef QT_NO_DOCKWIDGET
       
   514     if (i == 1)
       
   515         return dockAreaLayout.item(path.mid(1)).widgetItem;
       
   516 #endif //QT_NO_DOCKWIDGET
       
   517 
       
   518     return 0;
       
   519 }
       
   520 
       
   521 QRect QMainWindowLayoutState::itemRect(const QList<int> &path) const
       
   522 {
       
   523     int i = path.first();
       
   524 
       
   525 #ifndef QT_NO_TOOLBAR
       
   526     if (i == 0)
       
   527         return toolBarAreaLayout.itemRect(path.mid(1));
       
   528 #endif
       
   529 
       
   530 #ifndef QT_NO_DOCKWIDGET
       
   531     if (i == 1)
       
   532         return dockAreaLayout.itemRect(path.mid(1));
       
   533 #endif //QT_NO_DOCKWIDGET
       
   534 
       
   535     return QRect();
       
   536 }
       
   537 
       
   538 QRect QMainWindowLayoutState::gapRect(const QList<int> &path) const
       
   539 {
       
   540     int i = path.first();
       
   541 
       
   542 #ifndef QT_NO_TOOLBAR
       
   543     if (i == 0)
       
   544         return toolBarAreaLayout.itemRect(path.mid(1));
       
   545 #endif
       
   546 
       
   547 #ifndef QT_NO_DOCKWIDGET
       
   548     if (i == 1)
       
   549         return dockAreaLayout.gapRect(path.mid(1));
       
   550 #endif //QT_NO_DOCKWIDGET
       
   551 
       
   552     return QRect();
       
   553 }
       
   554 
       
   555 QLayoutItem *QMainWindowLayoutState::plug(const QList<int> &path)
       
   556 {
       
   557     int i = path.first();
       
   558 
       
   559 #ifndef QT_NO_TOOLBAR
       
   560     if (i == 0)
       
   561         return toolBarAreaLayout.plug(path.mid(1));
       
   562 #endif
       
   563 
       
   564 #ifndef QT_NO_DOCKWIDGET
       
   565     if (i == 1)
       
   566         return dockAreaLayout.plug(path.mid(1));
       
   567 #endif //QT_NO_DOCKWIDGET
       
   568 
       
   569     return 0;
       
   570 }
       
   571 
       
   572 QLayoutItem *QMainWindowLayoutState::unplug(const QList<int> &path, QMainWindowLayoutState *other)
       
   573 {
       
   574     int i = path.first();
       
   575 
       
   576 #ifdef QT_NO_TOOLBAR
       
   577     Q_UNUSED(other);
       
   578 #else
       
   579     if (i == 0)
       
   580         return toolBarAreaLayout.unplug(path.mid(1), other ? &other->toolBarAreaLayout : 0);
       
   581 #endif
       
   582 
       
   583 #ifndef QT_NO_DOCKWIDGET
       
   584     if (i == 1)
       
   585         return dockAreaLayout.unplug(path.mid(1));
       
   586 #endif //QT_NO_DOCKWIDGET
       
   587 
       
   588     return 0;
       
   589 }
       
   590 
       
   591 void QMainWindowLayoutState::saveState(QDataStream &stream) const
       
   592 {
       
   593 #ifndef QT_NO_DOCKWIDGET
       
   594     dockAreaLayout.saveState(stream);
       
   595 #endif
       
   596 #ifndef QT_NO_TOOLBAR
       
   597     toolBarAreaLayout.saveState(stream);
       
   598 #endif
       
   599 }
       
   600 
       
   601 template <typename T>
       
   602 static QList<T> findChildrenHelper(const QObject *o)
       
   603 {
       
   604     const QObjectList &list = o->children();
       
   605     QList<T> result;
       
   606 
       
   607     for (int i=0; i < list.size(); ++i) {
       
   608         if (T t = qobject_cast<T>(list[i])) {
       
   609             result.append(t);
       
   610         }
       
   611     }
       
   612 
       
   613     return result;
       
   614 }
       
   615 
       
   616 //pre4.3 tests the format that was used before 4.3
       
   617 bool QMainWindowLayoutState::checkFormat(QDataStream &stream, bool pre43)
       
   618 {
       
   619 #ifdef QT_NO_TOOLBAR
       
   620     Q_UNUSED(pre43);
       
   621 #endif
       
   622     while (!stream.atEnd()) {
       
   623         uchar marker;
       
   624         stream >> marker;
       
   625         switch(marker)
       
   626         {
       
   627 #ifndef QT_NO_TOOLBAR
       
   628             case QToolBarAreaLayout::ToolBarStateMarker:
       
   629             case QToolBarAreaLayout::ToolBarStateMarkerEx:
       
   630                 {
       
   631                     QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow);
       
   632                     if (!toolBarAreaLayout.restoreState(stream, toolBars, marker,
       
   633                         pre43 /*testing 4.3 format*/, true /*testing*/)) {
       
   634                             return false;
       
   635                     }
       
   636                 }
       
   637                 break;
       
   638 #endif // QT_NO_TOOLBAR
       
   639 
       
   640 #ifndef QT_NO_DOCKWIDGET
       
   641             case QDockAreaLayout::DockWidgetStateMarker:
       
   642                 {
       
   643                     QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
       
   644                     if (!dockAreaLayout.restoreState(stream, dockWidgets, true /*testing*/)) {
       
   645                         return false;
       
   646                     }
       
   647                 }
       
   648                 break;
       
   649 #endif
       
   650             default:
       
   651                 //there was an error during the parsing
       
   652                 return false;
       
   653         }// switch
       
   654     } //while
       
   655 
       
   656     //everything went fine: it must be a pre-4.3 saved state
       
   657     return true;
       
   658 }
       
   659 
       
   660 bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
       
   661                                         const QMainWindowLayoutState &oldState)
       
   662 {
       
   663     //make a copy of the data so that we can read it more than once
       
   664     QByteArray copy;
       
   665     while(!_stream.atEnd()) {
       
   666         int length = 1024;
       
   667         QByteArray ba(length, '\0');
       
   668         length = _stream.readRawData(ba.data(), ba.size());
       
   669         ba.resize(length);
       
   670         copy += ba;
       
   671     }
       
   672 
       
   673     QDataStream ds(copy);
       
   674     const bool oldFormat = !checkFormat(ds, false);
       
   675     if (oldFormat) {
       
   676         //we should try with the old format
       
   677         QDataStream ds2(copy);
       
   678         if (!checkFormat(ds2, true)) {
       
   679             return false; //format unknown
       
   680         }
       
   681     }
       
   682 
       
   683     QDataStream stream(copy);
       
   684 
       
   685     while (!stream.atEnd()) {
       
   686         uchar marker;
       
   687         stream >> marker;
       
   688         switch(marker)
       
   689         {
       
   690 #ifndef QT_NO_DOCKWIDGET
       
   691             case QDockAreaLayout::DockWidgetStateMarker:
       
   692                 {
       
   693                     QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
       
   694                     if (!dockAreaLayout.restoreState(stream, dockWidgets))
       
   695                         return false;
       
   696 
       
   697                     for (int i = 0; i < dockWidgets.size(); ++i) {
       
   698                         QDockWidget *w = dockWidgets.at(i);
       
   699                         QList<int> path = dockAreaLayout.indexOf(w);
       
   700                         if (path.isEmpty()) {
       
   701                             QList<int> oldPath = oldState.dockAreaLayout.indexOf(w);
       
   702                             if (oldPath.isEmpty()) {
       
   703                                 continue;
       
   704                             }
       
   705                             QDockAreaLayoutInfo *info = dockAreaLayout.info(oldPath);
       
   706                             if (info == 0) {
       
   707                                 continue;
       
   708                             }
       
   709                             info->item_list.append(QDockAreaLayoutItem(new QDockWidgetItem(w)));
       
   710                         }
       
   711                     }
       
   712                 }
       
   713                 break;
       
   714 #endif // QT_NO_DOCKWIDGET
       
   715 
       
   716 #ifndef QT_NO_TOOLBAR
       
   717             case QToolBarAreaLayout::ToolBarStateMarker:
       
   718             case QToolBarAreaLayout::ToolBarStateMarkerEx:
       
   719                 {
       
   720                     QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow);
       
   721                     if (!toolBarAreaLayout.restoreState(stream, toolBars, marker, oldFormat))
       
   722                         return false;
       
   723 
       
   724                     for (int i = 0; i < toolBars.size(); ++i) {
       
   725                         QToolBar *w = toolBars.at(i);
       
   726                         QList<int> path = toolBarAreaLayout.indexOf(w);
       
   727                         if (path.isEmpty()) {
       
   728                             QList<int> oldPath = oldState.toolBarAreaLayout.indexOf(w);
       
   729                             if (oldPath.isEmpty()) {
       
   730                                 continue;
       
   731                             }
       
   732                             toolBarAreaLayout.docks[oldPath.at(0)].insertToolBar(0, w);
       
   733                         }
       
   734                     }
       
   735                 }
       
   736                 break;
       
   737 #endif //QT_NO_TOOLBAR
       
   738             default:
       
   739                 return false;
       
   740         }// switch
       
   741     } //while
       
   742 
       
   743 
       
   744     return true;
       
   745 }
       
   746 
       
   747 /******************************************************************************
       
   748 ** QMainWindowLayoutState - toolbars
       
   749 */
       
   750 
       
   751 #ifndef QT_NO_TOOLBAR
       
   752 
       
   753 static inline void validateToolBarArea(Qt::ToolBarArea &area)
       
   754 {
       
   755     switch (area) {
       
   756     case Qt::LeftToolBarArea:
       
   757     case Qt::RightToolBarArea:
       
   758     case Qt::TopToolBarArea:
       
   759     case Qt::BottomToolBarArea:
       
   760         break;
       
   761     default:
       
   762         area = Qt::TopToolBarArea;
       
   763     }
       
   764 }
       
   765 
       
   766 static QInternal::DockPosition toDockPos(Qt::ToolBarArea area)
       
   767 {
       
   768     switch (area) {
       
   769         case Qt::LeftToolBarArea: return QInternal::LeftDock;
       
   770         case Qt::RightToolBarArea: return QInternal::RightDock;
       
   771         case Qt::TopToolBarArea: return QInternal::TopDock;
       
   772         case Qt::BottomToolBarArea: return QInternal::BottomDock;
       
   773         default:
       
   774             break;
       
   775     }
       
   776 
       
   777     return QInternal::DockCount;
       
   778 }
       
   779 
       
   780 static Qt::ToolBarArea toToolBarArea(QInternal::DockPosition pos)
       
   781 {
       
   782     switch (pos) {
       
   783         case QInternal::LeftDock:   return Qt::LeftToolBarArea;
       
   784         case QInternal::RightDock:  return Qt::RightToolBarArea;
       
   785         case QInternal::TopDock:    return Qt::TopToolBarArea;
       
   786         case QInternal::BottomDock: return Qt::BottomToolBarArea;
       
   787         default: break;
       
   788     }
       
   789     return Qt::NoToolBarArea;
       
   790 }
       
   791 
       
   792 static inline Qt::ToolBarArea toToolBarArea(int pos)
       
   793 {
       
   794     return toToolBarArea(static_cast<QInternal::DockPosition>(pos));
       
   795 }
       
   796 
       
   797 void QMainWindowLayout::addToolBarBreak(Qt::ToolBarArea area)
       
   798 {
       
   799     validateToolBarArea(area);
       
   800 
       
   801     layoutState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
       
   802     if (savedState.isValid())
       
   803         savedState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
       
   804 
       
   805     invalidate();
       
   806 }
       
   807 
       
   808 void QMainWindowLayout::insertToolBarBreak(QToolBar *before)
       
   809 {
       
   810     layoutState.toolBarAreaLayout.insertToolBarBreak(before);
       
   811     if (savedState.isValid())
       
   812         savedState.toolBarAreaLayout.insertToolBarBreak(before);
       
   813     invalidate();
       
   814 }
       
   815 
       
   816 void QMainWindowLayout::removeToolBarBreak(QToolBar *before)
       
   817 {
       
   818     layoutState.toolBarAreaLayout.removeToolBarBreak(before);
       
   819     if (savedState.isValid())
       
   820         savedState.toolBarAreaLayout.removeToolBarBreak(before);
       
   821     invalidate();
       
   822 }
       
   823 
       
   824 void QMainWindowLayout::moveToolBar(QToolBar *toolbar, int pos)
       
   825 {
       
   826     layoutState.toolBarAreaLayout.moveToolBar(toolbar, pos);
       
   827     if (savedState.isValid())
       
   828         savedState.toolBarAreaLayout.moveToolBar(toolbar, pos);
       
   829     invalidate();
       
   830 }
       
   831 
       
   832 /* Removes the toolbar from the mainwindow so that it can be added again. Does not
       
   833    explicitly hide the toolbar. */
       
   834 void QMainWindowLayout::removeToolBar(QToolBar *toolbar)
       
   835 {
       
   836     if (toolbar) {
       
   837         QObject::disconnect(parentWidget(), SIGNAL(iconSizeChanged(QSize)),
       
   838                    toolbar, SLOT(_q_updateIconSize(QSize)));
       
   839         QObject::disconnect(parentWidget(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
       
   840                    toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
       
   841 
       
   842 #ifdef Q_WS_MAC
       
   843         if (usesHIToolBar(toolbar)) {
       
   844             removeFromMacToolbar(toolbar);
       
   845         } else
       
   846 #endif // Q_WS_MAC
       
   847         {
       
   848             removeWidget(toolbar);
       
   849         }
       
   850     }
       
   851 }
       
   852 
       
   853 /*!
       
   854     Adds \a toolbar to \a area, continuing the current line.
       
   855 */
       
   856 void QMainWindowLayout::addToolBar(Qt::ToolBarArea area,
       
   857                                    QToolBar *toolbar,
       
   858                                    bool)
       
   859 {
       
   860     validateToolBarArea(area);
       
   861 #ifdef Q_WS_MAC
       
   862     if ((area == Qt::TopToolBarArea)
       
   863             && layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
       
   864         insertIntoMacToolbar(0, toolbar);
       
   865     } else
       
   866 #endif
       
   867     {
       
   868         //let's add the toolbar to the layout
       
   869         addChildWidget(toolbar);
       
   870         QLayoutItem * item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar);
       
   871         if (savedState.isValid() && item) {
       
   872             // copy the toolbar also in the saved state
       
   873             savedState.toolBarAreaLayout.insertItem(toDockPos(area), item);
       
   874         }
       
   875         invalidate();
       
   876 
       
   877         //this ensures that the toolbar has the right window flags (not floating any more)
       
   878         toolbar->d_func()->updateWindowFlags(false /*floating*/);
       
   879     }
       
   880 }
       
   881 
       
   882 /*!
       
   883     Adds \a toolbar before \a before
       
   884 */
       
   885 void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar)
       
   886 {
       
   887 #ifdef Q_WS_MAC
       
   888     if (usesHIToolBar(before)) {
       
   889         insertIntoMacToolbar(before, toolbar);
       
   890     } else
       
   891 #endif // Q_WS_MAC
       
   892     {
       
   893         addChildWidget(toolbar);
       
   894         QLayoutItem * item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar);
       
   895         if (savedState.isValid() && item) {
       
   896             // copy the toolbar also in the saved state
       
   897             savedState.toolBarAreaLayout.insertItem(before, item);
       
   898         }
       
   899         if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) {
       
   900             currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
       
   901             if (!currentGapPos.isEmpty()) {
       
   902                 currentGapPos.prepend(0);
       
   903                 currentGapRect = layoutState.itemRect(currentGapPos);
       
   904             }
       
   905         }
       
   906         invalidate();
       
   907     }
       
   908 }
       
   909 
       
   910 Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const
       
   911 {
       
   912     QInternal::DockPosition pos = layoutState.toolBarAreaLayout.findToolBar(toolbar);
       
   913     switch (pos) {
       
   914         case QInternal::LeftDock:   return Qt::LeftToolBarArea;
       
   915         case QInternal::RightDock:  return Qt::RightToolBarArea;
       
   916         case QInternal::TopDock:    return Qt::TopToolBarArea;
       
   917         case QInternal::BottomDock: return Qt::BottomToolBarArea;
       
   918         default: break;
       
   919     }
       
   920 #ifdef Q_WS_MAC
       
   921     if (pos == QInternal::DockCount) {
       
   922         if (qtoolbarsInUnifiedToolbarList.contains(toolbar))
       
   923             return Qt::TopToolBarArea;
       
   924     }
       
   925 #endif
       
   926     return Qt::NoToolBarArea;
       
   927 }
       
   928 
       
   929 bool QMainWindowLayout::toolBarBreak(QToolBar *toolBar) const
       
   930 {
       
   931     return layoutState.toolBarAreaLayout.toolBarBreak(toolBar);
       
   932 }
       
   933 
       
   934 void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const
       
   935 {
       
   936     option->toolBarArea = toolBarArea(toolBar);
       
   937     layoutState.toolBarAreaLayout.getStyleOptionInfo(option, toolBar);
       
   938 }
       
   939 
       
   940 void QMainWindowLayout::toggleToolBarsVisible()
       
   941 {
       
   942     bool updateNonUnifiedParts = true;
       
   943 #ifdef Q_WS_MAC
       
   944     if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
       
   945         // If we hit this case, someone has pressed the "toolbar button" which will
       
   946         // toggle the unified toolbar visiblity, because that's what the user wants.
       
   947         // We might be in a situation where someone has hidden all the toolbars
       
   948         // beforehand (maybe in construction), but now they've hit this button and
       
   949         // and are expecting the items to show. What do we do?
       
   950         // 1) Check the visibility of all the toolbars, if one is visible, do nothing, this
       
   951         //    preserves what people would expect (these toolbars were visible when I clicked last time).
       
   952         // 2) If NONE are visible, then show them all. Again, this preserves the user expectation
       
   953         //    of, "I want to see the toolbars." The user may get more toolbars than expected, but this
       
   954         //    is better seeing nothing.
       
   955         // Don't worry about any of this if we are going invisible. This does mean we may get
       
   956         // into issues when switching into and out of fullscreen mode, but this is probably minor.
       
   957         // If we ever need to do hiding, that would have to be taken care of after the unified toolbar
       
   958         // has finished hiding.
       
   959         // People can of course handle the QEvent::ToolBarChange event themselves and do
       
   960         // WHATEVER they want if they don't like what we are doing (though the unified toolbar
       
   961         // will fire regardless).
       
   962 
       
   963         // Check if we REALLY need to update the geometry below. If we only have items in the
       
   964         // unified toolbar, all the docks will be empty, so there's very little point
       
   965         // in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well).
       
   966         // FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar
       
   967         // visibility can get out of sync. I really don't think it's a big issue. It is kept
       
   968         // to a minimum because we only change the visibility if we absolutely must.
       
   969         // update the "non unified parts."
       
   970         updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty();
       
   971 
       
   972         // We get this function before the unified toolbar does its thing.
       
   973         // So, the value will be opposite of what we expect.
       
   974         bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow));
       
   975         if (goingVisible) {
       
   976             const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size();
       
   977             bool needAllVisible = true;
       
   978             for (int i = 0; i < ToolBarCount; ++i) {
       
   979                 if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) {
       
   980                     needAllVisible = false;
       
   981                     break;
       
   982                 }
       
   983             }
       
   984             if (needAllVisible) {
       
   985                 QBoolBlocker blocker(blockVisiblityCheck);  // Disable the visibilty check because
       
   986                                                             // the toggle has already happened.
       
   987                 for (int i = 0; i < ToolBarCount; ++i)
       
   988                     qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true);
       
   989             }
       
   990         }
       
   991         if (!updateNonUnifiedParts)
       
   992             layoutState.toolBarAreaLayout.visible = goingVisible;
       
   993     }
       
   994 #endif
       
   995     if (updateNonUnifiedParts) {
       
   996         layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible;
       
   997         if (!layoutState.mainWindow->isMaximized()) {
       
   998             QPoint topLeft = parentWidget()->geometry().topLeft();
       
   999             QRect r = parentWidget()->geometry();
       
  1000             r = layoutState.toolBarAreaLayout.rectHint(r);
       
  1001             r.moveTo(topLeft);
       
  1002             parentWidget()->setGeometry(r);
       
  1003         } else {
       
  1004             update();
       
  1005         }
       
  1006     }
       
  1007 }
       
  1008 
       
  1009 #endif // QT_NO_TOOLBAR
       
  1010 
       
  1011 /******************************************************************************
       
  1012 ** QMainWindowLayoutState - dock areas
       
  1013 */
       
  1014 
       
  1015 #ifndef QT_NO_DOCKWIDGET
       
  1016 
       
  1017 static inline void validateDockWidgetArea(Qt::DockWidgetArea &area)
       
  1018 {
       
  1019     switch (area) {
       
  1020     case Qt::LeftDockWidgetArea:
       
  1021     case Qt::RightDockWidgetArea:
       
  1022     case Qt::TopDockWidgetArea:
       
  1023     case Qt::BottomDockWidgetArea:
       
  1024         break;
       
  1025     default:
       
  1026         area = Qt::LeftDockWidgetArea;
       
  1027     }
       
  1028 }
       
  1029 
       
  1030 static QInternal::DockPosition toDockPos(Qt::DockWidgetArea area)
       
  1031 {
       
  1032     switch (area) {
       
  1033         case Qt::LeftDockWidgetArea: return QInternal::LeftDock;
       
  1034         case Qt::RightDockWidgetArea: return QInternal::RightDock;
       
  1035         case Qt::TopDockWidgetArea: return QInternal::TopDock;
       
  1036         case Qt::BottomDockWidgetArea: return QInternal::BottomDock;
       
  1037         default:
       
  1038             break;
       
  1039     }
       
  1040 
       
  1041     return QInternal::DockCount;
       
  1042 }
       
  1043 
       
  1044 static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
       
  1045 {
       
  1046     switch (pos) {
       
  1047         case QInternal::LeftDock : return Qt::LeftDockWidgetArea;
       
  1048         case QInternal::RightDock : return Qt::RightDockWidgetArea;
       
  1049         case QInternal::TopDock : return Qt::TopDockWidgetArea;
       
  1050         case QInternal::BottomDock : return Qt::BottomDockWidgetArea;
       
  1051         default:
       
  1052             break;
       
  1053     }
       
  1054 
       
  1055     return Qt::NoDockWidgetArea;
       
  1056 }
       
  1057 
       
  1058 inline static Qt::DockWidgetArea toDockWidgetArea(int pos)
       
  1059 {
       
  1060     return toDockWidgetArea(static_cast<QInternal::DockPosition>(pos));
       
  1061 }
       
  1062 
       
  1063 void QMainWindowLayout::setCorner(Qt::Corner corner, Qt::DockWidgetArea area)
       
  1064 {
       
  1065     if (layoutState.dockAreaLayout.corners[corner] == area)
       
  1066         return;
       
  1067     layoutState.dockAreaLayout.corners[corner] = area;
       
  1068     if (savedState.isValid())
       
  1069         savedState.dockAreaLayout.corners[corner] = area;
       
  1070     invalidate();
       
  1071 }
       
  1072 
       
  1073 Qt::DockWidgetArea QMainWindowLayout::corner(Qt::Corner corner) const
       
  1074 {
       
  1075     return layoutState.dockAreaLayout.corners[corner];
       
  1076 }
       
  1077 
       
  1078 void QMainWindowLayout::addDockWidget(Qt::DockWidgetArea area,
       
  1079                                              QDockWidget *dockwidget,
       
  1080                                              Qt::Orientation orientation)
       
  1081 {
       
  1082     addChildWidget(dockwidget);
       
  1083 
       
  1084     // If we are currently moving a separator, then we need to abort the move, since each
       
  1085     // time we move the mouse layoutState is replaced by savedState modified by the move.
       
  1086     if (!movingSeparator.isEmpty())
       
  1087         endSeparatorMove(movingSeparatorPos);
       
  1088 
       
  1089     layoutState.dockAreaLayout.addDockWidget(toDockPos(area), dockwidget, orientation);
       
  1090     emit dockwidget->dockLocationChanged(area);
       
  1091     invalidate();
       
  1092 }
       
  1093 
       
  1094 void QMainWindowLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
       
  1095 {
       
  1096     addChildWidget(second);
       
  1097     layoutState.dockAreaLayout.tabifyDockWidget(first, second);
       
  1098     emit second->dockLocationChanged(dockWidgetArea(first));
       
  1099     invalidate();
       
  1100 }
       
  1101 
       
  1102 bool QMainWindowLayout::restoreDockWidget(QDockWidget *dockwidget)
       
  1103 {
       
  1104     addChildWidget(dockwidget);
       
  1105     if (!layoutState.dockAreaLayout.restoreDockWidget(dockwidget))
       
  1106         return false;
       
  1107     emit dockwidget->dockLocationChanged(dockWidgetArea(dockwidget));
       
  1108     invalidate();
       
  1109     return true;
       
  1110 }
       
  1111 
       
  1112 #ifndef QT_NO_TABBAR
       
  1113 bool QMainWindowLayout::documentMode() const
       
  1114 {
       
  1115     return _documentMode;
       
  1116 }
       
  1117 
       
  1118 void QMainWindowLayout::setDocumentMode(bool enabled)
       
  1119 {
       
  1120     if (_documentMode == enabled)
       
  1121         return;
       
  1122 
       
  1123     _documentMode = enabled;
       
  1124 
       
  1125     // Update the document mode for all tab bars
       
  1126     foreach (QTabBar *bar, usedTabBars)
       
  1127         bar->setDocumentMode(_documentMode);
       
  1128     foreach (QTabBar *bar, unusedTabBars)
       
  1129         bar->setDocumentMode(_documentMode);
       
  1130 }
       
  1131 #endif // QT_NO_TABBAR
       
  1132 
       
  1133 void QMainWindowLayout::setVerticalTabsEnabled(bool enabled)
       
  1134 {
       
  1135 #ifdef QT_NO_TABBAR
       
  1136     Q_UNUSED(enabled);
       
  1137 #else
       
  1138     if (verticalTabsEnabled == enabled)
       
  1139         return;
       
  1140 
       
  1141     verticalTabsEnabled = enabled;
       
  1142 
       
  1143     updateTabBarShapes();
       
  1144 #endif // QT_NO_TABBAR
       
  1145 }
       
  1146 
       
  1147 #ifndef QT_NO_TABWIDGET
       
  1148 QTabWidget::TabShape QMainWindowLayout::tabShape() const
       
  1149 {
       
  1150     return _tabShape;
       
  1151 }
       
  1152 
       
  1153 void QMainWindowLayout::setTabShape(QTabWidget::TabShape tabShape)
       
  1154 {
       
  1155     if (_tabShape == tabShape)
       
  1156         return;
       
  1157 
       
  1158     _tabShape = tabShape;
       
  1159 
       
  1160     updateTabBarShapes();
       
  1161 }
       
  1162 
       
  1163 QTabWidget::TabPosition QMainWindowLayout::tabPosition(Qt::DockWidgetArea area) const
       
  1164 {
       
  1165     return tabPositions[toDockPos(area)];
       
  1166 }
       
  1167 
       
  1168 void QMainWindowLayout::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition)
       
  1169 {
       
  1170     const Qt::DockWidgetArea dockWidgetAreas[] = {
       
  1171         Qt::TopDockWidgetArea,
       
  1172         Qt::LeftDockWidgetArea,
       
  1173         Qt::BottomDockWidgetArea,
       
  1174         Qt::RightDockWidgetArea
       
  1175     };
       
  1176     const QInternal::DockPosition dockPositions[] = {
       
  1177         QInternal::TopDock,
       
  1178         QInternal::LeftDock,
       
  1179         QInternal::BottomDock,
       
  1180         QInternal::RightDock
       
  1181     };
       
  1182 
       
  1183     for (int i = 0; i < QInternal::DockCount; ++i)
       
  1184         if (areas & dockWidgetAreas[i])
       
  1185             tabPositions[dockPositions[i]] = tabPosition;
       
  1186 
       
  1187     updateTabBarShapes();
       
  1188 }
       
  1189 
       
  1190 static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
       
  1191 {
       
  1192     const bool rounded = (shape == QTabWidget::Rounded);
       
  1193     if (position == QTabWidget::North)
       
  1194         return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
       
  1195     if (position == QTabWidget::South)
       
  1196         return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
       
  1197     if (position == QTabWidget::East)
       
  1198         return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
       
  1199     if (position == QTabWidget::West)
       
  1200         return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
       
  1201     return QTabBar::RoundedNorth;
       
  1202 }
       
  1203 #endif // QT_NO_TABWIDGET
       
  1204 
       
  1205 #ifndef QT_NO_TABBAR
       
  1206 void QMainWindowLayout::updateTabBarShapes()
       
  1207 {
       
  1208 #ifndef QT_NO_TABWIDGET
       
  1209     const QTabWidget::TabPosition vertical[] = {
       
  1210         QTabWidget::West,
       
  1211         QTabWidget::East,
       
  1212         QTabWidget::North,
       
  1213         QTabWidget::South
       
  1214     };
       
  1215 #else
       
  1216     const QTabBar::Shape vertical[] = {
       
  1217         QTabBar::RoundedWest,
       
  1218         QTabBar::RoundedEast,
       
  1219         QTabBar::RoundedNorth,
       
  1220         QTabBar::RoundedSouth
       
  1221     };
       
  1222 #endif
       
  1223 
       
  1224     QDockAreaLayout &layout = layoutState.dockAreaLayout;
       
  1225 
       
  1226     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  1227 #ifndef QT_NO_TABWIDGET
       
  1228         QTabWidget::TabPosition pos = verticalTabsEnabled ? vertical[i] : tabPositions[i];
       
  1229         QTabBar::Shape shape = tabBarShapeFrom(_tabShape, pos);
       
  1230 #else
       
  1231         QTabBar::Shape shape = verticalTabsEnabled ? vertical[i] : QTabBar::RoundedSouth;
       
  1232 #endif
       
  1233         layout.docks[i].setTabBarShape(shape);
       
  1234     }
       
  1235 }
       
  1236 #endif // QT_NO_TABBAR
       
  1237 
       
  1238 void QMainWindowLayout::splitDockWidget(QDockWidget *after,
       
  1239                                         QDockWidget *dockwidget,
       
  1240                                         Qt::Orientation orientation)
       
  1241 {
       
  1242     addChildWidget(dockwidget);
       
  1243     layoutState.dockAreaLayout.splitDockWidget(after, dockwidget, orientation);
       
  1244     emit dockwidget->dockLocationChanged(dockWidgetArea(after));
       
  1245     invalidate();
       
  1246 }
       
  1247 
       
  1248 Qt::DockWidgetArea QMainWindowLayout::dockWidgetArea(QDockWidget *widget) const
       
  1249 {
       
  1250     QList<int> pathToWidget = layoutState.dockAreaLayout.indexOf(widget);
       
  1251     if (pathToWidget.isEmpty())
       
  1252         return Qt::NoDockWidgetArea;
       
  1253     return toDockWidgetArea(pathToWidget.first());
       
  1254 }
       
  1255 
       
  1256 void QMainWindowLayout::keepSize(QDockWidget *w)
       
  1257 {
       
  1258     layoutState.dockAreaLayout.keepSize(w);
       
  1259 }
       
  1260 
       
  1261 #ifndef QT_NO_TABBAR
       
  1262 
       
  1263 class QMainWindowTabBar : public QTabBar
       
  1264 {
       
  1265 public:
       
  1266     QMainWindowTabBar(QWidget *parent);
       
  1267 protected:
       
  1268     bool event(QEvent *e);
       
  1269 };
       
  1270 
       
  1271 QMainWindowTabBar::QMainWindowTabBar(QWidget *parent)
       
  1272     : QTabBar(parent)
       
  1273 {
       
  1274     setExpanding(false);
       
  1275 }
       
  1276 
       
  1277 bool QMainWindowTabBar::event(QEvent *e)
       
  1278 {
       
  1279     // show the tooltip if tab is too small to fit label
       
  1280 
       
  1281     if (e->type() != QEvent::ToolTip)
       
  1282         return QTabBar::event(e);
       
  1283     QSize size = this->size();
       
  1284     QSize hint = sizeHint();
       
  1285     if (shape() == QTabBar::RoundedWest || shape() == QTabBar::RoundedEast) {
       
  1286         size.transpose();
       
  1287         hint.transpose();
       
  1288     }
       
  1289     if (size.width() < hint.width())
       
  1290         return QTabBar::event(e);
       
  1291     e->accept();
       
  1292     return true;
       
  1293 }
       
  1294 
       
  1295 QTabBar *QMainWindowLayout::getTabBar()
       
  1296 {
       
  1297     QTabBar *result = 0;
       
  1298     if (!unusedTabBars.isEmpty()) {
       
  1299         result = unusedTabBars.takeLast();
       
  1300     } else {
       
  1301         result = new QMainWindowTabBar(parentWidget());
       
  1302         result->setDrawBase(true);
       
  1303         result->setElideMode(Qt::ElideRight);
       
  1304         result->setDocumentMode(_documentMode);
       
  1305         connect(result, SIGNAL(currentChanged(int)), this, SLOT(tabChanged()));
       
  1306     }
       
  1307 
       
  1308     usedTabBars.insert(result);
       
  1309     return result;
       
  1310 }
       
  1311 
       
  1312 // Allocates a new separator widget if needed
       
  1313 QWidget *QMainWindowLayout::getSeparatorWidget()
       
  1314 {
       
  1315     QWidget *result = 0;
       
  1316     if (!unusedSeparatorWidgets.isEmpty()) {
       
  1317         result = unusedSeparatorWidgets.takeLast();
       
  1318     } else {
       
  1319         result = new QWidget(parentWidget());
       
  1320         result->setAttribute(Qt::WA_MouseNoMask, true);
       
  1321         result->setAutoFillBackground(false);
       
  1322         result->setObjectName(QLatin1String("qt_qmainwindow_extended_splitter"));
       
  1323     }
       
  1324     usedSeparatorWidgets.insert(result);
       
  1325     return result;
       
  1326 }
       
  1327 
       
  1328 void QMainWindowLayout::tabChanged()
       
  1329 {
       
  1330     QTabBar *tb = qobject_cast<QTabBar*>(sender());
       
  1331     if (tb == 0)
       
  1332         return;
       
  1333     QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(tb);
       
  1334     if (info == 0)
       
  1335         return;
       
  1336     info->apply(false);
       
  1337 
       
  1338     if (QWidget *w = centralWidget())
       
  1339         w->raise();
       
  1340 }
       
  1341 #endif // QT_NO_TABBAR
       
  1342 
       
  1343 bool QMainWindowLayout::startSeparatorMove(const QPoint &pos)
       
  1344 {
       
  1345     movingSeparator = layoutState.dockAreaLayout.findSeparator(pos);
       
  1346 
       
  1347     if (movingSeparator.isEmpty())
       
  1348         return false;
       
  1349 
       
  1350     savedState = layoutState;
       
  1351     movingSeparatorPos = movingSeparatorOrigin = pos;
       
  1352 
       
  1353     return true;
       
  1354 }
       
  1355 
       
  1356 bool QMainWindowLayout::separatorMove(const QPoint &pos)
       
  1357 {
       
  1358     if (movingSeparator.isEmpty())
       
  1359         return false;
       
  1360     movingSeparatorPos = pos;
       
  1361     separatorMoveTimer.start(0, this);
       
  1362     return true;
       
  1363 }
       
  1364 
       
  1365 bool QMainWindowLayout::endSeparatorMove(const QPoint&)
       
  1366 {
       
  1367     bool result = !movingSeparator.isEmpty();
       
  1368     movingSeparator.clear();
       
  1369     savedState.clear();
       
  1370     return result;
       
  1371 }
       
  1372 
       
  1373 void QMainWindowLayout::raise(QDockWidget *widget)
       
  1374 {
       
  1375     QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget);
       
  1376     if (info == 0)
       
  1377         return;
       
  1378 #ifndef QT_NO_TABBAR
       
  1379     if (!info->tabbed)
       
  1380         return;
       
  1381     info->setCurrentTab(widget);
       
  1382 #endif
       
  1383 }
       
  1384 
       
  1385 #endif // QT_NO_DOCKWIDGET
       
  1386 
       
  1387 
       
  1388 /******************************************************************************
       
  1389 ** QMainWindowLayoutState - layout interface
       
  1390 */
       
  1391 
       
  1392 int QMainWindowLayout::count() const
       
  1393 {
       
  1394     qWarning("QMainWindowLayout::count: ?");
       
  1395     return 0; //#################################################
       
  1396 }
       
  1397 
       
  1398 QLayoutItem *QMainWindowLayout::itemAt(int index) const
       
  1399 {
       
  1400     int x = 0;
       
  1401 
       
  1402     if (QLayoutItem *ret = layoutState.itemAt(index, &x))
       
  1403         return ret;
       
  1404 
       
  1405     if (statusbar && x++ == index)
       
  1406         return statusbar;
       
  1407 
       
  1408     return 0;
       
  1409 }
       
  1410 
       
  1411 QLayoutItem *QMainWindowLayout::takeAt(int index)
       
  1412 {
       
  1413     int x = 0;
       
  1414 
       
  1415     if (QLayoutItem *ret = layoutState.takeAt(index, &x)) {
       
  1416         // the widget might in fact have been destroyed by now
       
  1417         if (QWidget *w = ret->widget()) {
       
  1418             widgetAnimator.abort(w);
       
  1419             if (w == pluggingWidget)
       
  1420                 pluggingWidget = 0;
       
  1421         }
       
  1422 
       
  1423         if (savedState.isValid() ) {
       
  1424             //we need to remove the item also from the saved state to prevent crash
       
  1425             savedState.remove(ret);
       
  1426             //Also, the item may be contained several times as a gap item.
       
  1427             layoutState.remove(ret);
       
  1428         }
       
  1429 
       
  1430 #ifndef QT_NO_TOOLBAR
       
  1431         if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) {
       
  1432             currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
       
  1433             if (!currentGapPos.isEmpty()) {
       
  1434                 currentGapPos.prepend(0);
       
  1435                 currentGapRect = layoutState.itemRect(currentGapPos);
       
  1436             }
       
  1437         }
       
  1438 #endif
       
  1439 
       
  1440         return ret;
       
  1441     }
       
  1442 
       
  1443     if (statusbar && x++ == index) {
       
  1444         QLayoutItem *ret = statusbar;
       
  1445         statusbar = 0;
       
  1446         return ret;
       
  1447     }
       
  1448 
       
  1449     return 0;
       
  1450 }
       
  1451 
       
  1452 void QMainWindowLayout::setGeometry(const QRect &_r)
       
  1453 {
       
  1454     if (savedState.isValid())
       
  1455         return;
       
  1456 
       
  1457     QRect r = _r;
       
  1458 
       
  1459     QLayout::setGeometry(r);
       
  1460 
       
  1461     if (statusbar) {
       
  1462         QRect sbr(QPoint(0, 0),
       
  1463                   QSize(r.width(), statusbar->heightForWidth(r.width()))
       
  1464                   .expandedTo(statusbar->minimumSize()));
       
  1465         sbr.moveBottom(r.bottom());
       
  1466         QRect vr = QStyle::visualRect(parentWidget()->layoutDirection(), _r, sbr);
       
  1467         statusbar->setGeometry(vr);
       
  1468         r.setBottom(sbr.top() - 1);
       
  1469     }
       
  1470 
       
  1471     layoutState.rect = r;
       
  1472     layoutState.fitLayout();
       
  1473     applyState(layoutState, false);
       
  1474 }
       
  1475 
       
  1476 void QMainWindowLayout::addItem(QLayoutItem *)
       
  1477 { qWarning("QMainWindowLayout::addItem: Please use the public QMainWindow API instead"); }
       
  1478 
       
  1479 QSize QMainWindowLayout::sizeHint() const
       
  1480 {
       
  1481     if (!szHint.isValid()) {
       
  1482         szHint = layoutState.sizeHint();
       
  1483         const QSize sbHint = statusbar ? statusbar->sizeHint() : QSize(0, 0);
       
  1484         szHint = QSize(qMax(sbHint.width(), szHint.width()),
       
  1485                         sbHint.height() + szHint.height());
       
  1486     }
       
  1487     return szHint;
       
  1488 }
       
  1489 
       
  1490 QSize QMainWindowLayout::minimumSize() const
       
  1491 {
       
  1492     if (!minSize.isValid()) {
       
  1493         minSize = layoutState.minimumSize();
       
  1494         const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0);
       
  1495         minSize = QSize(qMax(sbMin.width(), minSize.width()),
       
  1496                         sbMin.height() + minSize.height());
       
  1497 #ifdef Q_WS_MAC
       
  1498         const QSize storedSize = minSize;
       
  1499         int minWidth = 0;
       
  1500         foreach (QToolBar *toolbar, qtoolbarsInUnifiedToolbarList) {
       
  1501             minWidth += toolbar->sizeHint().width() + 20;
       
  1502         }
       
  1503         minSize = QSize(qMax(minWidth, storedSize.width()), storedSize.height());
       
  1504 #endif
       
  1505     }
       
  1506     return minSize;
       
  1507 }
       
  1508 
       
  1509 void QMainWindowLayout::invalidate()
       
  1510 {
       
  1511     QLayout::invalidate();
       
  1512     minSize = szHint = QSize();
       
  1513 }
       
  1514 
       
  1515 /******************************************************************************
       
  1516 ** QMainWindowLayout - remaining stuff
       
  1517 */
       
  1518 
       
  1519 static void fixToolBarOrientation(QLayoutItem *item, int dockPos)
       
  1520 {
       
  1521 #ifndef QT_NO_TOOLBAR
       
  1522     QToolBar *toolBar = qobject_cast<QToolBar*>(item->widget());
       
  1523     if (toolBar == 0)
       
  1524         return;
       
  1525 
       
  1526     QRect oldGeo = toolBar->geometry();
       
  1527 
       
  1528     QInternal::DockPosition pos
       
  1529         = static_cast<QInternal::DockPosition>(dockPos);
       
  1530     Qt::Orientation o = pos == QInternal::TopDock || pos == QInternal::BottomDock
       
  1531                         ? Qt::Horizontal : Qt::Vertical;
       
  1532     if (o != toolBar->orientation())
       
  1533         toolBar->setOrientation(o);
       
  1534 
       
  1535     QSize hint = toolBar->sizeHint().boundedTo(toolBar->maximumSize())
       
  1536                     .expandedTo(toolBar->minimumSize());
       
  1537 
       
  1538     if (toolBar->size() != hint) {
       
  1539         QRect newGeo(oldGeo.topLeft(), hint);
       
  1540         if (toolBar->layoutDirection() == Qt::RightToLeft)
       
  1541             newGeo.moveRight(oldGeo.right());
       
  1542         toolBar->setGeometry(newGeo);
       
  1543     }
       
  1544 
       
  1545 #else
       
  1546     Q_UNUSED(item);
       
  1547     Q_UNUSED(dockPos);
       
  1548 #endif
       
  1549 }
       
  1550 
       
  1551 void QMainWindowLayout::revert(QLayoutItem *widgetItem)
       
  1552 {
       
  1553     if (!savedState.isValid())
       
  1554         return;
       
  1555 
       
  1556     QWidget *widget = widgetItem->widget();
       
  1557     layoutState = savedState;
       
  1558     currentGapPos = layoutState.indexOf(widget);
       
  1559     fixToolBarOrientation(widgetItem, currentGapPos.at(1));
       
  1560     layoutState.unplug(currentGapPos);
       
  1561     layoutState.fitLayout();
       
  1562     currentGapRect = layoutState.itemRect(currentGapPos);
       
  1563 
       
  1564     plug(widgetItem);
       
  1565 }
       
  1566 
       
  1567 bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
       
  1568 {
       
  1569     if (!parentWidget()->isVisible() || parentWidget()->isMinimized() || currentGapPos.isEmpty())
       
  1570         return false;
       
  1571 
       
  1572     fixToolBarOrientation(widgetItem, currentGapPos.at(1));
       
  1573 
       
  1574     QWidget *widget = widgetItem->widget();
       
  1575 
       
  1576     QList<int> previousPath = layoutState.indexOf(widget);
       
  1577 
       
  1578     QLayoutItem *it = layoutState.plug(currentGapPos);
       
  1579     Q_ASSERT(it == widgetItem);
       
  1580     Q_UNUSED(it);
       
  1581     if (!previousPath.isEmpty())
       
  1582         layoutState.remove(previousPath);
       
  1583 
       
  1584     pluggingWidget = widget;
       
  1585     QRect globalRect = currentGapRect;
       
  1586     globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft()));
       
  1587 #ifndef QT_NO_DOCKWIDGET
       
  1588     if (qobject_cast<QDockWidget*>(widget) != 0) {
       
  1589         QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout());
       
  1590         if (layout->nativeWindowDeco()) {
       
  1591             globalRect.adjust(0, layout->titleHeight(), 0, 0);
       
  1592         } else {
       
  1593             int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, widget);
       
  1594             globalRect.adjust(-fw, -fw, fw, fw);
       
  1595         }
       
  1596     }
       
  1597 #endif
       
  1598     widgetAnimator.animate(widget, globalRect, dockOptions & QMainWindow::AnimatedDocks);
       
  1599 
       
  1600     return true;
       
  1601 }
       
  1602 
       
  1603 void QMainWindowLayout::animationFinished(QWidget *widget)
       
  1604 {
       
  1605     //this function is called from within the Widget Animator whenever an animation is finished
       
  1606     //on a certain widget
       
  1607 #ifndef QT_NO_TOOLBAR
       
  1608     if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
       
  1609         QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout());
       
  1610         if (tbl->animating) {
       
  1611             tbl->animating = false;
       
  1612             if (tbl->expanded)
       
  1613                 tbl->layoutActions(tb->size());
       
  1614             tb->update();
       
  1615         }
       
  1616     }
       
  1617 #endif
       
  1618 
       
  1619     if (widget == pluggingWidget) {
       
  1620 
       
  1621 #ifndef QT_NO_DOCKWIDGET
       
  1622         if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
       
  1623             dw->d_func()->plug(currentGapRect);
       
  1624 #endif
       
  1625 #ifndef QT_NO_TOOLBAR
       
  1626         if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
       
  1627             tb->d_func()->plug(currentGapRect);
       
  1628 #endif
       
  1629 
       
  1630 #ifndef QT_NO_DOCKWIDGET
       
  1631 #ifndef QT_NO_TABBAR
       
  1632         if (qobject_cast<QDockWidget*>(widget) != 0) {
       
  1633             // info() might return null if the widget is destroyed while
       
  1634             // animating but before the animationFinished signal is received.
       
  1635             if (QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget))
       
  1636                 info->setCurrentTab(widget);
       
  1637         }
       
  1638 #endif
       
  1639 #endif
       
  1640 
       
  1641         savedState.clear();
       
  1642         currentGapPos.clear();
       
  1643         pluggingWidget = 0;
       
  1644     }
       
  1645 
       
  1646     if (!widgetAnimator.animating()) {
       
  1647         //all animations are finished
       
  1648 #ifndef QT_NO_DOCKWIDGET
       
  1649         parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
       
  1650 #ifndef QT_NO_TABBAR
       
  1651         foreach (QTabBar *tab_bar, usedTabBars)
       
  1652             tab_bar->show();
       
  1653 #endif // QT_NO_TABBAR
       
  1654 #endif // QT_NO_DOCKWIDGET
       
  1655     }
       
  1656 
       
  1657     updateGapIndicator();
       
  1658 }
       
  1659 
       
  1660 void QMainWindowLayout::restore(bool keepSavedState)
       
  1661 {
       
  1662     if (!savedState.isValid())
       
  1663         return;
       
  1664 
       
  1665     layoutState = savedState;
       
  1666     applyState(layoutState);
       
  1667     if (!keepSavedState)
       
  1668         savedState.clear();
       
  1669     currentGapPos.clear();
       
  1670     pluggingWidget = 0;
       
  1671     updateGapIndicator();
       
  1672 }
       
  1673 
       
  1674 QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow)
       
  1675     : QLayout(mainwindow)
       
  1676     , layoutState(mainwindow)
       
  1677     , savedState(mainwindow)
       
  1678     , dockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks)
       
  1679     , statusbar(0)
       
  1680 #ifndef QT_NO_DOCKWIDGET
       
  1681 #ifndef QT_NO_TABBAR
       
  1682     , _documentMode(false)
       
  1683     , verticalTabsEnabled(false)
       
  1684 #ifndef QT_NO_TABWIDGET
       
  1685     , _tabShape(QTabWidget::Rounded)
       
  1686 #endif
       
  1687 #endif
       
  1688 #endif // QT_NO_DOCKWIDGET
       
  1689     , widgetAnimator(this)
       
  1690     , pluggingWidget(0)
       
  1691 #ifndef QT_NO_RUBBERBAND
       
  1692     , gapIndicator(new QRubberBand(QRubberBand::Rectangle, mainwindow))
       
  1693 #endif //QT_NO_RUBBERBAND
       
  1694 #ifdef Q_WS_MAC
       
  1695     , blockVisiblityCheck(false)
       
  1696 #endif
       
  1697 {
       
  1698 #ifndef QT_NO_DOCKWIDGET
       
  1699 #ifndef QT_NO_TABBAR
       
  1700     sep = mainwindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainwindow);
       
  1701 #endif
       
  1702 
       
  1703 #ifndef QT_NO_TABWIDGET
       
  1704     for (int i = 0; i < QInternal::DockCount; ++i)
       
  1705         tabPositions[i] = QTabWidget::South;
       
  1706 #endif
       
  1707 #endif // QT_NO_DOCKWIDGET
       
  1708 
       
  1709 #ifndef QT_NO_RUBBERBAND
       
  1710     // For accessibility to identify this special widget.
       
  1711     gapIndicator->setObjectName(QLatin1String("qt_rubberband"));
       
  1712     gapIndicator->hide();
       
  1713 #endif
       
  1714     pluggingWidget = 0;
       
  1715 
       
  1716     setObjectName(mainwindow->objectName() + QLatin1String("_layout"));
       
  1717 }
       
  1718 
       
  1719 QMainWindowLayout::~QMainWindowLayout()
       
  1720 {
       
  1721     layoutState.deleteAllLayoutItems();
       
  1722     layoutState.deleteCentralWidgetItem();
       
  1723 
       
  1724 #ifdef Q_WS_MAC
       
  1725     cleanUpMacToolbarItems();
       
  1726 #endif
       
  1727 
       
  1728     delete statusbar;
       
  1729 }
       
  1730 
       
  1731 void QMainWindowLayout::setDockOptions(QMainWindow::DockOptions opts)
       
  1732 {
       
  1733     if (opts == dockOptions)
       
  1734         return;
       
  1735 
       
  1736     dockOptions = opts;
       
  1737 
       
  1738 #ifndef QT_NO_DOCKWIDGET
       
  1739     setVerticalTabsEnabled(opts & QMainWindow::VerticalTabs);
       
  1740 #endif
       
  1741 
       
  1742     invalidate();
       
  1743 }
       
  1744 
       
  1745 #ifndef QT_NO_STATUSBAR
       
  1746 QStatusBar *QMainWindowLayout::statusBar() const
       
  1747 { return statusbar ? qobject_cast<QStatusBar *>(statusbar->widget()) : 0; }
       
  1748 
       
  1749 void QMainWindowLayout::setStatusBar(QStatusBar *sb)
       
  1750 {
       
  1751     if (sb)
       
  1752         addChildWidget(sb);
       
  1753     delete statusbar;
       
  1754     statusbar = sb ? new QWidgetItemV2(sb) : 0;
       
  1755     invalidate();
       
  1756 }
       
  1757 #endif // QT_NO_STATUSBAR
       
  1758 
       
  1759 QWidget *QMainWindowLayout::centralWidget() const
       
  1760 {
       
  1761     return layoutState.centralWidget();
       
  1762 }
       
  1763 
       
  1764 void QMainWindowLayout::setCentralWidget(QWidget *widget)
       
  1765 {
       
  1766     if (widget != 0)
       
  1767         addChildWidget(widget);
       
  1768     layoutState.setCentralWidget(widget);
       
  1769     if (savedState.isValid()) {
       
  1770 #ifndef QT_NO_DOCKWIDGET
       
  1771         savedState.dockAreaLayout.centralWidgetItem = layoutState.dockAreaLayout.centralWidgetItem;
       
  1772 #else
       
  1773         savedState.centralWidgetItem = layoutState.centralWidgetItem;
       
  1774 #endif
       
  1775     }
       
  1776     invalidate();
       
  1777 }
       
  1778 
       
  1779 QLayoutItem *QMainWindowLayout::unplug(QWidget *widget)
       
  1780 {
       
  1781     QList<int> path = layoutState.indexOf(widget);
       
  1782     if (path.isEmpty())
       
  1783         return 0;
       
  1784 
       
  1785     QLayoutItem *item = layoutState.item(path);
       
  1786     if (widget->isWindow())
       
  1787         return item;
       
  1788 
       
  1789     QRect r = layoutState.itemRect(path);
       
  1790     savedState = layoutState;
       
  1791 
       
  1792 #ifndef QT_NO_DOCKWIDGET
       
  1793     if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
       
  1794         dw->d_func()->unplug(r);
       
  1795     }
       
  1796 #endif
       
  1797 #ifndef QT_NO_TOOLBAR
       
  1798     if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
       
  1799         tb->d_func()->unplug(r);
       
  1800     }
       
  1801 #endif
       
  1802 
       
  1803 
       
  1804     layoutState.unplug(path ,&savedState);
       
  1805     savedState.fitLayout();
       
  1806     currentGapPos = path;
       
  1807     currentGapRect = r;
       
  1808     updateGapIndicator();
       
  1809 
       
  1810     fixToolBarOrientation(item, currentGapPos.at(1));
       
  1811 
       
  1812     return item;
       
  1813 }
       
  1814 
       
  1815 void QMainWindowLayout::updateGapIndicator()
       
  1816 {
       
  1817 #ifndef QT_NO_RUBBERBAND
       
  1818     gapIndicator->setVisible(!widgetAnimator.animating() && !currentGapPos.isEmpty());
       
  1819     gapIndicator->setGeometry(currentGapRect);
       
  1820 #endif
       
  1821 }
       
  1822 
       
  1823 QList<int> QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
       
  1824 {
       
  1825     if (!parentWidget()->isVisible() || parentWidget()->isMinimized()
       
  1826         || pluggingWidget != 0 || widgetItem == 0)
       
  1827         return QList<int>();
       
  1828 
       
  1829     QWidget *widget = widgetItem->widget();
       
  1830     QPoint pos = parentWidget()->mapFromGlobal(mousePos);
       
  1831 
       
  1832     if (!savedState.isValid())
       
  1833         savedState = layoutState;
       
  1834 
       
  1835     QList<int> path = savedState.gapIndex(widget, pos);
       
  1836 
       
  1837     if (!path.isEmpty()) {
       
  1838         bool allowed = false;
       
  1839 
       
  1840 #ifndef QT_NO_DOCKWIDGET
       
  1841         if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
       
  1842             allowed = dw->isAreaAllowed(toDockWidgetArea(path.at(1)));
       
  1843 #endif
       
  1844 #ifndef QT_NO_TOOLBAR
       
  1845         if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
       
  1846             allowed = tb->isAreaAllowed(toToolBarArea(path.at(1)));
       
  1847 #endif
       
  1848 
       
  1849         if (!allowed)
       
  1850             path.clear();
       
  1851     }
       
  1852 
       
  1853     if (path == currentGapPos)
       
  1854         return currentGapPos; // the gap is already there
       
  1855 
       
  1856     currentGapPos = path;
       
  1857     if (path.isEmpty()) {
       
  1858         fixToolBarOrientation(widgetItem, 2); // 2 = top dock, ie. horizontal
       
  1859         restore(true);
       
  1860         return QList<int>();
       
  1861     }
       
  1862 
       
  1863     fixToolBarOrientation(widgetItem, currentGapPos.at(1));
       
  1864 
       
  1865     QMainWindowLayoutState newState = savedState;
       
  1866 
       
  1867     if (!newState.insertGap(path, widgetItem)) {
       
  1868         restore(true); // not enough space
       
  1869         return QList<int>();
       
  1870     }
       
  1871 
       
  1872     QSize min = newState.minimumSize();
       
  1873     QSize size = newState.rect.size();
       
  1874 
       
  1875     if (min.width() > size.width() || min.height() > size.height()) {
       
  1876         restore(true);
       
  1877         return QList<int>();
       
  1878     }
       
  1879 
       
  1880     newState.fitLayout();
       
  1881 
       
  1882     currentGapRect = newState.gapRect(currentGapPos);
       
  1883 
       
  1884 #ifndef QT_NO_DOCKWIDGET
       
  1885     parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
       
  1886 #endif
       
  1887     layoutState = newState;
       
  1888     applyState(layoutState);
       
  1889 
       
  1890     updateGapIndicator();
       
  1891 
       
  1892     return path;
       
  1893 }
       
  1894 
       
  1895 void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animate)
       
  1896 {
       
  1897 #ifndef QT_NO_DOCKWIDGET
       
  1898 #ifndef QT_NO_TABBAR
       
  1899     QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars();
       
  1900     QSet<QTabBar*> retired = usedTabBars - used;
       
  1901     usedTabBars = used;
       
  1902     foreach (QTabBar *tab_bar, retired) {
       
  1903         tab_bar->hide();
       
  1904         while (tab_bar->count() > 0)
       
  1905             tab_bar->removeTab(0);
       
  1906         unusedTabBars.append(tab_bar);
       
  1907     }
       
  1908 
       
  1909     if (sep == 1) {
       
  1910         QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets();
       
  1911         QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps;
       
  1912         usedSeparatorWidgets = usedSeps;
       
  1913         foreach (QWidget *sepWidget, retiredSeps) {
       
  1914             unusedSeparatorWidgets.append(sepWidget);
       
  1915         }
       
  1916     }
       
  1917 
       
  1918 
       
  1919 #endif // QT_NO_TABBAR
       
  1920 #endif // QT_NO_DOCKWIDGET
       
  1921     newState.apply(dockOptions & QMainWindow::AnimatedDocks && animate);
       
  1922 }
       
  1923 
       
  1924 void QMainWindowLayout::saveState(QDataStream &stream) const
       
  1925 {
       
  1926     layoutState.saveState(stream);
       
  1927 }
       
  1928 
       
  1929 bool QMainWindowLayout::restoreState(QDataStream &stream)
       
  1930 {
       
  1931     savedState = layoutState;
       
  1932     layoutState.clear();
       
  1933     layoutState.rect = savedState.rect;
       
  1934 
       
  1935     if (!layoutState.restoreState(stream, savedState)) {
       
  1936         layoutState.deleteAllLayoutItems();
       
  1937         layoutState = savedState;
       
  1938         if (parentWidget()->isVisible())
       
  1939             applyState(layoutState, false); // hides tabBars allocated by newState
       
  1940         return false;
       
  1941     }
       
  1942 
       
  1943     if (parentWidget()->isVisible()) {
       
  1944         layoutState.fitLayout();
       
  1945         applyState(layoutState, false);
       
  1946     }
       
  1947 
       
  1948     savedState.deleteAllLayoutItems();
       
  1949     savedState.clear();
       
  1950 
       
  1951 #ifndef QT_NO_DOCKWIDGET
       
  1952     if (parentWidget()->isVisible()) {
       
  1953 #ifndef QT_NO_TABBAR
       
  1954         foreach (QTabBar *tab_bar, usedTabBars)
       
  1955             tab_bar->show();
       
  1956 
       
  1957 #endif
       
  1958     }
       
  1959 #endif // QT_NO_DOCKWIDGET
       
  1960 
       
  1961     return true;
       
  1962 }
       
  1963 
       
  1964 
       
  1965 // Returns if this toolbar *should* be using HIToolbar. Won't work for all in between cases
       
  1966 // for example, you have a toolbar in the top area and then you suddenly turn on
       
  1967 // HIToolbar.
       
  1968 bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const
       
  1969 {
       
  1970 #ifndef Q_WS_MAC
       
  1971     Q_UNUSED(toolbar);
       
  1972     return false;
       
  1973 #else
       
  1974     return qtoolbarsInUnifiedToolbarList.contains(toolbar)
       
  1975            || ((toolBarArea(toolbar) == Qt::TopToolBarArea)
       
  1976                 && layoutState.mainWindow->unifiedTitleAndToolBarOnMac());
       
  1977 #endif
       
  1978 }
       
  1979 
       
  1980 void QMainWindowLayout::timerEvent(QTimerEvent *e)
       
  1981 {
       
  1982 #ifndef QT_NO_DOCKWIDGET
       
  1983     if (e->timerId() == separatorMoveTimer.timerId()) {
       
  1984         //let's move the separators
       
  1985         separatorMoveTimer.stop();
       
  1986         if (movingSeparator.isEmpty())
       
  1987             return;
       
  1988         if (movingSeparatorOrigin == movingSeparatorPos)
       
  1989             return;
       
  1990 
       
  1991         //when moving the separator, we need to update the previous position
       
  1992         parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
       
  1993 
       
  1994         layoutState = savedState;
       
  1995         layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin,
       
  1996                                                     movingSeparatorPos);
       
  1997         movingSeparatorPos = movingSeparatorOrigin;
       
  1998     }
       
  1999 #endif
       
  2000     QLayout::timerEvent(e);
       
  2001 }
       
  2002 
       
  2003 
       
  2004 QT_END_NAMESPACE
       
  2005 
       
  2006 #endif // QT_NO_MAINWINDOW