util/src/gui/widgets/qdockarealayout.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "QtGui/qapplication.h"
       
    43 #include "QtGui/qwidget.h"
       
    44 #include "QtGui/qtabbar.h"
       
    45 #include "QtGui/qstyle.h"
       
    46 #include "QtGui/qdesktopwidget.h"
       
    47 #include "QtCore/qvariant.h"
       
    48 #include "qdockarealayout_p.h"
       
    49 #include "qdockwidget.h"
       
    50 #include "qmainwindow.h"
       
    51 #include "qwidgetanimator_p.h"
       
    52 #include "qmainwindowlayout_p.h"
       
    53 #include "qdockwidget_p.h"
       
    54 #include <private/qlayoutengine_p.h>
       
    55 
       
    56 #include <qpainter.h>
       
    57 #include <qstyleoption.h>
       
    58 
       
    59 #ifndef QT_NO_DOCKWIDGET
       
    60 
       
    61 QT_BEGIN_NAMESPACE
       
    62 
       
    63 enum { StateFlagVisible = 1, StateFlagFloating = 2 };
       
    64 
       
    65 /******************************************************************************
       
    66 ** QPlaceHolderItem
       
    67 */
       
    68 
       
    69 QPlaceHolderItem::QPlaceHolderItem(QWidget *w)
       
    70 {
       
    71     objectName = w->objectName();
       
    72     hidden = w->isHidden();
       
    73     window = w->isWindow();
       
    74     if (window)
       
    75         topLevelRect = w->geometry();
       
    76 }
       
    77 
       
    78 /******************************************************************************
       
    79 ** QDockAreaLayoutItem
       
    80 */
       
    81 
       
    82 QDockAreaLayoutItem::QDockAreaLayoutItem(QLayoutItem *_widgetItem)
       
    83     : widgetItem(_widgetItem), subinfo(0), placeHolderItem(0), pos(0), size(-1), flags(NoFlags)
       
    84 {
       
    85 }
       
    86 
       
    87 QDockAreaLayoutItem::QDockAreaLayoutItem(QDockAreaLayoutInfo *_subinfo)
       
    88     : widgetItem(0), subinfo(_subinfo), placeHolderItem(0), pos(0), size(-1), flags(NoFlags)
       
    89 {
       
    90 }
       
    91 
       
    92 QDockAreaLayoutItem::QDockAreaLayoutItem(QPlaceHolderItem *_placeHolderItem)
       
    93     : widgetItem(0), subinfo(0), placeHolderItem(_placeHolderItem), pos(0), size(-1), flags(NoFlags)
       
    94 {
       
    95 }
       
    96 
       
    97 QDockAreaLayoutItem::QDockAreaLayoutItem(const QDockAreaLayoutItem &other)
       
    98     : widgetItem(other.widgetItem), subinfo(0), placeHolderItem(0), pos(other.pos),
       
    99         size(other.size), flags(other.flags)
       
   100 {
       
   101     if (other.subinfo != 0)
       
   102         subinfo = new QDockAreaLayoutInfo(*other.subinfo);
       
   103     else if (other.placeHolderItem != 0)
       
   104         placeHolderItem = new QPlaceHolderItem(*other.placeHolderItem);
       
   105 }
       
   106 
       
   107 QDockAreaLayoutItem::~QDockAreaLayoutItem()
       
   108 {
       
   109     delete subinfo;
       
   110     delete placeHolderItem;
       
   111 }
       
   112 
       
   113 bool QDockAreaLayoutItem::skip() const
       
   114 {
       
   115     if (placeHolderItem != 0)
       
   116         return true;
       
   117 
       
   118     if (flags & GapItem)
       
   119         return false;
       
   120 
       
   121     if (widgetItem != 0)
       
   122         return widgetItem->isEmpty();
       
   123 
       
   124     if (subinfo != 0) {
       
   125         for (int i = 0; i < subinfo->item_list.count(); ++i) {
       
   126             if (!subinfo->item_list.at(i).skip())
       
   127                 return false;
       
   128         }
       
   129     }
       
   130 
       
   131     return true;
       
   132 }
       
   133 
       
   134 QSize QDockAreaLayoutItem::minimumSize() const
       
   135 {
       
   136     if (widgetItem != 0) {
       
   137         int left, top, right, bottom;
       
   138         widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom);
       
   139         return widgetItem->minimumSize() + QSize(left+right, top+bottom);
       
   140     }
       
   141     if (subinfo != 0)
       
   142         return subinfo->minimumSize();
       
   143     return QSize(0, 0);
       
   144 }
       
   145 
       
   146 QSize QDockAreaLayoutItem::maximumSize() const
       
   147 {
       
   148     if (widgetItem != 0) {
       
   149         int left, top, right, bottom;
       
   150         widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom);
       
   151         return widgetItem->maximumSize()+ QSize(left+right, top+bottom);
       
   152     }
       
   153     if (subinfo != 0)
       
   154         return subinfo->maximumSize();
       
   155     return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
       
   156 }
       
   157 
       
   158 bool QDockAreaLayoutItem::hasFixedSize(Qt::Orientation o) const
       
   159 {
       
   160     return perp(o, minimumSize()) == perp(o, maximumSize());
       
   161 }
       
   162 
       
   163 bool QDockAreaLayoutItem::expansive(Qt::Orientation o) const
       
   164 {
       
   165     if ((flags & GapItem) || placeHolderItem != 0)
       
   166         return false;
       
   167     if (widgetItem != 0)
       
   168         return ((widgetItem->expandingDirections() & o) == o);
       
   169     if (subinfo != 0)
       
   170         return subinfo->expansive(o);
       
   171     return false;
       
   172 }
       
   173 
       
   174 QSize QDockAreaLayoutItem::sizeHint() const
       
   175 {
       
   176     if (placeHolderItem != 0)
       
   177         return QSize(0, 0);
       
   178     if (widgetItem != 0) {
       
   179         int left, top, right, bottom;
       
   180         widgetItem->widget()->getContentsMargins(&left, &top, &right, &bottom);
       
   181         return widgetItem->sizeHint() + QSize(left+right, top+bottom);
       
   182     }
       
   183     if (subinfo != 0)
       
   184         return subinfo->sizeHint();
       
   185     return QSize(-1, -1);
       
   186 }
       
   187 
       
   188 QDockAreaLayoutItem
       
   189     &QDockAreaLayoutItem::operator = (const QDockAreaLayoutItem &other)
       
   190 {
       
   191     widgetItem = other.widgetItem;
       
   192     if (other.subinfo == 0)
       
   193         subinfo = 0;
       
   194     else
       
   195         subinfo = new QDockAreaLayoutInfo(*other.subinfo);
       
   196 
       
   197     delete placeHolderItem;
       
   198     if (other.placeHolderItem == 0)
       
   199         placeHolderItem = 0;
       
   200     else
       
   201         placeHolderItem = new QPlaceHolderItem(*other.placeHolderItem);
       
   202 
       
   203     pos = other.pos;
       
   204     size = other.size;
       
   205     flags = other.flags;
       
   206 
       
   207     return *this;
       
   208 }
       
   209 
       
   210 /******************************************************************************
       
   211 ** QDockAreaLayoutInfo
       
   212 */
       
   213 
       
   214 #ifndef QT_NO_TABBAR
       
   215 static quintptr tabId(const QDockAreaLayoutItem &item)
       
   216 {
       
   217     if (item.widgetItem == 0)
       
   218         return 0;
       
   219     return reinterpret_cast<quintptr>(item.widgetItem->widget());
       
   220 }
       
   221 #endif
       
   222 
       
   223 QDockAreaLayoutInfo::QDockAreaLayoutInfo()
       
   224     : sep(0), dockPos(QInternal::LeftDock), o(Qt::Horizontal), mainWindow(0)
       
   225 #ifndef QT_NO_TABBAR
       
   226     , tabbed(false), tabBar(0), tabBarShape(QTabBar::RoundedSouth), tabBarVisible(false)
       
   227 #endif
       
   228 {
       
   229 }
       
   230 
       
   231 QDockAreaLayoutInfo::QDockAreaLayoutInfo(int _sep, QInternal::DockPosition _dockPos,
       
   232                                             Qt::Orientation _o, int tbshape,
       
   233                                             QMainWindow *window)
       
   234     : sep(_sep), dockPos(_dockPos), o(_o), mainWindow(window)
       
   235 #ifndef QT_NO_TABBAR
       
   236     , tabbed(false), tabBar(0), tabBarShape(static_cast<QTabBar::Shape>(tbshape)), tabBarVisible(false)
       
   237 #endif
       
   238 {
       
   239 #ifdef QT_NO_TABBAR
       
   240     Q_UNUSED(tbshape);
       
   241 #endif
       
   242 }
       
   243 
       
   244 QSize QDockAreaLayoutInfo::size() const
       
   245 {
       
   246     return isEmpty() ? QSize(0, 0) : rect.size();
       
   247 }
       
   248 
       
   249 void QDockAreaLayoutInfo::clear()
       
   250 {
       
   251     item_list.clear();
       
   252     rect = QRect();
       
   253 #ifndef QT_NO_TABBAR
       
   254     tabbed = false;
       
   255     tabBar = 0;
       
   256 #endif
       
   257 }
       
   258 
       
   259 bool QDockAreaLayoutInfo::isEmpty() const
       
   260 {
       
   261     return next(-1) == -1;
       
   262 }
       
   263 
       
   264 QSize QDockAreaLayoutInfo::minimumSize() const
       
   265 {
       
   266     if (isEmpty())
       
   267         return QSize(0, 0);
       
   268 
       
   269     int a = 0, b = 0;
       
   270     bool first = true;
       
   271     for (int i = 0; i < item_list.size(); ++i) {
       
   272         const QDockAreaLayoutItem &item = item_list.at(i);
       
   273         if (item.skip())
       
   274             continue;
       
   275 
       
   276         QSize min_size = item.minimumSize();
       
   277 #ifndef QT_NO_TABBAR
       
   278         if (tabbed) {
       
   279             a = qMax(a, pick(o, min_size));
       
   280         } else
       
   281 #endif
       
   282         {
       
   283             if (!first)
       
   284                 a += sep;
       
   285             a += pick(o, min_size);
       
   286         }
       
   287         b = qMax(b, perp(o, min_size));
       
   288 
       
   289         first = false;
       
   290     }
       
   291 
       
   292     QSize result;
       
   293     rpick(o, result) = a;
       
   294     rperp(o, result) = b;
       
   295 
       
   296 #ifndef QT_NO_TABBAR
       
   297     if (tabbed) {
       
   298         QSize tbm = tabBarMinimumSize();
       
   299         switch (tabBarShape) {
       
   300             case QTabBar::RoundedNorth:
       
   301             case QTabBar::RoundedSouth:
       
   302             case QTabBar::TriangularNorth:
       
   303             case QTabBar::TriangularSouth:
       
   304                 result.rheight() += tbm.height();
       
   305                 result.rwidth() = qMax(tbm.width(), result.width());
       
   306                 break;
       
   307             case QTabBar::RoundedEast:
       
   308             case QTabBar::RoundedWest:
       
   309             case QTabBar::TriangularEast:
       
   310             case QTabBar::TriangularWest:
       
   311                 result.rheight() = qMax(tbm.height(), result.height());
       
   312                 result.rwidth() += tbm.width();
       
   313                 break;
       
   314             default:
       
   315                 break;
       
   316         }
       
   317     }
       
   318 #endif // QT_NO_TABBAR
       
   319 
       
   320     return result;
       
   321 }
       
   322 
       
   323 QSize QDockAreaLayoutInfo::maximumSize() const
       
   324 {
       
   325     if (isEmpty())
       
   326         return QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
       
   327 
       
   328     int a = 0, b = QWIDGETSIZE_MAX;
       
   329 #ifndef QT_NO_TABBAR
       
   330     if (tabbed)
       
   331         a = QWIDGETSIZE_MAX;
       
   332 #endif
       
   333 
       
   334     int min_perp = 0;
       
   335 
       
   336     bool first = true;
       
   337     for (int i = 0; i < item_list.size(); ++i) {
       
   338         const QDockAreaLayoutItem &item = item_list.at(i);
       
   339         if (item.skip())
       
   340             continue;
       
   341 
       
   342         QSize max_size = item.maximumSize();
       
   343         min_perp = qMax(min_perp, perp(o, item.minimumSize()));
       
   344 
       
   345 #ifndef QT_NO_TABBAR
       
   346         if (tabbed) {
       
   347             a = qMin(a, pick(o, max_size));
       
   348         } else
       
   349 #endif
       
   350         {
       
   351             if (!first)
       
   352                 a += sep;
       
   353             a += pick(o, max_size);
       
   354         }
       
   355         b = qMin(b, perp(o, max_size));
       
   356 
       
   357         a = qMin(a, int(QWIDGETSIZE_MAX));
       
   358         b = qMin(b, int(QWIDGETSIZE_MAX));
       
   359 
       
   360         first = false;
       
   361     }
       
   362 
       
   363     b = qMax(b, min_perp);
       
   364 
       
   365     QSize result;
       
   366     rpick(o, result) = a;
       
   367     rperp(o, result) = b;
       
   368 
       
   369 #ifndef QT_NO_TABBAR
       
   370     if (tabbed) {
       
   371         QSize tbh = tabBarSizeHint();
       
   372         switch (tabBarShape) {
       
   373             case QTabBar::RoundedNorth:
       
   374             case QTabBar::RoundedSouth:
       
   375                 result.rheight() += tbh.height();
       
   376                 break;
       
   377             case QTabBar::RoundedEast:
       
   378             case QTabBar::RoundedWest:
       
   379                 result.rwidth() += tbh.width();
       
   380                 break;
       
   381             default:
       
   382                 break;
       
   383         }
       
   384     }
       
   385 #endif // QT_NO_TABBAR
       
   386 
       
   387     return result;
       
   388 }
       
   389 
       
   390 QSize QDockAreaLayoutInfo::sizeHint() const
       
   391 {
       
   392     if (isEmpty())
       
   393         return QSize(0, 0);
       
   394 
       
   395     int a = 0, b = 0;
       
   396     int min_perp = 0;
       
   397     int max_perp = QWIDGETSIZE_MAX;
       
   398     const QDockAreaLayoutItem *previous = 0;
       
   399     for (int i = 0; i < item_list.size(); ++i) {
       
   400         const QDockAreaLayoutItem &item = item_list.at(i);
       
   401         if (item.skip())
       
   402             continue;
       
   403 
       
   404         bool gap = item.flags & QDockAreaLayoutItem::GapItem;
       
   405 
       
   406         QSize size_hint = item.sizeHint();
       
   407         min_perp = qMax(min_perp, perp(o, item.minimumSize()));
       
   408         max_perp = qMin(max_perp, perp(o, item.maximumSize()));
       
   409 
       
   410 #ifndef QT_NO_TABBAR
       
   411         if (tabbed) {
       
   412             a = qMax(a, gap ? item.size : pick(o, size_hint));
       
   413         } else
       
   414 #endif
       
   415         {
       
   416             if (previous && !gap && !(previous->flags &  QDockAreaLayoutItem::GapItem)
       
   417                 && !previous->hasFixedSize(o)) {
       
   418                 a += sep;
       
   419             }
       
   420             a += gap ? item.size : pick(o, size_hint);
       
   421         }
       
   422         b = qMax(b, perp(o, size_hint));
       
   423 
       
   424         previous = &item;
       
   425     }
       
   426 
       
   427     max_perp = qMax(max_perp, min_perp);
       
   428     b = qMax(b, min_perp);
       
   429     b = qMin(b, max_perp);
       
   430 
       
   431     QSize result;
       
   432     rpick(o, result) = a;
       
   433     rperp(o, result) = b;
       
   434 
       
   435 #ifndef QT_NO_TABBAR
       
   436     if (tabbed) {
       
   437         QSize tbh = tabBarSizeHint();
       
   438         switch (tabBarShape) {
       
   439             case QTabBar::RoundedNorth:
       
   440             case QTabBar::RoundedSouth:
       
   441             case QTabBar::TriangularNorth:
       
   442             case QTabBar::TriangularSouth:
       
   443                 result.rheight() += tbh.height();
       
   444                 result.rwidth() = qMax(tbh.width(), result.width());
       
   445                 break;
       
   446             case QTabBar::RoundedEast:
       
   447             case QTabBar::RoundedWest:
       
   448             case QTabBar::TriangularEast:
       
   449             case QTabBar::TriangularWest:
       
   450                 result.rheight() = qMax(tbh.height(), result.height());
       
   451                 result.rwidth() += tbh.width();
       
   452                 break;
       
   453             default:
       
   454                 break;
       
   455         }
       
   456     }
       
   457 #endif // QT_NO_TABBAR
       
   458 
       
   459     return result;
       
   460 }
       
   461 
       
   462 bool QDockAreaLayoutInfo::expansive(Qt::Orientation o) const
       
   463 {
       
   464     for (int i = 0; i < item_list.size(); ++i) {
       
   465         if (item_list.at(i).expansive(o))
       
   466             return true;
       
   467     }
       
   468     return false;
       
   469 }
       
   470 
       
   471 /* QDockAreaLayoutInfo::maximumSize() doesn't return the real max size. For example,
       
   472    if the layout is empty, it returns QWIDGETSIZE_MAX. This is so that empty dock areas
       
   473    don't constrain the size of the QMainWindow, but sometimes we really need to know the
       
   474    maximum size. Also, these functions take into account widgets that want to keep their
       
   475    size (f.ex. when they are hidden and then shown, they should not change size).
       
   476 */
       
   477 
       
   478 static int realMinSize(const QDockAreaLayoutInfo &info)
       
   479 {
       
   480     int result = 0;
       
   481     bool first = true;
       
   482     for (int i = 0; i < info.item_list.size(); ++i) {
       
   483         const QDockAreaLayoutItem &item = info.item_list.at(i);
       
   484         if (item.skip())
       
   485             continue;
       
   486 
       
   487         int min = 0;
       
   488         if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
       
   489             min = item.size;
       
   490         else
       
   491             min = pick(info.o, item.minimumSize());
       
   492 
       
   493         if (!first)
       
   494             result += info.sep;
       
   495         result += min;
       
   496 
       
   497         first = false;
       
   498     }
       
   499 
       
   500     return result;
       
   501 }
       
   502 
       
   503 static int realMaxSize(const QDockAreaLayoutInfo &info)
       
   504 {
       
   505     int result = 0;
       
   506     bool first = true;
       
   507     for (int i = 0; i < info.item_list.size(); ++i) {
       
   508         const QDockAreaLayoutItem &item = info.item_list.at(i);
       
   509         if (item.skip())
       
   510             continue;
       
   511 
       
   512         int max = 0;
       
   513         if ((item.flags & QDockAreaLayoutItem::KeepSize) && item.size != -1)
       
   514             max = item.size;
       
   515         else
       
   516             max = pick(info.o, item.maximumSize());
       
   517 
       
   518         if (!first)
       
   519             result += info.sep;
       
   520         result += max;
       
   521 
       
   522         if (result >= QWIDGETSIZE_MAX)
       
   523             return QWIDGETSIZE_MAX;
       
   524 
       
   525         first = false;
       
   526     }
       
   527 
       
   528     return result;
       
   529 }
       
   530 
       
   531 void QDockAreaLayoutInfo::fitItems()
       
   532 {
       
   533 #ifndef QT_NO_TABBAR
       
   534     if (tabbed) {
       
   535         return;
       
   536     }
       
   537 #endif
       
   538 
       
   539     QVector<QLayoutStruct> layout_struct_list(item_list.size()*2);
       
   540     int j = 0;
       
   541 
       
   542     int size = pick(o, rect.size());
       
   543     int min_size = realMinSize(*this);
       
   544     int max_size = realMaxSize(*this);
       
   545     int last_index = -1;
       
   546 
       
   547     const QDockAreaLayoutItem *previous = 0;
       
   548     for (int i = 0; i < item_list.size(); ++i) {
       
   549         QDockAreaLayoutItem &item = item_list[i];
       
   550         if (item.skip())
       
   551             continue;
       
   552 
       
   553         bool gap = item.flags & QDockAreaLayoutItem::GapItem;
       
   554         if (previous && !gap) {
       
   555             if (!(previous->flags & QDockAreaLayoutItem::GapItem)) {
       
   556                 QLayoutStruct &ls = layout_struct_list[j++];
       
   557                 ls.init();
       
   558                 ls.minimumSize = ls.maximumSize = ls.sizeHint = previous->hasFixedSize(o) ? 0 : sep;
       
   559                 ls.empty = false;
       
   560             }
       
   561         }
       
   562 
       
   563         if (item.flags & QDockAreaLayoutItem::KeepSize) {
       
   564             // Check if the item can keep its size, without violating size constraints
       
   565             // of other items.
       
   566 
       
   567             if (size < min_size) {
       
   568                 // There is too little space to keep this widget's size
       
   569                 item.flags &= ~QDockAreaLayoutItem::KeepSize;
       
   570                 min_size -= item.size;
       
   571                 min_size += pick(o, item.minimumSize());
       
   572                 min_size = qMax(0, min_size);
       
   573             } else if (size > max_size) {
       
   574                 // There is too much space to keep this widget's size
       
   575                 item.flags &= ~QDockAreaLayoutItem::KeepSize;
       
   576                 max_size -= item.size;
       
   577                 max_size += pick(o, item.maximumSize());
       
   578                 max_size = qMin<int>(QWIDGETSIZE_MAX, max_size);
       
   579             }
       
   580         }
       
   581 
       
   582         last_index = j;
       
   583         QLayoutStruct &ls = layout_struct_list[j++];
       
   584         ls.init();
       
   585         ls.empty = false;
       
   586         if (item.flags & QDockAreaLayoutItem::KeepSize) {
       
   587             ls.minimumSize = ls.maximumSize = ls.sizeHint = item.size;
       
   588             ls.expansive = false;
       
   589             ls.stretch = 0;
       
   590         } else {
       
   591             ls.maximumSize = pick(o, item.maximumSize());
       
   592             ls.expansive = item.expansive(o);
       
   593             ls.minimumSize = pick(o, item.minimumSize());
       
   594             ls.sizeHint = item.size == -1 ? pick(o, item.sizeHint()) : item.size;
       
   595             ls.stretch = ls.expansive ? ls.sizeHint : 0;
       
   596         }
       
   597 
       
   598         item.flags &= ~QDockAreaLayoutItem::KeepSize;
       
   599         previous = &item;
       
   600     }
       
   601     layout_struct_list.resize(j);
       
   602 
       
   603     // If there is more space than the widgets can take (due to maximum size constraints),
       
   604     // we detect it here and stretch the last widget to take up the rest of the space.
       
   605     if (size > max_size && last_index != -1) {
       
   606         layout_struct_list[last_index].maximumSize = QWIDGETSIZE_MAX;
       
   607         layout_struct_list[last_index].expansive = true;
       
   608     }
       
   609 
       
   610     qGeomCalc(layout_struct_list, 0, j, pick(o, rect.topLeft()), size, 0);
       
   611 
       
   612     j = 0;
       
   613     bool prev_gap = false;
       
   614     bool first = true;
       
   615     for (int i = 0; i < item_list.size(); ++i) {
       
   616         QDockAreaLayoutItem &item = item_list[i];
       
   617         if (item.skip())
       
   618             continue;
       
   619 
       
   620         bool gap = item.flags & QDockAreaLayoutItem::GapItem;
       
   621         if (!first && !gap && !prev_gap)
       
   622             ++j;
       
   623 
       
   624         const QLayoutStruct &ls = layout_struct_list.at(j++);
       
   625         item.size = ls.size;
       
   626         item.pos = ls.pos;
       
   627 
       
   628         if (item.subinfo != 0) {
       
   629             item.subinfo->rect = itemRect(i);
       
   630             item.subinfo->fitItems();
       
   631         }
       
   632 
       
   633         prev_gap = gap;
       
   634         first = false;
       
   635     }
       
   636 }
       
   637 
       
   638 static QInternal::DockPosition dockPosHelper(const QRect &rect, const QPoint &_pos,
       
   639                                         Qt::Orientation o,
       
   640                                         bool nestingEnabled,
       
   641                                         QDockAreaLayoutInfo::TabMode tabMode)
       
   642 {
       
   643     if (tabMode == QDockAreaLayoutInfo::ForceTabs)
       
   644         return QInternal::DockCount;
       
   645 
       
   646     QPoint pos = _pos - rect.topLeft();
       
   647 
       
   648     int x = pos.x();
       
   649     int y = pos.y();
       
   650     int w = rect.width();
       
   651     int h = rect.height();
       
   652 
       
   653     if (tabMode != QDockAreaLayoutInfo::NoTabs) {
       
   654         // is it in the center?
       
   655         if (nestingEnabled) {
       
   656         /*             2/3
       
   657                 +--------------+
       
   658                 |              |
       
   659                 |   CCCCCCCC   |
       
   660            2/3  |   CCCCCCCC   |
       
   661                 |   CCCCCCCC   |
       
   662                 |              |
       
   663                 +--------------+     */
       
   664 
       
   665             QRect center(w/6, h/6, 2*w/3, 2*h/3);
       
   666             if (center.contains(pos))
       
   667                 return QInternal::DockCount;
       
   668         } else if (o == Qt::Horizontal) {
       
   669         /*             2/3
       
   670                 +--------------+
       
   671                 |   CCCCCCCC   |
       
   672                 |   CCCCCCCC   |
       
   673                 |   CCCCCCCC   |
       
   674                 |   CCCCCCCC   |
       
   675                 |   CCCCCCCC   |
       
   676                 +--------------+     */
       
   677 
       
   678             if (x > w/6 && x < w*5/6)
       
   679                 return QInternal::DockCount;
       
   680         } else {
       
   681         /*
       
   682                 +--------------+
       
   683                 |              |
       
   684            2/3  |CCCCCCCCCCCCCC|
       
   685                 |CCCCCCCCCCCCCC|
       
   686                 |              |
       
   687                 +--------------+     */
       
   688             if (y > h/6 && y < 5*h/6)
       
   689                 return QInternal::DockCount;
       
   690         }
       
   691     }
       
   692 
       
   693     // not in the center. which edge?
       
   694     if (nestingEnabled) {
       
   695         if (o == Qt::Horizontal) {
       
   696     /*       1/3  1/3 1/3
       
   697             +------------+     (we've already ruled out the center)
       
   698             |LLLLTTTTRRRR|
       
   699             |LLLLTTTTRRRR|
       
   700             |LLLLBBBBRRRR|
       
   701             |LLLLBBBBRRRR|
       
   702             +------------+    */
       
   703 
       
   704             if (x < w/3)
       
   705                 return QInternal::LeftDock;
       
   706             if (x > 2*w/3)
       
   707                 return QInternal::RightDock;
       
   708             if (y < h/2)
       
   709                 return QInternal::TopDock;
       
   710             return QInternal::BottomDock;
       
   711         } else {
       
   712     /*      +------------+     (we've already ruled out the center)
       
   713         1/3 |TTTTTTTTTTTT|
       
   714             |LLLLLLRRRRRR|
       
   715         1/3 |LLLLLLRRRRRR|
       
   716         1/3 |BBBBBBBBBBBB|
       
   717             +------------+    */
       
   718 
       
   719             if (y < h/3)
       
   720                 return QInternal::TopDock;
       
   721             if (y > 2*h/3)
       
   722                 return QInternal::BottomDock;
       
   723             if (x < w/2)
       
   724                 return QInternal::LeftDock;
       
   725             return QInternal::RightDock;
       
   726         }
       
   727     } else {
       
   728         if (o == Qt::Horizontal) {
       
   729             return x < w/2
       
   730                     ? QInternal::LeftDock
       
   731                     : QInternal::RightDock;
       
   732         } else {
       
   733             return y < h/2
       
   734                     ? QInternal::TopDock
       
   735                     : QInternal::BottomDock;
       
   736         }
       
   737     }
       
   738 }
       
   739 
       
   740 QList<int> QDockAreaLayoutInfo::gapIndex(const QPoint& _pos,
       
   741                         bool nestingEnabled, TabMode tabMode) const
       
   742 {
       
   743     QList<int> result;
       
   744     QRect item_rect;
       
   745     int item_index = 0;
       
   746 
       
   747 #ifndef QT_NO_TABBAR
       
   748     if (tabbed) {
       
   749         item_rect = tabContentRect();
       
   750     } else
       
   751 #endif
       
   752     {
       
   753         int pos = pick(o, _pos);
       
   754 
       
   755         int last = -1;
       
   756         for (int i = 0; i < item_list.size(); ++i) {
       
   757             const QDockAreaLayoutItem &item = item_list.at(i);
       
   758             if (item.skip())
       
   759                 continue;
       
   760 
       
   761             last = i;
       
   762 
       
   763             if (item.pos + item.size < pos)
       
   764                 continue;
       
   765 
       
   766             if (item.subinfo != 0
       
   767 #ifndef QT_NO_TABBAR
       
   768                 && !item.subinfo->tabbed
       
   769 #endif
       
   770                 ) {
       
   771                 result = item.subinfo->gapIndex(_pos, nestingEnabled,
       
   772                                                     tabMode);
       
   773                 result.prepend(i);
       
   774                 return result;
       
   775             }
       
   776 
       
   777             item_rect = itemRect(i);
       
   778             item_index = i;
       
   779             break;
       
   780         }
       
   781 
       
   782         if (item_rect.isNull()) {
       
   783             result.append(last + 1);
       
   784             return result;
       
   785         }
       
   786     }
       
   787 
       
   788     Q_ASSERT(!item_rect.isNull());
       
   789 
       
   790     QInternal::DockPosition dock_pos
       
   791         = dockPosHelper(item_rect, _pos, o, nestingEnabled, tabMode);
       
   792 
       
   793     switch (dock_pos) {
       
   794         case QInternal::LeftDock:
       
   795             if (o == Qt::Horizontal)
       
   796                 result << item_index;
       
   797             else
       
   798                 result << item_index << 0; // this subinfo doesn't exist yet, but insertGap()
       
   799                                            // handles this by inserting it
       
   800             break;
       
   801         case QInternal::RightDock:
       
   802             if (o == Qt::Horizontal)
       
   803                 result << item_index + 1;
       
   804             else
       
   805                 result << item_index << 1;
       
   806             break;
       
   807         case QInternal::TopDock:
       
   808             if (o == Qt::Horizontal)
       
   809                 result << item_index << 0;
       
   810             else
       
   811                 result << item_index;
       
   812             break;
       
   813         case QInternal::BottomDock:
       
   814             if (o == Qt::Horizontal)
       
   815                 result << item_index << 1;
       
   816             else
       
   817                 result << item_index + 1;
       
   818             break;
       
   819         case  QInternal::DockCount:
       
   820             result << (-item_index - 1) << 0;   // negative item_index means "on top of"
       
   821                                                 // -item_index - 1, insertGap()
       
   822                                                 // will insert a tabbed subinfo
       
   823             break;
       
   824         default:
       
   825             break;
       
   826     }
       
   827 
       
   828     return result;
       
   829 }
       
   830 
       
   831 static inline int shrink(QLayoutStruct &ls, int delta)
       
   832 {
       
   833     if (ls.empty)
       
   834         return 0;
       
   835     int old_size = ls.size;
       
   836     ls.size = qMax(ls.size - delta, ls.minimumSize);
       
   837     return old_size - ls.size;
       
   838 }
       
   839 
       
   840 static inline int grow(QLayoutStruct &ls, int delta)
       
   841 {
       
   842     if (ls.empty)
       
   843         return 0;
       
   844     int old_size = ls.size;
       
   845     ls.size = qMin(ls.size + delta, ls.maximumSize);
       
   846     return ls.size - old_size;
       
   847 }
       
   848 
       
   849 static int separatorMoveHelper(QVector<QLayoutStruct> &list, int index, int delta, int sep)
       
   850 {
       
   851     // adjust sizes
       
   852     int pos = -1;
       
   853     for (int i = 0; i < list.size(); ++i) {
       
   854         const QLayoutStruct &ls = list.at(i);
       
   855         if (!ls.empty) {
       
   856             pos = ls.pos;
       
   857             break;
       
   858         }
       
   859     }
       
   860     if (pos == -1)
       
   861         return 0;
       
   862 
       
   863     if (delta > 0) {
       
   864         int growlimit = 0;
       
   865         for (int i = 0; i<=index; ++i) {
       
   866             const QLayoutStruct &ls = list.at(i);
       
   867             if (ls.empty)
       
   868                 continue;
       
   869             if (ls.maximumSize == QLAYOUTSIZE_MAX) {
       
   870                 growlimit = QLAYOUTSIZE_MAX;
       
   871                 break;
       
   872             }
       
   873             growlimit += ls.maximumSize - ls.size;
       
   874         }
       
   875         if (delta > growlimit)
       
   876             delta = growlimit;
       
   877 
       
   878         int d = 0;
       
   879         for (int i = index + 1; d < delta && i < list.count(); ++i)
       
   880             d += shrink(list[i], delta - d);
       
   881         delta = d;
       
   882         d = 0;
       
   883         for (int i = index; d < delta && i >= 0; --i)
       
   884             d += grow(list[i], delta - d);
       
   885     } else if (delta < 0) {
       
   886         int growlimit = 0;
       
   887         for (int i = index + 1; i < list.count(); ++i) {
       
   888             const QLayoutStruct &ls = list.at(i);
       
   889             if (ls.empty)
       
   890                 continue;
       
   891             if (ls.maximumSize == QLAYOUTSIZE_MAX) {
       
   892                 growlimit = QLAYOUTSIZE_MAX;
       
   893                 break;
       
   894             }
       
   895             growlimit += ls.maximumSize - ls.size;
       
   896         }
       
   897         if (-delta > growlimit)
       
   898             delta = -growlimit;
       
   899 
       
   900         int d = 0;
       
   901         for (int i = index; d < -delta && i >= 0; --i)
       
   902             d += shrink(list[i], -delta - d);
       
   903         delta = -d;
       
   904         d = 0;
       
   905         for (int i = index + 1; d < -delta && i < list.count(); ++i)
       
   906             d += grow(list[i], -delta - d);
       
   907     }
       
   908 
       
   909     // adjust positions
       
   910     bool first = true;
       
   911     for (int i = 0; i < list.size(); ++i) {
       
   912         QLayoutStruct &ls = list[i];
       
   913         if (ls.empty) {
       
   914             ls.pos = pos + (first ? 0 : sep);
       
   915             continue;
       
   916         }
       
   917         if (!first)
       
   918             pos += sep;
       
   919         ls.pos = pos;
       
   920         pos += ls.size;
       
   921         first = false;
       
   922     }
       
   923 
       
   924     return delta;
       
   925 }
       
   926 
       
   927 int QDockAreaLayoutInfo::separatorMove(int index, int delta)
       
   928 {
       
   929 #ifndef QT_NO_TABBAR
       
   930     Q_ASSERT(!tabbed);
       
   931 #endif
       
   932 
       
   933     QVector<QLayoutStruct> list(item_list.size());
       
   934     for (int i = 0; i < list.size(); ++i) {
       
   935         const QDockAreaLayoutItem &item = item_list.at(i);
       
   936         QLayoutStruct &ls = list[i];
       
   937         Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
       
   938         if (item.skip()) {
       
   939             ls.empty = true;
       
   940         } else {
       
   941             const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
       
   942             ls.empty = false;
       
   943             ls.pos = item.pos;
       
   944             ls.size = item.size + separatorSpace;
       
   945             ls.minimumSize = pick(o, item.minimumSize()) + separatorSpace;
       
   946             ls.maximumSize = pick(o, item.maximumSize()) + separatorSpace;
       
   947 
       
   948         }
       
   949     }
       
   950 
       
   951     //the separator space has been added to the size, so we pass 0 as a parameter
       
   952     delta = separatorMoveHelper(list, index, delta, 0 /*separator*/);
       
   953 
       
   954     for (int i = 0; i < list.size(); ++i) {
       
   955         QDockAreaLayoutItem &item = item_list[i];
       
   956         if (item.skip())
       
   957             continue;
       
   958         QLayoutStruct &ls = list[i];
       
   959         const int separatorSpace = item.hasFixedSize(o) ? 0 : sep;
       
   960         item.size = ls.size - separatorSpace;
       
   961         item.pos = ls.pos;
       
   962         if (item.subinfo != 0) {
       
   963             item.subinfo->rect = itemRect(i);
       
   964             item.subinfo->fitItems();
       
   965         }
       
   966     }
       
   967 
       
   968     return delta;
       
   969 }
       
   970 
       
   971 void QDockAreaLayoutInfo::unnest(int index)
       
   972 {
       
   973     QDockAreaLayoutItem &item = item_list[index];
       
   974     if (item.subinfo == 0)
       
   975         return;
       
   976     if (item.subinfo->item_list.count() > 1)
       
   977         return;
       
   978 
       
   979     if (item.subinfo->item_list.count() == 0) {
       
   980         item_list.removeAt(index);
       
   981     } else if (item.subinfo->item_list.count() == 1) {
       
   982         QDockAreaLayoutItem &child = item.subinfo->item_list.first();
       
   983         if (child.widgetItem != 0) {
       
   984             item.widgetItem = child.widgetItem;
       
   985             delete item.subinfo;
       
   986             item.subinfo = 0;
       
   987         } else if (child.subinfo != 0) {
       
   988             QDockAreaLayoutInfo *tmp = item.subinfo;
       
   989             item.subinfo = child.subinfo;
       
   990             child.subinfo = 0;
       
   991             tmp->item_list.clear();
       
   992             delete tmp;
       
   993         }
       
   994     }
       
   995 }
       
   996 
       
   997 void QDockAreaLayoutInfo::remove(const QList<int> &path)
       
   998 {
       
   999     Q_ASSERT(!path.isEmpty());
       
  1000 
       
  1001     if (path.count() > 1) {
       
  1002         const int index = path.first();
       
  1003         QDockAreaLayoutItem &item = item_list[index];
       
  1004         Q_ASSERT(item.subinfo != 0);
       
  1005         item.subinfo->remove(path.mid(1));
       
  1006         unnest(index);
       
  1007     } else {
       
  1008         int index = path.first();
       
  1009         item_list.removeAt(index);
       
  1010     }
       
  1011 }
       
  1012 
       
  1013 QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path)
       
  1014 {
       
  1015     Q_ASSERT(!path.isEmpty());
       
  1016 
       
  1017     int index = path.first();
       
  1018     if (index < 0)
       
  1019         index = -index - 1;
       
  1020 
       
  1021     if (path.count() > 1) {
       
  1022         const QDockAreaLayoutItem &item = item_list.at(index);
       
  1023         Q_ASSERT(item.subinfo != 0);
       
  1024         return item.subinfo->plug(path.mid(1));
       
  1025     }
       
  1026 
       
  1027     QDockAreaLayoutItem &item = item_list[index];
       
  1028 
       
  1029     Q_ASSERT(item.widgetItem != 0);
       
  1030     Q_ASSERT(item.flags & QDockAreaLayoutItem::GapItem);
       
  1031     item.flags &= ~QDockAreaLayoutItem::GapItem;
       
  1032 
       
  1033     QRect result;
       
  1034 
       
  1035 #ifndef QT_NO_TABBAR
       
  1036     if (tabbed) {
       
  1037     } else
       
  1038 #endif
       
  1039     {
       
  1040         int prev = this->prev(index);
       
  1041         int next = this->next(index);
       
  1042 
       
  1043         if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
       
  1044             item.pos += sep;
       
  1045             item.size -= sep;
       
  1046         }
       
  1047         if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
       
  1048             item.size -= sep;
       
  1049 
       
  1050         QPoint pos;
       
  1051         rpick(o, pos) = item.pos;
       
  1052         rperp(o, pos) = perp(o, rect.topLeft());
       
  1053         QSize s;
       
  1054         rpick(o, s) = item.size;
       
  1055         rperp(o, s) = perp(o, rect.size());
       
  1056         result = QRect(pos, s);
       
  1057     }
       
  1058 
       
  1059     return item.widgetItem;
       
  1060 }
       
  1061 
       
  1062 QLayoutItem *QDockAreaLayoutInfo::unplug(const QList<int> &path)
       
  1063 {
       
  1064     Q_ASSERT(!path.isEmpty());
       
  1065 
       
  1066     const int index = path.first();
       
  1067     if (path.count() > 1) {
       
  1068         const QDockAreaLayoutItem &item = item_list.at(index);
       
  1069         Q_ASSERT(item.subinfo != 0);
       
  1070         return item.subinfo->unplug(path.mid(1));
       
  1071     }
       
  1072 
       
  1073     QDockAreaLayoutItem &item = item_list[index];
       
  1074     int prev = this->prev(index);
       
  1075     int next = this->next(index);
       
  1076 
       
  1077     Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
       
  1078     item.flags |= QDockAreaLayoutItem::GapItem;
       
  1079 
       
  1080 #ifndef QT_NO_TABBAR
       
  1081     if (tabbed) {
       
  1082     } else
       
  1083 #endif
       
  1084     {
       
  1085         if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
       
  1086             item.pos -= sep;
       
  1087             item.size += sep;
       
  1088         }
       
  1089         if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
       
  1090             item.size += sep;
       
  1091     }
       
  1092 
       
  1093     return item.widgetItem;
       
  1094 }
       
  1095 
       
  1096 #ifndef QT_NO_TABBAR
       
  1097 
       
  1098 quintptr QDockAreaLayoutInfo::currentTabId() const
       
  1099 {
       
  1100     if (!tabbed || tabBar == 0)
       
  1101         return 0;
       
  1102 
       
  1103     int index = tabBar->currentIndex();
       
  1104     if (index == -1)
       
  1105         return 0;
       
  1106 
       
  1107     return qvariant_cast<quintptr>(tabBar->tabData(index));
       
  1108 }
       
  1109 
       
  1110 void QDockAreaLayoutInfo::setCurrentTab(QWidget *widget)
       
  1111 {
       
  1112     setCurrentTabId(reinterpret_cast<quintptr>(widget));
       
  1113 }
       
  1114 
       
  1115 void QDockAreaLayoutInfo::setCurrentTabId(quintptr id)
       
  1116 {
       
  1117     if (!tabbed || tabBar == 0)
       
  1118         return;
       
  1119 
       
  1120     for (int i = 0; i < tabBar->count(); ++i) {
       
  1121         if (qvariant_cast<quintptr>(tabBar->tabData(i)) == id) {
       
  1122             tabBar->setCurrentIndex(i);
       
  1123             return;
       
  1124         }
       
  1125     }
       
  1126 }
       
  1127 
       
  1128 #endif // QT_NO_TABBAR
       
  1129 
       
  1130 static QRect dockedGeometry(QWidget *widget)
       
  1131 {
       
  1132     int titleHeight = 0;
       
  1133 
       
  1134     QDockWidgetLayout *layout
       
  1135         = qobject_cast<QDockWidgetLayout*>(widget->layout());
       
  1136     if(layout != 0 && layout->nativeWindowDeco())
       
  1137         titleHeight = layout->titleHeight();
       
  1138 
       
  1139     QRect result = widget->geometry();
       
  1140     result.adjust(0, -titleHeight, 0, 0);
       
  1141     return result;
       
  1142 }
       
  1143 
       
  1144 bool QDockAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem)
       
  1145 {
       
  1146     Q_ASSERT(!path.isEmpty());
       
  1147 
       
  1148     bool insert_tabbed = false;
       
  1149     int index = path.first();
       
  1150     if (index < 0) {
       
  1151         insert_tabbed = true;
       
  1152         index = -index - 1;
       
  1153     }
       
  1154 
       
  1155 //    dump(qDebug() << "insertGap() before:" << index << tabIndex, *this, QString());
       
  1156 
       
  1157     if (path.count() > 1) {
       
  1158         QDockAreaLayoutItem &item = item_list[index];
       
  1159 
       
  1160         if (item.subinfo == 0
       
  1161 #ifndef QT_NO_TABBAR
       
  1162             || (item.subinfo->tabbed && !insert_tabbed)
       
  1163 #endif
       
  1164             ) {
       
  1165 
       
  1166             // this is not yet a nested layout - make it
       
  1167 
       
  1168             QDockAreaLayoutInfo *subinfo = item.subinfo;
       
  1169             QLayoutItem *widgetItem = item.widgetItem;
       
  1170             QPlaceHolderItem *placeHolderItem = item.placeHolderItem;
       
  1171             QRect r = subinfo == 0 ? widgetItem ? dockedGeometry(widgetItem->widget()) : placeHolderItem->topLevelRect : subinfo->rect;
       
  1172 
       
  1173             Qt::Orientation opposite = o == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal;
       
  1174 #ifdef QT_NO_TABBAR
       
  1175             const int tabBarShape = 0;
       
  1176 #endif
       
  1177             QDockAreaLayoutInfo *new_info
       
  1178                 = new QDockAreaLayoutInfo(sep, dockPos, opposite, tabBarShape, mainWindow);
       
  1179 
       
  1180             //item become a new top-level
       
  1181             item.subinfo = new_info;
       
  1182             item.widgetItem = 0;
       
  1183             item.placeHolderItem = 0;
       
  1184 
       
  1185             QDockAreaLayoutItem new_item
       
  1186                 = widgetItem == 0
       
  1187                     ? QDockAreaLayoutItem(subinfo)
       
  1188                     : widgetItem ? QDockAreaLayoutItem(widgetItem) : QDockAreaLayoutItem(placeHolderItem);
       
  1189             new_item.size = pick(opposite, r.size());
       
  1190             new_item.pos = pick(opposite, r.topLeft());
       
  1191             new_info->item_list.append(new_item);
       
  1192 #ifndef QT_NO_TABBAR
       
  1193             if (insert_tabbed) {
       
  1194                 new_info->tabbed = true;
       
  1195             }
       
  1196 #endif
       
  1197         }
       
  1198 
       
  1199         return item.subinfo->insertGap(path.mid(1), dockWidgetItem);
       
  1200     }
       
  1201 
       
  1202     // create the gap item
       
  1203     QDockAreaLayoutItem gap_item;
       
  1204     gap_item.flags |= QDockAreaLayoutItem::GapItem;
       
  1205     gap_item.widgetItem = dockWidgetItem;   // so minimumSize(), maximumSize() and
       
  1206                                             // sizeHint() will work
       
  1207 #ifndef QT_NO_TABBAR
       
  1208     if (!tabbed)
       
  1209 #endif
       
  1210     {
       
  1211         int prev = this->prev(index);
       
  1212         int next = this->next(index - 1);
       
  1213         // find out how much space we have in the layout
       
  1214         int space = 0;
       
  1215         if (isEmpty()) {
       
  1216             // I am an empty dock area, therefore I am a top-level dock area.
       
  1217             switch (dockPos) {
       
  1218                 case QInternal::LeftDock:
       
  1219                 case QInternal::RightDock:
       
  1220                     if (o == Qt::Vertical) {
       
  1221                         // the "size" is the height of the dock area (remember we are empty)
       
  1222                         space = pick(Qt::Vertical, rect.size());
       
  1223                     } else {
       
  1224                         space = pick(Qt::Horizontal, dockWidgetItem->widget()->size());
       
  1225                     }
       
  1226                     break;
       
  1227                 case QInternal::TopDock:
       
  1228                 case QInternal::BottomDock:
       
  1229                 default:
       
  1230                     if (o == Qt::Horizontal) {
       
  1231                         // the "size" is width of the dock area
       
  1232                         space = pick(Qt::Horizontal, rect.size());
       
  1233                     } else {
       
  1234                         space = pick(Qt::Vertical, dockWidgetItem->widget()->size());
       
  1235                     }
       
  1236                     break;
       
  1237             }
       
  1238         } else {
       
  1239             for (int i = 0; i < item_list.count(); ++i) {
       
  1240                 const QDockAreaLayoutItem &item = item_list.at(i);
       
  1241                 if (item.skip())
       
  1242                     continue;
       
  1243                 Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
       
  1244                 space += item.size - pick(o, item.minimumSize());
       
  1245             }
       
  1246         }
       
  1247 
       
  1248         // find the actual size of the gap
       
  1249         int gap_size = 0;
       
  1250         int sep_size = 0;
       
  1251         if (isEmpty()) {
       
  1252             gap_size = space;
       
  1253             sep_size = 0;
       
  1254         } else {
       
  1255             QRect r = dockedGeometry(dockWidgetItem->widget());
       
  1256             gap_size = pick(o, r.size());
       
  1257         if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem))
       
  1258                 sep_size += sep;
       
  1259             if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
       
  1260                 sep_size += sep;
       
  1261         }
       
  1262         if (gap_size + sep_size > space)
       
  1263             gap_size = pick(o, gap_item.minimumSize());
       
  1264         gap_item.size = gap_size + sep_size;
       
  1265     }
       
  1266 
       
  1267     // finally, insert the gap
       
  1268     item_list.insert(index, gap_item);
       
  1269 
       
  1270 //    dump(qDebug() << "insertGap() after:" << index << tabIndex, *this, QString());
       
  1271 
       
  1272     return true;
       
  1273 }
       
  1274 
       
  1275 QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(QWidget *widget)
       
  1276 {
       
  1277     for (int i = 0; i < item_list.count(); ++i) {
       
  1278         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1279         if (item.skip())
       
  1280             continue;
       
  1281 
       
  1282 #ifndef QT_NO_TABBAR
       
  1283         if (tabbed && widget == tabBar)
       
  1284             return this;
       
  1285 #endif
       
  1286 
       
  1287         if (item.widgetItem != 0 && item.widgetItem->widget() == widget)
       
  1288             return this;
       
  1289 
       
  1290         if (item.subinfo != 0) {
       
  1291             if (QDockAreaLayoutInfo *result = item.subinfo->info(widget))
       
  1292                 return result;
       
  1293         }
       
  1294     }
       
  1295 
       
  1296     return 0;
       
  1297 }
       
  1298 
       
  1299 QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(const QList<int> &path)
       
  1300 {
       
  1301     int index = path.first();
       
  1302     if (index < 0)
       
  1303         index = -index - 1;
       
  1304     if (index >= item_list.count())
       
  1305         return this;
       
  1306     if (path.count() == 1 || item_list[index].subinfo == 0)
       
  1307         return this;
       
  1308     return item_list[index].subinfo->info(path.mid(1));
       
  1309 }
       
  1310 
       
  1311 QRect QDockAreaLayoutInfo::itemRect(int index) const
       
  1312 {
       
  1313     const QDockAreaLayoutItem &item = item_list.at(index);
       
  1314 
       
  1315     if (item.skip())
       
  1316         return QRect();
       
  1317 
       
  1318     QRect result;
       
  1319 
       
  1320 #ifndef QT_NO_TABBAR
       
  1321     if (tabbed) {
       
  1322         if (tabId(item) == currentTabId())
       
  1323             result = tabContentRect();
       
  1324     } else
       
  1325 #endif
       
  1326     {
       
  1327         QPoint pos;
       
  1328         rpick(o, pos) = item.pos;
       
  1329         rperp(o, pos) = perp(o, rect.topLeft());
       
  1330         QSize s;
       
  1331         rpick(o, s) = item.size;
       
  1332         rperp(o, s) = perp(o, rect.size());
       
  1333         result = QRect(pos, s);
       
  1334     }
       
  1335 
       
  1336     return result;
       
  1337 }
       
  1338 
       
  1339 QRect QDockAreaLayoutInfo::itemRect(const QList<int> &path) const
       
  1340 {
       
  1341     Q_ASSERT(!path.isEmpty());
       
  1342 
       
  1343     const int index = path.first();
       
  1344     if (path.count() > 1) {
       
  1345         const QDockAreaLayoutItem &item = item_list.at(index);
       
  1346         Q_ASSERT(item.subinfo != 0);
       
  1347         return item.subinfo->itemRect(path.mid(1));
       
  1348     }
       
  1349 
       
  1350     return itemRect(index);
       
  1351 }
       
  1352 
       
  1353 QRect QDockAreaLayoutInfo::separatorRect(int index) const
       
  1354 {
       
  1355 #ifndef QT_NO_TABBAR
       
  1356     if (tabbed)
       
  1357         return QRect();
       
  1358 #endif
       
  1359 
       
  1360     const QDockAreaLayoutItem &item = item_list.at(index);
       
  1361     if (item.skip())
       
  1362         return QRect();
       
  1363 
       
  1364     QPoint pos = rect.topLeft();
       
  1365     rpick(o, pos) = item.pos + item.size;
       
  1366     QSize s = rect.size();
       
  1367     rpick(o, s) = sep;
       
  1368 
       
  1369     return QRect(pos, s);
       
  1370 }
       
  1371 
       
  1372 QRect QDockAreaLayoutInfo::separatorRect(const QList<int> &path) const
       
  1373 {
       
  1374     Q_ASSERT(!path.isEmpty());
       
  1375 
       
  1376     const int index = path.first();
       
  1377     if (path.count() > 1) {
       
  1378         const QDockAreaLayoutItem &item = item_list.at(index);
       
  1379         Q_ASSERT(item.subinfo != 0);
       
  1380         return item.subinfo->separatorRect(path.mid(1));
       
  1381     }
       
  1382     return separatorRect(index);
       
  1383 }
       
  1384 
       
  1385 QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
       
  1386 {
       
  1387 #ifndef QT_NO_TABBAR
       
  1388     if (tabbed)
       
  1389         return QList<int>();
       
  1390 #endif
       
  1391 
       
  1392     int pos = pick(o, _pos);
       
  1393 
       
  1394     for (int i = 0; i < item_list.size(); ++i) {
       
  1395         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1396         if (item.skip() || (item.flags & QDockAreaLayoutItem::GapItem))
       
  1397             continue;
       
  1398 
       
  1399         if (item.pos + item.size > pos) {
       
  1400             if (item.subinfo != 0) {
       
  1401                 QList<int> result = item.subinfo->findSeparator(_pos);
       
  1402                 if (!result.isEmpty()) {
       
  1403                     result.prepend(i);
       
  1404                     return result;
       
  1405                 } else {
       
  1406                     return QList<int>();
       
  1407                 }
       
  1408             }
       
  1409         }
       
  1410 
       
  1411         int next = this->next(i);
       
  1412         if (next == -1 || (item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
       
  1413             continue;
       
  1414 
       
  1415         QRect sepRect = separatorRect(i);
       
  1416         if (!sepRect.isNull() && sep == 1)
       
  1417             sepRect.adjust(-2, -2, 2, 2);
       
  1418         //we also make sure we don't find a separator that's not there
       
  1419         if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
       
  1420             return QList<int>() << i;
       
  1421         }
       
  1422 
       
  1423     }
       
  1424 
       
  1425     return QList<int>();
       
  1426 }
       
  1427 
       
  1428 QList<int> QDockAreaLayoutInfo::indexOfPlaceHolder(const QString &objectName) const
       
  1429 {
       
  1430     for (int i = 0; i < item_list.size(); ++i) {
       
  1431         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1432 
       
  1433         if (item.subinfo != 0) {
       
  1434             QList<int> result = item.subinfo->indexOfPlaceHolder(objectName);
       
  1435             if (!result.isEmpty()) {
       
  1436                 result.prepend(i);
       
  1437                 return result;
       
  1438             }
       
  1439             continue;
       
  1440         }
       
  1441 
       
  1442         if (item.placeHolderItem != 0 && item.placeHolderItem->objectName == objectName) {
       
  1443             QList<int> result;
       
  1444             result << i;
       
  1445             return result;
       
  1446         }
       
  1447     }
       
  1448 
       
  1449     return QList<int>();
       
  1450 }
       
  1451 
       
  1452 QList<int> QDockAreaLayoutInfo::indexOf(QWidget *widget) const
       
  1453 {
       
  1454     for (int i = 0; i < item_list.size(); ++i) {
       
  1455         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1456 
       
  1457         if (item.placeHolderItem != 0)
       
  1458             continue;
       
  1459 
       
  1460         if (item.subinfo != 0) {
       
  1461             QList<int> result = item.subinfo->indexOf(widget);
       
  1462             if (!result.isEmpty()) {
       
  1463                 result.prepend(i);
       
  1464                 return result;
       
  1465             }
       
  1466             continue;
       
  1467         }
       
  1468 
       
  1469         if (!(item.flags & QDockAreaLayoutItem::GapItem) && item.widgetItem->widget() == widget) {
       
  1470             QList<int> result;
       
  1471             result << i;
       
  1472             return result;
       
  1473         }
       
  1474     }
       
  1475 
       
  1476     return QList<int>();
       
  1477 }
       
  1478 
       
  1479 QMainWindowLayout *QDockAreaLayoutInfo::mainWindowLayout() const
       
  1480 {
       
  1481     QMainWindowLayout *result = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
       
  1482     Q_ASSERT(result != 0);
       
  1483     return result;
       
  1484 }
       
  1485 
       
  1486 bool QDockAreaLayoutInfo::hasFixedSize() const
       
  1487 {
       
  1488     return perp(o, minimumSize()) == perp(o, maximumSize());
       
  1489 }
       
  1490 
       
  1491 
       
  1492 void QDockAreaLayoutInfo::apply(bool animate)
       
  1493 {
       
  1494     QWidgetAnimator &widgetAnimator = mainWindowLayout()->widgetAnimator;
       
  1495 
       
  1496 #ifndef QT_NO_TABBAR
       
  1497     if (tabbed) {
       
  1498         QRect tab_rect;
       
  1499         QSize tbh = tabBarSizeHint();
       
  1500 
       
  1501         if (tabBarVisible) {
       
  1502             switch (tabBarShape) {
       
  1503                 case QTabBar::RoundedNorth:
       
  1504                 case QTabBar::TriangularNorth:
       
  1505                     tab_rect = QRect(rect.left(), rect.top(), rect.width(), tbh.height());
       
  1506                     break;
       
  1507                 case QTabBar::RoundedSouth:
       
  1508                 case QTabBar::TriangularSouth:
       
  1509                     tab_rect = QRect(rect.left(), rect.bottom() - tbh.height() + 1,
       
  1510                                         rect.width(), tbh.height());
       
  1511                     break;
       
  1512                 case QTabBar::RoundedEast:
       
  1513                 case QTabBar::TriangularEast:
       
  1514                     tab_rect = QRect(rect.right() - tbh.width() + 1, rect.top(),
       
  1515                                         tbh.width(), rect.height());
       
  1516                     break;
       
  1517                 case QTabBar::RoundedWest:
       
  1518                 case QTabBar::TriangularWest:
       
  1519                     tab_rect = QRect(rect.left(), rect.top(),
       
  1520                                         tbh.width(), rect.height());
       
  1521                     break;
       
  1522                 default:
       
  1523                     break;
       
  1524             }
       
  1525         }
       
  1526 
       
  1527         widgetAnimator.animate(tabBar, tab_rect, animate);
       
  1528     }
       
  1529 #endif // QT_NO_TABBAR
       
  1530 
       
  1531     for (int i = 0; i < item_list.size(); ++i) {
       
  1532         QDockAreaLayoutItem &item = item_list[i];
       
  1533 
       
  1534         if (item.flags & QDockAreaLayoutItem::GapItem)
       
  1535             continue;
       
  1536 
       
  1537         if (item.subinfo != 0) {
       
  1538             item.subinfo->apply(animate);
       
  1539             continue;
       
  1540         }
       
  1541 
       
  1542         if (item.skip())
       
  1543             continue;
       
  1544 
       
  1545         Q_ASSERT(item.widgetItem);
       
  1546         QRect r = itemRect(i);
       
  1547         QWidget *w = item.widgetItem->widget();
       
  1548 
       
  1549         QRect geo = w->geometry();
       
  1550         widgetAnimator.animate(w, r, animate);
       
  1551         if (!w->isHidden() && w->window()->isVisible()) {
       
  1552             QDockWidget *dw = qobject_cast<QDockWidget*>(w);
       
  1553             if (!r.isValid() && geo.right() >= 0 && geo.bottom() >= 0) {
       
  1554                 dw->lower();
       
  1555                 emit dw->visibilityChanged(false);
       
  1556             } else if (r.isValid()
       
  1557                         && (geo.right() < 0 || geo.bottom() < 0)) {
       
  1558                 emit dw->visibilityChanged(true);
       
  1559             }
       
  1560         }
       
  1561     }
       
  1562 #ifndef QT_NO_TABBAR
       
  1563     if (sep == 1)
       
  1564         updateSeparatorWidgets();
       
  1565 #endif //QT_NO_TABBAR
       
  1566 }
       
  1567 
       
  1568 static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over)
       
  1569 {
       
  1570     QStyleOption opt(0);
       
  1571     opt.state = QStyle::State_None;
       
  1572     if (w->isEnabled())
       
  1573         opt.state |= QStyle::State_Enabled;
       
  1574     if (o != Qt::Horizontal)
       
  1575         opt.state |= QStyle::State_Horizontal;
       
  1576     if (mouse_over)
       
  1577         opt.state |= QStyle::State_MouseOver;
       
  1578     opt.rect = r;
       
  1579     opt.palette = w->palette();
       
  1580 
       
  1581     w->style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, p, w);
       
  1582 }
       
  1583 
       
  1584 QRegion QDockAreaLayoutInfo::separatorRegion() const
       
  1585 {
       
  1586     QRegion result;
       
  1587 
       
  1588     if (isEmpty())
       
  1589         return result;
       
  1590 #ifndef QT_NO_TABBAR
       
  1591     if (tabbed)
       
  1592         return result;
       
  1593 #endif
       
  1594 
       
  1595     for (int i = 0; i < item_list.count(); ++i) {
       
  1596         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1597 
       
  1598         if (item.skip())
       
  1599             continue;
       
  1600 
       
  1601         int next = this->next(i);
       
  1602 
       
  1603         if (item.subinfo)
       
  1604             result |= item.subinfo->separatorRegion();
       
  1605 
       
  1606         if (next == -1)
       
  1607             break;
       
  1608         result |= separatorRect(i);
       
  1609     }
       
  1610 
       
  1611     return result;
       
  1612 }
       
  1613 
       
  1614 void QDockAreaLayoutInfo::paintSeparators(QPainter *p, QWidget *widget,
       
  1615                                                     const QRegion &clip,
       
  1616                                                     const QPoint &mouse) const
       
  1617 {
       
  1618     if (isEmpty())
       
  1619         return;
       
  1620 #ifndef QT_NO_TABBAR
       
  1621     if (tabbed)
       
  1622         return;
       
  1623 #endif
       
  1624 
       
  1625     for (int i = 0; i < item_list.count(); ++i) {
       
  1626         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1627 
       
  1628         if (item.skip())
       
  1629             continue;
       
  1630 
       
  1631         int next = this->next(i);
       
  1632         if ((item.flags & QDockAreaLayoutItem::GapItem)
       
  1633                 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
       
  1634             continue;
       
  1635 
       
  1636         if (item.subinfo) {
       
  1637             if (clip.contains(item.subinfo->rect))
       
  1638                 item.subinfo->paintSeparators(p, widget, clip, mouse);
       
  1639         }
       
  1640 
       
  1641         if (next == -1)
       
  1642             break;
       
  1643         QRect r = separatorRect(i);
       
  1644         if (clip.contains(r) && !item.hasFixedSize(o))
       
  1645             paintSep(p, widget, r, o, r.contains(mouse));
       
  1646     }
       
  1647 }
       
  1648 
       
  1649 int QDockAreaLayoutInfo::next(int index) const
       
  1650 {
       
  1651     for (int i = index + 1; i < item_list.size(); ++i) {
       
  1652         if (!item_list.at(i).skip())
       
  1653             return i;
       
  1654     }
       
  1655     return -1;
       
  1656 }
       
  1657 
       
  1658 int QDockAreaLayoutInfo::prev(int index) const
       
  1659 {
       
  1660     for (int i = index - 1; i >= 0; --i) {
       
  1661         if (!item_list.at(i).skip())
       
  1662             return i;
       
  1663     }
       
  1664     return -1;
       
  1665 }
       
  1666 
       
  1667 void QDockAreaLayoutInfo::tab(int index, QLayoutItem *dockWidgetItem)
       
  1668 {
       
  1669 #ifdef QT_NO_TABBAR
       
  1670     Q_UNUSED(index);
       
  1671     Q_UNUSED(dockWidgetItem);
       
  1672 #else
       
  1673     if (tabbed) {
       
  1674         item_list.append(QDockAreaLayoutItem(dockWidgetItem));
       
  1675         updateTabBar();
       
  1676         setCurrentTab(dockWidgetItem->widget());
       
  1677     } else {
       
  1678         QDockAreaLayoutInfo *new_info
       
  1679             = new QDockAreaLayoutInfo(sep, dockPos, o, tabBarShape, mainWindow);
       
  1680         item_list[index].subinfo = new_info;
       
  1681         new_info->item_list.append(item_list.at(index).widgetItem);
       
  1682         item_list[index].widgetItem = 0;
       
  1683         new_info->item_list.append(dockWidgetItem);
       
  1684         new_info->tabbed = true;
       
  1685         new_info->updateTabBar();
       
  1686         new_info->setCurrentTab(dockWidgetItem->widget());
       
  1687     }
       
  1688 #endif // QT_NO_TABBAR
       
  1689 }
       
  1690 
       
  1691 void QDockAreaLayoutInfo::split(int index, Qt::Orientation orientation,
       
  1692                                        QLayoutItem *dockWidgetItem)
       
  1693 {
       
  1694     if (orientation == o) {
       
  1695         item_list.insert(index + 1, QDockAreaLayoutItem(dockWidgetItem));
       
  1696     } else {
       
  1697 #ifdef QT_NO_TABBAR
       
  1698         const int tabBarShape = 0;
       
  1699 #endif
       
  1700         QDockAreaLayoutInfo *new_info
       
  1701             = new QDockAreaLayoutInfo(sep, dockPos, orientation, tabBarShape, mainWindow);
       
  1702         item_list[index].subinfo = new_info;
       
  1703         new_info->item_list.append(item_list.at(index).widgetItem);
       
  1704         item_list[index].widgetItem = 0;
       
  1705         new_info->item_list.append(dockWidgetItem);
       
  1706     }
       
  1707 }
       
  1708 
       
  1709 QDockAreaLayoutItem &QDockAreaLayoutInfo::item(const QList<int> &path)
       
  1710 {
       
  1711     Q_ASSERT(!path.isEmpty());
       
  1712     const int index = path.first();
       
  1713     if (path.count() > 1) {
       
  1714         const QDockAreaLayoutItem &item = item_list[index];
       
  1715         Q_ASSERT(item.subinfo != 0);
       
  1716         return item.subinfo->item(path.mid(1));
       
  1717     }
       
  1718     return item_list[index];
       
  1719 }
       
  1720 
       
  1721 QLayoutItem *QDockAreaLayoutInfo::itemAt(int *x, int index) const
       
  1722 {
       
  1723     for (int i = 0; i < item_list.count(); ++i) {
       
  1724         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1725         if (item.placeHolderItem != 0)
       
  1726             continue;
       
  1727         if (item.subinfo) {
       
  1728             if (QLayoutItem *ret = item.subinfo->itemAt(x, index))
       
  1729                 return ret;
       
  1730         } else if (item.widgetItem) {
       
  1731             if ((*x)++ == index)
       
  1732                 return item.widgetItem;
       
  1733         }
       
  1734     }
       
  1735     return 0;
       
  1736 }
       
  1737 
       
  1738 QLayoutItem *QDockAreaLayoutInfo::takeAt(int *x, int index)
       
  1739 {
       
  1740     for (int i = 0; i < item_list.count(); ++i) {
       
  1741         QDockAreaLayoutItem &item = item_list[i];
       
  1742         if (item.placeHolderItem != 0)
       
  1743             continue;
       
  1744         else if (item.subinfo) {
       
  1745             if (QLayoutItem *ret = item.subinfo->takeAt(x, index)) {
       
  1746                 unnest(i);
       
  1747                 return ret;
       
  1748             }
       
  1749         } else if (item.widgetItem) {
       
  1750             if ((*x)++ == index) {
       
  1751                 item.placeHolderItem = new QPlaceHolderItem(item.widgetItem->widget());
       
  1752                 QLayoutItem *ret = item.widgetItem;
       
  1753                 item.widgetItem = 0;
       
  1754                 if (item.size != -1)
       
  1755                     item.flags |= QDockAreaLayoutItem::KeepSize;
       
  1756                 return ret;
       
  1757             }
       
  1758         }
       
  1759     }
       
  1760     return 0;
       
  1761 }
       
  1762 
       
  1763 void QDockAreaLayoutInfo::deleteAllLayoutItems()
       
  1764 {
       
  1765     for (int i = 0; i < item_list.count(); ++i) {
       
  1766         QDockAreaLayoutItem &item= item_list[i];
       
  1767         if (item.subinfo) {
       
  1768             item.subinfo->deleteAllLayoutItems();
       
  1769         } else {
       
  1770             delete item.widgetItem;
       
  1771             item.widgetItem = 0;
       
  1772         }
       
  1773     }
       
  1774 }
       
  1775 
       
  1776 void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
       
  1777 {
       
  1778 #ifndef QT_NO_TABBAR
       
  1779     if (tabbed) {
       
  1780         stream << (uchar) TabMarker;
       
  1781 
       
  1782         // write the index in item_list of the widget that's currently on top.
       
  1783         quintptr id = currentTabId();
       
  1784         int index = -1;
       
  1785         for (int i = 0; i < item_list.count(); ++i) {
       
  1786             if (tabId(item_list.at(i)) == id) {
       
  1787                 index = i;
       
  1788                 break;
       
  1789             }
       
  1790         }
       
  1791         stream << index;
       
  1792     } else
       
  1793 #endif // QT_NO_TABBAR
       
  1794     {
       
  1795         stream << (uchar) SequenceMarker;
       
  1796     }
       
  1797 
       
  1798     stream << (uchar) o << item_list.count();
       
  1799 
       
  1800     for (int i = 0; i < item_list.count(); ++i) {
       
  1801         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1802         if (item.widgetItem != 0) {
       
  1803             stream << (uchar) WidgetMarker;
       
  1804             QWidget *w = item.widgetItem->widget();
       
  1805             QString name = w->objectName();
       
  1806             if (name.isEmpty()) {
       
  1807                 qWarning("QMainWindow::saveState(): 'objectName' not set for QDockWidget %p '%s;",
       
  1808                          w, qPrintable(w->windowTitle()));
       
  1809             }
       
  1810             stream << name;
       
  1811 
       
  1812             uchar flags = 0;
       
  1813             if (!w->isHidden())
       
  1814                 flags |= StateFlagVisible;
       
  1815             if (w->isWindow())
       
  1816                 flags |= StateFlagFloating;
       
  1817             stream << flags;
       
  1818 
       
  1819             if (w->isWindow()) {
       
  1820                 stream << w->x() << w->y() << w->width() << w->height();
       
  1821             } else {
       
  1822                 stream << item.pos << item.size << pick(o, item.minimumSize())
       
  1823                         << pick(o, item.maximumSize());
       
  1824             }
       
  1825         } else if (item.placeHolderItem != 0) {
       
  1826             stream << (uchar) WidgetMarker;
       
  1827             stream << item.placeHolderItem->objectName;
       
  1828             uchar flags = 0;
       
  1829             if (!item.placeHolderItem->hidden)
       
  1830                 flags |= StateFlagVisible;
       
  1831             if (item.placeHolderItem->window)
       
  1832                 flags |= StateFlagFloating;
       
  1833             stream << flags;
       
  1834             if (item.placeHolderItem->window) {
       
  1835                 QRect r = item.placeHolderItem->topLevelRect;
       
  1836                 stream << r.x() << r.y() << r.width() << r.height();
       
  1837             } else {
       
  1838                 stream << item.pos << item.size << (int)0 << (int)0;
       
  1839             }
       
  1840         } else if (item.subinfo != 0) {
       
  1841             stream << (uchar) SequenceMarker << item.pos << item.size << pick(o, item.minimumSize()) << pick(o, item.maximumSize());
       
  1842             item.subinfo->saveState(stream);
       
  1843         }
       
  1844     }
       
  1845 }
       
  1846 
       
  1847 static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
       
  1848 {
       
  1849     switch (pos) {
       
  1850         case QInternal::LeftDock:   return Qt::LeftDockWidgetArea;
       
  1851         case QInternal::RightDock:  return Qt::RightDockWidgetArea;
       
  1852         case QInternal::TopDock:    return Qt::TopDockWidgetArea;
       
  1853         case QInternal::BottomDock: return Qt::BottomDockWidgetArea;
       
  1854         default: break;
       
  1855     }
       
  1856     return Qt::NoDockWidgetArea;
       
  1857 }
       
  1858 
       
  1859 static QRect constrainedRect(QRect rect, const QRect &desktop)
       
  1860 {
       
  1861     if (desktop.isValid()) {
       
  1862         rect.setWidth(qMin(rect.width(), desktop.width()));
       
  1863         rect.setHeight(qMin(rect.height(), desktop.height()));
       
  1864         rect.moveLeft(qMax(rect.left(), desktop.left()));
       
  1865         rect.moveTop(qMax(rect.top(), desktop.top()));
       
  1866         rect.moveRight(qMin(rect.right(), desktop.right()));
       
  1867         rect.moveBottom(qMin(rect.bottom(), desktop.bottom()));
       
  1868     }
       
  1869 
       
  1870     return rect;
       
  1871 }
       
  1872 
       
  1873 bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> &widgets, bool testing)
       
  1874 {
       
  1875     uchar marker;
       
  1876     stream >> marker;
       
  1877     if (marker != TabMarker && marker != SequenceMarker)
       
  1878         return false;
       
  1879 
       
  1880 #ifndef QT_NO_TABBAR
       
  1881     tabbed = marker == TabMarker;
       
  1882 
       
  1883     int index = -1;
       
  1884     if (tabbed)
       
  1885         stream >> index;
       
  1886 #endif
       
  1887 
       
  1888     uchar orientation;
       
  1889     stream >> orientation;
       
  1890     o = static_cast<Qt::Orientation>(orientation);
       
  1891 
       
  1892     int cnt;
       
  1893     stream >> cnt;
       
  1894 
       
  1895     for (int i = 0; i < cnt; ++i) {
       
  1896         uchar nextMarker;
       
  1897         stream >> nextMarker;
       
  1898         if (nextMarker == WidgetMarker) {
       
  1899             QString name;
       
  1900             uchar flags;
       
  1901             stream >> name >> flags;
       
  1902             if (name.isEmpty()) {
       
  1903                 int dummy;
       
  1904                 stream >> dummy >> dummy >> dummy >> dummy;
       
  1905                 continue;
       
  1906             }
       
  1907 
       
  1908             QDockWidget *widget = 0;
       
  1909             for (int j = 0; j < widgets.count(); ++j) {
       
  1910                 if (widgets.at(j)->objectName() == name) {
       
  1911                     widget = widgets.takeAt(j);
       
  1912                     break;
       
  1913                 }
       
  1914             }
       
  1915 
       
  1916             if (widget == 0) {
       
  1917                 QPlaceHolderItem *placeHolder = new QPlaceHolderItem;
       
  1918                 QDockAreaLayoutItem item(placeHolder);
       
  1919 
       
  1920                 placeHolder->objectName = name;
       
  1921                 placeHolder->window = flags & StateFlagFloating;
       
  1922                 placeHolder->hidden = !(flags & StateFlagVisible);
       
  1923                 if (placeHolder->window) {
       
  1924                     int x, y, w, h;
       
  1925                     stream >> x >> y >> w >> h;
       
  1926                     placeHolder->topLevelRect = QRect(x, y, w, h);
       
  1927                 } else {
       
  1928                     int dummy;
       
  1929                     stream >> item.pos >> item.size >> dummy >> dummy;
       
  1930                 }
       
  1931                 if (item.size != -1)
       
  1932                     item.flags |= QDockAreaLayoutItem::KeepSize;
       
  1933                 if (!testing)
       
  1934                     item_list.append(item);
       
  1935             } else {
       
  1936                 QDockAreaLayoutItem item(new QDockWidgetItem(widget));
       
  1937                 if (flags & StateFlagFloating) {
       
  1938                	    bool drawer = false;
       
  1939 #ifdef Q_WS_MAC // drawer support
       
  1940                	    extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
       
  1941                     extern bool qt_mac_set_drawer_preferred_edge(QWidget *, Qt::DockWidgetArea); //qwidget_mac.cpp
       
  1942                     drawer = qt_mac_is_macdrawer(widget);
       
  1943 #endif
       
  1944 
       
  1945                     if (!testing) {
       
  1946                         widget->hide();
       
  1947                         if (!drawer)
       
  1948                             widget->setFloating(true);
       
  1949                     }
       
  1950 
       
  1951                     int x, y, w, h;
       
  1952                     stream >> x >> y >> w >> h;
       
  1953 
       
  1954 #ifdef Q_WS_MAC // drawer support
       
  1955                     if (drawer) {
       
  1956                         mainWindow->window()->createWinId();
       
  1957                         widget->window()->createWinId();
       
  1958                         qt_mac_set_drawer_preferred_edge(widget, toDockWidgetArea(dockPos));
       
  1959                     } else
       
  1960 #endif
       
  1961                     if (!testing) {
       
  1962                         QRect r(x, y, w, h);
       
  1963                         QDesktopWidget *desktop = QApplication::desktop();
       
  1964                         if (desktop->isVirtualDesktop())
       
  1965                             r = constrainedRect(r, desktop->screenGeometry(desktop->screenNumber(r.topLeft())));
       
  1966                         else
       
  1967                             r = constrainedRect(r, desktop->screenGeometry(widget));
       
  1968                         widget->move(r.topLeft());
       
  1969                         widget->resize(r.size());
       
  1970                     }
       
  1971 
       
  1972                     if (!testing) {
       
  1973                         widget->setVisible(flags & StateFlagVisible);
       
  1974                         item_list.append(item);
       
  1975                     }
       
  1976                 } else {
       
  1977                     int dummy;
       
  1978                     stream >> item.pos >> item.size >> dummy >> dummy;
       
  1979                     if (!testing) {
       
  1980                         item_list.append(item);
       
  1981                         widget->setFloating(false);
       
  1982                         widget->setVisible(flags & StateFlagVisible);
       
  1983                         emit widget->dockLocationChanged(toDockWidgetArea(dockPos));
       
  1984                     }
       
  1985                 }
       
  1986 
       
  1987             }
       
  1988         } else if (nextMarker == SequenceMarker) {
       
  1989             int dummy;
       
  1990 #ifdef QT_NO_TABBAR
       
  1991             const int tabBarShape = 0;
       
  1992 #endif
       
  1993             QDockAreaLayoutItem item(new QDockAreaLayoutInfo(sep, dockPos, o,
       
  1994                                                                 tabBarShape, mainWindow));
       
  1995             stream >> item.pos >> item.size >> dummy >> dummy;
       
  1996             //we need to make sure the element is in the list so the dock widget can eventually be docked correctly
       
  1997             if (!testing)
       
  1998                 item_list.append(item);
       
  1999             
       
  2000             //here we need to make sure we change the item in the item_list
       
  2001             QDockAreaLayoutItem &lastItem = testing ? item : item_list.last();
       
  2002 
       
  2003             if (!lastItem.subinfo->restoreState(stream, widgets, testing))
       
  2004                 return false;
       
  2005 
       
  2006         } else {
       
  2007             return false;
       
  2008         }
       
  2009     }
       
  2010 
       
  2011 #ifndef QT_NO_TABBAR
       
  2012     if (!testing && tabbed && index >= 0 && index < item_list.count()) {
       
  2013         updateTabBar();
       
  2014         setCurrentTabId(tabId(item_list.at(index)));
       
  2015     }
       
  2016     if (!testing && sep == 1)
       
  2017         updateSeparatorWidgets();
       
  2018 #endif
       
  2019 
       
  2020     return true;
       
  2021 }
       
  2022 
       
  2023 #ifndef QT_NO_TABBAR
       
  2024 void QDockAreaLayoutInfo::updateSeparatorWidgets() const
       
  2025 {
       
  2026     if (tabbed) {
       
  2027         separatorWidgets.clear();
       
  2028         return;
       
  2029     }
       
  2030 
       
  2031     int j = 0;
       
  2032     for (int i = 0; i < item_list.count(); ++i) {
       
  2033         const QDockAreaLayoutItem &item = item_list.at(i);
       
  2034 
       
  2035         if (item.skip())
       
  2036             continue;
       
  2037 
       
  2038         int next = this->next(i);
       
  2039         if ((item.flags & QDockAreaLayoutItem::GapItem)
       
  2040                 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
       
  2041             continue;
       
  2042 
       
  2043         if (item.subinfo) {
       
  2044             item.subinfo->updateSeparatorWidgets();
       
  2045         }
       
  2046 
       
  2047         if (next == -1)
       
  2048             break;
       
  2049 
       
  2050         QWidget *sepWidget;
       
  2051         if (j < separatorWidgets.size() && separatorWidgets.at(j)) {
       
  2052             sepWidget = separatorWidgets.at(j);
       
  2053         } else {
       
  2054             sepWidget = mainWindowLayout()->getSeparatorWidget();
       
  2055             separatorWidgets.append(sepWidget);
       
  2056         }
       
  2057         j++;
       
  2058 
       
  2059 #ifndef QT_MAC_USE_COCOA
       
  2060         sepWidget->raise();
       
  2061 #endif
       
  2062         QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
       
  2063         sepWidget->setGeometry(sepRect);
       
  2064         sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
       
  2065         sepWidget->show();
       
  2066     }
       
  2067 
       
  2068     for (int k = j; k < separatorWidgets.size(); ++k) {
       
  2069         separatorWidgets[k]->hide();
       
  2070     }
       
  2071     separatorWidgets.resize(j);
       
  2072     Q_ASSERT(separatorWidgets.size() == j);
       
  2073 }
       
  2074 #endif //QT_NO_TABBAR
       
  2075 
       
  2076 #ifndef QT_NO_TABBAR
       
  2077 void QDockAreaLayoutInfo::updateTabBar() const
       
  2078 {
       
  2079     if (!tabbed)
       
  2080         return;
       
  2081 
       
  2082     QDockAreaLayoutInfo *that = const_cast<QDockAreaLayoutInfo*>(this);
       
  2083 
       
  2084     if (that->tabBar == 0) {
       
  2085         that->tabBar = mainWindowLayout()->getTabBar();
       
  2086         that->tabBar->setShape(static_cast<QTabBar::Shape>(tabBarShape));
       
  2087         that->tabBar->setDrawBase(true);
       
  2088     }
       
  2089 
       
  2090     bool blocked = tabBar->blockSignals(true);
       
  2091     bool gap = false;
       
  2092 
       
  2093     int tab_idx = 0;
       
  2094     bool changed = false;
       
  2095     for (int i = 0; i < item_list.count(); ++i) {
       
  2096         const QDockAreaLayoutItem &item = item_list.at(i);
       
  2097         if (item.skip())
       
  2098             continue;
       
  2099         if (item.flags & QDockAreaLayoutItem::GapItem) {
       
  2100             gap = true;
       
  2101             continue;
       
  2102         }
       
  2103         if (item.widgetItem == 0)
       
  2104             continue;
       
  2105 
       
  2106         QDockWidget *dw = qobject_cast<QDockWidget*>(item.widgetItem->widget());
       
  2107         QString title = dw->d_func()->fixedWindowTitle;
       
  2108         quintptr id = tabId(item);
       
  2109         if (tab_idx == tabBar->count()) {
       
  2110             tabBar->insertTab(tab_idx, title);
       
  2111 #ifndef QT_NO_TOOLTIP
       
  2112             tabBar->setTabToolTip(tab_idx, title);
       
  2113 #endif
       
  2114             tabBar->setTabData(tab_idx, id);
       
  2115             changed = true;
       
  2116         } else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
       
  2117             if (tab_idx + 1 < tabBar->count()
       
  2118                     && qvariant_cast<quintptr>(tabBar->tabData(tab_idx + 1)) == id)
       
  2119                 tabBar->removeTab(tab_idx);
       
  2120             else {
       
  2121                 tabBar->insertTab(tab_idx, title);
       
  2122 #ifndef QT_NO_TOOLTIP
       
  2123                 tabBar->setTabToolTip(tab_idx, title);
       
  2124 #endif
       
  2125                 tabBar->setTabData(tab_idx, id);
       
  2126             }
       
  2127             changed = true;
       
  2128         }
       
  2129 
       
  2130         if (title != tabBar->tabText(tab_idx)) {
       
  2131             tabBar->setTabText(tab_idx, title);
       
  2132 #ifndef QT_NO_TOOLTIP
       
  2133             tabBar->setTabToolTip(tab_idx, title);
       
  2134 #endif
       
  2135             changed = true;
       
  2136         }
       
  2137 
       
  2138         ++tab_idx;
       
  2139     }
       
  2140 
       
  2141     while (tab_idx < tabBar->count()) {
       
  2142         tabBar->removeTab(tab_idx);
       
  2143         changed = true;
       
  2144     }
       
  2145 
       
  2146     tabBar->blockSignals(blocked);
       
  2147 
       
  2148     that->tabBarVisible = ( (gap ? 1 : 0) + tabBar->count()) > 1;
       
  2149 
       
  2150     if (changed || !tabBarMin.isValid() | !tabBarHint.isValid()) {
       
  2151         that->tabBarMin = tabBar->minimumSizeHint();
       
  2152         that->tabBarHint = tabBar->sizeHint();
       
  2153     }
       
  2154 }
       
  2155 
       
  2156 void QDockAreaLayoutInfo::setTabBarShape(int shape)
       
  2157 {
       
  2158     if (shape == tabBarShape)
       
  2159         return;
       
  2160     tabBarShape = shape;
       
  2161     if (tabBar != 0) {
       
  2162         tabBar->setShape(static_cast<QTabBar::Shape>(shape));
       
  2163         tabBarMin = QSize();
       
  2164         tabBarHint = QSize();
       
  2165     }
       
  2166 
       
  2167     for (int i = 0; i < item_list.count(); ++i) {
       
  2168         QDockAreaLayoutItem &item = item_list[i];
       
  2169         if (item.subinfo != 0)
       
  2170             item.subinfo->setTabBarShape(shape);
       
  2171     }
       
  2172 }
       
  2173 
       
  2174 QSize QDockAreaLayoutInfo::tabBarMinimumSize() const
       
  2175 {
       
  2176     if (!tabbed)
       
  2177         return QSize(0, 0);
       
  2178 
       
  2179     updateTabBar();
       
  2180 
       
  2181     return tabBarMin;
       
  2182 }
       
  2183 
       
  2184 QSize QDockAreaLayoutInfo::tabBarSizeHint() const
       
  2185 {
       
  2186     if (!tabbed)
       
  2187         return QSize(0, 0);
       
  2188 
       
  2189     updateTabBar();
       
  2190 
       
  2191     return tabBarHint;
       
  2192 }
       
  2193 
       
  2194 QSet<QTabBar*> QDockAreaLayoutInfo::usedTabBars() const
       
  2195 {
       
  2196     QSet<QTabBar*> result;
       
  2197 
       
  2198     if (tabbed) {
       
  2199         updateTabBar();
       
  2200         result.insert(tabBar);
       
  2201     }
       
  2202 
       
  2203     for (int i = 0; i < item_list.count(); ++i) {
       
  2204         const QDockAreaLayoutItem &item = item_list.at(i);
       
  2205         if (item.subinfo != 0)
       
  2206             result += item.subinfo->usedTabBars();
       
  2207     }
       
  2208 
       
  2209     return result;
       
  2210 }
       
  2211 
       
  2212 // returns a set of all used separator widgets for this dockarelayout info
       
  2213 // and all subinfos
       
  2214 QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets() const
       
  2215 {
       
  2216     QSet<QWidget*> result;
       
  2217 
       
  2218     for (int i = 0; i < separatorWidgets.count(); ++i)
       
  2219         result << separatorWidgets.at(i);
       
  2220 
       
  2221     for (int i = 0; i < item_list.count(); ++i) {
       
  2222         const QDockAreaLayoutItem &item = item_list.at(i);
       
  2223         if (item.subinfo != 0)
       
  2224             result += item.subinfo->usedSeparatorWidgets();
       
  2225     }
       
  2226 
       
  2227     return result;
       
  2228 }
       
  2229 
       
  2230 QRect QDockAreaLayoutInfo::tabContentRect() const
       
  2231 {
       
  2232     if (!tabbed)
       
  2233         return QRect();
       
  2234 
       
  2235     QRect result = rect;
       
  2236     QSize tbh = tabBarSizeHint();
       
  2237 
       
  2238     if (tabBarVisible) {
       
  2239         switch (tabBarShape) {
       
  2240             case QTabBar::RoundedNorth:
       
  2241             case QTabBar::TriangularNorth:
       
  2242                 result.adjust(0, tbh.height(), 0, 0);
       
  2243                 break;
       
  2244             case QTabBar::RoundedSouth:
       
  2245             case QTabBar::TriangularSouth:
       
  2246                 result.adjust(0, 0, 0, -tbh.height());
       
  2247                 break;
       
  2248             case QTabBar::RoundedEast:
       
  2249             case QTabBar::TriangularEast:
       
  2250                 result.adjust(0, 0, -tbh.width(), 0);
       
  2251                 break;
       
  2252             case QTabBar::RoundedWest:
       
  2253             case QTabBar::TriangularWest:
       
  2254                 result.adjust(tbh.width(), 0, 0, 0);
       
  2255                 break;
       
  2256             default:
       
  2257                 break;
       
  2258         }
       
  2259     }
       
  2260 
       
  2261     return result;
       
  2262 }
       
  2263 #endif // QT_NO_TABBAR
       
  2264 
       
  2265 /******************************************************************************
       
  2266 ** QDockAreaLayout
       
  2267 */
       
  2268 
       
  2269 QDockAreaLayout::QDockAreaLayout(QMainWindow *win) : fallbackToSizeHints(true)
       
  2270 {
       
  2271     mainWindow = win;
       
  2272     sep = win->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, win);
       
  2273 #ifndef QT_NO_TABBAR
       
  2274     const int tabShape = QTabBar::RoundedSouth;
       
  2275 #else
       
  2276     const int tabShape = 0;
       
  2277 #endif
       
  2278     docks[QInternal::LeftDock]
       
  2279         = QDockAreaLayoutInfo(sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
       
  2280     docks[QInternal::RightDock]
       
  2281         = QDockAreaLayoutInfo(sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
       
  2282     docks[QInternal::TopDock]
       
  2283         = QDockAreaLayoutInfo(sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
       
  2284     docks[QInternal::BottomDock]
       
  2285         = QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
       
  2286     centralWidgetItem = 0;
       
  2287 
       
  2288 
       
  2289     corners[Qt::TopLeftCorner] = Qt::TopDockWidgetArea;
       
  2290     corners[Qt::TopRightCorner] = Qt::TopDockWidgetArea;
       
  2291     corners[Qt::BottomLeftCorner] = Qt::BottomDockWidgetArea;
       
  2292     corners[Qt::BottomRightCorner] = Qt::BottomDockWidgetArea;
       
  2293 }
       
  2294 
       
  2295 bool QDockAreaLayout::isValid() const
       
  2296 {
       
  2297     return rect.isValid();
       
  2298 }
       
  2299 
       
  2300 void QDockAreaLayout::saveState(QDataStream &stream) const
       
  2301 {
       
  2302     stream << (uchar) DockWidgetStateMarker;
       
  2303     int cnt = 0;
       
  2304     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2305         if (!docks[i].item_list.isEmpty())
       
  2306             ++cnt;
       
  2307     }
       
  2308     stream << cnt;
       
  2309     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2310         if (docks[i].item_list.isEmpty())
       
  2311             continue;
       
  2312         stream << i << docks[i].rect.size();
       
  2313         docks[i].saveState(stream);
       
  2314     }
       
  2315 
       
  2316     stream << centralWidgetRect.size();
       
  2317 
       
  2318     for (int i = 0; i < 4; ++i)
       
  2319         stream << static_cast<int>(corners[i]);
       
  2320 }
       
  2321 
       
  2322 bool QDockAreaLayout::restoreState(QDataStream &stream, const QList<QDockWidget*> &_dockwidgets, bool testing)
       
  2323 {
       
  2324     QList<QDockWidget*> dockwidgets = _dockwidgets;
       
  2325 
       
  2326     int cnt;
       
  2327     stream >> cnt;
       
  2328     for (int i = 0; i < cnt; ++i) {
       
  2329         int pos;
       
  2330         stream >> pos;
       
  2331         QSize size;
       
  2332         stream >> size;
       
  2333         if (!testing) {
       
  2334             docks[pos].rect = QRect(QPoint(0, 0), size);
       
  2335         }
       
  2336         if (!docks[pos].restoreState(stream, dockwidgets, testing)) {
       
  2337             stream.setStatus(QDataStream::ReadCorruptData);
       
  2338             return false;
       
  2339         }
       
  2340     }
       
  2341 
       
  2342     QSize size;
       
  2343     stream >> size;
       
  2344     centralWidgetRect = QRect(QPoint(0, 0), size);
       
  2345 
       
  2346     bool ok = stream.status() == QDataStream::Ok;
       
  2347 
       
  2348     if (ok) {
       
  2349         int cornerData[4];
       
  2350         for (int i = 0; i < 4; ++i)
       
  2351             stream >> cornerData[i];
       
  2352         if (stream.status() == QDataStream::Ok) {
       
  2353             for (int i = 0; i < 4; ++i)
       
  2354                 corners[i] = static_cast<Qt::DockWidgetArea>(cornerData[i]);
       
  2355         }
       
  2356 
       
  2357         if (!testing)
       
  2358             fallbackToSizeHints = false;
       
  2359     }
       
  2360 
       
  2361     return ok;
       
  2362 }
       
  2363 
       
  2364 QList<int> QDockAreaLayout::indexOfPlaceHolder(const QString &objectName) const
       
  2365 {
       
  2366     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2367         QList<int> result = docks[i].indexOfPlaceHolder(objectName);
       
  2368         if (!result.isEmpty()) {
       
  2369             result.prepend(i);
       
  2370             return result;
       
  2371         }
       
  2372     }
       
  2373     return QList<int>();
       
  2374 }
       
  2375 
       
  2376 QList<int> QDockAreaLayout::indexOf(QWidget *dockWidget) const
       
  2377 {
       
  2378     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2379         QList<int> result = docks[i].indexOf(dockWidget);
       
  2380         if (!result.isEmpty()) {
       
  2381             result.prepend(i);
       
  2382             return result;
       
  2383         }
       
  2384     }
       
  2385     return QList<int>();
       
  2386 }
       
  2387 
       
  2388 QList<int> QDockAreaLayout::gapIndex(const QPoint &pos) const
       
  2389 {
       
  2390     QMainWindow::DockOptions opts = mainWindow->dockOptions();
       
  2391     bool nestingEnabled = opts & QMainWindow::AllowNestedDocks;
       
  2392     QDockAreaLayoutInfo::TabMode tabMode = QDockAreaLayoutInfo::NoTabs;
       
  2393 #ifndef QT_NO_TABBAR
       
  2394     if (opts & QMainWindow::AllowTabbedDocks
       
  2395         || opts & QMainWindow::VerticalTabs)
       
  2396         tabMode = QDockAreaLayoutInfo::AllowTabs;
       
  2397     if (opts & QMainWindow::ForceTabbedDocks)
       
  2398         tabMode = QDockAreaLayoutInfo::ForceTabs;
       
  2399 
       
  2400     if (tabMode == QDockAreaLayoutInfo::ForceTabs)
       
  2401         nestingEnabled = false;
       
  2402 #endif
       
  2403 
       
  2404 
       
  2405     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2406         const QDockAreaLayoutInfo &info = docks[i];
       
  2407 
       
  2408         if (!info.isEmpty() && info.rect.contains(pos)) {
       
  2409             QList<int> result
       
  2410                 = docks[i].gapIndex(pos, nestingEnabled, tabMode);
       
  2411             if (!result.isEmpty())
       
  2412                 result.prepend(i);
       
  2413             return result;
       
  2414         }
       
  2415     }
       
  2416 
       
  2417     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2418         const QDockAreaLayoutInfo &info = docks[i];
       
  2419 
       
  2420         if (info.isEmpty()) {
       
  2421             QRect r;
       
  2422             switch (i) {
       
  2423                 case QInternal::LeftDock:
       
  2424                     r = QRect(rect.left(), rect.top(), EmptyDropAreaSize, rect.height());
       
  2425                     break;
       
  2426                 case QInternal::RightDock:
       
  2427                     r = QRect(rect.right() - EmptyDropAreaSize, rect.top(),
       
  2428                                 EmptyDropAreaSize, rect.height());
       
  2429                     break;
       
  2430                 case QInternal::TopDock:
       
  2431                     r = QRect(rect.left(), rect.top(), rect.width(), EmptyDropAreaSize);
       
  2432                     break;
       
  2433                 case QInternal::BottomDock:
       
  2434                     r = QRect(rect.left(), rect.bottom() - EmptyDropAreaSize,
       
  2435                                 rect.width(), EmptyDropAreaSize);
       
  2436                     break;
       
  2437             }
       
  2438             if (r.contains(pos)) {
       
  2439                 if (opts & QMainWindow::ForceTabbedDocks && !info.item_list.isEmpty()) {
       
  2440                     //in case of ForceTabbedDocks, we pass -1 in order to force the gap to be tabbed
       
  2441                     //it mustn't be completely empty otherwise it won't work
       
  2442                     return QList<int>() << i << -1 << 0;
       
  2443                 } else {
       
  2444                     return QList<int>() << i << 0;
       
  2445                 }
       
  2446             }
       
  2447         }
       
  2448     }
       
  2449 
       
  2450     return QList<int>();
       
  2451 }
       
  2452 
       
  2453 QList<int> QDockAreaLayout::findSeparator(const QPoint &pos) const
       
  2454 {
       
  2455     QList<int> result;
       
  2456     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2457         const QDockAreaLayoutInfo &info = docks[i];
       
  2458         if (info.isEmpty())
       
  2459             continue;
       
  2460         QRect rect = separatorRect(i);
       
  2461         if (!rect.isNull() && sep == 1)
       
  2462             rect.adjust(-2, -2, 2, 2);
       
  2463         if (rect.contains(pos) && !info.hasFixedSize()) {
       
  2464             result << i;
       
  2465             break;
       
  2466         } else if (info.rect.contains(pos)) {
       
  2467             result = docks[i].findSeparator(pos);
       
  2468             if (!result.isEmpty()) {
       
  2469                 result.prepend(i);
       
  2470                 break;
       
  2471             }
       
  2472         }
       
  2473     }
       
  2474 
       
  2475     return result;
       
  2476 }
       
  2477 
       
  2478 QDockAreaLayoutInfo *QDockAreaLayout::info(QWidget *widget)
       
  2479 {
       
  2480     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2481         if (QDockAreaLayoutInfo *result = docks[i].info(widget))
       
  2482             return result;
       
  2483     }
       
  2484 
       
  2485     return 0;
       
  2486 }
       
  2487 
       
  2488 QDockAreaLayoutInfo *QDockAreaLayout::info(const QList<int> &path)
       
  2489 {
       
  2490     Q_ASSERT(!path.isEmpty());
       
  2491     const int index = path.first();
       
  2492     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2493 
       
  2494     if (path.count() == 1)
       
  2495         return &docks[index];
       
  2496 
       
  2497     return docks[index].info(path.mid(1));
       
  2498 }
       
  2499 
       
  2500 const QDockAreaLayoutInfo *QDockAreaLayout::info(const QList<int> &path) const
       
  2501 {
       
  2502     return const_cast<QDockAreaLayout*>(this)->info(path);
       
  2503 }
       
  2504 
       
  2505 QDockAreaLayoutItem &QDockAreaLayout::item(const QList<int> &path)
       
  2506 {
       
  2507     Q_ASSERT(!path.isEmpty());
       
  2508     const int index = path.first();
       
  2509     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2510     return docks[index].item(path.mid(1));
       
  2511 }
       
  2512 
       
  2513 QRect QDockAreaLayout::itemRect(const QList<int> &path) const
       
  2514 {
       
  2515     Q_ASSERT(!path.isEmpty());
       
  2516     const int index = path.first();
       
  2517     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2518     return docks[index].itemRect(path.mid(1));
       
  2519 }
       
  2520 
       
  2521 QRect QDockAreaLayout::separatorRect(int index) const
       
  2522 {
       
  2523     const QDockAreaLayoutInfo &dock = docks[index];
       
  2524     if (dock.isEmpty())
       
  2525         return QRect();
       
  2526     QRect r = dock.rect;
       
  2527     switch (index) {
       
  2528         case QInternal::LeftDock:
       
  2529             return QRect(r.right() + 1, r.top(), sep, r.height());
       
  2530         case QInternal::RightDock:
       
  2531             return QRect(r.left() - sep, r.top(), sep, r.height());
       
  2532         case QInternal::TopDock:
       
  2533             return QRect(r.left(), r.bottom() + 1, r.width(), sep);
       
  2534         case QInternal::BottomDock:
       
  2535             return QRect(r.left(), r.top() - sep, r.width(), sep);
       
  2536         default:
       
  2537             break;
       
  2538     }
       
  2539     return QRect();
       
  2540 }
       
  2541 
       
  2542 QRect QDockAreaLayout::separatorRect(const QList<int> &path) const
       
  2543 {
       
  2544     Q_ASSERT(!path.isEmpty());
       
  2545 
       
  2546     const int index = path.first();
       
  2547     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2548 
       
  2549     if (path.count() == 1)
       
  2550         return separatorRect(index);
       
  2551     else
       
  2552         return docks[index].separatorRect(path.mid(1));
       
  2553 }
       
  2554 
       
  2555 bool QDockAreaLayout::insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem)
       
  2556 {
       
  2557     Q_ASSERT(!path.isEmpty());
       
  2558     const int index = path.first();
       
  2559     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2560     return docks[index].insertGap(path.mid(1), dockWidgetItem);
       
  2561 }
       
  2562 
       
  2563 QLayoutItem *QDockAreaLayout::plug(const QList<int> &path)
       
  2564 {
       
  2565     Q_ASSERT(!path.isEmpty());
       
  2566     const int index = path.first();
       
  2567     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2568     return docks[index].plug(path.mid(1));
       
  2569 }
       
  2570 
       
  2571 QLayoutItem *QDockAreaLayout::unplug(const QList<int> &path)
       
  2572 {
       
  2573     Q_ASSERT(!path.isEmpty());
       
  2574     const int index = path.first();
       
  2575     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2576     return docks[index].unplug(path.mid(1));
       
  2577 }
       
  2578 
       
  2579 void QDockAreaLayout::remove(const QList<int> &path)
       
  2580 {
       
  2581     Q_ASSERT(!path.isEmpty());
       
  2582     const int index = path.first();
       
  2583     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2584     docks[index].remove(path.mid(1));
       
  2585 }
       
  2586 
       
  2587 static inline int qMin(int i1, int i2, int i3) { return qMin(i1, qMin(i2, i3)); }
       
  2588 static inline int qMax(int i1, int i2, int i3) { return qMax(i1, qMax(i2, i3)); }
       
  2589 
       
  2590 void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
       
  2591                                 QVector<QLayoutStruct> *_hor_struct_list)
       
  2592 {
       
  2593     QSize center_hint(0, 0);
       
  2594     QSize center_min(0, 0);
       
  2595     const bool have_central = centralWidgetItem != 0 && !centralWidgetItem->isEmpty();
       
  2596     if (have_central) {
       
  2597         center_hint = centralWidgetRect.size();
       
  2598         if (!center_hint.isValid())
       
  2599             center_hint = centralWidgetItem->sizeHint();
       
  2600         center_min = centralWidgetItem->minimumSize();
       
  2601     }
       
  2602 
       
  2603     QRect center_rect = rect;
       
  2604     if (!docks[QInternal::LeftDock].isEmpty())
       
  2605         center_rect.setLeft(rect.left() + docks[QInternal::LeftDock].rect.width() + sep);
       
  2606     if (!docks[QInternal::TopDock].isEmpty())
       
  2607         center_rect.setTop(rect.top() + docks[QInternal::TopDock].rect.height() + sep);
       
  2608     if (!docks[QInternal::RightDock].isEmpty())
       
  2609         center_rect.setRight(rect.right() - docks[QInternal::RightDock].rect.width() - sep);
       
  2610     if (!docks[QInternal::BottomDock].isEmpty())
       
  2611         center_rect.setBottom(rect.bottom() - docks[QInternal::BottomDock].rect.height() - sep);
       
  2612 
       
  2613     QSize left_hint = docks[QInternal::LeftDock].size();
       
  2614     if (left_hint.isNull() || fallbackToSizeHints)
       
  2615         left_hint = docks[QInternal::LeftDock].sizeHint();
       
  2616     QSize left_min = docks[QInternal::LeftDock].minimumSize();
       
  2617     QSize left_max = docks[QInternal::LeftDock].maximumSize();
       
  2618     left_hint = left_hint.boundedTo(left_max).expandedTo(left_min);
       
  2619 
       
  2620     QSize right_hint = docks[QInternal::RightDock].size();
       
  2621     if (right_hint.isNull() || fallbackToSizeHints)
       
  2622         right_hint = docks[QInternal::RightDock].sizeHint();
       
  2623     QSize right_min = docks[QInternal::RightDock].minimumSize();
       
  2624     QSize right_max = docks[QInternal::RightDock].maximumSize();
       
  2625     right_hint = right_hint.boundedTo(right_max).expandedTo(right_min);
       
  2626 
       
  2627     QSize top_hint = docks[QInternal::TopDock].size();
       
  2628     if (top_hint.isNull() || fallbackToSizeHints)
       
  2629         top_hint = docks[QInternal::TopDock].sizeHint();
       
  2630     QSize top_min = docks[QInternal::TopDock].minimumSize();
       
  2631     QSize top_max = docks[QInternal::TopDock].maximumSize();
       
  2632     top_hint = top_hint.boundedTo(top_max).expandedTo(top_min);
       
  2633 
       
  2634     QSize bottom_hint = docks[QInternal::BottomDock].size();
       
  2635     if (bottom_hint.isNull() || fallbackToSizeHints)
       
  2636         bottom_hint = docks[QInternal::BottomDock].sizeHint();
       
  2637     QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
       
  2638     QSize bottom_max = docks[QInternal::BottomDock].maximumSize();
       
  2639     bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
       
  2640 
       
  2641     fallbackToSizeHints = false;
       
  2642 
       
  2643     if (_ver_struct_list != 0) {
       
  2644         QVector<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
       
  2645         ver_struct_list.resize(3);
       
  2646 
       
  2647         // top --------------------------------------------------
       
  2648         ver_struct_list[0].init();
       
  2649         ver_struct_list[0].stretch = 0;
       
  2650         ver_struct_list[0].sizeHint = top_hint.height();
       
  2651         ver_struct_list[0].minimumSize = top_min.height();
       
  2652         ver_struct_list[0].maximumSize = top_max.height();
       
  2653         ver_struct_list[0].expansive = false;
       
  2654         ver_struct_list[0].empty = docks[QInternal::TopDock].isEmpty();
       
  2655         ver_struct_list[0].pos = docks[QInternal::TopDock].rect.top();
       
  2656         ver_struct_list[0].size = docks[QInternal::TopDock].rect.height();
       
  2657 
       
  2658         // center --------------------------------------------------
       
  2659         ver_struct_list[1].init();
       
  2660         ver_struct_list[1].stretch = center_hint.height();
       
  2661 
       
  2662         bool tl_significant = corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
       
  2663                                     || docks[QInternal::TopDock].isEmpty();
       
  2664         bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
       
  2665                                     || docks[QInternal::BottomDock].isEmpty();
       
  2666         bool tr_significant = corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
       
  2667                                     || docks[QInternal::TopDock].isEmpty();
       
  2668         bool br_significant = corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
       
  2669                                     || docks[QInternal::BottomDock].isEmpty();
       
  2670 
       
  2671         int left = (tl_significant && bl_significant) ? left_hint.height() : 0;
       
  2672         int right = (tr_significant && br_significant) ? right_hint.height() : 0;
       
  2673         ver_struct_list[1].sizeHint = qMax(left, center_hint.height(), right);
       
  2674 
       
  2675         left = (tl_significant && bl_significant) ? left_min.height() : 0;
       
  2676         right = (tr_significant && br_significant) ? right_min.height() : 0;
       
  2677         ver_struct_list[1].minimumSize = qMax(left, center_min.height(), right);
       
  2678         ver_struct_list[1].maximumSize = have_central ? QWIDGETSIZE_MAX : 0;
       
  2679         ver_struct_list[1].expansive = have_central;
       
  2680         ver_struct_list[1].empty = docks[QInternal::LeftDock].isEmpty()
       
  2681                                         && !have_central
       
  2682                                         && docks[QInternal::RightDock].isEmpty();
       
  2683         ver_struct_list[1].pos = center_rect.top();
       
  2684         ver_struct_list[1].size = center_rect.height();
       
  2685 
       
  2686         // bottom --------------------------------------------------
       
  2687         ver_struct_list[2].init();
       
  2688         ver_struct_list[2].stretch = 0;
       
  2689         ver_struct_list[2].sizeHint = bottom_hint.height();
       
  2690         ver_struct_list[2].minimumSize = bottom_min.height();
       
  2691         ver_struct_list[2].maximumSize = bottom_max.height();
       
  2692         ver_struct_list[2].expansive = false;
       
  2693         ver_struct_list[2].empty = docks[QInternal::BottomDock].isEmpty();
       
  2694         ver_struct_list[2].pos = docks[QInternal::BottomDock].rect.top();
       
  2695         ver_struct_list[2].size = docks[QInternal::BottomDock].rect.height();
       
  2696 
       
  2697         for (int i = 0; i < 3; ++i) {
       
  2698             ver_struct_list[i].sizeHint
       
  2699                 = qMax(ver_struct_list[i].sizeHint, ver_struct_list[i].minimumSize);
       
  2700         }
       
  2701     }
       
  2702 
       
  2703     if (_hor_struct_list != 0) {
       
  2704         QVector<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
       
  2705         hor_struct_list.resize(3);
       
  2706 
       
  2707         // left --------------------------------------------------
       
  2708         hor_struct_list[0].init();
       
  2709         hor_struct_list[0].stretch = 0;
       
  2710         hor_struct_list[0].sizeHint = left_hint.width();
       
  2711         hor_struct_list[0].minimumSize = left_min.width();
       
  2712         hor_struct_list[0].maximumSize = left_max.width();
       
  2713         hor_struct_list[0].expansive = false;
       
  2714         hor_struct_list[0].empty = docks[QInternal::LeftDock].isEmpty();
       
  2715         hor_struct_list[0].pos = docks[QInternal::LeftDock].rect.left();
       
  2716         hor_struct_list[0].size = docks[QInternal::LeftDock].rect.width();
       
  2717 
       
  2718         // center --------------------------------------------------
       
  2719         hor_struct_list[1].init();
       
  2720         hor_struct_list[1].stretch = center_hint.width();
       
  2721 
       
  2722         bool tl_significant = corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
       
  2723                                     || docks[QInternal::LeftDock].isEmpty();
       
  2724         bool tr_significant = corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
       
  2725                                     || docks[QInternal::RightDock].isEmpty();
       
  2726         bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
       
  2727                                     || docks[QInternal::LeftDock].isEmpty();
       
  2728         bool br_significant = corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
       
  2729                                     || docks[QInternal::RightDock].isEmpty();
       
  2730 
       
  2731         int top = (tl_significant && tr_significant) ? top_hint.width() : 0;
       
  2732         int bottom = (bl_significant && br_significant) ? bottom_hint.width() : 0;
       
  2733         hor_struct_list[1].sizeHint = qMax(top, center_hint.width(), bottom);
       
  2734 
       
  2735         top = (tl_significant && tr_significant) ? top_min.width() : 0;
       
  2736         bottom = (bl_significant && br_significant) ? bottom_min.width() : 0;
       
  2737         hor_struct_list[1].minimumSize = qMax(top, center_min.width(), bottom);
       
  2738 
       
  2739         hor_struct_list[1].maximumSize = have_central ? QWIDGETSIZE_MAX : 0;
       
  2740         hor_struct_list[1].expansive = have_central;
       
  2741         hor_struct_list[1].empty = !have_central;
       
  2742         hor_struct_list[1].pos = center_rect.left();
       
  2743         hor_struct_list[1].size = center_rect.width();
       
  2744 
       
  2745         // right --------------------------------------------------
       
  2746         hor_struct_list[2].init();
       
  2747         hor_struct_list[2].stretch = 0;
       
  2748         hor_struct_list[2].sizeHint = right_hint.width();
       
  2749         hor_struct_list[2].minimumSize = right_min.width();
       
  2750         hor_struct_list[2].maximumSize = right_max.width();
       
  2751         hor_struct_list[2].expansive = false;
       
  2752         hor_struct_list[2].empty = docks[QInternal::RightDock].isEmpty();
       
  2753         hor_struct_list[2].pos = docks[QInternal::RightDock].rect.left();
       
  2754         hor_struct_list[2].size = docks[QInternal::RightDock].rect.width();
       
  2755 
       
  2756         for (int i = 0; i < 3; ++i) {
       
  2757             hor_struct_list[i].sizeHint
       
  2758                 = qMax(hor_struct_list[i].sizeHint, hor_struct_list[i].minimumSize);
       
  2759         }
       
  2760     }
       
  2761 }
       
  2762 
       
  2763 void QDockAreaLayout::setGrid(QVector<QLayoutStruct> *ver_struct_list,
       
  2764                                 QVector<QLayoutStruct> *hor_struct_list)
       
  2765 {
       
  2766 
       
  2767     // top ---------------------------------------------------
       
  2768 
       
  2769     if (!docks[QInternal::TopDock].isEmpty()) {
       
  2770         QRect r = docks[QInternal::TopDock].rect;
       
  2771         if (hor_struct_list != 0) {
       
  2772             r.setLeft(corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
       
  2773                 || docks[QInternal::LeftDock].isEmpty()
       
  2774                 ? rect.left() : hor_struct_list->at(1).pos);
       
  2775             r.setRight(corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
       
  2776                 || docks[QInternal::RightDock].isEmpty()
       
  2777                 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
       
  2778         }
       
  2779         if (ver_struct_list != 0) {
       
  2780             r.setTop(rect.top());
       
  2781             r.setBottom(ver_struct_list->at(1).pos - sep - 1);
       
  2782         }
       
  2783         docks[QInternal::TopDock].rect = r;
       
  2784         docks[QInternal::TopDock].fitItems();
       
  2785     }
       
  2786 
       
  2787     // bottom ---------------------------------------------------
       
  2788 
       
  2789     if (!docks[QInternal::BottomDock].isEmpty()) {
       
  2790         QRect r = docks[QInternal::BottomDock].rect;
       
  2791         if (hor_struct_list != 0) {
       
  2792             r.setLeft(corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
       
  2793                         || docks[QInternal::LeftDock].isEmpty()
       
  2794                             ? rect.left() : hor_struct_list->at(1).pos);
       
  2795             r.setRight(corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
       
  2796                         || docks[QInternal::RightDock].isEmpty()
       
  2797                             ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
       
  2798         }
       
  2799         if (ver_struct_list != 0) {
       
  2800             r.setTop(ver_struct_list->at(2).pos);
       
  2801             r.setBottom(rect.bottom());
       
  2802         }
       
  2803         docks[QInternal::BottomDock].rect = r;
       
  2804         docks[QInternal::BottomDock].fitItems();
       
  2805     }
       
  2806 
       
  2807     // left ---------------------------------------------------
       
  2808 
       
  2809     if (!docks[QInternal::LeftDock].isEmpty()) {
       
  2810         QRect r = docks[QInternal::LeftDock].rect;
       
  2811         if (hor_struct_list != 0) {
       
  2812             r.setLeft(rect.left());
       
  2813             r.setRight(hor_struct_list->at(1).pos - sep - 1);
       
  2814         }
       
  2815         if (ver_struct_list != 0) {
       
  2816             r.setTop(corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
       
  2817                 || docks[QInternal::TopDock].isEmpty()
       
  2818                 ? rect.top() : ver_struct_list->at(1).pos);
       
  2819             r.setBottom(corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
       
  2820                 || docks[QInternal::BottomDock].isEmpty()
       
  2821                 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
       
  2822         }
       
  2823         docks[QInternal::LeftDock].rect = r;
       
  2824         docks[QInternal::LeftDock].fitItems();
       
  2825     }
       
  2826 
       
  2827     // right ---------------------------------------------------
       
  2828 
       
  2829     if (!docks[QInternal::RightDock].isEmpty()) {
       
  2830         QRect r = docks[QInternal::RightDock].rect;
       
  2831         if (hor_struct_list != 0) {
       
  2832             r.setLeft(hor_struct_list->at(2).pos);
       
  2833             r.setRight(rect.right());
       
  2834         }
       
  2835         if (ver_struct_list != 0) {
       
  2836             r.setTop(corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
       
  2837                         || docks[QInternal::TopDock].isEmpty()
       
  2838                             ? rect.top() : ver_struct_list->at(1).pos);
       
  2839             r.setBottom(corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
       
  2840                         || docks[QInternal::BottomDock].isEmpty()
       
  2841                             ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
       
  2842         }
       
  2843         docks[QInternal::RightDock].rect = r;
       
  2844         docks[QInternal::RightDock].fitItems();
       
  2845     }
       
  2846 
       
  2847     // center ---------------------------------------------------
       
  2848 
       
  2849     if (hor_struct_list != 0) {
       
  2850         centralWidgetRect.setLeft(hor_struct_list->at(1).pos);
       
  2851         centralWidgetRect.setWidth(hor_struct_list->at(1).size);
       
  2852     }
       
  2853     if (ver_struct_list != 0) {
       
  2854         centralWidgetRect.setTop(ver_struct_list->at(1).pos);
       
  2855         centralWidgetRect.setHeight(ver_struct_list->at(1).size);
       
  2856     }
       
  2857 }
       
  2858 
       
  2859 void QDockAreaLayout::fitLayout()
       
  2860 {
       
  2861     QVector<QLayoutStruct> ver_struct_list(3);
       
  2862     QVector<QLayoutStruct> hor_struct_list(3);
       
  2863     getGrid(&ver_struct_list, &hor_struct_list);
       
  2864 
       
  2865     qGeomCalc(ver_struct_list, 0, 3, rect.top(), rect.height(), sep);
       
  2866     qGeomCalc(hor_struct_list, 0, 3, rect.left(), rect.width(), sep);
       
  2867 
       
  2868     setGrid(&ver_struct_list, &hor_struct_list);
       
  2869 }
       
  2870 
       
  2871 void QDockAreaLayout::clear()
       
  2872 {
       
  2873     for (int i = 0; i < QInternal::DockCount; ++i)
       
  2874         docks[i].clear();
       
  2875 
       
  2876     rect = QRect();
       
  2877     centralWidgetRect = QRect();
       
  2878 }
       
  2879 
       
  2880 QSize QDockAreaLayout::sizeHint() const
       
  2881 {
       
  2882     int left_sep = 0;
       
  2883     int right_sep = 0;
       
  2884     int top_sep = 0;
       
  2885     int bottom_sep = 0;
       
  2886 
       
  2887     if (centralWidgetItem != 0) {
       
  2888         left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
       
  2889         right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
       
  2890         top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
       
  2891         bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
       
  2892     }
       
  2893 
       
  2894     QSize left = docks[QInternal::LeftDock].sizeHint() + QSize(left_sep, 0);
       
  2895     QSize right = docks[QInternal::RightDock].sizeHint() + QSize(right_sep, 0);
       
  2896     QSize top = docks[QInternal::TopDock].sizeHint() + QSize(0, top_sep);
       
  2897     QSize bottom = docks[QInternal::BottomDock].sizeHint() + QSize(0, bottom_sep);
       
  2898     QSize center = centralWidgetItem == 0 ? QSize(0, 0) : centralWidgetItem->sizeHint();
       
  2899 
       
  2900     int row1 = top.width();
       
  2901     int row2 = left.width() + center.width() + right.width();
       
  2902     int row3 = bottom.width();
       
  2903     int col1 = left.height();
       
  2904     int col2 = top.height() + center.height() + bottom.height();
       
  2905     int col3 = right.height();
       
  2906 
       
  2907     if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
       
  2908         row1 += left.width();
       
  2909     else
       
  2910         col1 += top.height();
       
  2911 
       
  2912     if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
       
  2913         row1 += right.width();
       
  2914     else
       
  2915         col3 += top.height();
       
  2916 
       
  2917     if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
       
  2918         row3 += left.width();
       
  2919     else
       
  2920         col1 += bottom.height();
       
  2921 
       
  2922     if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
       
  2923         row3 += right.width();
       
  2924     else
       
  2925         col3 += bottom.height();
       
  2926 
       
  2927     return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
       
  2928 }
       
  2929 
       
  2930 QSize QDockAreaLayout::minimumSize() const
       
  2931 {
       
  2932     int left_sep = 0;
       
  2933     int right_sep = 0;
       
  2934     int top_sep = 0;
       
  2935     int bottom_sep = 0;
       
  2936 
       
  2937     if (centralWidgetItem != 0) {
       
  2938         left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
       
  2939         right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
       
  2940         top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
       
  2941         bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
       
  2942     }
       
  2943 
       
  2944     QSize left = docks[QInternal::LeftDock].minimumSize() + QSize(left_sep, 0);
       
  2945     QSize right = docks[QInternal::RightDock].minimumSize() + QSize(right_sep, 0);
       
  2946     QSize top = docks[QInternal::TopDock].minimumSize() + QSize(0, top_sep);
       
  2947     QSize bottom = docks[QInternal::BottomDock].minimumSize() + QSize(0, bottom_sep);
       
  2948     QSize center = centralWidgetItem == 0 ? QSize(0, 0) : centralWidgetItem->minimumSize();
       
  2949 
       
  2950     int row1 = top.width();
       
  2951     int row2 = left.width() + center.width() + right.width();
       
  2952     int row3 = bottom.width();
       
  2953     int col1 = left.height();
       
  2954     int col2 = top.height() + center.height() + bottom.height();
       
  2955     int col3 = right.height();
       
  2956 
       
  2957     if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
       
  2958         row1 += left.width();
       
  2959     else
       
  2960         col1 += top.height();
       
  2961 
       
  2962     if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
       
  2963         row1 += right.width();
       
  2964     else
       
  2965         col3 += top.height();
       
  2966 
       
  2967     if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
       
  2968         row3 += left.width();
       
  2969     else
       
  2970         col1 += bottom.height();
       
  2971 
       
  2972     if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
       
  2973         row3 += right.width();
       
  2974     else
       
  2975         col3 += bottom.height();
       
  2976 
       
  2977     return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
       
  2978 }
       
  2979 
       
  2980 bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
       
  2981 {
       
  2982     QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
       
  2983     if (index.isEmpty())
       
  2984         return false;
       
  2985 
       
  2986     QDockAreaLayoutItem &item = this->item(index);
       
  2987     QPlaceHolderItem *placeHolder = item.placeHolderItem;
       
  2988     Q_ASSERT(placeHolder != 0);
       
  2989 
       
  2990     item.widgetItem = new QDockWidgetItem(dockWidget);
       
  2991 
       
  2992     if (placeHolder->window) {
       
  2993         QDesktopWidget desktop;
       
  2994         QRect r = constrainedRect(placeHolder->topLevelRect, desktop.screenGeometry(dockWidget));
       
  2995         dockWidget->d_func()->setWindowState(true, true, r);
       
  2996     }
       
  2997     dockWidget->show();
       
  2998 //    dockWidget->setVisible(!placeHolder->hidden);
       
  2999 #ifdef Q_WS_X11
       
  3000     if (placeHolder->window) // gets rid of the X11BypassWindowManager window flag
       
  3001         dockWidget->d_func()->setWindowState(true);
       
  3002 #endif
       
  3003 
       
  3004     item.placeHolderItem = 0;
       
  3005     delete placeHolder;
       
  3006 
       
  3007     return true;
       
  3008 }
       
  3009 
       
  3010 void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *dockWidget,
       
  3011                                              Qt::Orientation orientation)
       
  3012 {
       
  3013     QLayoutItem *dockWidgetItem = new QDockWidgetItem(dockWidget);
       
  3014     QDockAreaLayoutInfo &info = docks[pos];
       
  3015     if (orientation == info.o || info.item_list.count() <= 1) {
       
  3016         // empty dock areas, or dock areas containing exactly one widget can have their orientation
       
  3017         // switched.
       
  3018         info.o = orientation;
       
  3019 
       
  3020         QDockAreaLayoutItem new_item(dockWidgetItem);
       
  3021         info.item_list.append(new_item);
       
  3022 #ifndef QT_NO_TABBAR
       
  3023         if (info.tabbed && !new_item.skip()) {
       
  3024             info.updateTabBar();
       
  3025             info.setCurrentTabId(tabId(new_item));
       
  3026         }
       
  3027 #endif
       
  3028     } else {
       
  3029 #ifndef QT_NO_TABBAR
       
  3030         int tbshape = info.tabBarShape;
       
  3031 #else
       
  3032         int tbshape = 0;
       
  3033 #endif
       
  3034         QDockAreaLayoutInfo new_info(sep, pos, orientation, tbshape, mainWindow);
       
  3035         new_info.item_list.append(new QDockAreaLayoutInfo(info));
       
  3036         new_info.item_list.append(dockWidgetItem);
       
  3037         info = new_info;
       
  3038     }
       
  3039 
       
  3040     QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
       
  3041     if (!index.isEmpty())
       
  3042         remove(index);
       
  3043 }
       
  3044 
       
  3045 void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
       
  3046 {
       
  3047     QList<int> path = indexOf(first);
       
  3048     if (path.isEmpty())
       
  3049         return;
       
  3050 
       
  3051     QDockAreaLayoutInfo *info = this->info(path);
       
  3052     Q_ASSERT(info != 0);
       
  3053     info->tab(path.last(), new QDockWidgetItem(second));
       
  3054 
       
  3055     QList<int> index = indexOfPlaceHolder(second->objectName());
       
  3056     if (!index.isEmpty())
       
  3057         remove(index);
       
  3058 }
       
  3059 
       
  3060 void QDockAreaLayout::splitDockWidget(QDockWidget *after,
       
  3061                                                QDockWidget *dockWidget,
       
  3062                                                Qt::Orientation orientation)
       
  3063 {
       
  3064     QList<int> path = indexOf(after);
       
  3065     if (path.isEmpty())
       
  3066         return;
       
  3067 
       
  3068     QDockAreaLayoutInfo *info = this->info(path);
       
  3069     Q_ASSERT(info != 0);
       
  3070     info->split(path.last(), orientation, new QDockWidgetItem(dockWidget));
       
  3071 
       
  3072     QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
       
  3073     if (!index.isEmpty())
       
  3074         remove(index);
       
  3075 }
       
  3076 
       
  3077 void QDockAreaLayout::apply(bool animate)
       
  3078 {
       
  3079     QWidgetAnimator &widgetAnimator
       
  3080         = qobject_cast<QMainWindowLayout*>(mainWindow->layout())->widgetAnimator;
       
  3081 
       
  3082     for (int i = 0; i < QInternal::DockCount; ++i)
       
  3083         docks[i].apply(animate);
       
  3084     if (centralWidgetItem != 0 && !centralWidgetItem->isEmpty()) {
       
  3085         widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect,
       
  3086                                 animate);
       
  3087     }
       
  3088 #ifndef QT_NO_TABBAR
       
  3089     if (sep == 1)
       
  3090         updateSeparatorWidgets();
       
  3091 #endif //QT_NO_TABBAR
       
  3092 }
       
  3093 
       
  3094 void QDockAreaLayout::paintSeparators(QPainter *p, QWidget *widget,
       
  3095                                                 const QRegion &clip,
       
  3096                                                 const QPoint &mouse) const
       
  3097 {
       
  3098     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3099         const QDockAreaLayoutInfo &dock = docks[i];
       
  3100         if (dock.isEmpty())
       
  3101             continue;
       
  3102         QRect r = separatorRect(i);
       
  3103         if (clip.contains(r) && !dock.hasFixedSize()) {
       
  3104             Qt::Orientation opposite = dock.o == Qt::Horizontal
       
  3105                                         ? Qt::Vertical : Qt::Horizontal;
       
  3106             paintSep(p, widget, r, opposite, r.contains(mouse));
       
  3107         }
       
  3108         if (clip.contains(dock.rect))
       
  3109             dock.paintSeparators(p, widget, clip, mouse);
       
  3110     }
       
  3111 }
       
  3112 
       
  3113 QRegion QDockAreaLayout::separatorRegion() const
       
  3114 {
       
  3115     QRegion result;
       
  3116 
       
  3117     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3118         const QDockAreaLayoutInfo &dock = docks[i];
       
  3119         if (dock.isEmpty())
       
  3120             continue;
       
  3121         result |= separatorRect(i);
       
  3122         result |= dock.separatorRegion();
       
  3123     }
       
  3124 
       
  3125     return result;
       
  3126 }
       
  3127 
       
  3128 int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &origin,
       
  3129                                                 const QPoint &dest)
       
  3130 {
       
  3131     int delta = 0;
       
  3132     int index = separator.last();
       
  3133 
       
  3134     if (separator.count() > 1) {
       
  3135         QDockAreaLayoutInfo *info = this->info(separator);
       
  3136         delta = pick(info->o, dest - origin);
       
  3137         if (delta != 0)
       
  3138             delta = info->separatorMove(index, delta);
       
  3139         info->apply(false);
       
  3140         return delta;
       
  3141     }
       
  3142 
       
  3143     QVector<QLayoutStruct> list;
       
  3144 
       
  3145     if (index == QInternal::LeftDock || index == QInternal::RightDock)
       
  3146         getGrid(0, &list);
       
  3147     else
       
  3148         getGrid(&list, 0);
       
  3149 
       
  3150     int sep_index = index == QInternal::LeftDock || index == QInternal::TopDock
       
  3151                         ? 0 : 1;
       
  3152     Qt::Orientation o = index == QInternal::LeftDock || index == QInternal::RightDock
       
  3153                         ? Qt::Horizontal
       
  3154                         : Qt::Vertical;
       
  3155 
       
  3156     delta = pick(o, dest - origin);
       
  3157     delta = separatorMoveHelper(list, sep_index, delta, sep);
       
  3158 
       
  3159     if (index == QInternal::LeftDock || index == QInternal::RightDock)
       
  3160         setGrid(0, &list);
       
  3161     else
       
  3162         setGrid(&list, 0);
       
  3163 
       
  3164     apply(false);
       
  3165 
       
  3166     return delta;
       
  3167 }
       
  3168 
       
  3169 #ifndef QT_NO_TABBAR
       
  3170 // Sets the correct positions for the seperator widgets
       
  3171 // Allocates new sepearator widgets with getSeparatorWidget
       
  3172 void QDockAreaLayout::updateSeparatorWidgets() const
       
  3173 {
       
  3174     int j = 0;
       
  3175 
       
  3176     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3177         const QDockAreaLayoutInfo &dock = docks[i];
       
  3178         if (dock.isEmpty())
       
  3179             continue;
       
  3180 
       
  3181         QWidget *sepWidget;
       
  3182         if (j < separatorWidgets.size()) {
       
  3183             sepWidget = separatorWidgets.at(j);
       
  3184         } else {
       
  3185             sepWidget = qobject_cast<QMainWindowLayout*>(mainWindow->layout())->getSeparatorWidget();
       
  3186             separatorWidgets.append(sepWidget);
       
  3187         }
       
  3188         j++;
       
  3189 
       
  3190 #ifndef QT_MAC_USE_COCOA
       
  3191         sepWidget->raise();
       
  3192 #endif
       
  3193         QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
       
  3194         sepWidget->setGeometry(sepRect);
       
  3195         sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
       
  3196         sepWidget->show();
       
  3197     }
       
  3198     for (int i = j; i < separatorWidgets.size(); ++i)
       
  3199         separatorWidgets.at(i)->hide();
       
  3200 
       
  3201     separatorWidgets.resize(j);
       
  3202 }
       
  3203 #endif //QT_NO_TABBAR
       
  3204 
       
  3205 QLayoutItem *QDockAreaLayout::itemAt(int *x, int index) const
       
  3206 {
       
  3207     Q_ASSERT(x != 0);
       
  3208 
       
  3209     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3210         const QDockAreaLayoutInfo &dock = docks[i];
       
  3211         if (QLayoutItem *ret = dock.itemAt(x, index))
       
  3212             return ret;
       
  3213     }
       
  3214 
       
  3215     if (centralWidgetItem && (*x)++ == index)
       
  3216         return centralWidgetItem;
       
  3217 
       
  3218     return 0;
       
  3219 }
       
  3220 
       
  3221 QLayoutItem *QDockAreaLayout::takeAt(int *x, int index)
       
  3222 {
       
  3223     Q_ASSERT(x != 0);
       
  3224 
       
  3225     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3226         QDockAreaLayoutInfo &dock = docks[i];
       
  3227         if (QLayoutItem *ret = dock.takeAt(x, index))
       
  3228             return ret;
       
  3229     }
       
  3230 
       
  3231     if (centralWidgetItem && (*x)++ == index) {
       
  3232         QLayoutItem *ret = centralWidgetItem;
       
  3233         centralWidgetItem = 0;
       
  3234         return ret;
       
  3235     }
       
  3236 
       
  3237     return 0;
       
  3238 }
       
  3239 
       
  3240 void QDockAreaLayout::deleteAllLayoutItems()
       
  3241 {
       
  3242     for (int i = 0; i < QInternal::DockCount; ++i)
       
  3243         docks[i].deleteAllLayoutItems();
       
  3244 }
       
  3245 
       
  3246 #ifndef QT_NO_TABBAR
       
  3247 QSet<QTabBar*> QDockAreaLayout::usedTabBars() const
       
  3248 {
       
  3249     QSet<QTabBar*> result;
       
  3250     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3251         const QDockAreaLayoutInfo &dock = docks[i];
       
  3252         result += dock.usedTabBars();
       
  3253     }
       
  3254     return result;
       
  3255 }
       
  3256 
       
  3257 // Returns the set of all used separator widgets
       
  3258 QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets() const
       
  3259 {
       
  3260     QSet<QWidget*> result;
       
  3261 
       
  3262     for (int i = 0; i < separatorWidgets.count(); ++i)
       
  3263         result << separatorWidgets.at(i);
       
  3264     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3265         const QDockAreaLayoutInfo &dock = docks[i];
       
  3266         result += dock.usedSeparatorWidgets();
       
  3267     }
       
  3268     return result;
       
  3269 }
       
  3270 #endif
       
  3271 
       
  3272 QRect QDockAreaLayout::gapRect(const QList<int> &path) const
       
  3273 {
       
  3274     const QDockAreaLayoutInfo *info = this->info(path);
       
  3275     if (info == 0)
       
  3276         return QRect();
       
  3277     const QList<QDockAreaLayoutItem> &item_list = info->item_list;
       
  3278     Qt::Orientation o = info->o;
       
  3279     int index = path.last();
       
  3280     if (index < 0 || index >= item_list.count())
       
  3281         return QRect();
       
  3282     const QDockAreaLayoutItem &item = item_list.at(index);
       
  3283     if (!(item.flags & QDockAreaLayoutItem::GapItem))
       
  3284         return QRect();
       
  3285 
       
  3286     QRect result;
       
  3287 
       
  3288 #ifndef QT_NO_TABBAR
       
  3289     if (info->tabbed) {
       
  3290         result = info->tabContentRect();
       
  3291     } else
       
  3292 #endif
       
  3293     {
       
  3294         int pos = item.pos;
       
  3295         int size = item.size;
       
  3296 
       
  3297         int prev = info->prev(index);
       
  3298         int next = info->next(index);
       
  3299 
       
  3300         if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
       
  3301             pos += sep;
       
  3302             size -= sep;
       
  3303         }
       
  3304         if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
       
  3305             size -= sep;
       
  3306 
       
  3307         QPoint p;
       
  3308         rpick(o, p) = pos;
       
  3309         rperp(o, p) = perp(o, info->rect.topLeft());
       
  3310         QSize s;
       
  3311         rpick(o, s) = size;
       
  3312         rperp(o, s) = perp(o, info->rect.size());
       
  3313 
       
  3314         result = QRect(p, s);
       
  3315     }
       
  3316 
       
  3317     return result;
       
  3318 }
       
  3319 
       
  3320 void QDockAreaLayout::keepSize(QDockWidget *w)
       
  3321 {
       
  3322     QList<int> path = indexOf(w);
       
  3323     if (path.isEmpty())
       
  3324         return;
       
  3325     QDockAreaLayoutItem &item = this->item(path);
       
  3326     if (item.size != -1)
       
  3327         item.flags |= QDockAreaLayoutItem::KeepSize;
       
  3328 }
       
  3329 
       
  3330 QT_END_NAMESPACE
       
  3331 
       
  3332 #endif // QT_NO_DOCKWIDGET