src/gui/widgets/qmainwindowlayout.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/widgets/qmainwindowlayout.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,2006 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmainwindowlayout_p.h"
+#include "qdockarealayout_p.h"
+
+#ifndef QT_NO_MAINWINDOW
+#include "qdockwidget.h"
+#include "qdockwidget_p.h"
+#include "qtoolbar_p.h"
+#include "qmainwindow.h"
+#include "qmainwindowlayout_p.h"
+#include "qtoolbar.h"
+#include "qtoolbarlayout_p.h"
+#include "qwidgetanimator_p.h"
+#include "qrubberband.h"
+#include "qdockwidget_p.h"
+#include "qtabbar_p.h"
+
+#include <qapplication.h>
+#include <qstatusbar.h>
+#include <qstring.h>
+#include <qstyle.h>
+#include <qvarlengtharray.h>
+#include <qstack.h>
+#include <qmap.h>
+#include <qtimer.h>
+
+#include <qdebug.h>
+
+#include <private/qapplication_p.h>
+#include <private/qlayoutengine_p.h>
+#ifdef Q_WS_MAC
+#   include <private/qcore_mac_p.h>
+#   include <private/qt_cocoa_helpers_mac_p.h>
+#endif
+
+#ifdef Q_DEBUG_MAINWINDOW_LAYOUT
+#   include <QTextStream>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/******************************************************************************
+** debug
+*/
+
+#if defined(Q_DEBUG_MAINWINDOW_LAYOUT) && !defined(QT_NO_DOCKWIDGET)
+
+static QTextStream qout(stderr, QIODevice::WriteOnly);
+
+static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent);
+
+static void dumpLayout(QTextStream &qout, const QDockAreaLayoutItem &item, QString indent)
+{
+    qout << indent << "QDockAreaLayoutItem: "
+            << "pos: " << item.pos << " size:" << item.size
+            << " gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
+            << " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize) << '\n';
+    indent += QLatin1String("  ");
+    if (item.widgetItem != 0) {
+        qout << indent << "widget: "
+            << item.widgetItem->widget()->metaObject()->className()
+            << ' ' << item.widgetItem->widget()->windowTitle() << '\n';
+    } else if (item.subinfo != 0) {
+        qout << indent << "subinfo:\n";
+        dumpLayout(qout, *item.subinfo, indent + QLatin1String("  "));
+    } else if (item.placeHolderItem != 0) {
+        QRect r = item.placeHolderItem->topLevelRect;
+        qout << indent << "placeHolder: "
+            << "pos: " << item.pos << " size:" << item.size
+            << " gap:" << (item.flags & QDockAreaLayoutItem::GapItem)
+            << " keepSize:" << (item.flags & QDockAreaLayoutItem::KeepSize)
+            << " objectName:" << item.placeHolderItem->objectName
+            << " hidden:" << item.placeHolderItem->hidden
+            << " window:" << item.placeHolderItem->window
+            << " rect:" << r.x() << ',' << r.y() << ' '
+            << r.width() << 'x' << r.height() << '\n';
+    }
+    qout.flush();
+}
+
+static void dumpLayout(QTextStream &qout, const QDockAreaLayoutInfo &layout, QString indent)
+{
+    qout << indent << "QDockAreaLayoutInfo: "
+            << layout.rect.left() << ','
+            << layout.rect.top() << ' '
+            << layout.rect.width() << 'x'
+            << layout.rect.height()
+            << " orient:" << layout.o
+            << " tabbed:" << layout.tabbed
+            << " tbshape:" << layout.tabBarShape << '\n';
+
+    indent += QLatin1String("  ");
+
+    for (int i = 0; i < layout.item_list.count(); ++i) {
+        qout << indent << "Item: " << i << '\n';
+        dumpLayout(qout, layout.item_list.at(i), indent + QLatin1String("  "));
+    }
+    qout.flush();
+};
+
+static void dumpLayout(QTextStream &qout, const QDockAreaLayout &layout, QString indent)
+{
+    qout << indent << "QDockAreaLayout: "
+            << layout.rect.left() << ','
+            << layout.rect.top() << ' '
+            << layout.rect.width() << 'x'
+            << layout.rect.height() << '\n';
+
+    qout << indent << "TopDockArea:\n";
+    dumpLayout(qout, layout.docks[QInternal::TopDock], indent + QLatin1String("  "));
+    qout << indent << "LeftDockArea:\n";
+    dumpLayout(qout, layout.docks[QInternal::LeftDock], indent + QLatin1String("  "));
+    qout << indent << "RightDockArea:\n";
+    dumpLayout(qout, layout.docks[QInternal::RightDock], indent + QLatin1String("  "));
+    qout << indent << "BottomDockArea:\n";
+    dumpLayout(qout, layout.docks[QInternal::BottomDock], indent + QLatin1String("  "));
+
+    qout.flush();
+};
+
+void qt_dumpLayout(QTextStream &qout, QMainWindow *window)
+{
+    QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(window->layout());
+    dumpLayout(qout, layout->layoutState.dockAreaLayout, QString());
+}
+
+#endif // Q_DEBUG_MAINWINDOW_LAYOUT && !QT_NO_DOCKWIDGET
+
+/******************************************************************************
+** QMainWindowLayoutState
+*/
+
+// we deal with all the #ifndefferry here so QMainWindowLayout code is clean
+
+QMainWindowLayoutState::QMainWindowLayoutState(QMainWindow *win)
+    :
+#ifndef QT_NO_TOOLBAR
+    toolBarAreaLayout(win),
+#endif
+#ifndef QT_NO_DOCKWIDGET
+    dockAreaLayout(win)
+#else
+    centralWidgetItem(0)
+#endif
+
+{
+    mainWindow = win;
+}
+
+QSize QMainWindowLayoutState::sizeHint() const
+{
+
+    QSize result(0, 0);
+
+#ifndef QT_NO_DOCKWIDGET
+    result = dockAreaLayout.sizeHint();
+#else
+    if (centralWidgetItem != 0)
+        result = centralWidgetItem->sizeHint();
+#endif
+
+#ifndef QT_NO_TOOLBAR
+    result = toolBarAreaLayout.sizeHint(result);
+#endif // QT_NO_TOOLBAR
+
+    return result;
+}
+
+QSize QMainWindowLayoutState::minimumSize() const
+{
+    QSize result(0, 0);
+
+#ifndef QT_NO_DOCKWIDGET
+    result = dockAreaLayout.minimumSize();
+#else
+    if (centralWidgetItem != 0)
+        result = centralWidgetItem->minimumSize();
+#endif
+
+#ifndef QT_NO_TOOLBAR
+    result = toolBarAreaLayout.minimumSize(result);
+#endif // QT_NO_TOOLBAR
+
+    return result;
+}
+
+void QMainWindowLayoutState::apply(bool animated)
+{
+#ifndef QT_NO_TOOLBAR
+    toolBarAreaLayout.apply(animated);
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+//    dumpLayout(dockAreaLayout, QString());
+    dockAreaLayout.apply(animated);
+#else
+    if (centralWidgetItem != 0) {
+        QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
+        Q_ASSERT(layout != 0);
+        layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animated);
+    }
+#endif
+}
+
+void QMainWindowLayoutState::fitLayout()
+{
+    QRect r;
+#ifdef QT_NO_TOOLBAR
+    r = rect;
+#else
+    toolBarAreaLayout.rect = rect;
+    r = toolBarAreaLayout.fitLayout();
+#endif // QT_NO_TOOLBAR
+
+#ifndef QT_NO_DOCKWIDGET
+    dockAreaLayout.rect = r;
+    dockAreaLayout.fitLayout();
+#else
+    centralWidgetRect = r;
+#endif
+}
+
+void QMainWindowLayoutState::deleteAllLayoutItems()
+{
+#ifndef QT_NO_TOOLBAR
+    toolBarAreaLayout.deleteAllLayoutItems();
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    dockAreaLayout.deleteAllLayoutItems();
+#endif
+}
+
+void QMainWindowLayoutState::deleteCentralWidgetItem()
+{
+#ifndef QT_NO_DOCKWIDGET
+    delete dockAreaLayout.centralWidgetItem;
+    dockAreaLayout.centralWidgetItem = 0;
+#else
+    delete centralWidgetItem;
+    centralWidgetItem = 0;
+#endif
+}
+
+QLayoutItem *QMainWindowLayoutState::itemAt(int index, int *x) const
+{
+#ifndef QT_NO_TOOLBAR
+    if (QLayoutItem *ret = toolBarAreaLayout.itemAt(x, index))
+        return ret;
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    if (QLayoutItem *ret = dockAreaLayout.itemAt(x, index))
+        return ret;
+#else
+    if (centralWidgetItem != 0 && (*x)++ == index)
+        return centralWidgetItem;
+#endif
+
+    return 0;
+}
+
+QLayoutItem *QMainWindowLayoutState::takeAt(int index, int *x)
+{
+#ifndef QT_NO_TOOLBAR
+    if (QLayoutItem *ret = toolBarAreaLayout.takeAt(x, index))
+        return ret;
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    if (QLayoutItem *ret = dockAreaLayout.takeAt(x, index))
+        return ret;
+#else
+    if (centralWidgetItem != 0 && (*x)++ == index) {
+        QLayoutItem *ret = centralWidgetItem;
+        centralWidgetItem = 0;
+        return ret;
+    }
+#endif
+
+    return 0;
+}
+
+QList<int> QMainWindowLayoutState::indexOf(QWidget *widget) const
+{
+    QList<int> result;
+
+#ifndef QT_NO_TOOLBAR
+    // is it a toolbar?
+    if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
+        result = toolBarAreaLayout.indexOf(toolBar);
+        if (!result.isEmpty())
+            result.prepend(0);
+        return result;
+    }
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    // is it a dock widget?
+    if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(widget)) {
+        result = dockAreaLayout.indexOf(dockWidget);
+        if (!result.isEmpty())
+            result.prepend(1);
+        return result;
+    }
+#endif //QT_NO_DOCKWIDGET
+
+    return result;
+}
+
+bool QMainWindowLayoutState::contains(QWidget *widget) const
+{
+#ifndef QT_NO_DOCKWIDGET
+    if (dockAreaLayout.centralWidgetItem != 0 && dockAreaLayout.centralWidgetItem->widget() == widget)
+        return true;
+    if (!dockAreaLayout.indexOf(widget).isEmpty())
+        return true;
+#else
+    if (centralWidgetItem != 0 && centralWidgetItem->widget() == widget)
+        return true;
+#endif
+
+#ifndef QT_NO_TOOLBAR
+    if (!toolBarAreaLayout.indexOf(widget).isEmpty())
+        return true;
+#endif
+    return false;
+}
+
+void QMainWindowLayoutState::setCentralWidget(QWidget *widget)
+{
+    QLayoutItem *item = 0;
+    //make sure we remove the widget
+    deleteCentralWidgetItem();
+
+    if (widget != 0)
+        item = new QWidgetItemV2(widget);
+
+#ifndef QT_NO_DOCKWIDGET
+    dockAreaLayout.centralWidgetItem = item;
+#else
+    centralWidgetItem = item;
+#endif
+}
+
+QWidget *QMainWindowLayoutState::centralWidget() const
+{
+    QLayoutItem *item = 0;
+
+#ifndef QT_NO_DOCKWIDGET
+    item = dockAreaLayout.centralWidgetItem;
+#else
+    item = centralWidgetItem;
+#endif
+
+    if (item != 0)
+        return item->widget();
+    return 0;
+}
+
+QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget,
+                                            const QPoint &pos) const
+{
+    QList<int> result;
+
+#ifndef QT_NO_TOOLBAR
+    // is it a toolbar?
+    if (qobject_cast<QToolBar*>(widget) != 0) {
+        result = toolBarAreaLayout.gapIndex(pos);
+        if (!result.isEmpty())
+            result.prepend(0);
+        return result;
+    }
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    // is it a dock widget?
+    if (qobject_cast<QDockWidget *>(widget) != 0) {
+        result = dockAreaLayout.gapIndex(pos);
+        if (!result.isEmpty())
+            result.prepend(1);
+        return result;
+    }
+#endif //QT_NO_DOCKWIDGET
+
+    return result;
+}
+
+bool QMainWindowLayoutState::insertGap(const QList<int> &path, QLayoutItem *item)
+{
+    if (path.isEmpty())
+        return false;
+
+    int i = path.first();
+
+#ifndef QT_NO_TOOLBAR
+    if (i == 0) {
+        Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) != 0);
+        return toolBarAreaLayout.insertGap(path.mid(1), item);
+    }
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    if (i == 1) {
+        Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) != 0);
+        return dockAreaLayout.insertGap(path.mid(1), item);
+    }
+#endif //QT_NO_DOCKWIDGET
+
+    return false;
+}
+
+void QMainWindowLayoutState::remove(const QList<int> &path)
+{
+    int i = path.first();
+
+#ifndef QT_NO_TOOLBAR
+    if (i == 0)
+        toolBarAreaLayout.remove(path.mid(1));
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    if (i == 1)
+        dockAreaLayout.remove(path.mid(1));
+#endif //QT_NO_DOCKWIDGET
+}
+
+void QMainWindowLayoutState::remove(QLayoutItem *item)
+{
+#ifndef QT_NO_TOOLBAR
+    toolBarAreaLayout.remove(item);
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    // is it a dock widget?
+    if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(item->widget())) {
+        QList<int> path = dockAreaLayout.indexOf(dockWidget);
+        if (!path.isEmpty())
+            dockAreaLayout.remove(path);
+    }
+#endif //QT_NO_DOCKWIDGET
+}
+
+void QMainWindowLayoutState::clear()
+{
+#ifndef QT_NO_TOOLBAR
+    toolBarAreaLayout.clear();
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    dockAreaLayout.clear();
+#else
+    centralWidgetRect = QRect();
+#endif
+
+    rect = QRect();
+}
+
+bool QMainWindowLayoutState::isValid() const
+{
+    return rect.isValid();
+}
+
+QLayoutItem *QMainWindowLayoutState::item(const QList<int> &path)
+{
+    int i = path.first();
+
+#ifndef QT_NO_TOOLBAR
+    if (i == 0)
+        return toolBarAreaLayout.item(path.mid(1)).widgetItem;
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    if (i == 1)
+        return dockAreaLayout.item(path.mid(1)).widgetItem;
+#endif //QT_NO_DOCKWIDGET
+
+    return 0;
+}
+
+QRect QMainWindowLayoutState::itemRect(const QList<int> &path) const
+{
+    int i = path.first();
+
+#ifndef QT_NO_TOOLBAR
+    if (i == 0)
+        return toolBarAreaLayout.itemRect(path.mid(1));
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    if (i == 1)
+        return dockAreaLayout.itemRect(path.mid(1));
+#endif //QT_NO_DOCKWIDGET
+
+    return QRect();
+}
+
+QRect QMainWindowLayoutState::gapRect(const QList<int> &path) const
+{
+    int i = path.first();
+
+#ifndef QT_NO_TOOLBAR
+    if (i == 0)
+        return toolBarAreaLayout.itemRect(path.mid(1));
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    if (i == 1)
+        return dockAreaLayout.gapRect(path.mid(1));
+#endif //QT_NO_DOCKWIDGET
+
+    return QRect();
+}
+
+QLayoutItem *QMainWindowLayoutState::plug(const QList<int> &path)
+{
+    int i = path.first();
+
+#ifndef QT_NO_TOOLBAR
+    if (i == 0)
+        return toolBarAreaLayout.plug(path.mid(1));
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    if (i == 1)
+        return dockAreaLayout.plug(path.mid(1));
+#endif //QT_NO_DOCKWIDGET
+
+    return 0;
+}
+
+QLayoutItem *QMainWindowLayoutState::unplug(const QList<int> &path, QMainWindowLayoutState *other)
+{
+    int i = path.first();
+
+#ifdef QT_NO_TOOLBAR
+    Q_UNUSED(other);
+#else
+    if (i == 0)
+        return toolBarAreaLayout.unplug(path.mid(1), other ? &other->toolBarAreaLayout : 0);
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+    if (i == 1)
+        return dockAreaLayout.unplug(path.mid(1));
+#endif //QT_NO_DOCKWIDGET
+
+    return 0;
+}
+
+void QMainWindowLayoutState::saveState(QDataStream &stream) const
+{
+#ifndef QT_NO_DOCKWIDGET
+    dockAreaLayout.saveState(stream);
+#endif
+#ifndef QT_NO_TOOLBAR
+    toolBarAreaLayout.saveState(stream);
+#endif
+}
+
+template <typename T>
+static QList<T> findChildrenHelper(const QObject *o)
+{
+    const QObjectList &list = o->children();
+    QList<T> result;
+
+    for (int i=0; i < list.size(); ++i) {
+        if (T t = qobject_cast<T>(list[i])) {
+            result.append(t);
+        }
+    }
+
+    return result;
+}
+
+//pre4.3 tests the format that was used before 4.3
+bool QMainWindowLayoutState::checkFormat(QDataStream &stream, bool pre43)
+{
+#ifdef QT_NO_TOOLBAR
+    Q_UNUSED(pre43);
+#endif
+    while (!stream.atEnd()) {
+        uchar marker;
+        stream >> marker;
+        switch(marker)
+        {
+#ifndef QT_NO_TOOLBAR
+            case QToolBarAreaLayout::ToolBarStateMarker:
+            case QToolBarAreaLayout::ToolBarStateMarkerEx:
+                {
+                    QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow);
+                    if (!toolBarAreaLayout.restoreState(stream, toolBars, marker,
+                        pre43 /*testing 4.3 format*/, true /*testing*/)) {
+                            return false;
+                    }
+                }
+                break;
+#endif // QT_NO_TOOLBAR
+
+#ifndef QT_NO_DOCKWIDGET
+            case QDockAreaLayout::DockWidgetStateMarker:
+                {
+                    QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
+                    if (!dockAreaLayout.restoreState(stream, dockWidgets, true /*testing*/)) {
+                        return false;
+                    }
+                }
+                break;
+#endif
+            default:
+                //there was an error during the parsing
+                return false;
+        }// switch
+    } //while
+
+    //everything went fine: it must be a pre-4.3 saved state
+    return true;
+}
+
+bool QMainWindowLayoutState::restoreState(QDataStream &_stream,
+                                        const QMainWindowLayoutState &oldState)
+{
+    //make a copy of the data so that we can read it more than once
+    QByteArray copy;
+    while(!_stream.atEnd()) {
+        int length = 1024;
+        QByteArray ba(length, '\0');
+        length = _stream.readRawData(ba.data(), ba.size());
+        ba.resize(length);
+        copy += ba;
+    }
+
+    QDataStream ds(copy);
+    const bool oldFormat = !checkFormat(ds, false);
+    if (oldFormat) {
+        //we should try with the old format
+        QDataStream ds2(copy);
+        if (!checkFormat(ds2, true)) {
+            return false; //format unknown
+        }
+    }
+
+    QDataStream stream(copy);
+
+    while (!stream.atEnd()) {
+        uchar marker;
+        stream >> marker;
+        switch(marker)
+        {
+#ifndef QT_NO_DOCKWIDGET
+            case QDockAreaLayout::DockWidgetStateMarker:
+                {
+                    QList<QDockWidget *> dockWidgets = findChildrenHelper<QDockWidget*>(mainWindow);
+                    if (!dockAreaLayout.restoreState(stream, dockWidgets))
+                        return false;
+
+                    for (int i = 0; i < dockWidgets.size(); ++i) {
+                        QDockWidget *w = dockWidgets.at(i);
+                        QList<int> path = dockAreaLayout.indexOf(w);
+                        if (path.isEmpty()) {
+                            QList<int> oldPath = oldState.dockAreaLayout.indexOf(w);
+                            if (oldPath.isEmpty()) {
+                                continue;
+                            }
+                            QDockAreaLayoutInfo *info = dockAreaLayout.info(oldPath);
+                            if (info == 0) {
+                                continue;
+                            }
+                            info->item_list.append(QDockAreaLayoutItem(new QDockWidgetItem(w)));
+                        }
+                    }
+                }
+                break;
+#endif // QT_NO_DOCKWIDGET
+
+#ifndef QT_NO_TOOLBAR
+            case QToolBarAreaLayout::ToolBarStateMarker:
+            case QToolBarAreaLayout::ToolBarStateMarkerEx:
+                {
+                    QList<QToolBar *> toolBars = findChildrenHelper<QToolBar*>(mainWindow);
+                    if (!toolBarAreaLayout.restoreState(stream, toolBars, marker, oldFormat))
+                        return false;
+
+                    for (int i = 0; i < toolBars.size(); ++i) {
+                        QToolBar *w = toolBars.at(i);
+                        QList<int> path = toolBarAreaLayout.indexOf(w);
+                        if (path.isEmpty()) {
+                            QList<int> oldPath = oldState.toolBarAreaLayout.indexOf(w);
+                            if (oldPath.isEmpty()) {
+                                continue;
+                            }
+                            toolBarAreaLayout.docks[oldPath.at(0)].insertToolBar(0, w);
+                        }
+                    }
+                }
+                break;
+#endif //QT_NO_TOOLBAR
+            default:
+                return false;
+        }// switch
+    } //while
+
+
+    return true;
+}
+
+/******************************************************************************
+** QMainWindowLayoutState - toolbars
+*/
+
+#ifndef QT_NO_TOOLBAR
+
+static inline void validateToolBarArea(Qt::ToolBarArea &area)
+{
+    switch (area) {
+    case Qt::LeftToolBarArea:
+    case Qt::RightToolBarArea:
+    case Qt::TopToolBarArea:
+    case Qt::BottomToolBarArea:
+        break;
+    default:
+        area = Qt::TopToolBarArea;
+    }
+}
+
+static QInternal::DockPosition toDockPos(Qt::ToolBarArea area)
+{
+    switch (area) {
+        case Qt::LeftToolBarArea: return QInternal::LeftDock;
+        case Qt::RightToolBarArea: return QInternal::RightDock;
+        case Qt::TopToolBarArea: return QInternal::TopDock;
+        case Qt::BottomToolBarArea: return QInternal::BottomDock;
+        default:
+            break;
+    }
+
+    return QInternal::DockCount;
+}
+
+static Qt::ToolBarArea toToolBarArea(QInternal::DockPosition pos)
+{
+    switch (pos) {
+        case QInternal::LeftDock:   return Qt::LeftToolBarArea;
+        case QInternal::RightDock:  return Qt::RightToolBarArea;
+        case QInternal::TopDock:    return Qt::TopToolBarArea;
+        case QInternal::BottomDock: return Qt::BottomToolBarArea;
+        default: break;
+    }
+    return Qt::NoToolBarArea;
+}
+
+static inline Qt::ToolBarArea toToolBarArea(int pos)
+{
+    return toToolBarArea(static_cast<QInternal::DockPosition>(pos));
+}
+
+void QMainWindowLayout::addToolBarBreak(Qt::ToolBarArea area)
+{
+    validateToolBarArea(area);
+
+    layoutState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
+    if (savedState.isValid())
+        savedState.toolBarAreaLayout.addToolBarBreak(toDockPos(area));
+
+    invalidate();
+}
+
+void QMainWindowLayout::insertToolBarBreak(QToolBar *before)
+{
+    layoutState.toolBarAreaLayout.insertToolBarBreak(before);
+    if (savedState.isValid())
+        savedState.toolBarAreaLayout.insertToolBarBreak(before);
+    invalidate();
+}
+
+void QMainWindowLayout::removeToolBarBreak(QToolBar *before)
+{
+    layoutState.toolBarAreaLayout.removeToolBarBreak(before);
+    if (savedState.isValid())
+        savedState.toolBarAreaLayout.removeToolBarBreak(before);
+    invalidate();
+}
+
+void QMainWindowLayout::moveToolBar(QToolBar *toolbar, int pos)
+{
+    layoutState.toolBarAreaLayout.moveToolBar(toolbar, pos);
+    if (savedState.isValid())
+        savedState.toolBarAreaLayout.moveToolBar(toolbar, pos);
+    invalidate();
+}
+
+/* Removes the toolbar from the mainwindow so that it can be added again. Does not
+   explicitly hide the toolbar. */
+void QMainWindowLayout::removeToolBar(QToolBar *toolbar)
+{
+    if (toolbar) {
+        QObject::disconnect(parentWidget(), SIGNAL(iconSizeChanged(QSize)),
+                   toolbar, SLOT(_q_updateIconSize(QSize)));
+        QObject::disconnect(parentWidget(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
+                   toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
+
+#ifdef Q_WS_MAC
+        if (usesHIToolBar(toolbar)) {
+            removeFromMacToolbar(toolbar);
+        } else
+#endif // Q_WS_MAC
+        {
+            removeWidget(toolbar);
+        }
+    }
+}
+
+/*!
+    Adds \a toolbar to \a area, continuing the current line.
+*/
+void QMainWindowLayout::addToolBar(Qt::ToolBarArea area,
+                                   QToolBar *toolbar,
+                                   bool)
+{
+    validateToolBarArea(area);
+#ifdef Q_WS_MAC
+    if ((area == Qt::TopToolBarArea)
+            && layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
+        insertIntoMacToolbar(0, toolbar);
+    } else
+#endif
+    {
+        //let's add the toolbar to the layout
+        addChildWidget(toolbar);
+        QLayoutItem * item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar);
+        if (savedState.isValid() && item) {
+            // copy the toolbar also in the saved state
+            savedState.toolBarAreaLayout.insertItem(toDockPos(area), item);
+        }
+        invalidate();
+
+        //this ensures that the toolbar has the right window flags (not floating any more)
+        toolbar->d_func()->updateWindowFlags(false /*floating*/);
+    }
+}
+
+/*!
+    Adds \a toolbar before \a before
+*/
+void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar)
+{
+#ifdef Q_WS_MAC
+    if (usesHIToolBar(before)) {
+        insertIntoMacToolbar(before, toolbar);
+    } else
+#endif // Q_WS_MAC
+    {
+        addChildWidget(toolbar);
+        QLayoutItem * item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar);
+        if (savedState.isValid() && item) {
+            // copy the toolbar also in the saved state
+            savedState.toolBarAreaLayout.insertItem(before, item);
+        }
+        if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) {
+            currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
+            if (!currentGapPos.isEmpty()) {
+                currentGapPos.prepend(0);
+                currentGapRect = layoutState.itemRect(currentGapPos);
+            }
+        }
+        invalidate();
+    }
+}
+
+Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const
+{
+    QInternal::DockPosition pos = layoutState.toolBarAreaLayout.findToolBar(toolbar);
+    switch (pos) {
+        case QInternal::LeftDock:   return Qt::LeftToolBarArea;
+        case QInternal::RightDock:  return Qt::RightToolBarArea;
+        case QInternal::TopDock:    return Qt::TopToolBarArea;
+        case QInternal::BottomDock: return Qt::BottomToolBarArea;
+        default: break;
+    }
+#ifdef Q_WS_MAC
+    if (pos == QInternal::DockCount) {
+        if (qtoolbarsInUnifiedToolbarList.contains(toolbar))
+            return Qt::TopToolBarArea;
+    }
+#endif
+    return Qt::NoToolBarArea;
+}
+
+bool QMainWindowLayout::toolBarBreak(QToolBar *toolBar) const
+{
+    return layoutState.toolBarAreaLayout.toolBarBreak(toolBar);
+}
+
+void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const
+{
+    option->toolBarArea = toolBarArea(toolBar);
+    layoutState.toolBarAreaLayout.getStyleOptionInfo(option, toolBar);
+}
+
+void QMainWindowLayout::toggleToolBarsVisible()
+{
+    bool updateNonUnifiedParts = true;
+#ifdef Q_WS_MAC
+    if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
+        // If we hit this case, someone has pressed the "toolbar button" which will
+        // toggle the unified toolbar visiblity, because that's what the user wants.
+        // We might be in a situation where someone has hidden all the toolbars
+        // beforehand (maybe in construction), but now they've hit this button and
+        // and are expecting the items to show. What do we do?
+        // 1) Check the visibility of all the toolbars, if one is visible, do nothing, this
+        //    preserves what people would expect (these toolbars were visible when I clicked last time).
+        // 2) If NONE are visible, then show them all. Again, this preserves the user expectation
+        //    of, "I want to see the toolbars." The user may get more toolbars than expected, but this
+        //    is better seeing nothing.
+        // Don't worry about any of this if we are going invisible. This does mean we may get
+        // into issues when switching into and out of fullscreen mode, but this is probably minor.
+        // If we ever need to do hiding, that would have to be taken care of after the unified toolbar
+        // has finished hiding.
+        // People can of course handle the QEvent::ToolBarChange event themselves and do
+        // WHATEVER they want if they don't like what we are doing (though the unified toolbar
+        // will fire regardless).
+
+        // Check if we REALLY need to update the geometry below. If we only have items in the
+        // unified toolbar, all the docks will be empty, so there's very little point
+        // in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well).
+        // FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar
+        // visibility can get out of sync. I really don't think it's a big issue. It is kept
+        // to a minimum because we only change the visibility if we absolutely must.
+        // update the "non unified parts."
+        updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty();
+
+        // We get this function before the unified toolbar does its thing.
+        // So, the value will be opposite of what we expect.
+        bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow));
+        if (goingVisible) {
+            const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size();
+            bool needAllVisible = true;
+            for (int i = 0; i < ToolBarCount; ++i) {
+                if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) {
+                    needAllVisible = false;
+                    break;
+                }
+            }
+            if (needAllVisible) {
+                QBoolBlocker blocker(blockVisiblityCheck);  // Disable the visibilty check because
+                                                            // the toggle has already happened.
+                for (int i = 0; i < ToolBarCount; ++i)
+                    qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true);
+            }
+        }
+        if (!updateNonUnifiedParts)
+            layoutState.toolBarAreaLayout.visible = goingVisible;
+    }
+#endif
+    if (updateNonUnifiedParts) {
+        layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible;
+        if (!layoutState.mainWindow->isMaximized()) {
+            QPoint topLeft = parentWidget()->geometry().topLeft();
+            QRect r = parentWidget()->geometry();
+            r = layoutState.toolBarAreaLayout.rectHint(r);
+            r.moveTo(topLeft);
+            parentWidget()->setGeometry(r);
+        } else {
+            update();
+        }
+    }
+}
+
+#endif // QT_NO_TOOLBAR
+
+/******************************************************************************
+** QMainWindowLayoutState - dock areas
+*/
+
+#ifndef QT_NO_DOCKWIDGET
+
+static inline void validateDockWidgetArea(Qt::DockWidgetArea &area)
+{
+    switch (area) {
+    case Qt::LeftDockWidgetArea:
+    case Qt::RightDockWidgetArea:
+    case Qt::TopDockWidgetArea:
+    case Qt::BottomDockWidgetArea:
+        break;
+    default:
+        area = Qt::LeftDockWidgetArea;
+    }
+}
+
+static QInternal::DockPosition toDockPos(Qt::DockWidgetArea area)
+{
+    switch (area) {
+        case Qt::LeftDockWidgetArea: return QInternal::LeftDock;
+        case Qt::RightDockWidgetArea: return QInternal::RightDock;
+        case Qt::TopDockWidgetArea: return QInternal::TopDock;
+        case Qt::BottomDockWidgetArea: return QInternal::BottomDock;
+        default:
+            break;
+    }
+
+    return QInternal::DockCount;
+}
+
+static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
+{
+    switch (pos) {
+        case QInternal::LeftDock : return Qt::LeftDockWidgetArea;
+        case QInternal::RightDock : return Qt::RightDockWidgetArea;
+        case QInternal::TopDock : return Qt::TopDockWidgetArea;
+        case QInternal::BottomDock : return Qt::BottomDockWidgetArea;
+        default:
+            break;
+    }
+
+    return Qt::NoDockWidgetArea;
+}
+
+inline static Qt::DockWidgetArea toDockWidgetArea(int pos)
+{
+    return toDockWidgetArea(static_cast<QInternal::DockPosition>(pos));
+}
+
+void QMainWindowLayout::setCorner(Qt::Corner corner, Qt::DockWidgetArea area)
+{
+    if (layoutState.dockAreaLayout.corners[corner] == area)
+        return;
+    layoutState.dockAreaLayout.corners[corner] = area;
+    if (savedState.isValid())
+        savedState.dockAreaLayout.corners[corner] = area;
+    invalidate();
+}
+
+Qt::DockWidgetArea QMainWindowLayout::corner(Qt::Corner corner) const
+{
+    return layoutState.dockAreaLayout.corners[corner];
+}
+
+void QMainWindowLayout::addDockWidget(Qt::DockWidgetArea area,
+                                             QDockWidget *dockwidget,
+                                             Qt::Orientation orientation)
+{
+    addChildWidget(dockwidget);
+
+    // If we are currently moving a separator, then we need to abort the move, since each
+    // time we move the mouse layoutState is replaced by savedState modified by the move.
+    if (!movingSeparator.isEmpty())
+        endSeparatorMove(movingSeparatorPos);
+
+    layoutState.dockAreaLayout.addDockWidget(toDockPos(area), dockwidget, orientation);
+    emit dockwidget->dockLocationChanged(area);
+    invalidate();
+}
+
+void QMainWindowLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
+{
+    addChildWidget(second);
+    layoutState.dockAreaLayout.tabifyDockWidget(first, second);
+    emit second->dockLocationChanged(dockWidgetArea(first));
+    invalidate();
+}
+
+bool QMainWindowLayout::restoreDockWidget(QDockWidget *dockwidget)
+{
+    addChildWidget(dockwidget);
+    if (!layoutState.dockAreaLayout.restoreDockWidget(dockwidget))
+        return false;
+    emit dockwidget->dockLocationChanged(dockWidgetArea(dockwidget));
+    invalidate();
+    return true;
+}
+
+#ifndef QT_NO_TABBAR
+bool QMainWindowLayout::documentMode() const
+{
+    return _documentMode;
+}
+
+void QMainWindowLayout::setDocumentMode(bool enabled)
+{
+    if (_documentMode == enabled)
+        return;
+
+    _documentMode = enabled;
+
+    // Update the document mode for all tab bars
+    foreach (QTabBar *bar, usedTabBars)
+        bar->setDocumentMode(_documentMode);
+    foreach (QTabBar *bar, unusedTabBars)
+        bar->setDocumentMode(_documentMode);
+}
+#endif // QT_NO_TABBAR
+
+void QMainWindowLayout::setVerticalTabsEnabled(bool enabled)
+{
+#ifdef QT_NO_TABBAR
+    Q_UNUSED(enabled);
+#else
+    if (verticalTabsEnabled == enabled)
+        return;
+
+    verticalTabsEnabled = enabled;
+
+    updateTabBarShapes();
+#endif // QT_NO_TABBAR
+}
+
+#ifndef QT_NO_TABWIDGET
+QTabWidget::TabShape QMainWindowLayout::tabShape() const
+{
+    return _tabShape;
+}
+
+void QMainWindowLayout::setTabShape(QTabWidget::TabShape tabShape)
+{
+    if (_tabShape == tabShape)
+        return;
+
+    _tabShape = tabShape;
+
+    updateTabBarShapes();
+}
+
+QTabWidget::TabPosition QMainWindowLayout::tabPosition(Qt::DockWidgetArea area) const
+{
+    return tabPositions[toDockPos(area)];
+}
+
+void QMainWindowLayout::setTabPosition(Qt::DockWidgetAreas areas, QTabWidget::TabPosition tabPosition)
+{
+    const Qt::DockWidgetArea dockWidgetAreas[] = {
+        Qt::TopDockWidgetArea,
+        Qt::LeftDockWidgetArea,
+        Qt::BottomDockWidgetArea,
+        Qt::RightDockWidgetArea
+    };
+    const QInternal::DockPosition dockPositions[] = {
+        QInternal::TopDock,
+        QInternal::LeftDock,
+        QInternal::BottomDock,
+        QInternal::RightDock
+    };
+
+    for (int i = 0; i < QInternal::DockCount; ++i)
+        if (areas & dockWidgetAreas[i])
+            tabPositions[dockPositions[i]] = tabPosition;
+
+    updateTabBarShapes();
+}
+
+static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
+{
+    const bool rounded = (shape == QTabWidget::Rounded);
+    if (position == QTabWidget::North)
+        return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
+    if (position == QTabWidget::South)
+        return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
+    if (position == QTabWidget::East)
+        return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
+    if (position == QTabWidget::West)
+        return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
+    return QTabBar::RoundedNorth;
+}
+#endif // QT_NO_TABWIDGET
+
+#ifndef QT_NO_TABBAR
+void QMainWindowLayout::updateTabBarShapes()
+{
+#ifndef QT_NO_TABWIDGET
+    const QTabWidget::TabPosition vertical[] = {
+        QTabWidget::West,
+        QTabWidget::East,
+        QTabWidget::North,
+        QTabWidget::South
+    };
+#else
+    const QTabBar::Shape vertical[] = {
+        QTabBar::RoundedWest,
+        QTabBar::RoundedEast,
+        QTabBar::RoundedNorth,
+        QTabBar::RoundedSouth
+    };
+#endif
+
+    QDockAreaLayout &layout = layoutState.dockAreaLayout;
+
+    for (int i = 0; i < QInternal::DockCount; ++i) {
+#ifndef QT_NO_TABWIDGET
+        QTabWidget::TabPosition pos = verticalTabsEnabled ? vertical[i] : tabPositions[i];
+        QTabBar::Shape shape = tabBarShapeFrom(_tabShape, pos);
+#else
+        QTabBar::Shape shape = verticalTabsEnabled ? vertical[i] : QTabBar::RoundedSouth;
+#endif
+        layout.docks[i].setTabBarShape(shape);
+    }
+}
+#endif // QT_NO_TABBAR
+
+void QMainWindowLayout::splitDockWidget(QDockWidget *after,
+                                        QDockWidget *dockwidget,
+                                        Qt::Orientation orientation)
+{
+    addChildWidget(dockwidget);
+    layoutState.dockAreaLayout.splitDockWidget(after, dockwidget, orientation);
+    emit dockwidget->dockLocationChanged(dockWidgetArea(after));
+    invalidate();
+}
+
+Qt::DockWidgetArea QMainWindowLayout::dockWidgetArea(QDockWidget *widget) const
+{
+    QList<int> pathToWidget = layoutState.dockAreaLayout.indexOf(widget);
+    if (pathToWidget.isEmpty())
+        return Qt::NoDockWidgetArea;
+    return toDockWidgetArea(pathToWidget.first());
+}
+
+void QMainWindowLayout::keepSize(QDockWidget *w)
+{
+    layoutState.dockAreaLayout.keepSize(w);
+}
+
+#ifndef QT_NO_TABBAR
+
+class QMainWindowTabBar : public QTabBar
+{
+public:
+    QMainWindowTabBar(QWidget *parent);
+protected:
+    bool event(QEvent *e);
+};
+
+QMainWindowTabBar::QMainWindowTabBar(QWidget *parent)
+    : QTabBar(parent)
+{
+    setExpanding(false);
+}
+
+bool QMainWindowTabBar::event(QEvent *e)
+{
+    // show the tooltip if tab is too small to fit label
+
+    if (e->type() != QEvent::ToolTip)
+        return QTabBar::event(e);
+    QSize size = this->size();
+    QSize hint = sizeHint();
+    if (shape() == QTabBar::RoundedWest || shape() == QTabBar::RoundedEast) {
+        size.transpose();
+        hint.transpose();
+    }
+    if (size.width() < hint.width())
+        return QTabBar::event(e);
+    e->accept();
+    return true;
+}
+
+QTabBar *QMainWindowLayout::getTabBar()
+{
+    QTabBar *result = 0;
+    if (!unusedTabBars.isEmpty()) {
+        result = unusedTabBars.takeLast();
+    } else {
+        result = new QMainWindowTabBar(parentWidget());
+        result->setDrawBase(true);
+        result->setElideMode(Qt::ElideRight);
+        result->setDocumentMode(_documentMode);
+        connect(result, SIGNAL(currentChanged(int)), this, SLOT(tabChanged()));
+    }
+
+    usedTabBars.insert(result);
+    return result;
+}
+
+// Allocates a new separator widget if needed
+QWidget *QMainWindowLayout::getSeparatorWidget()
+{
+    QWidget *result = 0;
+    if (!unusedSeparatorWidgets.isEmpty()) {
+        result = unusedSeparatorWidgets.takeLast();
+    } else {
+        result = new QWidget(parentWidget());
+        result->setAttribute(Qt::WA_MouseNoMask, true);
+        result->setAutoFillBackground(false);
+        result->setObjectName(QLatin1String("qt_qmainwindow_extended_splitter"));
+    }
+    usedSeparatorWidgets.insert(result);
+    return result;
+}
+
+void QMainWindowLayout::tabChanged()
+{
+    QTabBar *tb = qobject_cast<QTabBar*>(sender());
+    if (tb == 0)
+        return;
+    QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(tb);
+    if (info == 0)
+        return;
+    info->apply(false);
+
+    if (QWidget *w = centralWidget())
+        w->raise();
+}
+#endif // QT_NO_TABBAR
+
+bool QMainWindowLayout::startSeparatorMove(const QPoint &pos)
+{
+    movingSeparator = layoutState.dockAreaLayout.findSeparator(pos);
+
+    if (movingSeparator.isEmpty())
+        return false;
+
+    savedState = layoutState;
+    movingSeparatorPos = movingSeparatorOrigin = pos;
+
+    return true;
+}
+
+bool QMainWindowLayout::separatorMove(const QPoint &pos)
+{
+    if (movingSeparator.isEmpty())
+        return false;
+    movingSeparatorPos = pos;
+    separatorMoveTimer.start(0, this);
+    return true;
+}
+
+bool QMainWindowLayout::endSeparatorMove(const QPoint&)
+{
+    bool result = !movingSeparator.isEmpty();
+    movingSeparator.clear();
+    savedState.clear();
+    return result;
+}
+
+void QMainWindowLayout::raise(QDockWidget *widget)
+{
+    QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget);
+    if (info == 0)
+        return;
+#ifndef QT_NO_TABBAR
+    if (!info->tabbed)
+        return;
+    info->setCurrentTab(widget);
+#endif
+}
+
+#endif // QT_NO_DOCKWIDGET
+
+
+/******************************************************************************
+** QMainWindowLayoutState - layout interface
+*/
+
+int QMainWindowLayout::count() const
+{
+    qWarning("QMainWindowLayout::count: ?");
+    return 0; //#################################################
+}
+
+QLayoutItem *QMainWindowLayout::itemAt(int index) const
+{
+    int x = 0;
+
+    if (QLayoutItem *ret = layoutState.itemAt(index, &x))
+        return ret;
+
+    if (statusbar && x++ == index)
+        return statusbar;
+
+    return 0;
+}
+
+QLayoutItem *QMainWindowLayout::takeAt(int index)
+{
+    int x = 0;
+
+    if (QLayoutItem *ret = layoutState.takeAt(index, &x)) {
+        // the widget might in fact have been destroyed by now
+        if (QWidget *w = ret->widget()) {
+            widgetAnimator.abort(w);
+            if (w == pluggingWidget)
+                pluggingWidget = 0;
+        }
+
+        if (savedState.isValid() ) {
+            //we need to remove the item also from the saved state to prevent crash
+            savedState.remove(ret);
+            //Also, the item may be contained several times as a gap item.
+            layoutState.remove(ret);
+        }
+
+#ifndef QT_NO_TOOLBAR
+        if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) {
+            currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
+            if (!currentGapPos.isEmpty()) {
+                currentGapPos.prepend(0);
+                currentGapRect = layoutState.itemRect(currentGapPos);
+            }
+        }
+#endif
+
+        return ret;
+    }
+
+    if (statusbar && x++ == index) {
+        QLayoutItem *ret = statusbar;
+        statusbar = 0;
+        return ret;
+    }
+
+    return 0;
+}
+
+void QMainWindowLayout::setGeometry(const QRect &_r)
+{
+    if (savedState.isValid())
+        return;
+
+    QRect r = _r;
+
+    QLayout::setGeometry(r);
+
+    if (statusbar) {
+        QRect sbr(QPoint(0, 0),
+                  QSize(r.width(), statusbar->heightForWidth(r.width()))
+                  .expandedTo(statusbar->minimumSize()));
+        sbr.moveBottom(r.bottom());
+        QRect vr = QStyle::visualRect(parentWidget()->layoutDirection(), _r, sbr);
+        statusbar->setGeometry(vr);
+        r.setBottom(sbr.top() - 1);
+    }
+
+    layoutState.rect = r;
+    layoutState.fitLayout();
+    applyState(layoutState, false);
+}
+
+void QMainWindowLayout::addItem(QLayoutItem *)
+{ qWarning("QMainWindowLayout::addItem: Please use the public QMainWindow API instead"); }
+
+QSize QMainWindowLayout::sizeHint() const
+{
+    if (!szHint.isValid()) {
+        szHint = layoutState.sizeHint();
+        const QSize sbHint = statusbar ? statusbar->sizeHint() : QSize(0, 0);
+        szHint = QSize(qMax(sbHint.width(), szHint.width()),
+                        sbHint.height() + szHint.height());
+    }
+    return szHint;
+}
+
+QSize QMainWindowLayout::minimumSize() const
+{
+    if (!minSize.isValid()) {
+        minSize = layoutState.minimumSize();
+        const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0);
+        minSize = QSize(qMax(sbMin.width(), minSize.width()),
+                        sbMin.height() + minSize.height());
+#ifdef Q_WS_MAC
+        const QSize storedSize = minSize;
+        int minWidth = 0;
+        foreach (QToolBar *toolbar, qtoolbarsInUnifiedToolbarList) {
+            minWidth += toolbar->sizeHint().width() + 20;
+        }
+        minSize = QSize(qMax(minWidth, storedSize.width()), storedSize.height());
+#endif
+    }
+    return minSize;
+}
+
+void QMainWindowLayout::invalidate()
+{
+    QLayout::invalidate();
+    minSize = szHint = QSize();
+}
+
+/******************************************************************************
+** QMainWindowLayout - remaining stuff
+*/
+
+static void fixToolBarOrientation(QLayoutItem *item, int dockPos)
+{
+#ifndef QT_NO_TOOLBAR
+    QToolBar *toolBar = qobject_cast<QToolBar*>(item->widget());
+    if (toolBar == 0)
+        return;
+
+    QRect oldGeo = toolBar->geometry();
+
+    QInternal::DockPosition pos
+        = static_cast<QInternal::DockPosition>(dockPos);
+    Qt::Orientation o = pos == QInternal::TopDock || pos == QInternal::BottomDock
+                        ? Qt::Horizontal : Qt::Vertical;
+    if (o != toolBar->orientation())
+        toolBar->setOrientation(o);
+
+    QSize hint = toolBar->sizeHint().boundedTo(toolBar->maximumSize())
+                    .expandedTo(toolBar->minimumSize());
+
+    if (toolBar->size() != hint) {
+        QRect newGeo(oldGeo.topLeft(), hint);
+        if (toolBar->layoutDirection() == Qt::RightToLeft)
+            newGeo.moveRight(oldGeo.right());
+        toolBar->setGeometry(newGeo);
+    }
+
+#else
+    Q_UNUSED(item);
+    Q_UNUSED(dockPos);
+#endif
+}
+
+void QMainWindowLayout::revert(QLayoutItem *widgetItem)
+{
+    if (!savedState.isValid())
+        return;
+
+    QWidget *widget = widgetItem->widget();
+    layoutState = savedState;
+    currentGapPos = layoutState.indexOf(widget);
+    fixToolBarOrientation(widgetItem, currentGapPos.at(1));
+    layoutState.unplug(currentGapPos);
+    layoutState.fitLayout();
+    currentGapRect = layoutState.itemRect(currentGapPos);
+
+    plug(widgetItem);
+}
+
+bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
+{
+    if (!parentWidget()->isVisible() || parentWidget()->isMinimized() || currentGapPos.isEmpty())
+        return false;
+
+    fixToolBarOrientation(widgetItem, currentGapPos.at(1));
+
+    QWidget *widget = widgetItem->widget();
+
+    QList<int> previousPath = layoutState.indexOf(widget);
+
+    QLayoutItem *it = layoutState.plug(currentGapPos);
+    Q_ASSERT(it == widgetItem);
+    Q_UNUSED(it);
+    if (!previousPath.isEmpty())
+        layoutState.remove(previousPath);
+
+    pluggingWidget = widget;
+    QRect globalRect = currentGapRect;
+    globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft()));
+#ifndef QT_NO_DOCKWIDGET
+    if (qobject_cast<QDockWidget*>(widget) != 0) {
+        QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout());
+        if (layout->nativeWindowDeco()) {
+            globalRect.adjust(0, layout->titleHeight(), 0, 0);
+        } else {
+            int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, widget);
+            globalRect.adjust(-fw, -fw, fw, fw);
+        }
+    }
+#endif
+    widgetAnimator.animate(widget, globalRect, dockOptions & QMainWindow::AnimatedDocks);
+
+    return true;
+}
+
+void QMainWindowLayout::animationFinished(QWidget *widget)
+{
+    //this function is called from within the Widget Animator whenever an animation is finished
+    //on a certain widget
+#ifndef QT_NO_TOOLBAR
+    if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
+        QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout());
+        if (tbl->animating) {
+            tbl->animating = false;
+            if (tbl->expanded)
+                tbl->layoutActions(tb->size());
+            tb->update();
+        }
+    }
+#endif
+
+    if (widget == pluggingWidget) {
+
+#ifndef QT_NO_DOCKWIDGET
+        if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
+            dw->d_func()->plug(currentGapRect);
+#endif
+#ifndef QT_NO_TOOLBAR
+        if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
+            tb->d_func()->plug(currentGapRect);
+#endif
+
+#ifndef QT_NO_DOCKWIDGET
+#ifndef QT_NO_TABBAR
+        if (qobject_cast<QDockWidget*>(widget) != 0) {
+            // info() might return null if the widget is destroyed while
+            // animating but before the animationFinished signal is received.
+            if (QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget))
+                info->setCurrentTab(widget);
+        }
+#endif
+#endif
+
+        savedState.clear();
+        currentGapPos.clear();
+        pluggingWidget = 0;
+    }
+
+    if (!widgetAnimator.animating()) {
+        //all animations are finished
+#ifndef QT_NO_DOCKWIDGET
+        parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
+#ifndef QT_NO_TABBAR
+        foreach (QTabBar *tab_bar, usedTabBars)
+            tab_bar->show();
+#endif // QT_NO_TABBAR
+#endif // QT_NO_DOCKWIDGET
+    }
+
+    updateGapIndicator();
+}
+
+void QMainWindowLayout::restore(bool keepSavedState)
+{
+    if (!savedState.isValid())
+        return;
+
+    layoutState = savedState;
+    applyState(layoutState);
+    if (!keepSavedState)
+        savedState.clear();
+    currentGapPos.clear();
+    pluggingWidget = 0;
+    updateGapIndicator();
+}
+
+QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow)
+    : QLayout(mainwindow)
+    , layoutState(mainwindow)
+    , savedState(mainwindow)
+    , dockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowTabbedDocks)
+    , statusbar(0)
+#ifndef QT_NO_DOCKWIDGET
+#ifndef QT_NO_TABBAR
+    , _documentMode(false)
+    , verticalTabsEnabled(false)
+#ifndef QT_NO_TABWIDGET
+    , _tabShape(QTabWidget::Rounded)
+#endif
+#endif
+#endif // QT_NO_DOCKWIDGET
+    , widgetAnimator(this)
+    , pluggingWidget(0)
+#ifndef QT_NO_RUBBERBAND
+    , gapIndicator(new QRubberBand(QRubberBand::Rectangle, mainwindow))
+#endif //QT_NO_RUBBERBAND
+#ifdef Q_WS_MAC
+    , blockVisiblityCheck(false)
+#endif
+{
+#ifndef QT_NO_DOCKWIDGET
+#ifndef QT_NO_TABBAR
+    sep = mainwindow->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, mainwindow);
+#endif
+
+#ifndef QT_NO_TABWIDGET
+    for (int i = 0; i < QInternal::DockCount; ++i)
+        tabPositions[i] = QTabWidget::South;
+#endif
+#endif // QT_NO_DOCKWIDGET
+
+#ifndef QT_NO_RUBBERBAND
+    // For accessibility to identify this special widget.
+    gapIndicator->setObjectName(QLatin1String("qt_rubberband"));
+    gapIndicator->hide();
+#endif
+    pluggingWidget = 0;
+
+    setObjectName(mainwindow->objectName() + QLatin1String("_layout"));
+}
+
+QMainWindowLayout::~QMainWindowLayout()
+{
+    layoutState.deleteAllLayoutItems();
+    layoutState.deleteCentralWidgetItem();
+
+#ifdef Q_WS_MAC
+    cleanUpMacToolbarItems();
+#endif
+
+    delete statusbar;
+}
+
+void QMainWindowLayout::setDockOptions(QMainWindow::DockOptions opts)
+{
+    if (opts == dockOptions)
+        return;
+
+    dockOptions = opts;
+
+#ifndef QT_NO_DOCKWIDGET
+    setVerticalTabsEnabled(opts & QMainWindow::VerticalTabs);
+#endif
+
+    invalidate();
+}
+
+#ifndef QT_NO_STATUSBAR
+QStatusBar *QMainWindowLayout::statusBar() const
+{ return statusbar ? qobject_cast<QStatusBar *>(statusbar->widget()) : 0; }
+
+void QMainWindowLayout::setStatusBar(QStatusBar *sb)
+{
+    if (sb)
+        addChildWidget(sb);
+    delete statusbar;
+    statusbar = sb ? new QWidgetItemV2(sb) : 0;
+    invalidate();
+}
+#endif // QT_NO_STATUSBAR
+
+QWidget *QMainWindowLayout::centralWidget() const
+{
+    return layoutState.centralWidget();
+}
+
+void QMainWindowLayout::setCentralWidget(QWidget *widget)
+{
+    if (widget != 0)
+        addChildWidget(widget);
+    layoutState.setCentralWidget(widget);
+    if (savedState.isValid()) {
+#ifndef QT_NO_DOCKWIDGET
+        savedState.dockAreaLayout.centralWidgetItem = layoutState.dockAreaLayout.centralWidgetItem;
+#else
+        savedState.centralWidgetItem = layoutState.centralWidgetItem;
+#endif
+    }
+    invalidate();
+}
+
+QLayoutItem *QMainWindowLayout::unplug(QWidget *widget)
+{
+    QList<int> path = layoutState.indexOf(widget);
+    if (path.isEmpty())
+        return 0;
+
+    QLayoutItem *item = layoutState.item(path);
+    if (widget->isWindow())
+        return item;
+
+    QRect r = layoutState.itemRect(path);
+    savedState = layoutState;
+
+#ifndef QT_NO_DOCKWIDGET
+    if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
+        dw->d_func()->unplug(r);
+    }
+#endif
+#ifndef QT_NO_TOOLBAR
+    if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) {
+        tb->d_func()->unplug(r);
+    }
+#endif
+
+
+    layoutState.unplug(path ,&savedState);
+    savedState.fitLayout();
+    currentGapPos = path;
+    currentGapRect = r;
+    updateGapIndicator();
+
+    fixToolBarOrientation(item, currentGapPos.at(1));
+
+    return item;
+}
+
+void QMainWindowLayout::updateGapIndicator()
+{
+#ifndef QT_NO_RUBBERBAND
+    gapIndicator->setVisible(!widgetAnimator.animating() && !currentGapPos.isEmpty());
+    gapIndicator->setGeometry(currentGapRect);
+#endif
+}
+
+QList<int> QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
+{
+    if (!parentWidget()->isVisible() || parentWidget()->isMinimized()
+        || pluggingWidget != 0 || widgetItem == 0)
+        return QList<int>();
+
+    QWidget *widget = widgetItem->widget();
+    QPoint pos = parentWidget()->mapFromGlobal(mousePos);
+
+    if (!savedState.isValid())
+        savedState = layoutState;
+
+    QList<int> path = savedState.gapIndex(widget, pos);
+
+    if (!path.isEmpty()) {
+        bool allowed = false;
+
+#ifndef QT_NO_DOCKWIDGET
+        if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget))
+            allowed = dw->isAreaAllowed(toDockWidgetArea(path.at(1)));
+#endif
+#ifndef QT_NO_TOOLBAR
+        if (QToolBar *tb = qobject_cast<QToolBar*>(widget))
+            allowed = tb->isAreaAllowed(toToolBarArea(path.at(1)));
+#endif
+
+        if (!allowed)
+            path.clear();
+    }
+
+    if (path == currentGapPos)
+        return currentGapPos; // the gap is already there
+
+    currentGapPos = path;
+    if (path.isEmpty()) {
+        fixToolBarOrientation(widgetItem, 2); // 2 = top dock, ie. horizontal
+        restore(true);
+        return QList<int>();
+    }
+
+    fixToolBarOrientation(widgetItem, currentGapPos.at(1));
+
+    QMainWindowLayoutState newState = savedState;
+
+    if (!newState.insertGap(path, widgetItem)) {
+        restore(true); // not enough space
+        return QList<int>();
+    }
+
+    QSize min = newState.minimumSize();
+    QSize size = newState.rect.size();
+
+    if (min.width() > size.width() || min.height() > size.height()) {
+        restore(true);
+        return QList<int>();
+    }
+
+    newState.fitLayout();
+
+    currentGapRect = newState.gapRect(currentGapPos);
+
+#ifndef QT_NO_DOCKWIDGET
+    parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
+#endif
+    layoutState = newState;
+    applyState(layoutState);
+
+    updateGapIndicator();
+
+    return path;
+}
+
+void QMainWindowLayout::applyState(QMainWindowLayoutState &newState, bool animate)
+{
+#ifndef QT_NO_DOCKWIDGET
+#ifndef QT_NO_TABBAR
+    QSet<QTabBar*> used = newState.dockAreaLayout.usedTabBars();
+    QSet<QTabBar*> retired = usedTabBars - used;
+    usedTabBars = used;
+    foreach (QTabBar *tab_bar, retired) {
+        tab_bar->hide();
+        while (tab_bar->count() > 0)
+            tab_bar->removeTab(0);
+        unusedTabBars.append(tab_bar);
+    }
+
+    if (sep == 1) {
+        QSet<QWidget*> usedSeps = newState.dockAreaLayout.usedSeparatorWidgets();
+        QSet<QWidget*> retiredSeps = usedSeparatorWidgets - usedSeps;
+        usedSeparatorWidgets = usedSeps;
+        foreach (QWidget *sepWidget, retiredSeps) {
+            unusedSeparatorWidgets.append(sepWidget);
+        }
+    }
+
+
+#endif // QT_NO_TABBAR
+#endif // QT_NO_DOCKWIDGET
+    newState.apply(dockOptions & QMainWindow::AnimatedDocks && animate);
+}
+
+void QMainWindowLayout::saveState(QDataStream &stream) const
+{
+    layoutState.saveState(stream);
+}
+
+bool QMainWindowLayout::restoreState(QDataStream &stream)
+{
+    savedState = layoutState;
+    layoutState.clear();
+    layoutState.rect = savedState.rect;
+
+    if (!layoutState.restoreState(stream, savedState)) {
+        layoutState.deleteAllLayoutItems();
+        layoutState = savedState;
+        if (parentWidget()->isVisible())
+            applyState(layoutState, false); // hides tabBars allocated by newState
+        return false;
+    }
+
+    if (parentWidget()->isVisible()) {
+        layoutState.fitLayout();
+        applyState(layoutState, false);
+    }
+
+    savedState.deleteAllLayoutItems();
+    savedState.clear();
+
+#ifndef QT_NO_DOCKWIDGET
+    if (parentWidget()->isVisible()) {
+#ifndef QT_NO_TABBAR
+        foreach (QTabBar *tab_bar, usedTabBars)
+            tab_bar->show();
+
+#endif
+    }
+#endif // QT_NO_DOCKWIDGET
+
+    return true;
+}
+
+
+// Returns if this toolbar *should* be using HIToolbar. Won't work for all in between cases
+// for example, you have a toolbar in the top area and then you suddenly turn on
+// HIToolbar.
+bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const
+{
+#ifndef Q_WS_MAC
+    Q_UNUSED(toolbar);
+    return false;
+#else
+    return qtoolbarsInUnifiedToolbarList.contains(toolbar)
+           || ((toolBarArea(toolbar) == Qt::TopToolBarArea)
+                && layoutState.mainWindow->unifiedTitleAndToolBarOnMac());
+#endif
+}
+
+void QMainWindowLayout::timerEvent(QTimerEvent *e)
+{
+#ifndef QT_NO_DOCKWIDGET
+    if (e->timerId() == separatorMoveTimer.timerId()) {
+        //let's move the separators
+        separatorMoveTimer.stop();
+        if (movingSeparator.isEmpty())
+            return;
+        if (movingSeparatorOrigin == movingSeparatorPos)
+            return;
+
+        //when moving the separator, we need to update the previous position
+        parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
+
+        layoutState = savedState;
+        layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin,
+                                                    movingSeparatorPos);
+        movingSeparatorPos = movingSeparatorOrigin;
+    }
+#endif
+    QLayout::timerEvent(e);
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_MAINWINDOW