src/gui/widgets/qdockarealayout.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "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             QRect r = subinfo == 0 ? dockedGeometry(widgetItem->widget()) : subinfo->rect;
       
  1171 
       
  1172             Qt::Orientation opposite = o == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal;
       
  1173 #ifdef QT_NO_TABBAR
       
  1174             const int tabBarShape = 0;
       
  1175 #endif
       
  1176             QDockAreaLayoutInfo *new_info
       
  1177                 = new QDockAreaLayoutInfo(sep, dockPos, opposite, tabBarShape, mainWindow);
       
  1178 
       
  1179             item.subinfo = new_info;
       
  1180             item.widgetItem = 0;
       
  1181 
       
  1182             QDockAreaLayoutItem new_item
       
  1183                 = widgetItem == 0
       
  1184                     ? QDockAreaLayoutItem(subinfo)
       
  1185                     : QDockAreaLayoutItem(widgetItem);
       
  1186             new_item.size = pick(opposite, r.size());
       
  1187             new_item.pos = pick(opposite, r.topLeft());
       
  1188             new_info->item_list.append(new_item);
       
  1189 #ifndef QT_NO_TABBAR
       
  1190             if (insert_tabbed) {
       
  1191                 new_info->tabbed = true;
       
  1192             }
       
  1193 #endif
       
  1194         }
       
  1195 
       
  1196         return item.subinfo->insertGap(path.mid(1), dockWidgetItem);
       
  1197     }
       
  1198 
       
  1199     // create the gap item
       
  1200     QDockAreaLayoutItem gap_item;
       
  1201     gap_item.flags |= QDockAreaLayoutItem::GapItem;
       
  1202     gap_item.widgetItem = dockWidgetItem;   // so minimumSize(), maximumSize() and
       
  1203                                             // sizeHint() will work
       
  1204 #ifndef QT_NO_TABBAR
       
  1205     if (!tabbed)
       
  1206 #endif
       
  1207     {
       
  1208         int prev = this->prev(index);
       
  1209         int next = this->next(index - 1);
       
  1210         // find out how much space we have in the layout
       
  1211         int space = 0;
       
  1212         if (isEmpty()) {
       
  1213             // I am an empty dock area, therefore I am a top-level dock area.
       
  1214             switch (dockPos) {
       
  1215                 case QInternal::LeftDock:
       
  1216                 case QInternal::RightDock:
       
  1217                     if (o == Qt::Vertical) {
       
  1218                         // the "size" is the height of the dock area (remember we are empty)
       
  1219                         space = pick(Qt::Vertical, rect.size());
       
  1220                     } else {
       
  1221                         space = pick(Qt::Horizontal, dockWidgetItem->widget()->size());
       
  1222                     }
       
  1223                     break;
       
  1224                 case QInternal::TopDock:
       
  1225                 case QInternal::BottomDock:
       
  1226                 default:
       
  1227                     if (o == Qt::Horizontal) {
       
  1228                         // the "size" is width of the dock area
       
  1229                         space = pick(Qt::Horizontal, rect.size());
       
  1230                     } else {
       
  1231                         space = pick(Qt::Vertical, dockWidgetItem->widget()->size());
       
  1232                     }
       
  1233                     break;
       
  1234             }
       
  1235         } else {
       
  1236             for (int i = 0; i < item_list.count(); ++i) {
       
  1237                 const QDockAreaLayoutItem &item = item_list.at(i);
       
  1238                 if (item.skip())
       
  1239                     continue;
       
  1240                 Q_ASSERT(!(item.flags & QDockAreaLayoutItem::GapItem));
       
  1241                 space += item.size - pick(o, item.minimumSize());
       
  1242             }
       
  1243         }
       
  1244 
       
  1245         // find the actual size of the gap
       
  1246         int gap_size = 0;
       
  1247         int sep_size = 0;
       
  1248         if (isEmpty()) {
       
  1249             gap_size = space;
       
  1250             sep_size = 0;
       
  1251         } else {
       
  1252             QRect r = dockedGeometry(dockWidgetItem->widget());
       
  1253             gap_size = pick(o, r.size());
       
  1254         if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem))
       
  1255                 sep_size += sep;
       
  1256             if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
       
  1257                 sep_size += sep;
       
  1258         }
       
  1259         if (gap_size + sep_size > space)
       
  1260             gap_size = pick(o, gap_item.minimumSize());
       
  1261         gap_item.size = gap_size + sep_size;
       
  1262     }
       
  1263 
       
  1264     // finally, insert the gap
       
  1265     item_list.insert(index, gap_item);
       
  1266 
       
  1267 //    dump(qDebug() << "insertGap() after:" << index << tabIndex, *this, QString());
       
  1268 
       
  1269     return true;
       
  1270 }
       
  1271 
       
  1272 QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(QWidget *widget)
       
  1273 {
       
  1274     for (int i = 0; i < item_list.count(); ++i) {
       
  1275         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1276         if (item.skip())
       
  1277             continue;
       
  1278 
       
  1279 #ifndef QT_NO_TABBAR
       
  1280         if (tabbed && widget == tabBar)
       
  1281             return this;
       
  1282 #endif
       
  1283 
       
  1284         if (item.widgetItem != 0 && item.widgetItem->widget() == widget)
       
  1285             return this;
       
  1286 
       
  1287         if (item.subinfo != 0) {
       
  1288             if (QDockAreaLayoutInfo *result = item.subinfo->info(widget))
       
  1289                 return result;
       
  1290         }
       
  1291     }
       
  1292 
       
  1293     return 0;
       
  1294 }
       
  1295 
       
  1296 QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(const QList<int> &path)
       
  1297 {
       
  1298     int index = path.first();
       
  1299     if (index < 0)
       
  1300         index = -index - 1;
       
  1301     if (index >= item_list.count())
       
  1302         return this;
       
  1303     if (path.count() == 1 || item_list.at(index).subinfo == 0)
       
  1304         return this;
       
  1305     return item_list.at(index).subinfo->info(path.mid(1));
       
  1306 }
       
  1307 
       
  1308 QRect QDockAreaLayoutInfo::itemRect(int index) const
       
  1309 {
       
  1310     const QDockAreaLayoutItem &item = item_list.at(index);
       
  1311 
       
  1312     if (item.skip())
       
  1313         return QRect();
       
  1314 
       
  1315     QRect result;
       
  1316 
       
  1317 #ifndef QT_NO_TABBAR
       
  1318     if (tabbed) {
       
  1319         if (tabId(item) == currentTabId())
       
  1320             result = tabContentRect();
       
  1321     } else
       
  1322 #endif
       
  1323     {
       
  1324         QPoint pos;
       
  1325         rpick(o, pos) = item.pos;
       
  1326         rperp(o, pos) = perp(o, rect.topLeft());
       
  1327         QSize s;
       
  1328         rpick(o, s) = item.size;
       
  1329         rperp(o, s) = perp(o, rect.size());
       
  1330         result = QRect(pos, s);
       
  1331     }
       
  1332 
       
  1333     return result;
       
  1334 }
       
  1335 
       
  1336 QRect QDockAreaLayoutInfo::itemRect(const QList<int> &path) const
       
  1337 {
       
  1338     Q_ASSERT(!path.isEmpty());
       
  1339 
       
  1340     const int index = path.first();
       
  1341     if (path.count() > 1) {
       
  1342         const QDockAreaLayoutItem &item = item_list.at(index);
       
  1343         Q_ASSERT(item.subinfo != 0);
       
  1344         return item.subinfo->itemRect(path.mid(1));
       
  1345     }
       
  1346 
       
  1347     return itemRect(index);
       
  1348 }
       
  1349 
       
  1350 QRect QDockAreaLayoutInfo::separatorRect(int index) const
       
  1351 {
       
  1352 #ifndef QT_NO_TABBAR
       
  1353     if (tabbed)
       
  1354         return QRect();
       
  1355 #endif
       
  1356 
       
  1357     const QDockAreaLayoutItem &item = item_list.at(index);
       
  1358     if (item.skip())
       
  1359         return QRect();
       
  1360 
       
  1361     QPoint pos = rect.topLeft();
       
  1362     rpick(o, pos) = item.pos + item.size;
       
  1363     QSize s = rect.size();
       
  1364     rpick(o, s) = sep;
       
  1365 
       
  1366     return QRect(pos, s);
       
  1367 }
       
  1368 
       
  1369 QRect QDockAreaLayoutInfo::separatorRect(const QList<int> &path) const
       
  1370 {
       
  1371     Q_ASSERT(!path.isEmpty());
       
  1372 
       
  1373     const int index = path.first();
       
  1374     if (path.count() > 1) {
       
  1375         const QDockAreaLayoutItem &item = item_list.at(index);
       
  1376         Q_ASSERT(item.subinfo != 0);
       
  1377         return item.subinfo->separatorRect(path.mid(1));
       
  1378     }
       
  1379     return separatorRect(index);
       
  1380 }
       
  1381 
       
  1382 QList<int> QDockAreaLayoutInfo::findSeparator(const QPoint &_pos) const
       
  1383 {
       
  1384 #ifndef QT_NO_TABBAR
       
  1385     if (tabbed)
       
  1386         return QList<int>();
       
  1387 #endif
       
  1388 
       
  1389     int pos = pick(o, _pos);
       
  1390 
       
  1391     for (int i = 0; i < item_list.size(); ++i) {
       
  1392         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1393         if (item.skip() || (item.flags & QDockAreaLayoutItem::GapItem))
       
  1394             continue;
       
  1395 
       
  1396         if (item.pos + item.size > pos) {
       
  1397             if (item.subinfo != 0) {
       
  1398                 QList<int> result = item.subinfo->findSeparator(_pos);
       
  1399                 if (!result.isEmpty()) {
       
  1400                     result.prepend(i);
       
  1401                     return result;
       
  1402                 } else {
       
  1403                     return QList<int>();
       
  1404                 }
       
  1405             }
       
  1406         }
       
  1407 
       
  1408         int next = this->next(i);
       
  1409         if (next == -1 || (item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
       
  1410             continue;
       
  1411 
       
  1412         QRect sepRect = separatorRect(i);
       
  1413         if (!sepRect.isNull() && sep == 1)
       
  1414             sepRect.adjust(-2, -2, 2, 2);
       
  1415         //we also make sure we don't find a separator that's not there
       
  1416         if (sepRect.contains(_pos) && !item.hasFixedSize(o)) {
       
  1417             return QList<int>() << i;
       
  1418         }
       
  1419 
       
  1420     }
       
  1421 
       
  1422     return QList<int>();
       
  1423 }
       
  1424 
       
  1425 QList<int> QDockAreaLayoutInfo::indexOfPlaceHolder(const QString &objectName) const
       
  1426 {
       
  1427     for (int i = 0; i < item_list.size(); ++i) {
       
  1428         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1429 
       
  1430         if (item.subinfo != 0) {
       
  1431             QList<int> result = item.subinfo->indexOfPlaceHolder(objectName);
       
  1432             if (!result.isEmpty()) {
       
  1433                 result.prepend(i);
       
  1434                 return result;
       
  1435             }
       
  1436             continue;
       
  1437         }
       
  1438 
       
  1439         if (item.placeHolderItem != 0 && item.placeHolderItem->objectName == objectName) {
       
  1440             QList<int> result;
       
  1441             result << i;
       
  1442             return result;
       
  1443         }
       
  1444     }
       
  1445 
       
  1446     return QList<int>();
       
  1447 }
       
  1448 
       
  1449 QList<int> QDockAreaLayoutInfo::indexOf(QWidget *widget) const
       
  1450 {
       
  1451     for (int i = 0; i < item_list.size(); ++i) {
       
  1452         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1453 
       
  1454         if (item.placeHolderItem != 0)
       
  1455             continue;
       
  1456 
       
  1457         if (item.subinfo != 0) {
       
  1458             QList<int> result = item.subinfo->indexOf(widget);
       
  1459             if (!result.isEmpty()) {
       
  1460                 result.prepend(i);
       
  1461                 return result;
       
  1462             }
       
  1463             continue;
       
  1464         }
       
  1465 
       
  1466         if (!(item.flags & QDockAreaLayoutItem::GapItem) && item.widgetItem->widget() == widget) {
       
  1467             QList<int> result;
       
  1468             result << i;
       
  1469             return result;
       
  1470         }
       
  1471     }
       
  1472 
       
  1473     return QList<int>();
       
  1474 }
       
  1475 
       
  1476 QMainWindowLayout *QDockAreaLayoutInfo::mainWindowLayout() const
       
  1477 {
       
  1478     QMainWindowLayout *result = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
       
  1479     Q_ASSERT(result != 0);
       
  1480     return result;
       
  1481 }
       
  1482 
       
  1483 bool QDockAreaLayoutInfo::hasFixedSize() const
       
  1484 {
       
  1485     return perp(o, minimumSize()) == perp(o, maximumSize());
       
  1486 }
       
  1487 
       
  1488 
       
  1489 void QDockAreaLayoutInfo::apply(bool animate)
       
  1490 {
       
  1491     QWidgetAnimator &widgetAnimator = mainWindowLayout()->widgetAnimator;
       
  1492 
       
  1493 #ifndef QT_NO_TABBAR
       
  1494     if (tabbed) {
       
  1495         QRect tab_rect;
       
  1496         QSize tbh = tabBarSizeHint();
       
  1497 
       
  1498         if (tabBarVisible) {
       
  1499             switch (tabBarShape) {
       
  1500                 case QTabBar::RoundedNorth:
       
  1501                 case QTabBar::TriangularNorth:
       
  1502                     tab_rect = QRect(rect.left(), rect.top(), rect.width(), tbh.height());
       
  1503                     break;
       
  1504                 case QTabBar::RoundedSouth:
       
  1505                 case QTabBar::TriangularSouth:
       
  1506                     tab_rect = QRect(rect.left(), rect.bottom() - tbh.height() + 1,
       
  1507                                         rect.width(), tbh.height());
       
  1508                     break;
       
  1509                 case QTabBar::RoundedEast:
       
  1510                 case QTabBar::TriangularEast:
       
  1511                     tab_rect = QRect(rect.right() - tbh.width() + 1, rect.top(),
       
  1512                                         tbh.width(), rect.height());
       
  1513                     break;
       
  1514                 case QTabBar::RoundedWest:
       
  1515                 case QTabBar::TriangularWest:
       
  1516                     tab_rect = QRect(rect.left(), rect.top(),
       
  1517                                         tbh.width(), rect.height());
       
  1518                     break;
       
  1519                 default:
       
  1520                     break;
       
  1521             }
       
  1522         }
       
  1523 
       
  1524         widgetAnimator.animate(tabBar, tab_rect, animate);
       
  1525     }
       
  1526 #endif // QT_NO_TABBAR
       
  1527 
       
  1528     for (int i = 0; i < item_list.size(); ++i) {
       
  1529         QDockAreaLayoutItem &item = item_list[i];
       
  1530 
       
  1531         if (item.flags & QDockAreaLayoutItem::GapItem)
       
  1532             continue;
       
  1533 
       
  1534         if (item.subinfo != 0) {
       
  1535             item.subinfo->apply(animate);
       
  1536             continue;
       
  1537         }
       
  1538 
       
  1539         if (item.skip())
       
  1540             continue;
       
  1541 
       
  1542         Q_ASSERT(item.widgetItem);
       
  1543         QRect r = itemRect(i);
       
  1544         QWidget *w = item.widgetItem->widget();
       
  1545 
       
  1546         QRect geo = w->geometry();
       
  1547         widgetAnimator.animate(w, r, animate);
       
  1548         if (!w->isHidden() && w->window()->isVisible()) {
       
  1549             QDockWidget *dw = qobject_cast<QDockWidget*>(w);
       
  1550             if (!r.isValid() && geo.right() >= 0 && geo.bottom() >= 0) {
       
  1551                 dw->lower();
       
  1552                 emit dw->visibilityChanged(false);
       
  1553             } else if (r.isValid()
       
  1554                         && (geo.right() < 0 || geo.bottom() < 0)) {
       
  1555                 emit dw->visibilityChanged(true);
       
  1556             }
       
  1557         }
       
  1558     }
       
  1559 
       
  1560     if (sep == 1)
       
  1561         updateSeparatorWidgets();
       
  1562 }
       
  1563 
       
  1564 static void paintSep(QPainter *p, QWidget *w, const QRect &r, Qt::Orientation o, bool mouse_over)
       
  1565 {
       
  1566     QStyleOption opt(0);
       
  1567     opt.state = QStyle::State_None;
       
  1568     if (w->isEnabled())
       
  1569         opt.state |= QStyle::State_Enabled;
       
  1570     if (o != Qt::Horizontal)
       
  1571         opt.state |= QStyle::State_Horizontal;
       
  1572     if (mouse_over)
       
  1573         opt.state |= QStyle::State_MouseOver;
       
  1574     opt.rect = r;
       
  1575     opt.palette = w->palette();
       
  1576 
       
  1577     w->style()->drawPrimitive(QStyle::PE_IndicatorDockWidgetResizeHandle, &opt, p, w);
       
  1578 }
       
  1579 
       
  1580 QRegion QDockAreaLayoutInfo::separatorRegion() const
       
  1581 {
       
  1582     QRegion result;
       
  1583 
       
  1584     if (isEmpty())
       
  1585         return result;
       
  1586 #ifndef QT_NO_TABBAR
       
  1587     if (tabbed)
       
  1588         return result;
       
  1589 #endif
       
  1590 
       
  1591     for (int i = 0; i < item_list.count(); ++i) {
       
  1592         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1593 
       
  1594         if (item.skip())
       
  1595             continue;
       
  1596 
       
  1597         int next = this->next(i);
       
  1598 
       
  1599         if (item.subinfo)
       
  1600             result |= item.subinfo->separatorRegion();
       
  1601 
       
  1602         if (next == -1)
       
  1603             break;
       
  1604         result |= separatorRect(i);
       
  1605     }
       
  1606 
       
  1607     return result;
       
  1608 }
       
  1609 
       
  1610 void QDockAreaLayoutInfo::paintSeparators(QPainter *p, QWidget *widget,
       
  1611                                                     const QRegion &clip,
       
  1612                                                     const QPoint &mouse) const
       
  1613 {
       
  1614     if (isEmpty())
       
  1615         return;
       
  1616 #ifndef QT_NO_TABBAR
       
  1617     if (tabbed)
       
  1618         return;
       
  1619 #endif
       
  1620 
       
  1621     for (int i = 0; i < item_list.count(); ++i) {
       
  1622         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1623 
       
  1624         if (item.skip())
       
  1625             continue;
       
  1626 
       
  1627         int next = this->next(i);
       
  1628         if ((item.flags & QDockAreaLayoutItem::GapItem)
       
  1629                 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
       
  1630             continue;
       
  1631 
       
  1632         if (item.subinfo) {
       
  1633             if (clip.contains(item.subinfo->rect))
       
  1634                 item.subinfo->paintSeparators(p, widget, clip, mouse);
       
  1635         }
       
  1636 
       
  1637         if (next == -1)
       
  1638             break;
       
  1639         QRect r = separatorRect(i);
       
  1640         if (clip.contains(r) && !item.hasFixedSize(o))
       
  1641             paintSep(p, widget, r, o, r.contains(mouse));
       
  1642     }
       
  1643 }
       
  1644 
       
  1645 int QDockAreaLayoutInfo::next(int index) const
       
  1646 {
       
  1647     for (int i = index + 1; i < item_list.size(); ++i) {
       
  1648         if (!item_list.at(i).skip())
       
  1649             return i;
       
  1650     }
       
  1651     return -1;
       
  1652 }
       
  1653 
       
  1654 int QDockAreaLayoutInfo::prev(int index) const
       
  1655 {
       
  1656     for (int i = index - 1; i >= 0; --i) {
       
  1657         if (!item_list.at(i).skip())
       
  1658             return i;
       
  1659     }
       
  1660     return -1;
       
  1661 }
       
  1662 
       
  1663 void QDockAreaLayoutInfo::tab(int index, QLayoutItem *dockWidgetItem)
       
  1664 {
       
  1665 #ifdef QT_NO_TABBAR
       
  1666     Q_UNUSED(index);
       
  1667     Q_UNUSED(dockWidgetItem);
       
  1668 #else
       
  1669     if (tabbed) {
       
  1670         item_list.append(QDockAreaLayoutItem(dockWidgetItem));
       
  1671         updateTabBar();
       
  1672         setCurrentTab(dockWidgetItem->widget());
       
  1673     } else {
       
  1674         QDockAreaLayoutInfo *new_info
       
  1675             = new QDockAreaLayoutInfo(sep, dockPos, o, tabBarShape, mainWindow);
       
  1676         item_list[index].subinfo = new_info;
       
  1677         new_info->item_list.append(item_list.at(index).widgetItem);
       
  1678         item_list[index].widgetItem = 0;
       
  1679         new_info->item_list.append(dockWidgetItem);
       
  1680         new_info->tabbed = true;
       
  1681         new_info->updateTabBar();
       
  1682         new_info->setCurrentTab(dockWidgetItem->widget());
       
  1683     }
       
  1684 #endif // QT_NO_TABBAR
       
  1685 }
       
  1686 
       
  1687 void QDockAreaLayoutInfo::split(int index, Qt::Orientation orientation,
       
  1688                                        QLayoutItem *dockWidgetItem)
       
  1689 {
       
  1690     if (orientation == o) {
       
  1691         item_list.insert(index + 1, QDockAreaLayoutItem(dockWidgetItem));
       
  1692     } else {
       
  1693 #ifdef QT_NO_TABBAR
       
  1694         const int tabBarShape = 0;
       
  1695 #endif
       
  1696         QDockAreaLayoutInfo *new_info
       
  1697             = new QDockAreaLayoutInfo(sep, dockPos, orientation, tabBarShape, mainWindow);
       
  1698         item_list[index].subinfo = new_info;
       
  1699         new_info->item_list.append(item_list.at(index).widgetItem);
       
  1700         item_list[index].widgetItem = 0;
       
  1701         new_info->item_list.append(dockWidgetItem);
       
  1702     }
       
  1703 }
       
  1704 
       
  1705 QDockAreaLayoutItem &QDockAreaLayoutInfo::item(const QList<int> &path)
       
  1706 {
       
  1707     Q_ASSERT(!path.isEmpty());
       
  1708     const int index = path.first();
       
  1709     if (path.count() > 1) {
       
  1710         const QDockAreaLayoutItem &item = item_list[index];
       
  1711         Q_ASSERT(item.subinfo != 0);
       
  1712         return item.subinfo->item(path.mid(1));
       
  1713     }
       
  1714     return item_list[index];
       
  1715 }
       
  1716 
       
  1717 QLayoutItem *QDockAreaLayoutInfo::itemAt(int *x, int index) const
       
  1718 {
       
  1719     for (int i = 0; i < item_list.count(); ++i) {
       
  1720         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1721         if (item.placeHolderItem != 0)
       
  1722             continue;
       
  1723         if (item.subinfo) {
       
  1724             if (QLayoutItem *ret = item.subinfo->itemAt(x, index))
       
  1725                 return ret;
       
  1726         } else if (item.widgetItem) {
       
  1727             if ((*x)++ == index)
       
  1728                 return item.widgetItem;
       
  1729         }
       
  1730     }
       
  1731     return 0;
       
  1732 }
       
  1733 
       
  1734 QLayoutItem *QDockAreaLayoutInfo::takeAt(int *x, int index)
       
  1735 {
       
  1736     for (int i = 0; i < item_list.count(); ++i) {
       
  1737         QDockAreaLayoutItem &item = item_list[i];
       
  1738         if (item.placeHolderItem != 0)
       
  1739             continue;
       
  1740         else if (item.subinfo) {
       
  1741             if (QLayoutItem *ret = item.subinfo->takeAt(x, index)) {
       
  1742                 unnest(i);
       
  1743                 return ret;
       
  1744             }
       
  1745         } else if (item.widgetItem) {
       
  1746             if ((*x)++ == index) {
       
  1747                 item.placeHolderItem = new QPlaceHolderItem(item.widgetItem->widget());
       
  1748                 QLayoutItem *ret = item.widgetItem;
       
  1749                 item.widgetItem = 0;
       
  1750                 if (item.size != -1)
       
  1751                     item.flags |= QDockAreaLayoutItem::KeepSize;
       
  1752                 return ret;
       
  1753             }
       
  1754         }
       
  1755     }
       
  1756     return 0;
       
  1757 }
       
  1758 
       
  1759 void QDockAreaLayoutInfo::deleteAllLayoutItems()
       
  1760 {
       
  1761     for (int i = 0; i < item_list.count(); ++i) {
       
  1762         QDockAreaLayoutItem &item= item_list[i];
       
  1763         if (item.subinfo) {
       
  1764             item.subinfo->deleteAllLayoutItems();
       
  1765         } else {
       
  1766             delete item.widgetItem;
       
  1767             item.widgetItem = 0;
       
  1768         }
       
  1769     }
       
  1770 }
       
  1771 
       
  1772 void QDockAreaLayoutInfo::saveState(QDataStream &stream) const
       
  1773 {
       
  1774 #ifndef QT_NO_TABBAR
       
  1775     if (tabbed) {
       
  1776         stream << (uchar) TabMarker;
       
  1777 
       
  1778         // write the index in item_list of the widget that's currently on top.
       
  1779         quintptr id = currentTabId();
       
  1780         int index = -1;
       
  1781         for (int i = 0; i < item_list.count(); ++i) {
       
  1782             if (tabId(item_list.at(i)) == id) {
       
  1783                 index = i;
       
  1784                 break;
       
  1785             }
       
  1786         }
       
  1787         stream << index;
       
  1788     } else
       
  1789 #endif // QT_NO_TABBAR
       
  1790     {
       
  1791         stream << (uchar) SequenceMarker;
       
  1792     }
       
  1793 
       
  1794     stream << (uchar) o << item_list.count();
       
  1795 
       
  1796     for (int i = 0; i < item_list.count(); ++i) {
       
  1797         const QDockAreaLayoutItem &item = item_list.at(i);
       
  1798         if (item.widgetItem != 0) {
       
  1799             stream << (uchar) WidgetMarker;
       
  1800             QWidget *w = item.widgetItem->widget();
       
  1801             QString name = w->objectName();
       
  1802             if (name.isEmpty()) {
       
  1803                 qWarning("QMainWindow::saveState(): 'objectName' not set for QDockWidget %p '%s;",
       
  1804                          w, qPrintable(w->windowTitle()));
       
  1805             }
       
  1806             stream << name;
       
  1807 
       
  1808             uchar flags = 0;
       
  1809             if (!w->isHidden())
       
  1810                 flags |= StateFlagVisible;
       
  1811             if (w->isWindow())
       
  1812                 flags |= StateFlagFloating;
       
  1813             stream << flags;
       
  1814 
       
  1815             if (w->isWindow()) {
       
  1816                 stream << w->x() << w->y() << w->width() << w->height();
       
  1817             } else {
       
  1818                 stream << item.pos << item.size << pick(o, item.minimumSize())
       
  1819                         << pick(o, item.maximumSize());
       
  1820             }
       
  1821         } else if (item.placeHolderItem != 0) {
       
  1822             stream << (uchar) WidgetMarker;
       
  1823             stream << item.placeHolderItem->objectName;
       
  1824             uchar flags = 0;
       
  1825             if (!item.placeHolderItem->hidden)
       
  1826                 flags |= StateFlagVisible;
       
  1827             if (item.placeHolderItem->window)
       
  1828                 flags |= StateFlagFloating;
       
  1829             stream << flags;
       
  1830             if (item.placeHolderItem->window) {
       
  1831                 QRect r = item.placeHolderItem->topLevelRect;
       
  1832                 stream << r.x() << r.y() << r.width() << r.height();
       
  1833             } else {
       
  1834                 stream << item.pos << item.size << (int)0 << (int)0;
       
  1835             }
       
  1836         } else if (item.subinfo != 0) {
       
  1837             stream << (uchar) SequenceMarker << item.pos << item.size << pick(o, item.minimumSize()) << pick(o, item.maximumSize());
       
  1838             item.subinfo->saveState(stream);
       
  1839         }
       
  1840     }
       
  1841 }
       
  1842 
       
  1843 #ifdef Q_WS_MAC
       
  1844 static Qt::DockWidgetArea toDockWidgetArea(QInternal::DockPosition pos)
       
  1845 {
       
  1846     switch (pos) {
       
  1847         case QInternal::LeftDock:   return Qt::LeftDockWidgetArea;
       
  1848         case QInternal::RightDock:  return Qt::RightDockWidgetArea;
       
  1849         case QInternal::TopDock:    return Qt::TopDockWidgetArea;
       
  1850         case QInternal::BottomDock: return Qt::BottomDockWidgetArea;
       
  1851         default: break;
       
  1852     }
       
  1853     return Qt::NoDockWidgetArea;
       
  1854 }
       
  1855 #endif
       
  1856 
       
  1857 static QRect constrainedRect(QRect rect, const QRect &desktop)
       
  1858 {
       
  1859     if (desktop.isValid()) {
       
  1860         rect.setWidth(qMin(rect.width(), desktop.width()));
       
  1861         rect.setHeight(qMin(rect.height(), desktop.height()));
       
  1862         rect.moveLeft(qMax(rect.left(), desktop.left()));
       
  1863         rect.moveTop(qMax(rect.top(), desktop.top()));
       
  1864         rect.moveRight(qMin(rect.right(), desktop.right()));
       
  1865         rect.moveBottom(qMin(rect.bottom(), desktop.bottom()));
       
  1866     }
       
  1867 
       
  1868     return rect;
       
  1869 }
       
  1870 
       
  1871 bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> &widgets, bool testing)
       
  1872 {
       
  1873     uchar marker;
       
  1874     stream >> marker;
       
  1875     if (marker != TabMarker && marker != SequenceMarker)
       
  1876         return false;
       
  1877 
       
  1878 #ifndef QT_NO_TABBAR
       
  1879     tabbed = marker == TabMarker;
       
  1880 
       
  1881     int index = -1;
       
  1882     if (tabbed)
       
  1883         stream >> index;
       
  1884 #endif
       
  1885 
       
  1886     uchar orientation;
       
  1887     stream >> orientation;
       
  1888     o = static_cast<Qt::Orientation>(orientation);
       
  1889 
       
  1890     int cnt;
       
  1891     stream >> cnt;
       
  1892 
       
  1893     for (int i = 0; i < cnt; ++i) {
       
  1894         uchar nextMarker;
       
  1895         stream >> nextMarker;
       
  1896         if (nextMarker == WidgetMarker) {
       
  1897             QString name;
       
  1898             uchar flags;
       
  1899             stream >> name >> flags;
       
  1900             if (name.isEmpty()) {
       
  1901                 int dummy;
       
  1902                 stream >> dummy >> dummy >> dummy >> dummy;
       
  1903                 continue;
       
  1904             }
       
  1905 
       
  1906             QDockWidget *widget = 0;
       
  1907             for (int j = 0; j < widgets.count(); ++j) {
       
  1908                 if (widgets.at(j)->objectName() == name) {
       
  1909                     widget = widgets.takeAt(j);
       
  1910                     break;
       
  1911                 }
       
  1912             }
       
  1913 
       
  1914             if (widget == 0) {
       
  1915                 QPlaceHolderItem *placeHolder = new QPlaceHolderItem;
       
  1916                 QDockAreaLayoutItem item(placeHolder);
       
  1917 
       
  1918                 placeHolder->objectName = name;
       
  1919                 placeHolder->window = flags & StateFlagFloating;
       
  1920                 placeHolder->hidden = !(flags & StateFlagVisible);
       
  1921                 if (placeHolder->window) {
       
  1922                     int x, y, w, h;
       
  1923                     stream >> x >> y >> w >> h;
       
  1924                     placeHolder->topLevelRect = QRect(x, y, w, h);
       
  1925                 } else {
       
  1926                     int dummy;
       
  1927                     stream >> item.pos >> item.size >> dummy >> dummy;
       
  1928                 }
       
  1929                 if (item.size != -1)
       
  1930                     item.flags |= QDockAreaLayoutItem::KeepSize;
       
  1931                 if (!testing)
       
  1932                     item_list.append(item);
       
  1933             } else {
       
  1934                 QDockAreaLayoutItem item(new QDockWidgetItem(widget));
       
  1935                 if (flags & StateFlagFloating) {
       
  1936                	    bool drawer = false;
       
  1937 #ifdef Q_WS_MAC // drawer support
       
  1938                	    extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
       
  1939                     extern bool qt_mac_set_drawer_preferred_edge(QWidget *, Qt::DockWidgetArea); //qwidget_mac.cpp
       
  1940                     drawer = qt_mac_is_macdrawer(widget);
       
  1941 #endif
       
  1942 
       
  1943                     if (!testing) {
       
  1944                         widget->hide();
       
  1945                         if (!drawer)
       
  1946                             widget->setFloating(true);
       
  1947                     }
       
  1948 
       
  1949                     int x, y, w, h;
       
  1950                     stream >> x >> y >> w >> h;
       
  1951 
       
  1952 #ifdef Q_WS_MAC // drawer support
       
  1953                     if (drawer) {
       
  1954                         mainWindow->window()->createWinId();
       
  1955                         widget->window()->createWinId();
       
  1956                         qt_mac_set_drawer_preferred_edge(widget, toDockWidgetArea(dockPos));
       
  1957                     } else
       
  1958 #endif
       
  1959                     if (!testing) {
       
  1960                         QRect r(x, y, w, h);
       
  1961                         QDesktopWidget *desktop = QApplication::desktop();
       
  1962                         if (desktop->isVirtualDesktop())
       
  1963                             r = constrainedRect(r, desktop->screenGeometry(desktop->screenNumber(r.topLeft())));
       
  1964                         else
       
  1965                             r = constrainedRect(r, desktop->screenGeometry(widget));
       
  1966                         widget->move(r.topLeft());
       
  1967                         widget->resize(r.size());
       
  1968                     }
       
  1969 
       
  1970                     if (!testing) {
       
  1971                         widget->setVisible(flags & StateFlagVisible);
       
  1972                     }
       
  1973                 } else {
       
  1974                     int dummy;
       
  1975                     stream >> item.pos >> item.size >> dummy >> dummy;
       
  1976                     if (!testing) {
       
  1977                         widget->setFloating(false);
       
  1978                         widget->setVisible(flags & StateFlagVisible);
       
  1979                     }
       
  1980                 }
       
  1981 
       
  1982                 if (!testing) {
       
  1983                     item_list.append(item);
       
  1984                 }
       
  1985             }
       
  1986         } else if (nextMarker == SequenceMarker) {
       
  1987             int dummy;
       
  1988 #ifdef QT_NO_TABBAR
       
  1989             const int tabBarShape = 0;
       
  1990 #endif
       
  1991             QDockAreaLayoutInfo *info = new QDockAreaLayoutInfo(sep, dockPos, o,
       
  1992                                                                 tabBarShape, mainWindow);
       
  1993             QDockAreaLayoutItem item(info);
       
  1994             stream >> item.pos >> item.size >> dummy >> dummy;
       
  1995             if (!info->restoreState(stream, widgets, testing))
       
  1996                 return false;
       
  1997 
       
  1998             if (!testing) {
       
  1999                 item_list.append(item);
       
  2000             }
       
  2001         } else {
       
  2002             return false;
       
  2003         }
       
  2004     }
       
  2005 
       
  2006 #ifndef QT_NO_TABBAR
       
  2007     if (!testing && tabbed && index >= 0 && index < item_list.count()) {
       
  2008         updateTabBar();
       
  2009         setCurrentTabId(tabId(item_list.at(index)));
       
  2010     }
       
  2011 #endif
       
  2012     if (!testing && sep == 1)
       
  2013         updateSeparatorWidgets();
       
  2014 
       
  2015     return true;
       
  2016 }
       
  2017 
       
  2018 void QDockAreaLayoutInfo::updateSeparatorWidgets() const
       
  2019 {
       
  2020     if (tabbed) {
       
  2021         separatorWidgets.clear();
       
  2022         return;
       
  2023     }
       
  2024 
       
  2025     int j = 0;
       
  2026     for (int i = 0; i < item_list.count(); ++i) {
       
  2027         const QDockAreaLayoutItem &item = item_list.at(i);
       
  2028 
       
  2029         if (item.skip())
       
  2030             continue;
       
  2031 
       
  2032         int next = this->next(i);
       
  2033         if ((item.flags & QDockAreaLayoutItem::GapItem)
       
  2034                 || (next != -1 && (item_list.at(next).flags & QDockAreaLayoutItem::GapItem)))
       
  2035             continue;
       
  2036 
       
  2037         if (item.subinfo) {
       
  2038             item.subinfo->updateSeparatorWidgets();
       
  2039         }
       
  2040 
       
  2041         if (next == -1)
       
  2042             break;
       
  2043 
       
  2044         QWidget *sepWidget;
       
  2045         if (j < separatorWidgets.size() && separatorWidgets.at(j)) {
       
  2046             sepWidget = separatorWidgets.at(j);
       
  2047         } else {
       
  2048             sepWidget = mainWindowLayout()->getSeparatorWidget();
       
  2049             separatorWidgets.append(sepWidget);
       
  2050         }
       
  2051         j++;
       
  2052 
       
  2053 #ifndef QT_MAC_USE_COCOA
       
  2054         sepWidget->raise();
       
  2055 #endif
       
  2056         QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
       
  2057         sepWidget->setGeometry(sepRect);
       
  2058         sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
       
  2059         sepWidget->show();
       
  2060     }
       
  2061 
       
  2062     for (int k = j; k < separatorWidgets.size(); ++k) {
       
  2063         separatorWidgets[k]->hide();
       
  2064     }
       
  2065     separatorWidgets.resize(j);
       
  2066     Q_ASSERT(separatorWidgets.size() == j);
       
  2067 }
       
  2068 
       
  2069 #ifndef QT_NO_TABBAR
       
  2070 void QDockAreaLayoutInfo::updateTabBar() const
       
  2071 {
       
  2072     if (!tabbed)
       
  2073         return;
       
  2074 
       
  2075     QDockAreaLayoutInfo *that = const_cast<QDockAreaLayoutInfo*>(this);
       
  2076 
       
  2077     if (that->tabBar == 0) {
       
  2078         that->tabBar = mainWindowLayout()->getTabBar();
       
  2079         that->tabBar->setShape(static_cast<QTabBar::Shape>(tabBarShape));
       
  2080         that->tabBar->setDrawBase(true);
       
  2081     }
       
  2082 
       
  2083     bool blocked = tabBar->blockSignals(true);
       
  2084     bool gap = false;
       
  2085 
       
  2086     int tab_idx = 0;
       
  2087     bool changed = false;
       
  2088     for (int i = 0; i < item_list.count(); ++i) {
       
  2089         const QDockAreaLayoutItem &item = item_list.at(i);
       
  2090         if (item.skip())
       
  2091             continue;
       
  2092         if (item.flags & QDockAreaLayoutItem::GapItem) {
       
  2093             gap = true;
       
  2094             continue;
       
  2095         }
       
  2096         if (item.widgetItem == 0)
       
  2097             continue;
       
  2098 
       
  2099         QDockWidget *dw = qobject_cast<QDockWidget*>(item.widgetItem->widget());
       
  2100         QString title = dw->d_func()->fixedWindowTitle;
       
  2101         quintptr id = tabId(item);
       
  2102         if (tab_idx == tabBar->count()) {
       
  2103             tabBar->insertTab(tab_idx, title);
       
  2104 #ifndef QT_NO_TOOLTIP
       
  2105             tabBar->setTabToolTip(tab_idx, title);
       
  2106 #endif
       
  2107             tabBar->setTabData(tab_idx, id);
       
  2108             changed = true;
       
  2109         } else if (qvariant_cast<quintptr>(tabBar->tabData(tab_idx)) != id) {
       
  2110             if (tab_idx + 1 < tabBar->count()
       
  2111                     && qvariant_cast<quintptr>(tabBar->tabData(tab_idx + 1)) == id)
       
  2112                 tabBar->removeTab(tab_idx);
       
  2113             else {
       
  2114                 tabBar->insertTab(tab_idx, title);
       
  2115 #ifndef QT_NO_TOOLTIP
       
  2116                 tabBar->setTabToolTip(tab_idx, title);
       
  2117 #endif
       
  2118                 tabBar->setTabData(tab_idx, id);
       
  2119             }
       
  2120             changed = true;
       
  2121         }
       
  2122 
       
  2123         if (title != tabBar->tabText(tab_idx)) {
       
  2124             tabBar->setTabText(tab_idx, title);
       
  2125 #ifndef QT_NO_TOOLTIP
       
  2126             tabBar->setTabToolTip(tab_idx, title);
       
  2127 #endif
       
  2128             changed = true;
       
  2129         }
       
  2130 
       
  2131         ++tab_idx;
       
  2132     }
       
  2133 
       
  2134     while (tab_idx < tabBar->count()) {
       
  2135         tabBar->removeTab(tab_idx);
       
  2136         changed = true;
       
  2137     }
       
  2138 
       
  2139     tabBar->blockSignals(blocked);
       
  2140 
       
  2141     that->tabBarVisible = ( (gap ? 1 : 0) + tabBar->count()) > 1;
       
  2142 
       
  2143     if (changed || !tabBarMin.isValid() | !tabBarHint.isValid()) {
       
  2144         that->tabBarMin = tabBar->minimumSizeHint();
       
  2145         that->tabBarHint = tabBar->sizeHint();
       
  2146     }
       
  2147 }
       
  2148 
       
  2149 void QDockAreaLayoutInfo::setTabBarShape(int shape)
       
  2150 {
       
  2151     if (shape == tabBarShape)
       
  2152         return;
       
  2153     tabBarShape = shape;
       
  2154     if (tabBar != 0) {
       
  2155         tabBar->setShape(static_cast<QTabBar::Shape>(shape));
       
  2156         tabBarMin = QSize();
       
  2157         tabBarHint = QSize();
       
  2158     }
       
  2159 
       
  2160     for (int i = 0; i < item_list.count(); ++i) {
       
  2161         QDockAreaLayoutItem &item = item_list[i];
       
  2162         if (item.subinfo != 0)
       
  2163             item.subinfo->setTabBarShape(shape);
       
  2164     }
       
  2165 }
       
  2166 
       
  2167 QSize QDockAreaLayoutInfo::tabBarMinimumSize() const
       
  2168 {
       
  2169     if (!tabbed)
       
  2170         return QSize(0, 0);
       
  2171 
       
  2172     updateTabBar();
       
  2173 
       
  2174     return tabBarMin;
       
  2175 }
       
  2176 
       
  2177 QSize QDockAreaLayoutInfo::tabBarSizeHint() const
       
  2178 {
       
  2179     if (!tabbed)
       
  2180         return QSize(0, 0);
       
  2181 
       
  2182     updateTabBar();
       
  2183 
       
  2184     return tabBarHint;
       
  2185 }
       
  2186 
       
  2187 QSet<QTabBar*> QDockAreaLayoutInfo::usedTabBars() const
       
  2188 {
       
  2189     QSet<QTabBar*> result;
       
  2190 
       
  2191     if (tabbed) {
       
  2192         updateTabBar();
       
  2193         result.insert(tabBar);
       
  2194     }
       
  2195 
       
  2196     for (int i = 0; i < item_list.count(); ++i) {
       
  2197         const QDockAreaLayoutItem &item = item_list.at(i);
       
  2198         if (item.subinfo != 0)
       
  2199             result += item.subinfo->usedTabBars();
       
  2200     }
       
  2201 
       
  2202     return result;
       
  2203 }
       
  2204 
       
  2205 // returns a set of all used separator widgets for this dockarelayout info
       
  2206 // and all subinfos
       
  2207 QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets() const
       
  2208 {
       
  2209     QSet<QWidget*> result;
       
  2210 
       
  2211     for (int i = 0; i < separatorWidgets.count(); ++i)
       
  2212         result << separatorWidgets.at(i);
       
  2213 
       
  2214     for (int i = 0; i < item_list.count(); ++i) {
       
  2215         const QDockAreaLayoutItem &item = item_list.at(i);
       
  2216         if (item.subinfo != 0)
       
  2217             result += item.subinfo->usedSeparatorWidgets();
       
  2218     }
       
  2219 
       
  2220     return result;
       
  2221 }
       
  2222 
       
  2223 QRect QDockAreaLayoutInfo::tabContentRect() const
       
  2224 {
       
  2225     if (!tabbed)
       
  2226         return QRect();
       
  2227 
       
  2228     QRect result = rect;
       
  2229     QSize tbh = tabBarSizeHint();
       
  2230 
       
  2231     if (tabBarVisible) {
       
  2232         switch (tabBarShape) {
       
  2233             case QTabBar::RoundedNorth:
       
  2234             case QTabBar::TriangularNorth:
       
  2235                 result.adjust(0, tbh.height(), 0, 0);
       
  2236                 break;
       
  2237             case QTabBar::RoundedSouth:
       
  2238             case QTabBar::TriangularSouth:
       
  2239                 result.adjust(0, 0, 0, -tbh.height());
       
  2240                 break;
       
  2241             case QTabBar::RoundedEast:
       
  2242             case QTabBar::TriangularEast:
       
  2243                 result.adjust(0, 0, -tbh.width(), 0);
       
  2244                 break;
       
  2245             case QTabBar::RoundedWest:
       
  2246             case QTabBar::TriangularWest:
       
  2247                 result.adjust(tbh.width(), 0, 0, 0);
       
  2248                 break;
       
  2249             default:
       
  2250                 break;
       
  2251         }
       
  2252     }
       
  2253 
       
  2254     return result;
       
  2255 }
       
  2256 #endif // QT_NO_TABBAR
       
  2257 
       
  2258 /******************************************************************************
       
  2259 ** QDockAreaLayout
       
  2260 */
       
  2261 
       
  2262 QDockAreaLayout::QDockAreaLayout(QMainWindow *win)
       
  2263 {
       
  2264     mainWindow = win;
       
  2265     sep = win->style()->pixelMetric(QStyle::PM_DockWidgetSeparatorExtent, 0, win);
       
  2266 #ifndef QT_NO_TABBAR
       
  2267     const int tabShape = QTabBar::RoundedSouth;
       
  2268 #else
       
  2269     const int tabShape = 0;
       
  2270 #endif
       
  2271     docks[QInternal::LeftDock]
       
  2272         = QDockAreaLayoutInfo(sep, QInternal::LeftDock, Qt::Vertical, tabShape, win);
       
  2273     docks[QInternal::RightDock]
       
  2274         = QDockAreaLayoutInfo(sep, QInternal::RightDock, Qt::Vertical, tabShape, win);
       
  2275     docks[QInternal::TopDock]
       
  2276         = QDockAreaLayoutInfo(sep, QInternal::TopDock, Qt::Horizontal, tabShape, win);
       
  2277     docks[QInternal::BottomDock]
       
  2278         = QDockAreaLayoutInfo(sep, QInternal::BottomDock, Qt::Horizontal, tabShape, win);
       
  2279     centralWidgetItem = 0;
       
  2280 
       
  2281 
       
  2282     corners[Qt::TopLeftCorner] = Qt::TopDockWidgetArea;
       
  2283     corners[Qt::TopRightCorner] = Qt::TopDockWidgetArea;
       
  2284     corners[Qt::BottomLeftCorner] = Qt::BottomDockWidgetArea;
       
  2285     corners[Qt::BottomRightCorner] = Qt::BottomDockWidgetArea;
       
  2286 }
       
  2287 
       
  2288 bool QDockAreaLayout::isValid() const
       
  2289 {
       
  2290     return rect.isValid();
       
  2291 }
       
  2292 
       
  2293 void QDockAreaLayout::saveState(QDataStream &stream) const
       
  2294 {
       
  2295     stream << (uchar) DockWidgetStateMarker;
       
  2296     int cnt = 0;
       
  2297     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2298         if (!docks[i].item_list.isEmpty())
       
  2299             ++cnt;
       
  2300     }
       
  2301     stream << cnt;
       
  2302     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2303         if (docks[i].item_list.isEmpty())
       
  2304             continue;
       
  2305         stream << i << docks[i].rect.size();
       
  2306         docks[i].saveState(stream);
       
  2307     }
       
  2308 
       
  2309     stream << centralWidgetRect.size();
       
  2310 
       
  2311     for (int i = 0; i < 4; ++i)
       
  2312         stream << static_cast<int>(corners[i]);
       
  2313 }
       
  2314 
       
  2315 bool QDockAreaLayout::restoreState(QDataStream &stream, const QList<QDockWidget*> &_dockwidgets, bool testing)
       
  2316 {
       
  2317     QList<QDockWidget*> dockwidgets = _dockwidgets;
       
  2318 
       
  2319     int cnt;
       
  2320     stream >> cnt;
       
  2321     for (int i = 0; i < cnt; ++i) {
       
  2322         int pos;
       
  2323         stream >> pos;
       
  2324         QSize size;
       
  2325         stream >> size;
       
  2326         if (!testing) {
       
  2327             docks[pos].rect = QRect(QPoint(0, 0), size);
       
  2328         }
       
  2329         if (!docks[pos].restoreState(stream, dockwidgets, testing)) {
       
  2330             stream.setStatus(QDataStream::ReadCorruptData);
       
  2331             return false;
       
  2332         }
       
  2333     }
       
  2334 
       
  2335     QSize size;
       
  2336     stream >> size;
       
  2337     centralWidgetRect = QRect(QPoint(0, 0), size);
       
  2338 
       
  2339     bool ok = stream.status() == QDataStream::Ok;
       
  2340 
       
  2341     if (ok) {
       
  2342         int cornerData[4];
       
  2343         for (int i = 0; i < 4; ++i)
       
  2344             stream >> cornerData[i];
       
  2345         if (stream.status() == QDataStream::Ok) {
       
  2346             for (int i = 0; i < 4; ++i)
       
  2347                 corners[i] = static_cast<Qt::DockWidgetArea>(cornerData[i]);
       
  2348         }
       
  2349     }
       
  2350 
       
  2351     return ok;
       
  2352 }
       
  2353 
       
  2354 QList<int> QDockAreaLayout::indexOfPlaceHolder(const QString &objectName) const
       
  2355 {
       
  2356     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2357         QList<int> result = docks[i].indexOfPlaceHolder(objectName);
       
  2358         if (!result.isEmpty()) {
       
  2359             result.prepend(i);
       
  2360             return result;
       
  2361         }
       
  2362     }
       
  2363     return QList<int>();
       
  2364 }
       
  2365 
       
  2366 QList<int> QDockAreaLayout::indexOf(QWidget *dockWidget) const
       
  2367 {
       
  2368     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2369         QList<int> result = docks[i].indexOf(dockWidget);
       
  2370         if (!result.isEmpty()) {
       
  2371             result.prepend(i);
       
  2372             return result;
       
  2373         }
       
  2374     }
       
  2375     return QList<int>();
       
  2376 }
       
  2377 
       
  2378 QList<int> QDockAreaLayout::gapIndex(const QPoint &pos) const
       
  2379 {
       
  2380     QMainWindow::DockOptions opts = mainWindow->dockOptions();
       
  2381     bool nestingEnabled = opts & QMainWindow::AllowNestedDocks;
       
  2382     QDockAreaLayoutInfo::TabMode tabMode = QDockAreaLayoutInfo::NoTabs;
       
  2383 #ifndef QT_NO_TABBAR
       
  2384     if (opts & QMainWindow::AllowTabbedDocks
       
  2385         || opts & QMainWindow::VerticalTabs)
       
  2386         tabMode = QDockAreaLayoutInfo::AllowTabs;
       
  2387     if (opts & QMainWindow::ForceTabbedDocks)
       
  2388         tabMode = QDockAreaLayoutInfo::ForceTabs;
       
  2389 
       
  2390     if (tabMode == QDockAreaLayoutInfo::ForceTabs)
       
  2391         nestingEnabled = false;
       
  2392 #endif
       
  2393 
       
  2394 
       
  2395     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2396         const QDockAreaLayoutInfo &info = docks[i];
       
  2397 
       
  2398         if (!info.isEmpty() && info.rect.contains(pos)) {
       
  2399             QList<int> result
       
  2400                 = docks[i].gapIndex(pos, nestingEnabled, tabMode);
       
  2401             if (!result.isEmpty())
       
  2402                 result.prepend(i);
       
  2403             return result;
       
  2404         }
       
  2405     }
       
  2406 
       
  2407     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2408         const QDockAreaLayoutInfo &info = docks[i];
       
  2409 
       
  2410         if (info.isEmpty()) {
       
  2411             QRect r;
       
  2412             switch (i) {
       
  2413                 case QInternal::LeftDock:
       
  2414                     r = QRect(rect.left(), rect.top(), EmptyDropAreaSize, rect.height());
       
  2415                     break;
       
  2416                 case QInternal::RightDock:
       
  2417                     r = QRect(rect.right() - EmptyDropAreaSize, rect.top(),
       
  2418                                 EmptyDropAreaSize, rect.height());
       
  2419                     break;
       
  2420                 case QInternal::TopDock:
       
  2421                     r = QRect(rect.left(), rect.top(), rect.width(), EmptyDropAreaSize);
       
  2422                     break;
       
  2423                 case QInternal::BottomDock:
       
  2424                     r = QRect(rect.left(), rect.bottom() - EmptyDropAreaSize,
       
  2425                                 rect.width(), EmptyDropAreaSize);
       
  2426                     break;
       
  2427             }
       
  2428             if (r.contains(pos)) {
       
  2429                 if (opts & QMainWindow::ForceTabbedDocks && !info.item_list.isEmpty()) {
       
  2430                     //in case of ForceTabbedDocks, we pass -1 in order to force the gap to be tabbed
       
  2431                     //it mustn't be completely empty otherwise it won't work
       
  2432                     return QList<int>() << i << -1 << 0;
       
  2433                 } else {
       
  2434                     return QList<int>() << i << 0;
       
  2435                 }
       
  2436             }
       
  2437         }
       
  2438     }
       
  2439 
       
  2440     return QList<int>();
       
  2441 }
       
  2442 
       
  2443 QList<int> QDockAreaLayout::findSeparator(const QPoint &pos) const
       
  2444 {
       
  2445     QList<int> result;
       
  2446     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2447         const QDockAreaLayoutInfo &info = docks[i];
       
  2448         if (info.isEmpty())
       
  2449             continue;
       
  2450         QRect rect = separatorRect(i);
       
  2451         if (!rect.isNull() && sep == 1)
       
  2452             rect.adjust(-2, -2, 2, 2);
       
  2453         if (rect.contains(pos) && !info.hasFixedSize()) {
       
  2454             result << i;
       
  2455             break;
       
  2456         } else if (info.rect.contains(pos)) {
       
  2457             result = docks[i].findSeparator(pos);
       
  2458             if (!result.isEmpty()) {
       
  2459                 result.prepend(i);
       
  2460                 break;
       
  2461             }
       
  2462         }
       
  2463     }
       
  2464 
       
  2465     return result;
       
  2466 }
       
  2467 
       
  2468 QDockAreaLayoutInfo *QDockAreaLayout::info(QWidget *widget)
       
  2469 {
       
  2470     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  2471         if (QDockAreaLayoutInfo *result = docks[i].info(widget))
       
  2472             return result;
       
  2473     }
       
  2474 
       
  2475     return 0;
       
  2476 }
       
  2477 
       
  2478 QDockAreaLayoutInfo *QDockAreaLayout::info(const QList<int> &path)
       
  2479 {
       
  2480     Q_ASSERT(!path.isEmpty());
       
  2481     const int index = path.first();
       
  2482     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2483 
       
  2484     if (path.count() == 1)
       
  2485         return &docks[index];
       
  2486 
       
  2487     return docks[index].info(path.mid(1));
       
  2488 }
       
  2489 
       
  2490 const QDockAreaLayoutInfo *QDockAreaLayout::info(const QList<int> &path) const
       
  2491 {
       
  2492     return const_cast<QDockAreaLayout*>(this)->info(path);
       
  2493 }
       
  2494 
       
  2495 QDockAreaLayoutItem &QDockAreaLayout::item(const QList<int> &path)
       
  2496 {
       
  2497     Q_ASSERT(!path.isEmpty());
       
  2498     const int index = path.first();
       
  2499     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2500     return docks[index].item(path.mid(1));
       
  2501 }
       
  2502 
       
  2503 QRect QDockAreaLayout::itemRect(const QList<int> &path) const
       
  2504 {
       
  2505     Q_ASSERT(!path.isEmpty());
       
  2506     const int index = path.first();
       
  2507     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2508     return docks[index].itemRect(path.mid(1));
       
  2509 }
       
  2510 
       
  2511 QRect QDockAreaLayout::separatorRect(int index) const
       
  2512 {
       
  2513     const QDockAreaLayoutInfo &dock = docks[index];
       
  2514     if (dock.isEmpty())
       
  2515         return QRect();
       
  2516     QRect r = dock.rect;
       
  2517     switch (index) {
       
  2518         case QInternal::LeftDock:
       
  2519             return QRect(r.right() + 1, r.top(), sep, r.height());
       
  2520         case QInternal::RightDock:
       
  2521             return QRect(r.left() - sep, r.top(), sep, r.height());
       
  2522         case QInternal::TopDock:
       
  2523             return QRect(r.left(), r.bottom() + 1, r.width(), sep);
       
  2524         case QInternal::BottomDock:
       
  2525             return QRect(r.left(), r.top() - sep, r.width(), sep);
       
  2526         default:
       
  2527             break;
       
  2528     }
       
  2529     return QRect();
       
  2530 }
       
  2531 
       
  2532 QRect QDockAreaLayout::separatorRect(const QList<int> &path) const
       
  2533 {
       
  2534     Q_ASSERT(!path.isEmpty());
       
  2535 
       
  2536     const int index = path.first();
       
  2537     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2538 
       
  2539     if (path.count() == 1)
       
  2540         return separatorRect(index);
       
  2541     else
       
  2542         return docks[index].separatorRect(path.mid(1));
       
  2543 }
       
  2544 
       
  2545 bool QDockAreaLayout::insertGap(const QList<int> &path, QLayoutItem *dockWidgetItem)
       
  2546 {
       
  2547     Q_ASSERT(!path.isEmpty());
       
  2548     const int index = path.first();
       
  2549     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2550     return docks[index].insertGap(path.mid(1), dockWidgetItem);
       
  2551 }
       
  2552 
       
  2553 QLayoutItem *QDockAreaLayout::plug(const QList<int> &path)
       
  2554 {
       
  2555     Q_ASSERT(!path.isEmpty());
       
  2556     const int index = path.first();
       
  2557     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2558     return docks[index].plug(path.mid(1));
       
  2559 }
       
  2560 
       
  2561 QLayoutItem *QDockAreaLayout::unplug(const QList<int> &path)
       
  2562 {
       
  2563     Q_ASSERT(!path.isEmpty());
       
  2564     const int index = path.first();
       
  2565     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2566     return docks[index].unplug(path.mid(1));
       
  2567 }
       
  2568 
       
  2569 void QDockAreaLayout::remove(const QList<int> &path)
       
  2570 {
       
  2571     Q_ASSERT(!path.isEmpty());
       
  2572     const int index = path.first();
       
  2573     Q_ASSERT(index >= 0 && index < QInternal::DockCount);
       
  2574     docks[index].remove(path.mid(1));
       
  2575 }
       
  2576 
       
  2577 static inline int qMin(int i1, int i2, int i3) { return qMin(i1, qMin(i2, i3)); }
       
  2578 static inline int qMax(int i1, int i2, int i3) { return qMax(i1, qMax(i2, i3)); }
       
  2579 
       
  2580 void QDockAreaLayout::getGrid(QVector<QLayoutStruct> *_ver_struct_list,
       
  2581                                 QVector<QLayoutStruct> *_hor_struct_list)
       
  2582 {
       
  2583     QSize center_hint(0, 0);
       
  2584     QSize center_min(0, 0);
       
  2585     bool have_central = centralWidgetItem != 0 && !centralWidgetItem->isEmpty();
       
  2586     if (have_central) {
       
  2587         center_hint = centralWidgetRect.size();
       
  2588         if (!center_hint.isValid())
       
  2589             center_hint = centralWidgetItem->sizeHint();
       
  2590         center_min = centralWidgetItem->minimumSize();
       
  2591     }
       
  2592 
       
  2593     QRect center_rect = rect;
       
  2594     if (!docks[QInternal::LeftDock].isEmpty())
       
  2595         center_rect.setLeft(rect.left() + docks[QInternal::LeftDock].rect.width() + sep);
       
  2596     if (!docks[QInternal::TopDock].isEmpty())
       
  2597         center_rect.setTop(rect.top() + docks[QInternal::TopDock].rect.height() + sep);
       
  2598     if (!docks[QInternal::RightDock].isEmpty())
       
  2599         center_rect.setRight(rect.right() - docks[QInternal::RightDock].rect.width() - sep);
       
  2600     if (!docks[QInternal::BottomDock].isEmpty())
       
  2601         center_rect.setBottom(rect.bottom() - docks[QInternal::BottomDock].rect.height() - sep);
       
  2602 
       
  2603     QSize left_hint = docks[QInternal::LeftDock].size();
       
  2604     if (left_hint.isNull())
       
  2605         left_hint = docks[QInternal::LeftDock].sizeHint();
       
  2606     QSize left_min = docks[QInternal::LeftDock].minimumSize();
       
  2607     QSize left_max = docks[QInternal::LeftDock].maximumSize();
       
  2608     left_hint = left_hint.boundedTo(left_max).expandedTo(left_min);
       
  2609 
       
  2610     QSize right_hint = docks[QInternal::RightDock].size();
       
  2611     if (right_hint.isNull())
       
  2612         right_hint = docks[QInternal::RightDock].sizeHint();
       
  2613     QSize right_min = docks[QInternal::RightDock].minimumSize();
       
  2614     QSize right_max = docks[QInternal::RightDock].maximumSize();
       
  2615     right_hint = right_hint.boundedTo(right_max).expandedTo(right_min);
       
  2616 
       
  2617     QSize top_hint = docks[QInternal::TopDock].size();
       
  2618     if (top_hint.isNull())
       
  2619         top_hint = docks[QInternal::TopDock].sizeHint();
       
  2620     QSize top_min = docks[QInternal::TopDock].minimumSize();
       
  2621     QSize top_max = docks[QInternal::TopDock].maximumSize();
       
  2622     top_hint = top_hint.boundedTo(top_max).expandedTo(top_min);
       
  2623 
       
  2624     QSize bottom_hint = docks[QInternal::BottomDock].size();
       
  2625     if (bottom_hint.isNull())
       
  2626         bottom_hint = docks[QInternal::BottomDock].sizeHint();
       
  2627     QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
       
  2628     QSize bottom_max = docks[QInternal::BottomDock].maximumSize();
       
  2629     bottom_hint = bottom_hint.boundedTo(bottom_max).expandedTo(bottom_min);
       
  2630 
       
  2631     if (_ver_struct_list != 0) {
       
  2632         QVector<QLayoutStruct> &ver_struct_list = *_ver_struct_list;
       
  2633         ver_struct_list.resize(3);
       
  2634 
       
  2635         // top --------------------------------------------------
       
  2636         ver_struct_list[0].init();
       
  2637         ver_struct_list[0].stretch = 0;
       
  2638         ver_struct_list[0].sizeHint = top_hint.height();
       
  2639         ver_struct_list[0].minimumSize = top_min.height();
       
  2640         ver_struct_list[0].maximumSize = top_max.height();
       
  2641         ver_struct_list[0].expansive = false;
       
  2642         ver_struct_list[0].empty = docks[QInternal::TopDock].isEmpty();
       
  2643         ver_struct_list[0].pos = docks[QInternal::TopDock].rect.top();
       
  2644         ver_struct_list[0].size = docks[QInternal::TopDock].rect.height();
       
  2645 
       
  2646         // center --------------------------------------------------
       
  2647         ver_struct_list[1].init();
       
  2648         ver_struct_list[1].stretch = center_hint.height();
       
  2649 
       
  2650         bool tl_significant = corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
       
  2651                                     || docks[QInternal::TopDock].isEmpty();
       
  2652         bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
       
  2653                                     || docks[QInternal::BottomDock].isEmpty();
       
  2654         bool tr_significant = corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
       
  2655                                     || docks[QInternal::TopDock].isEmpty();
       
  2656         bool br_significant = corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
       
  2657                                     || docks[QInternal::BottomDock].isEmpty();
       
  2658 
       
  2659         int left = (tl_significant && bl_significant) ? left_hint.height() : 0;
       
  2660         int right = (tr_significant && br_significant) ? right_hint.height() : 0;
       
  2661         ver_struct_list[1].sizeHint = qMax(left, center_hint.height(), right);
       
  2662 
       
  2663         left = (tl_significant && bl_significant) ? left_min.height() : 0;
       
  2664         right = (tr_significant && br_significant) ? right_min.height() : 0;
       
  2665         ver_struct_list[1].minimumSize = qMax(left, center_min.height(), right);
       
  2666         ver_struct_list[1].maximumSize = have_central ? QWIDGETSIZE_MAX : 0;
       
  2667         ver_struct_list[1].expansive = have_central;
       
  2668         ver_struct_list[1].empty = docks[QInternal::LeftDock].isEmpty()
       
  2669                                         && !have_central
       
  2670                                         && docks[QInternal::RightDock].isEmpty();
       
  2671         ver_struct_list[1].pos = center_rect.top();
       
  2672         ver_struct_list[1].size = center_rect.height();
       
  2673 
       
  2674         // bottom --------------------------------------------------
       
  2675         ver_struct_list[2].init();
       
  2676         ver_struct_list[2].stretch = 0;
       
  2677         ver_struct_list[2].sizeHint = bottom_hint.height();
       
  2678         ver_struct_list[2].minimumSize = bottom_min.height();
       
  2679         ver_struct_list[2].maximumSize = bottom_max.height();
       
  2680         ver_struct_list[2].expansive = false;
       
  2681         ver_struct_list[2].empty = docks[QInternal::BottomDock].isEmpty();
       
  2682         ver_struct_list[2].pos = docks[QInternal::BottomDock].rect.top();
       
  2683         ver_struct_list[2].size = docks[QInternal::BottomDock].rect.height();
       
  2684 
       
  2685         for (int i = 0; i < 3; ++i) {
       
  2686             ver_struct_list[i].sizeHint
       
  2687                 = qMax(ver_struct_list[i].sizeHint, ver_struct_list[i].minimumSize);
       
  2688         }
       
  2689     }
       
  2690 
       
  2691     if (_hor_struct_list != 0) {
       
  2692         QVector<QLayoutStruct> &hor_struct_list = *_hor_struct_list;
       
  2693         hor_struct_list.resize(3);
       
  2694 
       
  2695         // left --------------------------------------------------
       
  2696         hor_struct_list[0].init();
       
  2697         hor_struct_list[0].stretch = 0;
       
  2698         hor_struct_list[0].sizeHint = left_hint.width();
       
  2699         hor_struct_list[0].minimumSize = left_min.width();
       
  2700         hor_struct_list[0].maximumSize = left_max.width();
       
  2701         hor_struct_list[0].expansive = false;
       
  2702         hor_struct_list[0].empty = docks[QInternal::LeftDock].isEmpty();
       
  2703         hor_struct_list[0].pos = docks[QInternal::LeftDock].rect.left();
       
  2704         hor_struct_list[0].size = docks[QInternal::LeftDock].rect.width();
       
  2705 
       
  2706         // center --------------------------------------------------
       
  2707         hor_struct_list[1].init();
       
  2708         hor_struct_list[1].stretch = center_hint.width();
       
  2709 
       
  2710         bool tl_significant = corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
       
  2711                                     || docks[QInternal::LeftDock].isEmpty();
       
  2712         bool tr_significant = corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
       
  2713                                     || docks[QInternal::RightDock].isEmpty();
       
  2714         bool bl_significant = corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
       
  2715                                     || docks[QInternal::LeftDock].isEmpty();
       
  2716         bool br_significant = corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
       
  2717                                     || docks[QInternal::RightDock].isEmpty();
       
  2718 
       
  2719         int top = (tl_significant && tr_significant) ? top_hint.width() : 0;
       
  2720         int bottom = (bl_significant && br_significant) ? bottom_hint.width() : 0;
       
  2721         hor_struct_list[1].sizeHint = qMax(top, center_hint.width(), bottom);
       
  2722 
       
  2723         top = (tl_significant && tr_significant) ? top_min.width() : 0;
       
  2724         bottom = (bl_significant && br_significant) ? bottom_min.width() : 0;
       
  2725         hor_struct_list[1].minimumSize = qMax(top, center_min.width(), bottom);
       
  2726 
       
  2727         hor_struct_list[1].maximumSize = have_central ? QWIDGETSIZE_MAX : 0;
       
  2728         hor_struct_list[1].expansive = have_central;
       
  2729         hor_struct_list[1].empty = !have_central;
       
  2730         hor_struct_list[1].pos = center_rect.left();
       
  2731         hor_struct_list[1].size = center_rect.width();
       
  2732 
       
  2733         // right --------------------------------------------------
       
  2734         hor_struct_list[2].init();
       
  2735         hor_struct_list[2].stretch = 0;
       
  2736         hor_struct_list[2].sizeHint = right_hint.width();
       
  2737         hor_struct_list[2].minimumSize = right_min.width();
       
  2738         hor_struct_list[2].maximumSize = right_max.width();
       
  2739         hor_struct_list[2].expansive = false;
       
  2740         hor_struct_list[2].empty = docks[QInternal::RightDock].isEmpty();
       
  2741         hor_struct_list[2].pos = docks[QInternal::RightDock].rect.left();
       
  2742         hor_struct_list[2].size = docks[QInternal::RightDock].rect.width();
       
  2743 
       
  2744         for (int i = 0; i < 3; ++i) {
       
  2745             hor_struct_list[i].sizeHint
       
  2746                 = qMax(hor_struct_list[i].sizeHint, hor_struct_list[i].minimumSize);
       
  2747         }
       
  2748     }
       
  2749 }
       
  2750 
       
  2751 void QDockAreaLayout::setGrid(QVector<QLayoutStruct> *ver_struct_list,
       
  2752                                 QVector<QLayoutStruct> *hor_struct_list)
       
  2753 {
       
  2754 
       
  2755     // top ---------------------------------------------------
       
  2756 
       
  2757     if (!docks[QInternal::TopDock].isEmpty()) {
       
  2758         QRect r = docks[QInternal::TopDock].rect;
       
  2759         if (hor_struct_list != 0) {
       
  2760             r.setLeft(corners[Qt::TopLeftCorner] == Qt::TopDockWidgetArea
       
  2761                 || docks[QInternal::LeftDock].isEmpty()
       
  2762                 ? rect.left() : hor_struct_list->at(1).pos);
       
  2763             r.setRight(corners[Qt::TopRightCorner] == Qt::TopDockWidgetArea
       
  2764                 || docks[QInternal::RightDock].isEmpty()
       
  2765                 ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
       
  2766         }
       
  2767         if (ver_struct_list != 0) {
       
  2768             r.setTop(rect.top());
       
  2769             r.setBottom(ver_struct_list->at(1).pos - sep - 1);
       
  2770         }
       
  2771         docks[QInternal::TopDock].rect = r;
       
  2772         docks[QInternal::TopDock].fitItems();
       
  2773     }
       
  2774 
       
  2775     // bottom ---------------------------------------------------
       
  2776 
       
  2777     if (!docks[QInternal::BottomDock].isEmpty()) {
       
  2778         QRect r = docks[QInternal::BottomDock].rect;
       
  2779         if (hor_struct_list != 0) {
       
  2780             r.setLeft(corners[Qt::BottomLeftCorner] == Qt::BottomDockWidgetArea
       
  2781                         || docks[QInternal::LeftDock].isEmpty()
       
  2782                             ? rect.left() : hor_struct_list->at(1).pos);
       
  2783             r.setRight(corners[Qt::BottomRightCorner] == Qt::BottomDockWidgetArea
       
  2784                         || docks[QInternal::RightDock].isEmpty()
       
  2785                             ? rect.right() : hor_struct_list->at(2).pos - sep - 1);
       
  2786         }
       
  2787         if (ver_struct_list != 0) {
       
  2788             r.setTop(ver_struct_list->at(2).pos);
       
  2789             r.setBottom(rect.bottom());
       
  2790         }
       
  2791         docks[QInternal::BottomDock].rect = r;
       
  2792         docks[QInternal::BottomDock].fitItems();
       
  2793     }
       
  2794 
       
  2795     // left ---------------------------------------------------
       
  2796 
       
  2797     if (!docks[QInternal::LeftDock].isEmpty()) {
       
  2798         QRect r = docks[QInternal::LeftDock].rect;
       
  2799         if (hor_struct_list != 0) {
       
  2800             r.setLeft(rect.left());
       
  2801             r.setRight(hor_struct_list->at(1).pos - sep - 1);
       
  2802         }
       
  2803         if (ver_struct_list != 0) {
       
  2804             r.setTop(corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea
       
  2805                 || docks[QInternal::TopDock].isEmpty()
       
  2806                 ? rect.top() : ver_struct_list->at(1).pos);
       
  2807             r.setBottom(corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea
       
  2808                 || docks[QInternal::BottomDock].isEmpty()
       
  2809                 ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
       
  2810         }
       
  2811         docks[QInternal::LeftDock].rect = r;
       
  2812         docks[QInternal::LeftDock].fitItems();
       
  2813     }
       
  2814 
       
  2815     // right ---------------------------------------------------
       
  2816 
       
  2817     if (!docks[QInternal::RightDock].isEmpty()) {
       
  2818         QRect r = docks[QInternal::RightDock].rect;
       
  2819         if (hor_struct_list != 0) {
       
  2820             r.setLeft(hor_struct_list->at(2).pos);
       
  2821             r.setRight(rect.right());
       
  2822         }
       
  2823         if (ver_struct_list != 0) {
       
  2824             r.setTop(corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea
       
  2825                         || docks[QInternal::TopDock].isEmpty()
       
  2826                             ? rect.top() : ver_struct_list->at(1).pos);
       
  2827             r.setBottom(corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea
       
  2828                         || docks[QInternal::BottomDock].isEmpty()
       
  2829                             ? rect.bottom() : ver_struct_list->at(2).pos - sep - 1);
       
  2830         }
       
  2831         docks[QInternal::RightDock].rect = r;
       
  2832         docks[QInternal::RightDock].fitItems();
       
  2833     }
       
  2834 
       
  2835     // center ---------------------------------------------------
       
  2836 
       
  2837     if (hor_struct_list != 0) {
       
  2838         centralWidgetRect.setLeft(hor_struct_list->at(1).pos);
       
  2839         centralWidgetRect.setWidth(hor_struct_list->at(1).size);
       
  2840     }
       
  2841     if (ver_struct_list != 0) {
       
  2842         centralWidgetRect.setTop(ver_struct_list->at(1).pos);
       
  2843         centralWidgetRect.setHeight(ver_struct_list->at(1).size);
       
  2844     }
       
  2845 }
       
  2846 
       
  2847 void QDockAreaLayout::fitLayout()
       
  2848 {
       
  2849     QVector<QLayoutStruct> ver_struct_list(3);
       
  2850     QVector<QLayoutStruct> hor_struct_list(3);
       
  2851     getGrid(&ver_struct_list, &hor_struct_list);
       
  2852 
       
  2853     qGeomCalc(ver_struct_list, 0, 3, rect.top(), rect.height(), sep);
       
  2854     qGeomCalc(hor_struct_list, 0, 3, rect.left(), rect.width(), sep);
       
  2855 
       
  2856     setGrid(&ver_struct_list, &hor_struct_list);
       
  2857 }
       
  2858 
       
  2859 void QDockAreaLayout::clear()
       
  2860 {
       
  2861     for (int i = 0; i < QInternal::DockCount; ++i)
       
  2862         docks[i].clear();
       
  2863 
       
  2864     rect = QRect();
       
  2865     centralWidgetRect = QRect();
       
  2866 }
       
  2867 
       
  2868 QSize QDockAreaLayout::sizeHint() const
       
  2869 {
       
  2870     int left_sep = 0;
       
  2871     int right_sep = 0;
       
  2872     int top_sep = 0;
       
  2873     int bottom_sep = 0;
       
  2874 
       
  2875     if (centralWidgetItem != 0) {
       
  2876         left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
       
  2877         right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
       
  2878         top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
       
  2879         bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
       
  2880     }
       
  2881 
       
  2882     QSize left = docks[QInternal::LeftDock].sizeHint() + QSize(left_sep, 0);
       
  2883     QSize right = docks[QInternal::RightDock].sizeHint() + QSize(right_sep, 0);
       
  2884     QSize top = docks[QInternal::TopDock].sizeHint() + QSize(0, top_sep);
       
  2885     QSize bottom = docks[QInternal::BottomDock].sizeHint() + QSize(0, bottom_sep);
       
  2886     QSize center = centralWidgetItem == 0 ? QSize(0, 0) : centralWidgetItem->sizeHint();
       
  2887 
       
  2888     int row1 = top.width();
       
  2889     int row2 = left.width() + center.width() + right.width();
       
  2890     int row3 = bottom.width();
       
  2891     int col1 = left.height();
       
  2892     int col2 = top.height() + center.height() + bottom.height();
       
  2893     int col3 = right.height();
       
  2894 
       
  2895     if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
       
  2896         row1 += left.width();
       
  2897     else
       
  2898         col1 += top.height();
       
  2899 
       
  2900     if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
       
  2901         row1 += right.width();
       
  2902     else
       
  2903         col3 += top.height();
       
  2904 
       
  2905     if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
       
  2906         row3 += left.width();
       
  2907     else
       
  2908         col1 += bottom.height();
       
  2909 
       
  2910     if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
       
  2911         row3 += right.width();
       
  2912     else
       
  2913         col3 += bottom.height();
       
  2914 
       
  2915     return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
       
  2916 }
       
  2917 
       
  2918 QSize QDockAreaLayout::minimumSize() const
       
  2919 {
       
  2920     int left_sep = 0;
       
  2921     int right_sep = 0;
       
  2922     int top_sep = 0;
       
  2923     int bottom_sep = 0;
       
  2924 
       
  2925     if (centralWidgetItem != 0) {
       
  2926         left_sep = docks[QInternal::LeftDock].isEmpty() ? 0 : sep;
       
  2927         right_sep = docks[QInternal::RightDock].isEmpty() ? 0 : sep;
       
  2928         top_sep = docks[QInternal::TopDock].isEmpty() ? 0 : sep;
       
  2929         bottom_sep = docks[QInternal::BottomDock].isEmpty() ? 0 : sep;
       
  2930     }
       
  2931 
       
  2932     QSize left = docks[QInternal::LeftDock].minimumSize() + QSize(left_sep, 0);
       
  2933     QSize right = docks[QInternal::RightDock].minimumSize() + QSize(right_sep, 0);
       
  2934     QSize top = docks[QInternal::TopDock].minimumSize() + QSize(0, top_sep);
       
  2935     QSize bottom = docks[QInternal::BottomDock].minimumSize() + QSize(0, bottom_sep);
       
  2936     QSize center = centralWidgetItem == 0 ? QSize(0, 0) : centralWidgetItem->minimumSize();
       
  2937 
       
  2938     int row1 = top.width();
       
  2939     int row2 = left.width() + center.width() + right.width();
       
  2940     int row3 = bottom.width();
       
  2941     int col1 = left.height();
       
  2942     int col2 = top.height() + center.height() + bottom.height();
       
  2943     int col3 = right.height();
       
  2944 
       
  2945     if (corners[Qt::TopLeftCorner] == Qt::LeftDockWidgetArea)
       
  2946         row1 += left.width();
       
  2947     else
       
  2948         col1 += top.height();
       
  2949 
       
  2950     if (corners[Qt::TopRightCorner] == Qt::RightDockWidgetArea)
       
  2951         row1 += right.width();
       
  2952     else
       
  2953         col3 += top.height();
       
  2954 
       
  2955     if (corners[Qt::BottomLeftCorner] == Qt::LeftDockWidgetArea)
       
  2956         row3 += left.width();
       
  2957     else
       
  2958         col1 += bottom.height();
       
  2959 
       
  2960     if (corners[Qt::BottomRightCorner] == Qt::RightDockWidgetArea)
       
  2961         row3 += right.width();
       
  2962     else
       
  2963         col3 += bottom.height();
       
  2964 
       
  2965     return QSize(qMax(row1, row2, row3), qMax(col1, col2, col3));
       
  2966 }
       
  2967 
       
  2968 bool QDockAreaLayout::restoreDockWidget(QDockWidget *dockWidget)
       
  2969 {
       
  2970     QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
       
  2971     if (index.isEmpty())
       
  2972         return false;
       
  2973 
       
  2974     QDockAreaLayoutItem &item = this->item(index);
       
  2975     QPlaceHolderItem *placeHolder = item.placeHolderItem;
       
  2976     Q_ASSERT(placeHolder != 0);
       
  2977 
       
  2978     item.widgetItem = new QDockWidgetItem(dockWidget);
       
  2979 
       
  2980     if (placeHolder->window) {
       
  2981         QDesktopWidget desktop;
       
  2982         QRect r = constrainedRect(placeHolder->topLevelRect, desktop.screenGeometry(dockWidget));
       
  2983         dockWidget->d_func()->setWindowState(true, true, r);
       
  2984     }
       
  2985     dockWidget->show();
       
  2986 //    dockWidget->setVisible(!placeHolder->hidden);
       
  2987 #ifdef Q_WS_X11
       
  2988     if (placeHolder->window) // gets rid of the X11BypassWindowManager window flag
       
  2989         dockWidget->d_func()->setWindowState(true);
       
  2990 #endif
       
  2991 
       
  2992     item.placeHolderItem = 0;
       
  2993     delete placeHolder;
       
  2994 
       
  2995     return true;
       
  2996 }
       
  2997 
       
  2998 void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *dockWidget,
       
  2999                                              Qt::Orientation orientation)
       
  3000 {
       
  3001     QLayoutItem *dockWidgetItem = new QDockWidgetItem(dockWidget);
       
  3002     QDockAreaLayoutInfo &info = docks[pos];
       
  3003     if (orientation == info.o || info.item_list.count() <= 1) {
       
  3004         // empty dock areas, or dock areas containing exactly one widget can have their orientation
       
  3005         // switched.
       
  3006         info.o = orientation;
       
  3007 
       
  3008         QDockAreaLayoutItem new_item(dockWidgetItem);
       
  3009         info.item_list.append(new_item);
       
  3010 #ifndef QT_NO_TABBAR
       
  3011         if (info.tabbed && !new_item.skip()) {
       
  3012             info.updateTabBar();
       
  3013             info.setCurrentTabId(tabId(new_item));
       
  3014         }
       
  3015 #endif
       
  3016     } else {
       
  3017 #ifndef QT_NO_TABBAR
       
  3018         int tbshape = info.tabBarShape;
       
  3019 #else
       
  3020         int tbshape = 0;
       
  3021 #endif
       
  3022         QDockAreaLayoutInfo new_info(sep, pos, orientation, tbshape, mainWindow);
       
  3023         new_info.item_list.append(new QDockAreaLayoutInfo(info));
       
  3024         new_info.item_list.append(dockWidgetItem);
       
  3025         info = new_info;
       
  3026     }
       
  3027 
       
  3028     QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
       
  3029     if (!index.isEmpty())
       
  3030         remove(index);
       
  3031 }
       
  3032 
       
  3033 void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second)
       
  3034 {
       
  3035     QList<int> path = indexOf(first);
       
  3036     if (path.isEmpty())
       
  3037         return;
       
  3038 
       
  3039     QDockAreaLayoutInfo *info = this->info(path);
       
  3040     Q_ASSERT(info != 0);
       
  3041     info->tab(path.last(), new QDockWidgetItem(second));
       
  3042 
       
  3043     QList<int> index = indexOfPlaceHolder(second->objectName());
       
  3044     if (!index.isEmpty())
       
  3045         remove(index);
       
  3046 }
       
  3047 
       
  3048 void QDockAreaLayout::splitDockWidget(QDockWidget *after,
       
  3049                                                QDockWidget *dockWidget,
       
  3050                                                Qt::Orientation orientation)
       
  3051 {
       
  3052     QList<int> path = indexOf(after);
       
  3053     if (path.isEmpty())
       
  3054         return;
       
  3055 
       
  3056     QDockAreaLayoutInfo *info = this->info(path);
       
  3057     Q_ASSERT(info != 0);
       
  3058     info->split(path.last(), orientation, new QDockWidgetItem(dockWidget));
       
  3059 
       
  3060     QList<int> index = indexOfPlaceHolder(dockWidget->objectName());
       
  3061     if (!index.isEmpty())
       
  3062         remove(index);
       
  3063 }
       
  3064 
       
  3065 void QDockAreaLayout::apply(bool animate)
       
  3066 {
       
  3067     QWidgetAnimator &widgetAnimator
       
  3068         = qobject_cast<QMainWindowLayout*>(mainWindow->layout())->widgetAnimator;
       
  3069 
       
  3070     for (int i = 0; i < QInternal::DockCount; ++i)
       
  3071         docks[i].apply(animate);
       
  3072     if (centralWidgetItem != 0 && !centralWidgetItem->isEmpty()) {
       
  3073         widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect,
       
  3074                                 animate);
       
  3075     }
       
  3076 
       
  3077     if (sep == 1)
       
  3078         updateSeparatorWidgets();
       
  3079 }
       
  3080 
       
  3081 void QDockAreaLayout::paintSeparators(QPainter *p, QWidget *widget,
       
  3082                                                 const QRegion &clip,
       
  3083                                                 const QPoint &mouse) const
       
  3084 {
       
  3085     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3086         const QDockAreaLayoutInfo &dock = docks[i];
       
  3087         if (dock.isEmpty())
       
  3088             continue;
       
  3089         QRect r = separatorRect(i);
       
  3090         if (clip.contains(r) && !dock.hasFixedSize()) {
       
  3091             Qt::Orientation opposite = dock.o == Qt::Horizontal
       
  3092                                         ? Qt::Vertical : Qt::Horizontal;
       
  3093             paintSep(p, widget, r, opposite, r.contains(mouse));
       
  3094         }
       
  3095         if (clip.contains(dock.rect))
       
  3096             dock.paintSeparators(p, widget, clip, mouse);
       
  3097     }
       
  3098 }
       
  3099 
       
  3100 QRegion QDockAreaLayout::separatorRegion() const
       
  3101 {
       
  3102     QRegion result;
       
  3103 
       
  3104     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3105         const QDockAreaLayoutInfo &dock = docks[i];
       
  3106         if (dock.isEmpty())
       
  3107             continue;
       
  3108         result |= separatorRect(i);
       
  3109         result |= dock.separatorRegion();
       
  3110     }
       
  3111 
       
  3112     return result;
       
  3113 }
       
  3114 
       
  3115 int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &origin,
       
  3116                                                 const QPoint &dest)
       
  3117 {
       
  3118     int delta = 0;
       
  3119     int index = separator.last();
       
  3120 
       
  3121     if (separator.count() > 1) {
       
  3122         QDockAreaLayoutInfo *info = this->info(separator);
       
  3123         delta = pick(info->o, dest - origin);
       
  3124         if (delta != 0)
       
  3125             delta = info->separatorMove(index, delta);
       
  3126         info->apply(false);
       
  3127         return delta;
       
  3128     }
       
  3129 
       
  3130     QVector<QLayoutStruct> list;
       
  3131 
       
  3132     if (index == QInternal::LeftDock || index == QInternal::RightDock)
       
  3133         getGrid(0, &list);
       
  3134     else
       
  3135         getGrid(&list, 0);
       
  3136 
       
  3137     int sep_index = index == QInternal::LeftDock || index == QInternal::TopDock
       
  3138                         ? 0 : 1;
       
  3139     Qt::Orientation o = index == QInternal::LeftDock || index == QInternal::RightDock
       
  3140                         ? Qt::Horizontal
       
  3141                         : Qt::Vertical;
       
  3142 
       
  3143     delta = pick(o, dest - origin);
       
  3144     delta = separatorMoveHelper(list, sep_index, delta, sep);
       
  3145 
       
  3146     if (index == QInternal::LeftDock || index == QInternal::RightDock)
       
  3147         setGrid(0, &list);
       
  3148     else
       
  3149         setGrid(&list, 0);
       
  3150 
       
  3151     apply(false);
       
  3152 
       
  3153     return delta;
       
  3154 }
       
  3155 
       
  3156 // Sets the correct positions for the seperator widgets
       
  3157 // Allocates new sepearator widgets with getSeparatorWidget
       
  3158 void QDockAreaLayout::updateSeparatorWidgets() const
       
  3159 {
       
  3160     int j = 0;
       
  3161 
       
  3162     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3163         const QDockAreaLayoutInfo &dock = docks[i];
       
  3164         if (dock.isEmpty())
       
  3165             continue;
       
  3166 
       
  3167         QWidget *sepWidget;
       
  3168         if (j < separatorWidgets.size()) {
       
  3169             sepWidget = separatorWidgets.at(j);
       
  3170         } else {
       
  3171             sepWidget = qobject_cast<QMainWindowLayout*>(mainWindow->layout())->getSeparatorWidget();
       
  3172             separatorWidgets.append(sepWidget);
       
  3173         }
       
  3174         j++;
       
  3175 
       
  3176 #ifndef QT_MAC_USE_COCOA
       
  3177         sepWidget->raise();
       
  3178 #endif
       
  3179         QRect sepRect = separatorRect(i).adjusted(-2, -2, 2, 2);
       
  3180         sepWidget->setGeometry(sepRect);
       
  3181         sepWidget->setMask( QRegion(separatorRect(i).translated( - sepRect.topLeft())));
       
  3182         sepWidget->show();
       
  3183     }
       
  3184     for (int i = j; i < separatorWidgets.size(); ++i)
       
  3185         separatorWidgets.at(i)->hide();
       
  3186 
       
  3187     separatorWidgets.resize(j);
       
  3188 }
       
  3189 
       
  3190 QLayoutItem *QDockAreaLayout::itemAt(int *x, int index) const
       
  3191 {
       
  3192     Q_ASSERT(x != 0);
       
  3193 
       
  3194     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3195         const QDockAreaLayoutInfo &dock = docks[i];
       
  3196         if (QLayoutItem *ret = dock.itemAt(x, index))
       
  3197             return ret;
       
  3198     }
       
  3199 
       
  3200     if (centralWidgetItem && (*x)++ == index)
       
  3201         return centralWidgetItem;
       
  3202 
       
  3203     return 0;
       
  3204 }
       
  3205 
       
  3206 QLayoutItem *QDockAreaLayout::takeAt(int *x, int index)
       
  3207 {
       
  3208     Q_ASSERT(x != 0);
       
  3209 
       
  3210     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3211         QDockAreaLayoutInfo &dock = docks[i];
       
  3212         if (QLayoutItem *ret = dock.takeAt(x, index))
       
  3213             return ret;
       
  3214     }
       
  3215 
       
  3216     if (centralWidgetItem && (*x)++ == index) {
       
  3217         QLayoutItem *ret = centralWidgetItem;
       
  3218         centralWidgetItem = 0;
       
  3219         return ret;
       
  3220     }
       
  3221 
       
  3222     return 0;
       
  3223 }
       
  3224 
       
  3225 void QDockAreaLayout::deleteAllLayoutItems()
       
  3226 {
       
  3227     for (int i = 0; i < QInternal::DockCount; ++i)
       
  3228         docks[i].deleteAllLayoutItems();
       
  3229 }
       
  3230 
       
  3231 #ifndef QT_NO_TABBAR
       
  3232 QSet<QTabBar*> QDockAreaLayout::usedTabBars() const
       
  3233 {
       
  3234     QSet<QTabBar*> result;
       
  3235     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3236         const QDockAreaLayoutInfo &dock = docks[i];
       
  3237         result += dock.usedTabBars();
       
  3238     }
       
  3239     return result;
       
  3240 }
       
  3241 #endif
       
  3242 
       
  3243 // Returns the set of all used separator widgets
       
  3244 QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets() const
       
  3245 {
       
  3246     QSet<QWidget*> result;
       
  3247 
       
  3248     for (int i = 0; i < separatorWidgets.count(); ++i)
       
  3249         result << separatorWidgets.at(i);
       
  3250     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  3251         const QDockAreaLayoutInfo &dock = docks[i];
       
  3252         result += dock.usedSeparatorWidgets();
       
  3253     }
       
  3254     return result;
       
  3255 }
       
  3256 
       
  3257 QRect QDockAreaLayout::gapRect(const QList<int> &path) const
       
  3258 {
       
  3259     const QDockAreaLayoutInfo *info = this->info(path);
       
  3260     if (info == 0)
       
  3261         return QRect();
       
  3262     const QList<QDockAreaLayoutItem> &item_list = info->item_list;
       
  3263     Qt::Orientation o = info->o;
       
  3264     int index = path.last();
       
  3265     if (index < 0 || index >= item_list.count())
       
  3266         return QRect();
       
  3267     const QDockAreaLayoutItem &item = item_list.at(index);
       
  3268     if (!(item.flags & QDockAreaLayoutItem::GapItem))
       
  3269         return QRect();
       
  3270 
       
  3271     QRect result;
       
  3272 
       
  3273 #ifndef QT_NO_TABBAR
       
  3274     if (info->tabbed) {
       
  3275         result = info->tabContentRect();
       
  3276     } else
       
  3277 #endif
       
  3278     {
       
  3279         int pos = item.pos;
       
  3280         int size = item.size;
       
  3281 
       
  3282         int prev = info->prev(index);
       
  3283         int next = info->next(index);
       
  3284 
       
  3285         if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
       
  3286             pos += sep;
       
  3287             size -= sep;
       
  3288         }
       
  3289         if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
       
  3290             size -= sep;
       
  3291 
       
  3292         QPoint p;
       
  3293         rpick(o, p) = pos;
       
  3294         rperp(o, p) = perp(o, info->rect.topLeft());
       
  3295         QSize s;
       
  3296         rpick(o, s) = size;
       
  3297         rperp(o, s) = perp(o, info->rect.size());
       
  3298 
       
  3299         result = QRect(p, s);
       
  3300     }
       
  3301 
       
  3302     return result;
       
  3303 }
       
  3304 
       
  3305 void QDockAreaLayout::keepSize(QDockWidget *w)
       
  3306 {
       
  3307     QList<int> path = indexOf(w);
       
  3308     if (path.isEmpty())
       
  3309         return;
       
  3310     QDockAreaLayoutItem &item = this->item(path);
       
  3311     if (item.size != -1)
       
  3312         item.flags |= QDockAreaLayoutItem::KeepSize;
       
  3313 }
       
  3314 
       
  3315 QT_END_NAMESPACE
       
  3316 
       
  3317 #endif // QT_NO_DOCKWIDGET