src/gui/widgets/qtoolbararealayout.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 <QWidgetItem>
       
    43 #include <QToolBar>
       
    44 #include <QStyleOption>
       
    45 #include <QApplication>
       
    46 #include <qdebug.h>
       
    47 
       
    48 #include "qtoolbararealayout_p.h"
       
    49 #include "qmainwindowlayout_p.h"
       
    50 #include "qwidgetanimator_p.h"
       
    51 #include "qtoolbarlayout_p.h"
       
    52 #include "qtoolbar_p.h"
       
    53 
       
    54 /******************************************************************************
       
    55 ** QToolBarAreaLayoutItem
       
    56 */
       
    57 
       
    58 #ifndef QT_NO_TOOLBAR
       
    59 
       
    60 QT_BEGIN_NAMESPACE
       
    61 
       
    62 QSize QToolBarAreaLayoutItem::minimumSize() const
       
    63 {
       
    64     if (skip())
       
    65         return QSize(0, 0);
       
    66     return qSmartMinSize(static_cast<QWidgetItem*>(widgetItem));
       
    67 }
       
    68 
       
    69 QSize QToolBarAreaLayoutItem::sizeHint() const
       
    70 {
       
    71     if (skip())
       
    72         return QSize(0, 0);
       
    73 
       
    74     return realSizeHint();
       
    75 }
       
    76 
       
    77 //returns the real size hint not taking into account the visibility of the widget
       
    78 QSize QToolBarAreaLayoutItem::realSizeHint() const
       
    79 {
       
    80     QWidget *wid = widgetItem->widget();
       
    81     QSize s = wid->sizeHint().expandedTo(wid->minimumSizeHint());
       
    82     if (wid->sizePolicy().horizontalPolicy() == QSizePolicy::Ignored)
       
    83         s.setWidth(0);
       
    84     if (wid->sizePolicy().verticalPolicy() == QSizePolicy::Ignored)
       
    85         s.setHeight(0);
       
    86     s = s.boundedTo(wid->maximumSize())
       
    87         .expandedTo(wid->minimumSize());
       
    88     return s;
       
    89 }
       
    90 
       
    91 bool QToolBarAreaLayoutItem::skip() const
       
    92 {
       
    93     if (gap)
       
    94         return false;
       
    95     return widgetItem == 0 || widgetItem->isEmpty();
       
    96 }
       
    97 
       
    98 /******************************************************************************
       
    99 ** QToolBarAreaLayoutLine
       
   100 */
       
   101 
       
   102 QToolBarAreaLayoutLine::QToolBarAreaLayoutLine(Qt::Orientation orientation)
       
   103     : o(orientation)
       
   104 {
       
   105 }
       
   106 
       
   107 QSize QToolBarAreaLayoutLine::sizeHint() const
       
   108 {
       
   109     int a = 0, b = 0;
       
   110     for (int i = 0; i < toolBarItems.count(); ++i) {
       
   111         const QToolBarAreaLayoutItem &item = toolBarItems.at(i);
       
   112         if (item.skip())
       
   113             continue;
       
   114 
       
   115         QSize sh = item.sizeHint();
       
   116         a += item.preferredSize > 0 ? item.preferredSize : pick(o, sh);
       
   117         b = qMax(b, perp(o, sh));
       
   118     }
       
   119 
       
   120     QSize result;
       
   121     rpick(o, result) = a;
       
   122     rperp(o, result) = b;
       
   123 
       
   124     return result;
       
   125 }
       
   126 
       
   127 QSize QToolBarAreaLayoutLine::minimumSize() const
       
   128 {
       
   129     int a = 0, b = 0;
       
   130     for (int i = 0; i < toolBarItems.count(); ++i) {
       
   131         const QToolBarAreaLayoutItem &item = toolBarItems[i];
       
   132         if (item.skip())
       
   133             continue;
       
   134 
       
   135         QSize ms = item.minimumSize();
       
   136         a += pick(o, ms);
       
   137         b = qMax(b, perp(o, ms));
       
   138     }
       
   139 
       
   140     QSize result;
       
   141     rpick(o, result) = a;
       
   142     rperp(o, result) = b;
       
   143 
       
   144     return result;
       
   145 }
       
   146 
       
   147 void QToolBarAreaLayoutLine::fitLayout()
       
   148 {
       
   149     int last = -1;
       
   150     int min = pick(o, minimumSize());
       
   151     int space = pick(o, rect.size());
       
   152     int extra = qMax(0, space - min);
       
   153 
       
   154     for (int i = 0; i < toolBarItems.count(); ++i) {
       
   155         QToolBarAreaLayoutItem &item = toolBarItems[i];
       
   156         if (item.skip())
       
   157             continue;
       
   158 
       
   159         if (QToolBarLayout *tblayout = qobject_cast<QToolBarLayout*>(item.widgetItem->widget()->layout()))
       
   160             tblayout->checkUsePopupMenu();
       
   161 
       
   162         const int itemMin = pick(o, item.minimumSize());
       
   163         //preferredSize is the default if it is set, otherwise, we take the sizehint
       
   164         item.size = item.preferredSize > 0 ? item.preferredSize : pick(o, item.sizeHint());
       
   165 
       
   166         //the extraspace is the space above the item minimum sizehint
       
   167         const int extraSpace = qMin(item.size - itemMin, extra);
       
   168         item.size = itemMin + extraSpace; //that is the real size
       
   169 
       
   170         extra -= extraSpace;
       
   171 
       
   172         last = i;
       
   173     }
       
   174 
       
   175     // calculate the positions from the sizes
       
   176     int pos = 0;
       
   177     for (int i = 0; i < toolBarItems.count(); ++i) {
       
   178         QToolBarAreaLayoutItem &item = toolBarItems[i];
       
   179         if (item.skip())
       
   180             continue;
       
   181 
       
   182         item.pos = pos;
       
   183         if (i == last) // stretch the last item to the end of the line
       
   184             item.size = qMax(0, pick(o, rect.size()) - item.pos);
       
   185         pos += item.size;
       
   186     }
       
   187 }
       
   188 
       
   189 bool QToolBarAreaLayoutLine::skip() const
       
   190 {
       
   191     for (int i = 0; i < toolBarItems.count(); ++i) {
       
   192         if (!toolBarItems.at(i).skip())
       
   193             return false;
       
   194     }
       
   195     return true;
       
   196 }
       
   197 
       
   198 /******************************************************************************
       
   199 ** QToolBarAreaLayoutInfo
       
   200 */
       
   201 
       
   202 QToolBarAreaLayoutInfo::QToolBarAreaLayoutInfo(QInternal::DockPosition pos)
       
   203     : dockPos(pos), dirty(false)
       
   204 {
       
   205     switch (pos) {
       
   206         case QInternal::LeftDock:
       
   207         case QInternal::RightDock:
       
   208             o = Qt::Vertical;
       
   209             break;
       
   210         case QInternal::TopDock:
       
   211         case QInternal::BottomDock:
       
   212             o = Qt::Horizontal;
       
   213             break;
       
   214         default:
       
   215             o = Qt::Horizontal;
       
   216             break;
       
   217     }
       
   218 }
       
   219 
       
   220 QSize QToolBarAreaLayoutInfo::sizeHint() const
       
   221 {
       
   222     int a = 0, b = 0;
       
   223     for (int i = 0; i < lines.count(); ++i) {
       
   224         const QToolBarAreaLayoutLine &l = lines.at(i);
       
   225         if (l.skip())
       
   226             continue;
       
   227 
       
   228         QSize hint = l.sizeHint();
       
   229         a = qMax(a, pick(o, hint));
       
   230         b += perp(o, hint);
       
   231     }
       
   232 
       
   233     QSize result;
       
   234     rpick(o, result) = a;
       
   235     rperp(o, result) = b;
       
   236 
       
   237     return result;
       
   238 }
       
   239 
       
   240 QSize QToolBarAreaLayoutInfo::minimumSize() const
       
   241 {
       
   242     int a = 0, b = 0;
       
   243     for (int i = 0; i < lines.count(); ++i) {
       
   244         const QToolBarAreaLayoutLine &l = lines.at(i);
       
   245         if (l.skip())
       
   246             continue;
       
   247 
       
   248         QSize m = l.minimumSize();
       
   249         a = qMax(a, pick(o, m));
       
   250         b += perp(o, m);
       
   251     }
       
   252 
       
   253     QSize result;
       
   254     rpick(o, result) = a;
       
   255     rperp(o, result) = b;
       
   256 
       
   257     return result;
       
   258 }
       
   259 
       
   260 void QToolBarAreaLayoutInfo::fitLayout()
       
   261 {
       
   262     dirty = false;
       
   263 
       
   264     int b = 0;
       
   265 
       
   266     bool reverse = dockPos == QInternal::RightDock || dockPos == QInternal::BottomDock;
       
   267 
       
   268     int i = reverse ? lines.count() - 1 : 0;
       
   269     for (;;) {
       
   270         if ((reverse && i < 0) || (!reverse && i == lines.count()))
       
   271             break;
       
   272 
       
   273         QToolBarAreaLayoutLine &l = lines[i];
       
   274         if (!l.skip()) {
       
   275             if (o == Qt::Horizontal) {
       
   276                 l.rect.setLeft(rect.left());
       
   277                 l.rect.setRight(rect.right());
       
   278                 l.rect.setTop(b + rect.top());
       
   279                 b += l.sizeHint().height();
       
   280                 l.rect.setBottom(b - 1 + rect.top());
       
   281             } else {
       
   282                 l.rect.setTop(rect.top());
       
   283                 l.rect.setBottom(rect.bottom());
       
   284                 l.rect.setLeft(b + rect.left());
       
   285                 b += l.sizeHint().width();
       
   286                 l.rect.setRight(b - 1 + rect.left());
       
   287             }
       
   288 
       
   289             l.fitLayout();
       
   290         }
       
   291 
       
   292         i += reverse ? -1 : 1;
       
   293     }
       
   294 }
       
   295 
       
   296 QLayoutItem *QToolBarAreaLayoutInfo::insertToolBar(QToolBar *before, QToolBar *toolBar)
       
   297 {
       
   298     toolBar->setOrientation(o);
       
   299     QLayoutItem *item = new QWidgetItemV2(toolBar);
       
   300     insertItem(before, item);
       
   301     return item;
       
   302 }
       
   303 
       
   304 void QToolBarAreaLayoutInfo::insertItem(QToolBar *before, QLayoutItem *item)
       
   305 {
       
   306     if (before == 0) {
       
   307         if (lines.isEmpty())
       
   308             lines.append(QToolBarAreaLayoutLine(o));
       
   309         lines.last().toolBarItems.append(item);
       
   310         return;
       
   311     }
       
   312 
       
   313     for (int j = 0; j < lines.count(); ++j) {
       
   314         QToolBarAreaLayoutLine &line = lines[j];
       
   315 
       
   316         for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   317             if (line.toolBarItems.at(k).widgetItem->widget() == before) {
       
   318                 line.toolBarItems.insert(k, item);
       
   319                 return;
       
   320             }
       
   321         }
       
   322     }
       
   323 }
       
   324 
       
   325 void QToolBarAreaLayoutInfo::removeToolBar(QToolBar *toolBar)
       
   326 {
       
   327     for (int j = 0; j < lines.count(); ++j) {
       
   328         QToolBarAreaLayoutLine &line = lines[j];
       
   329 
       
   330         for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   331             QToolBarAreaLayoutItem &item = line.toolBarItems[k];
       
   332             if (item.widgetItem->widget() == toolBar) {
       
   333                 delete item.widgetItem;
       
   334                 item.widgetItem = 0;
       
   335                 line.toolBarItems.removeAt(k);
       
   336 
       
   337                 if (line.toolBarItems.isEmpty() && j < lines.count() - 1)
       
   338                     lines.removeAt(j);
       
   339 
       
   340                 return;
       
   341             }
       
   342         }
       
   343     }
       
   344 }
       
   345 
       
   346 void QToolBarAreaLayoutInfo::insertToolBarBreak(QToolBar *before)
       
   347 {
       
   348     if (before == 0) {
       
   349         if (!lines.isEmpty() && lines.last().toolBarItems.isEmpty())
       
   350             return;
       
   351         lines.append(QToolBarAreaLayoutLine(o));
       
   352         return;
       
   353     }
       
   354 
       
   355     for (int j = 0; j < lines.count(); ++j) {
       
   356         QToolBarAreaLayoutLine &line = lines[j];
       
   357 
       
   358         for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   359             if (line.toolBarItems.at(k).widgetItem->widget() == before) {
       
   360                 if (k == 0)
       
   361                     return;
       
   362 
       
   363                 QToolBarAreaLayoutLine newLine(o);
       
   364                 newLine.toolBarItems = line.toolBarItems.mid(k);
       
   365                 line.toolBarItems = line.toolBarItems.mid(0, k);
       
   366                 lines.insert(j + 1, newLine);
       
   367 
       
   368                 return;
       
   369             }
       
   370         }
       
   371     }
       
   372 }
       
   373 
       
   374 void QToolBarAreaLayoutInfo::removeToolBarBreak(QToolBar *before)
       
   375 {
       
   376     for (int j = 0; j < lines.count(); ++j) {
       
   377         const QToolBarAreaLayoutLine &line = lines.at(j);
       
   378 
       
   379         for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   380             if (line.toolBarItems.at(k).widgetItem->widget() == before) {
       
   381                 if (k != 0)
       
   382                     return;
       
   383                 if (j == 0)
       
   384                     return;
       
   385 
       
   386                 lines[j - 1].toolBarItems += lines[j].toolBarItems;
       
   387                 lines.removeAt(j);
       
   388 
       
   389                 return;
       
   390             }
       
   391         }
       
   392     }
       
   393 }
       
   394 
       
   395 void QToolBarAreaLayoutInfo::moveToolBar(QToolBar *toolbar, int pos)
       
   396 {
       
   397     if (dirty)
       
   398         fitLayout();
       
   399 
       
   400     dirty = true;
       
   401 
       
   402     if (o == Qt::Vertical)
       
   403         pos -= rect.top();
       
   404 
       
   405     //here we actually update the preferredSize for the line containing the toolbar so that we move it
       
   406     for (int j = 0; j < lines.count(); ++j) {
       
   407         QToolBarAreaLayoutLine &line = lines[j];
       
   408 
       
   409         int previousIndex = -1;
       
   410         int minPos = 0;
       
   411         for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   412             QToolBarAreaLayoutItem &current = line.toolBarItems[k];
       
   413             if (current.widgetItem->widget() == toolbar) {
       
   414                 int newPos = current.pos;
       
   415 
       
   416                 if (previousIndex >= 0) {
       
   417                     QToolBarAreaLayoutItem &previous = line.toolBarItems[previousIndex];
       
   418                     if (pos < current.pos) {
       
   419                         newPos = qMax(pos, minPos);
       
   420                     } else {
       
   421                         //we check the max value for the position (until everything at the right is "compressed")
       
   422                         int maxPos = pick(o, rect.size());
       
   423                         for(int l = k; l < line.toolBarItems.count(); ++l) {
       
   424                             const QToolBarAreaLayoutItem &item = line.toolBarItems.at(l);
       
   425                             if (!item.skip()) {
       
   426                                 maxPos -= pick(o, item.minimumSize());
       
   427                             }
       
   428                         }
       
   429                         newPos = qMin(pos, maxPos);
       
   430                     }
       
   431 
       
   432                     //extra is the number of pixels to add to the previous toolbar
       
   433                     int extra = newPos - current.pos;
       
   434 
       
   435                     //we check if the previous is near its size hint
       
   436                     //in which case we try to stick to it
       
   437                     const int diff = pick(o, previous.sizeHint()) - (previous.size + extra);
       
   438                     if (qAbs(diff) < QApplication::startDragDistance()) {
       
   439                         //we stick to the default place and size
       
   440                         extra += diff;
       
   441                     }
       
   442 
       
   443                     //update for the current item
       
   444                     current.extendSize(line.o, -extra);
       
   445 
       
   446                     if (extra >= 0) {
       
   447                         previous.extendSize(line.o, extra);
       
   448                     } else {
       
   449                         //we need to push the toolbars on the left starting with previous
       
   450                         extra = -extra; // we just need to know the number of pixels
       
   451                         ///at this point we need to get extra pixels from the toolbars at the left
       
   452                         for(int l = previousIndex; l >=0; --l) {
       
   453                             QToolBarAreaLayoutItem &item = line.toolBarItems[l];
       
   454                             if (!item.skip()) {
       
   455                                 const int minPreferredSize = pick(o, item.minimumSize());
       
   456                                 const int margin =  item.size - minPreferredSize;
       
   457                                 if (margin < extra) {
       
   458                                     item.resize(line.o, minPreferredSize);
       
   459                                     extra -= margin;
       
   460                                 } else {
       
   461                                     item.extendSize(line.o, -extra);
       
   462                                     extra = 0;
       
   463                                 }
       
   464                             }
       
   465                         }
       
   466                         Q_ASSERT(extra == 0);
       
   467                     }
       
   468                 } else {
       
   469                     //the item is the first one, it should be at position 0
       
   470                 }
       
   471 
       
   472                 return;
       
   473 
       
   474             } else if (!current.skip()) {
       
   475                 previousIndex = k;
       
   476                 minPos += pick(o, current.minimumSize());
       
   477             }
       
   478         }
       
   479     }
       
   480 }
       
   481 
       
   482 
       
   483 QList<int> QToolBarAreaLayoutInfo::gapIndex(const QPoint &pos) const
       
   484 {
       
   485     int p = pick(o, pos);
       
   486 
       
   487     if (rect.contains(pos)) {
       
   488         for (int j = 0; j < lines.count(); ++j) {
       
   489             const QToolBarAreaLayoutLine &line = lines.at(j);
       
   490             if (line.skip())
       
   491                 continue;
       
   492             if (!line.rect.contains(pos))
       
   493                 continue;
       
   494 
       
   495             int k = 0;
       
   496             for (; k < line.toolBarItems.count(); ++k) {
       
   497                 const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
       
   498                 if (item.skip())
       
   499                     continue;
       
   500 
       
   501                 int size = qMin(item.size, pick(o, item.sizeHint()));
       
   502 
       
   503                 if (p > item.pos + size)
       
   504                     continue;
       
   505                 if (p > item.pos + size/2)
       
   506                     ++k;
       
   507                 break;
       
   508             }
       
   509 
       
   510             QList<int> result;
       
   511             result << j << k;
       
   512             return result;
       
   513         }
       
   514     } else if (appendLineDropRect().contains(pos)) {
       
   515         QList<int> result;
       
   516         result << lines.count() << 0;
       
   517         return result;
       
   518     }
       
   519 
       
   520     return QList<int>();
       
   521 }
       
   522 
       
   523 bool QToolBarAreaLayoutInfo::insertGap(const QList<int> &path, QLayoutItem *item)
       
   524 {
       
   525     Q_ASSERT(path.count() == 2);
       
   526     int j = path.first();
       
   527     if (j == lines.count())
       
   528         lines.append(QToolBarAreaLayoutLine(o));
       
   529 
       
   530     QToolBarAreaLayoutLine &line = lines[j];
       
   531     const int k = path.at(1);
       
   532 
       
   533     QToolBarAreaLayoutItem gap_item;
       
   534     gap_item.gap = true;
       
   535     gap_item.widgetItem = item;
       
   536 
       
   537     //update the previous item's preferred size
       
   538     for(int p = k - 1 ; p >= 0; --p) {
       
   539         QToolBarAreaLayoutItem &previous = line.toolBarItems[p];
       
   540         if (!previous.skip()) {
       
   541             //we found the previous one
       
   542             int previousSizeHint = pick(line.o, previous.sizeHint());
       
   543             int previousExtraSpace = previous.size - previousSizeHint;
       
   544 
       
   545             if (previousExtraSpace > 0) {
       
   546                 //in this case we reset the space
       
   547                 previous.preferredSize = -1;
       
   548                 previous.size = previousSizeHint;
       
   549 
       
   550                 gap_item.resize(o, previousExtraSpace);
       
   551             }
       
   552 
       
   553             break;
       
   554         }
       
   555     }
       
   556 
       
   557     line.toolBarItems.insert(k, gap_item);
       
   558     return true;
       
   559 
       
   560 }
       
   561 
       
   562 void QToolBarAreaLayoutInfo::clear()
       
   563 {
       
   564     lines.clear();
       
   565     rect = QRect();
       
   566 }
       
   567 
       
   568 QRect QToolBarAreaLayoutInfo::itemRect(const QList<int> &path) const
       
   569 {
       
   570     Q_ASSERT(path.count() == 2);
       
   571     int j = path.at(0);
       
   572     int k = path.at(1);
       
   573 
       
   574     const QToolBarAreaLayoutLine &line = lines.at(j);
       
   575     const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
       
   576 
       
   577     QRect result = line.rect;
       
   578 
       
   579     if (o == Qt::Horizontal) {
       
   580         result.setLeft(item.pos + line.rect.left());
       
   581         result.setWidth(item.size);
       
   582     } else {
       
   583         result.setTop(item.pos + line.rect.top());
       
   584         result.setHeight(item.size);
       
   585     }
       
   586 
       
   587     return result;
       
   588 }
       
   589 
       
   590 QRect QToolBarAreaLayoutInfo::appendLineDropRect() const
       
   591 {
       
   592     QRect result;
       
   593 
       
   594     switch (dockPos) {
       
   595         case QInternal::LeftDock:
       
   596             result = QRect(rect.right(), rect.top(),
       
   597                             EmptyDockAreaSize, rect.height());
       
   598             break;
       
   599         case QInternal::RightDock:
       
   600             result = QRect(rect.left() - EmptyDockAreaSize, rect.top(),
       
   601                             EmptyDockAreaSize, rect.height());
       
   602             break;
       
   603         case QInternal::TopDock:
       
   604             result = QRect(rect.left(), rect.bottom() + 1,
       
   605                             rect.width(), EmptyDockAreaSize);
       
   606             break;
       
   607         case QInternal::BottomDock:
       
   608             result = QRect(rect.left(), rect.top() - EmptyDockAreaSize,
       
   609                             rect.width(), EmptyDockAreaSize);
       
   610             break;
       
   611         default:
       
   612             break;
       
   613     }
       
   614 
       
   615     return result;
       
   616 }
       
   617 
       
   618 /******************************************************************************
       
   619 ** QToolBarAreaLayout
       
   620 */
       
   621 
       
   622 QToolBarAreaLayout::QToolBarAreaLayout(const QMainWindow *win) : mainWindow(win), visible(true)
       
   623 {
       
   624     for (int i = 0; i < QInternal::DockCount; ++i) {
       
   625         QInternal::DockPosition pos = static_cast<QInternal::DockPosition>(i);
       
   626         docks[i] = QToolBarAreaLayoutInfo(pos);
       
   627     }
       
   628 }
       
   629 
       
   630 QRect QToolBarAreaLayout::fitLayout()
       
   631 {
       
   632     if (!visible)
       
   633         return rect;
       
   634 
       
   635     QSize left_hint = docks[QInternal::LeftDock].sizeHint();
       
   636     QSize right_hint = docks[QInternal::RightDock].sizeHint();
       
   637     QSize top_hint = docks[QInternal::TopDock].sizeHint();
       
   638     QSize bottom_hint = docks[QInternal::BottomDock].sizeHint();
       
   639 
       
   640     QRect center = rect.adjusted(left_hint.width(), top_hint.height(),
       
   641                                     -right_hint.width(), -bottom_hint.height());
       
   642 
       
   643     docks[QInternal::TopDock].rect = QRect(rect.left(), rect.top(),
       
   644                                 rect.width(), top_hint.height());
       
   645     docks[QInternal::LeftDock].rect = QRect(rect.left(), center.top(),
       
   646                                 left_hint.width(), center.height());
       
   647     docks[QInternal::RightDock].rect = QRect(center.right() + 1, center.top(),
       
   648                                     right_hint.width(), center.height());
       
   649     docks[QInternal::BottomDock].rect = QRect(rect.left(), center.bottom() + 1,
       
   650                                     rect.width(), bottom_hint.height());
       
   651 
       
   652     if (!mainWindow->unifiedTitleAndToolBarOnMac()) {
       
   653         docks[QInternal::TopDock].fitLayout();
       
   654     }
       
   655     docks[QInternal::LeftDock].fitLayout();
       
   656     docks[QInternal::RightDock].fitLayout();
       
   657     docks[QInternal::BottomDock].fitLayout();
       
   658 
       
   659     return center;
       
   660 }
       
   661 
       
   662 QSize QToolBarAreaLayout::minimumSize(const QSize &centerMin) const
       
   663 {
       
   664     if (!visible)
       
   665         return centerMin;
       
   666 
       
   667     QSize result = centerMin;
       
   668 
       
   669     QSize left_min = docks[QInternal::LeftDock].minimumSize();
       
   670     QSize right_min = docks[QInternal::RightDock].minimumSize();
       
   671     QSize top_min = docks[QInternal::TopDock].minimumSize();
       
   672     QSize bottom_min = docks[QInternal::BottomDock].minimumSize();
       
   673 
       
   674     result.setWidth(qMax(top_min.width(), result.width()));
       
   675     result.setWidth(qMax(bottom_min.width(), result.width()));
       
   676     result.setHeight(qMax(left_min.height(), result.height()));
       
   677     result.setHeight(qMax(right_min.height(), result.height()));
       
   678 
       
   679     result.rwidth() += left_min.width() + right_min.width();
       
   680     result.rheight() += top_min.height() + bottom_min.height();
       
   681 
       
   682     return result;
       
   683 }
       
   684 
       
   685 QSize QToolBarAreaLayout::sizeHint(const QSize &centerHint) const
       
   686 {
       
   687     if (!visible)
       
   688         return centerHint;
       
   689 
       
   690     QSize result = centerHint;
       
   691 
       
   692     QSize left_hint = docks[QInternal::LeftDock].sizeHint();
       
   693     QSize right_hint = docks[QInternal::RightDock].sizeHint();
       
   694     QSize top_hint = docks[QInternal::TopDock].sizeHint();
       
   695     QSize bottom_hint = docks[QInternal::BottomDock].sizeHint();
       
   696 
       
   697     result.setWidth(qMax(top_hint.width(), result.width()));
       
   698     result.setWidth(qMax(bottom_hint.width(), result.width()));
       
   699     result.setHeight(qMax(left_hint.height(), result.height()));
       
   700     result.setHeight(qMax(right_hint.height(), result.height()));
       
   701 
       
   702     result.rwidth() += left_hint.width() + right_hint.width();
       
   703     result.rheight() += top_hint.height() + bottom_hint.height();
       
   704 
       
   705     return result;
       
   706 }
       
   707 
       
   708 QRect QToolBarAreaLayout::rectHint(const QRect &r) const
       
   709 {
       
   710     int coef = visible ? 1 : -1;
       
   711 
       
   712     QRect result = r;
       
   713 
       
   714     QSize left_hint = docks[QInternal::LeftDock].sizeHint();
       
   715     QSize right_hint = docks[QInternal::RightDock].sizeHint();
       
   716     QSize top_hint = docks[QInternal::TopDock].sizeHint();
       
   717     QSize bottom_hint = docks[QInternal::BottomDock].sizeHint();
       
   718 
       
   719     result.adjust(-left_hint.width()*coef, -top_hint.height()*coef,
       
   720                     right_hint.width()*coef, bottom_hint.height()*coef);
       
   721 
       
   722     return result;
       
   723 }
       
   724 
       
   725 QLayoutItem *QToolBarAreaLayout::itemAt(int *x, int index) const
       
   726 {
       
   727     Q_ASSERT(x != 0);
       
   728 
       
   729     for (int i = 0; i < QInternal::DockCount; ++i) {
       
   730         const QToolBarAreaLayoutInfo &dock = docks[i];
       
   731 
       
   732         for (int j = 0; j < dock.lines.count(); ++j) {
       
   733             const QToolBarAreaLayoutLine &line = dock.lines.at(j);
       
   734 
       
   735             for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   736                 if ((*x)++ == index)
       
   737                     return line.toolBarItems.at(k).widgetItem;
       
   738             }
       
   739         }
       
   740     }
       
   741 
       
   742     return 0;
       
   743 }
       
   744 
       
   745 QLayoutItem *QToolBarAreaLayout::takeAt(int *x, int index)
       
   746 {
       
   747     Q_ASSERT(x != 0);
       
   748 
       
   749     for (int i = 0; i < QInternal::DockCount; ++i) {
       
   750         QToolBarAreaLayoutInfo &dock = docks[i];
       
   751 
       
   752         for (int j = 0; j < dock.lines.count(); ++j) {
       
   753             QToolBarAreaLayoutLine &line = dock.lines[j];
       
   754 
       
   755             for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   756                 if ((*x)++ == index) {
       
   757                     QLayoutItem *result = line.toolBarItems.takeAt(k).widgetItem;
       
   758                     if (line.toolBarItems.isEmpty())
       
   759                         dock.lines.removeAt(j);
       
   760                     return result;
       
   761                 }
       
   762             }
       
   763         }
       
   764     }
       
   765 
       
   766     return 0;
       
   767 }
       
   768 
       
   769 void QToolBarAreaLayout::deleteAllLayoutItems()
       
   770 {
       
   771     for (int i = 0; i < QInternal::DockCount; ++i) {
       
   772         QToolBarAreaLayoutInfo &dock = docks[i];
       
   773 
       
   774         for (int j = 0; j < dock.lines.count(); ++j) {
       
   775             QToolBarAreaLayoutLine &line = dock.lines[j];
       
   776 
       
   777             for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   778                 QToolBarAreaLayoutItem &item = line.toolBarItems[k];
       
   779                 if (!item.gap)
       
   780                     delete item.widgetItem;
       
   781                 item.widgetItem = 0;
       
   782             }
       
   783         }
       
   784     }
       
   785 }
       
   786 
       
   787 QInternal::DockPosition QToolBarAreaLayout::findToolBar(QToolBar *toolBar) const
       
   788 {
       
   789     for (int i = 0; i < QInternal::DockCount; ++i) {
       
   790         const QToolBarAreaLayoutInfo &dock = docks[i];
       
   791 
       
   792         for (int j = 0; j < dock.lines.count(); ++j) {
       
   793             const QToolBarAreaLayoutLine &line = dock.lines.at(j);
       
   794 
       
   795             for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   796                 if (line.toolBarItems.at(k).widgetItem->widget() == toolBar)
       
   797                     return static_cast<QInternal::DockPosition>(i);
       
   798             }
       
   799         }
       
   800     }
       
   801 
       
   802     return QInternal::DockCount;
       
   803 }
       
   804 
       
   805 QLayoutItem *QToolBarAreaLayout::insertToolBar(QToolBar *before, QToolBar *toolBar)
       
   806 {
       
   807     QInternal::DockPosition pos = findToolBar(before);
       
   808     if (pos == QInternal::DockCount)
       
   809         return 0;
       
   810     
       
   811     return docks[pos].insertToolBar(before, toolBar);
       
   812 }
       
   813 
       
   814 void QToolBarAreaLayout::removeToolBar(QToolBar *toolBar)
       
   815 {
       
   816     QInternal::DockPosition pos = findToolBar(toolBar);
       
   817     if (pos == QInternal::DockCount)
       
   818         return;
       
   819     docks[pos].removeToolBar(toolBar);
       
   820 }
       
   821 
       
   822 QLayoutItem *QToolBarAreaLayout::addToolBar(QInternal::DockPosition pos, QToolBar *toolBar)
       
   823 {
       
   824     return docks[pos].insertToolBar(0, toolBar);
       
   825 }
       
   826 
       
   827 void QToolBarAreaLayout::insertToolBarBreak(QToolBar *before)
       
   828 {
       
   829     QInternal::DockPosition pos = findToolBar(before);
       
   830     if (pos == QInternal::DockCount)
       
   831         return;
       
   832     docks[pos].insertToolBarBreak(before);
       
   833 }
       
   834 
       
   835 void QToolBarAreaLayout::removeToolBarBreak(QToolBar *before)
       
   836 {
       
   837     QInternal::DockPosition pos = findToolBar(before);
       
   838     if (pos == QInternal::DockCount)
       
   839         return;
       
   840     docks[pos].removeToolBarBreak(before);
       
   841 }
       
   842 
       
   843 void QToolBarAreaLayout::addToolBarBreak(QInternal::DockPosition pos)
       
   844 {
       
   845     docks[pos].insertToolBarBreak(0);
       
   846 }
       
   847 
       
   848 void QToolBarAreaLayout::moveToolBar(QToolBar *toolbar, int p)
       
   849 {
       
   850     QInternal::DockPosition pos = findToolBar(toolbar);
       
   851     if (pos == QInternal::DockCount)
       
   852         return;
       
   853     docks[pos].moveToolBar(toolbar, p);
       
   854 }
       
   855 
       
   856 
       
   857 void QToolBarAreaLayout::insertItem(QInternal::DockPosition pos, QLayoutItem *item)
       
   858 {
       
   859     if (docks[pos].lines.isEmpty())
       
   860         docks[pos].lines.append(QToolBarAreaLayoutLine(docks[pos].o));
       
   861     docks[pos].lines.last().toolBarItems.append(item);
       
   862 }
       
   863 
       
   864 void QToolBarAreaLayout::insertItem(QToolBar *before, QLayoutItem *item)
       
   865 {
       
   866     QInternal::DockPosition pos = findToolBar(before);
       
   867     if (pos == QInternal::DockCount)
       
   868         return;
       
   869     
       
   870     docks[pos].insertItem(before, item);
       
   871 }
       
   872 
       
   873 void QToolBarAreaLayout::apply(bool animate)
       
   874 {
       
   875     QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(mainWindow->layout());
       
   876     Q_ASSERT(layout != 0);
       
   877 
       
   878     Qt::LayoutDirection dir = mainWindow->layoutDirection();
       
   879 
       
   880     for (int i = 0; i < QInternal::DockCount; ++i) {
       
   881         const QToolBarAreaLayoutInfo &dock = docks[i];
       
   882 
       
   883         for (int j = 0; j < dock.lines.count(); ++j) {
       
   884             const QToolBarAreaLayoutLine &line = dock.lines.at(j);
       
   885             if (line.skip())
       
   886                 continue;
       
   887 
       
   888             for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   889                 const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
       
   890                 if (item.skip() || item.gap)
       
   891                     continue;
       
   892 
       
   893                 QRect geo;
       
   894                 if (visible) {
       
   895                     if (line.o == Qt::Horizontal) {
       
   896                         geo.setTop(line.rect.top());
       
   897                         geo.setBottom(line.rect.bottom());
       
   898                         geo.setLeft(line.rect.left() + item.pos);
       
   899                         geo.setRight(line.rect.left() + item.pos + item.size - 1);
       
   900                     } else {
       
   901                         geo.setLeft(line.rect.left());
       
   902                         geo.setRight(line.rect.right());
       
   903                         geo.setTop(line.rect.top() + item.pos);
       
   904                         geo.setBottom(line.rect.top() + item.pos + item.size - 1);
       
   905                     }
       
   906                 }
       
   907 
       
   908                 QWidget *widget = item.widgetItem->widget();
       
   909                 if (QToolBar *toolBar = qobject_cast<QToolBar*>(widget)) {
       
   910                     QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(toolBar->layout());
       
   911                     if (tbl->expanded) {
       
   912                         QPoint tr = geo.topRight();
       
   913                         QSize size = tbl->expandedSize(geo.size());
       
   914                         geo.setSize(size);
       
   915                         geo.moveTopRight(tr);
       
   916                         if (geo.bottom() > rect.bottom())
       
   917                             geo.moveBottom(rect.bottom());
       
   918                         if (geo.right() > rect.right())
       
   919                             geo.moveRight(rect.right());
       
   920                         if (geo.left() < 0)
       
   921                             geo.moveLeft(0);
       
   922                         if (geo.top() < 0)
       
   923                             geo.moveTop(0);
       
   924                     }
       
   925                 }
       
   926 
       
   927                 if (visible && dock.o == Qt::Horizontal)
       
   928                     geo = QStyle::visualRect(dir, line.rect, geo);
       
   929 
       
   930                 layout->widgetAnimator.animate(widget, geo, animate);
       
   931             }
       
   932         }
       
   933     }
       
   934 }
       
   935 
       
   936 bool QToolBarAreaLayout::toolBarBreak(QToolBar *toolBar) const
       
   937 {
       
   938     for (int i = 0; i < QInternal::DockCount; ++i) {
       
   939         const QToolBarAreaLayoutInfo &dock = docks[i];
       
   940 
       
   941         for (int j = 0; j < dock.lines.count(); ++j) {
       
   942             const QToolBarAreaLayoutLine &line = dock.lines.at(j);
       
   943 
       
   944             for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   945                 if (line.toolBarItems.at(k).widgetItem->widget() == toolBar)
       
   946                     return j > 0 && k == 0;
       
   947             }
       
   948         }
       
   949     }
       
   950 
       
   951     return false;
       
   952 }
       
   953 
       
   954 void QToolBarAreaLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar *toolBar) const
       
   955 {
       
   956     for (int i = 0; i < QInternal::DockCount; ++i) {
       
   957         const QToolBarAreaLayoutInfo &dock = docks[i];
       
   958 
       
   959         for (int j = 0; j < dock.lines.count(); ++j) {
       
   960             const QToolBarAreaLayoutLine &line = dock.lines.at(j);
       
   961 
       
   962             for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
   963                 if (line.toolBarItems.at(k).widgetItem->widget() == toolBar) {
       
   964                     if (line.toolBarItems.count() == 1)
       
   965                         option->positionWithinLine = QStyleOptionToolBar::OnlyOne;
       
   966                     else if (k == 0)
       
   967                         option->positionWithinLine = QStyleOptionToolBar::Beginning;
       
   968                     else if (k == line.toolBarItems.count() - 1)
       
   969                         option->positionWithinLine = QStyleOptionToolBar::End;
       
   970                     else
       
   971                         option->positionWithinLine = QStyleOptionToolBar::Middle;
       
   972 
       
   973                     if (dock.lines.count() == 1)
       
   974                         option->positionOfLine = QStyleOptionToolBar::OnlyOne;
       
   975                     else if (j == 0)
       
   976                         option->positionOfLine = QStyleOptionToolBar::Beginning;
       
   977                     else if (j == dock.lines.count() - 1)
       
   978                         option->positionOfLine = QStyleOptionToolBar::End;
       
   979                     else
       
   980                         option->positionOfLine = QStyleOptionToolBar::Middle;
       
   981 
       
   982                     return;
       
   983                 }
       
   984             }
       
   985         }
       
   986     }
       
   987 }
       
   988 
       
   989 QList<int> QToolBarAreaLayout::indexOf(QWidget *toolBar) const
       
   990 {
       
   991     QList<int> result;
       
   992 
       
   993     bool found = false;
       
   994 
       
   995     for (int i = 0; i < QInternal::DockCount; ++i) {
       
   996         const QToolBarAreaLayoutInfo &dock = docks[i];
       
   997 
       
   998         for (int j = 0; j < dock.lines.count(); ++j) {
       
   999             const QToolBarAreaLayoutLine &line = dock.lines.at(j);
       
  1000 
       
  1001             for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
  1002                 const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
       
  1003                 if (!item.gap && item.widgetItem->widget() == toolBar) {
       
  1004                     found = true;
       
  1005                     result.prepend(k);
       
  1006                     break;
       
  1007                 }
       
  1008             }
       
  1009 
       
  1010             if (found) {
       
  1011                 result.prepend(j);
       
  1012                 break;
       
  1013             }
       
  1014         }
       
  1015 
       
  1016         if (found) {
       
  1017             result.prepend(i);
       
  1018             break;
       
  1019         }
       
  1020     }
       
  1021 
       
  1022     return result;
       
  1023 }
       
  1024 
       
  1025 QList<int> QToolBarAreaLayout::gapIndex(const QPoint &pos) const
       
  1026 {
       
  1027     Qt::LayoutDirection dir = mainWindow->layoutDirection();
       
  1028     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  1029         QPoint p = pos;
       
  1030         if (docks[i].o == Qt::Horizontal)
       
  1031             p = QStyle::visualPos(dir, docks[i].rect, p);
       
  1032         QList<int> result = docks[i].gapIndex(p);
       
  1033         if (!result.isEmpty()) {
       
  1034             result.prepend(i);
       
  1035             return result;
       
  1036         }
       
  1037     }
       
  1038 
       
  1039     return QList<int>();
       
  1040 }
       
  1041 
       
  1042 QList<int> QToolBarAreaLayout::currentGapIndex() const
       
  1043 {
       
  1044     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  1045         const QToolBarAreaLayoutInfo &dock = docks[i];
       
  1046 
       
  1047         for (int j = 0; j < dock.lines.count(); ++j) {
       
  1048             const QToolBarAreaLayoutLine &line = dock.lines[j];
       
  1049 
       
  1050             for (int k = 0; k < line.toolBarItems.count(); k++) {
       
  1051                 if (line.toolBarItems[k].gap) {
       
  1052                     QList<int> result;
       
  1053                     result << i << j << k;
       
  1054                     return result;
       
  1055                 }
       
  1056             }
       
  1057         }
       
  1058     }
       
  1059     return QList<int>();
       
  1060 }
       
  1061 
       
  1062 bool QToolBarAreaLayout::insertGap(const QList<int> &path, QLayoutItem *item)
       
  1063 {
       
  1064     Q_ASSERT(path.count() == 3);
       
  1065     const int i = path.first();
       
  1066     Q_ASSERT(i >= 0 && i < QInternal::DockCount);
       
  1067     return docks[i].insertGap(path.mid(1), item);
       
  1068 }
       
  1069 
       
  1070 void QToolBarAreaLayout::remove(const QList<int> &path)
       
  1071 {
       
  1072     Q_ASSERT(path.count() == 3);
       
  1073     docks[path.at(0)].lines[path.at(1)].toolBarItems.removeAt(path.at(2));
       
  1074 }
       
  1075 
       
  1076 void QToolBarAreaLayout::remove(QLayoutItem *item)
       
  1077 {
       
  1078     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  1079         QToolBarAreaLayoutInfo &dock = docks[i];
       
  1080 
       
  1081         for (int j = 0; j < dock.lines.count(); ++j) {
       
  1082             QToolBarAreaLayoutLine &line = dock.lines[j];
       
  1083 
       
  1084             for (int k = 0; k < line.toolBarItems.count(); k++) {
       
  1085                 if (line.toolBarItems[k].widgetItem == item) {
       
  1086                     line.toolBarItems.removeAt(k);
       
  1087                     if (line.toolBarItems.isEmpty())
       
  1088                         dock.lines.removeAt(j);
       
  1089                     return;
       
  1090                 }
       
  1091             }
       
  1092         }
       
  1093     }
       
  1094 }
       
  1095 
       
  1096 void QToolBarAreaLayout::clear()
       
  1097 {
       
  1098     for (int i = 0; i < QInternal::DockCount; ++i)
       
  1099         docks[i].clear();
       
  1100     rect = QRect();
       
  1101 }
       
  1102 
       
  1103 QToolBarAreaLayoutItem &QToolBarAreaLayout::item(const QList<int> &path)
       
  1104 {
       
  1105     Q_ASSERT(path.count() == 3);
       
  1106 
       
  1107     Q_ASSERT(path.at(0) >= 0 && path.at(0) < QInternal::DockCount);
       
  1108     QToolBarAreaLayoutInfo &info = docks[path.at(0)];
       
  1109     Q_ASSERT(path.at(1) >= 0 && path.at(1) < info.lines.count());
       
  1110     QToolBarAreaLayoutLine &line = info.lines[path.at(1)];
       
  1111     Q_ASSERT(path.at(2) >= 0 && path.at(2) < line.toolBarItems.count());
       
  1112     return line.toolBarItems[path.at(2)];
       
  1113 }
       
  1114 
       
  1115 QRect QToolBarAreaLayout::itemRect(const QList<int> &path) const
       
  1116 {
       
  1117     const int i = path.first();
       
  1118 
       
  1119     QRect r = docks[i].itemRect(path.mid(1));
       
  1120     if (docks[i].o == Qt::Horizontal)
       
  1121         r = QStyle::visualRect(mainWindow->layoutDirection(),
       
  1122                                 docks[i].rect, r);
       
  1123     return r;
       
  1124 }
       
  1125 
       
  1126 QLayoutItem *QToolBarAreaLayout::plug(const QList<int> &path)
       
  1127 {
       
  1128     QToolBarAreaLayoutItem &item = this->item(path);
       
  1129     Q_ASSERT(item.gap);
       
  1130     Q_ASSERT(item.widgetItem != 0);
       
  1131     item.gap = false;
       
  1132     return item.widgetItem;
       
  1133 }
       
  1134 
       
  1135 QLayoutItem *QToolBarAreaLayout::unplug(const QList<int> &path, QToolBarAreaLayout *other)
       
  1136 {
       
  1137     //other needs to be update as well
       
  1138     Q_ASSERT(path.count() == 3);
       
  1139     QToolBarAreaLayoutItem &item = this->item(path);
       
  1140 
       
  1141     //update the leading space here
       
  1142     QToolBarAreaLayoutInfo &info = docks[path.at(0)];
       
  1143     QToolBarAreaLayoutLine &line = info.lines[path.at(1)];
       
  1144     if (item.size != pick(line.o, item.realSizeHint())) {
       
  1145         //the item doesn't have its default size
       
  1146         //so we'll give this to the next item
       
  1147         int newExtraSpace = 0;
       
  1148         //let's iterate over the siblings of the current item that pare placed before it
       
  1149         //we need to find just the one before
       
  1150         for (int i = path.at(2) - 1; i >= 0; --i) {
       
  1151             QToolBarAreaLayoutItem &previous = line.toolBarItems[i];
       
  1152             if (!previous.skip()) {
       
  1153                 //we need to check if it has a previous element and a next one
       
  1154                 //the previous will get its size changed
       
  1155                 for (int j = path.at(2) + 1; j < line.toolBarItems.count(); ++j) {
       
  1156                     const QToolBarAreaLayoutItem &next = line.toolBarItems.at(j);
       
  1157                     if (!next.skip()) {
       
  1158                         newExtraSpace = next.pos - previous.pos - pick(line.o, previous.sizeHint());
       
  1159                         previous.resize(line.o, next.pos - previous.pos);
       
  1160                         break;
       
  1161                     }
       
  1162                 }
       
  1163                 break;
       
  1164             }
       
  1165         }
       
  1166 
       
  1167         if (other) {
       
  1168             QToolBarAreaLayoutInfo &info = other->docks[path.at(0)];
       
  1169             QToolBarAreaLayoutLine &line = info.lines[path.at(1)];
       
  1170             for (int i = path.at(2) - 1; i >= 0; --i) {
       
  1171                 QToolBarAreaLayoutItem &previous = line.toolBarItems[i];
       
  1172                 if (!previous.skip()) {
       
  1173                     previous.resize(line.o, pick(line.o, previous.sizeHint()) + newExtraSpace);
       
  1174                     break;
       
  1175                 }
       
  1176             }
       
  1177 
       
  1178         }
       
  1179     }
       
  1180 
       
  1181     Q_ASSERT(!item.gap);
       
  1182     item.gap = true;
       
  1183     return item.widgetItem;
       
  1184 }
       
  1185 
       
  1186 static QRect unpackRect(uint geom0, uint geom1, bool *floating)
       
  1187 {
       
  1188     *floating = geom0 & 1;
       
  1189     if (!*floating)
       
  1190         return QRect();
       
  1191 
       
  1192     geom0 >>= 1;
       
  1193 
       
  1194     int x = (int)(geom0 & 0x0000ffff) - 0x7FFF;
       
  1195     int y = (int)(geom1 & 0x0000ffff) - 0x7FFF;
       
  1196 
       
  1197     geom0 >>= 16;
       
  1198     geom1 >>= 16;
       
  1199 
       
  1200     int w = geom0 & 0x0000ffff;
       
  1201     int h = geom1 & 0x0000ffff;
       
  1202 
       
  1203     return QRect(x, y, w, h);
       
  1204 }
       
  1205 
       
  1206 static void packRect(uint *geom0, uint *geom1, const QRect &rect, bool floating)
       
  1207 {
       
  1208     *geom0 = 0;
       
  1209     *geom1 = 0;
       
  1210 
       
  1211     if (!floating)
       
  1212         return;
       
  1213 
       
  1214     // The 0x7FFF is half of 0xFFFF. We add it so we can handle negative coordinates on
       
  1215     // dual monitors. It's subtracted when unpacking.
       
  1216 
       
  1217     *geom0 |= qMax(0, rect.width()) & 0x0000ffff;
       
  1218     *geom1 |= qMax(0, rect.height()) & 0x0000ffff;
       
  1219 
       
  1220     *geom0 <<= 16;
       
  1221     *geom1 <<= 16;
       
  1222 
       
  1223     *geom0 |= qMax(0, rect.x() + 0x7FFF) & 0x0000ffff;
       
  1224     *geom1 |= qMax(0, rect.y() + 0x7FFF) & 0x0000ffff;
       
  1225 
       
  1226     // yeah, we chop one bit off the width, but it still has a range up to 32512
       
  1227 
       
  1228     *geom0 <<= 1;
       
  1229     *geom0 |= 1;
       
  1230 }
       
  1231 
       
  1232 
       
  1233 void QToolBarAreaLayout::saveState(QDataStream &stream) const
       
  1234 {
       
  1235     // save toolbar state
       
  1236     stream << (uchar) ToolBarStateMarkerEx;
       
  1237 
       
  1238     int lineCount = 0;
       
  1239     for (int i = 0; i < QInternal::DockCount; ++i)
       
  1240         lineCount += docks[i].lines.count();
       
  1241 
       
  1242     stream << lineCount;
       
  1243 
       
  1244     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  1245         const QToolBarAreaLayoutInfo &dock = docks[i];
       
  1246 
       
  1247         for (int j = 0; j < dock.lines.count(); ++j) {
       
  1248             const QToolBarAreaLayoutLine &line = dock.lines.at(j);
       
  1249 
       
  1250             stream << i << line.toolBarItems.count();
       
  1251 
       
  1252             for (int k = 0; k < line.toolBarItems.count(); ++k) {
       
  1253                 const QToolBarAreaLayoutItem &item = line.toolBarItems.at(k);
       
  1254                 QWidget *widget = const_cast<QLayoutItem*>(item.widgetItem)->widget();
       
  1255                 QString objectName = widget->objectName();
       
  1256                 if (objectName.isEmpty()) {
       
  1257                     qWarning("QMainWindow::saveState(): 'objectName' not set for QToolBar %p '%s'",
       
  1258                                 widget, widget->windowTitle().toLocal8Bit().constData());
       
  1259                 }
       
  1260                 stream << objectName;
       
  1261                 // we store information as:
       
  1262                 // 1st bit: 1 if shown
       
  1263                 // 2nd bit: 1 if orientation is vertical (default is horizontal)
       
  1264                 uchar shownOrientation = (uchar)!widget->isHidden();
       
  1265                 if (QToolBar * tb= qobject_cast<QToolBar*>(widget)) {
       
  1266                     if (tb->orientation() == Qt::Vertical)
       
  1267                         shownOrientation |= 2;
       
  1268                 }
       
  1269                 stream << shownOrientation;
       
  1270                 stream << item.pos;
       
  1271                 //we store the preferred size. If the use rdidn't resize the toolbars it will be -1
       
  1272                 stream << item.preferredSize;
       
  1273 
       
  1274                 uint geom0, geom1;
       
  1275                 packRect(&geom0, &geom1, widget->geometry(), widget->isWindow());
       
  1276                 stream << geom0 << geom1;
       
  1277             }
       
  1278         }
       
  1279     }
       
  1280 }
       
  1281 
       
  1282 static inline int getInt(QDataStream &stream, Qt::Orientation o, bool pre43)
       
  1283 {
       
  1284     if (pre43) {
       
  1285         QPoint p;
       
  1286         stream >> p;
       
  1287         return pick(o, p);
       
  1288     } else {
       
  1289         int x;
       
  1290         stream >> x;
       
  1291         return x;
       
  1292     }
       
  1293 }
       
  1294 
       
  1295 
       
  1296 bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList<QToolBar*> &_toolBars, uchar tmarker, bool pre43, bool testing)
       
  1297 {
       
  1298     QList<QToolBar*> toolBars = _toolBars;
       
  1299     int lines;
       
  1300     stream >> lines;
       
  1301 
       
  1302     for (int j = 0; j < lines; ++j) {
       
  1303         int pos;
       
  1304         stream >> pos;
       
  1305         if (pos < 0 || pos >= QInternal::DockCount)
       
  1306             return false;
       
  1307         int cnt;
       
  1308         stream >> cnt;
       
  1309 
       
  1310         QToolBarAreaLayoutInfo &dock = docks[pos];
       
  1311         QToolBarAreaLayoutLine line(dock.o);
       
  1312 
       
  1313         for (int k = 0; k < cnt; ++k) {
       
  1314             QToolBarAreaLayoutItem item;
       
  1315 
       
  1316             QString objectName;
       
  1317             stream >> objectName;
       
  1318             uchar shown;
       
  1319             stream >> shown;
       
  1320             item.pos = getInt(stream, dock.o, pre43);
       
  1321             item.size = getInt(stream, dock.o, pre43);
       
  1322 
       
  1323             /*
       
  1324                4.3.0 added floating toolbars, but failed to add the ability to restore them.
       
  1325                We need to store there geometry (four ints). We cannot change the format in a
       
  1326                patch release (4.3.1) by adding ToolBarStateMarkerEx2 to signal extra data. So
       
  1327                for now we'll pack it in the two legacy ints we no longer used in Qt4.3.0.
       
  1328                In 4.4, we should add ToolBarStateMarkerEx2 and fix this properly.
       
  1329             */
       
  1330 
       
  1331             QRect rect;
       
  1332             bool floating = false;
       
  1333             uint geom0, geom1;
       
  1334             geom0 = getInt(stream, dock.o, pre43);
       
  1335             if (tmarker == ToolBarStateMarkerEx) {
       
  1336                 geom1 = getInt(stream, dock.o, pre43);
       
  1337                 rect = unpackRect(geom0, geom1, &floating);
       
  1338             }
       
  1339 
       
  1340             QToolBar *toolBar = 0;
       
  1341             for (int x = 0; x < toolBars.count(); ++x) {
       
  1342                 if (toolBars.at(x)->objectName() == objectName) {
       
  1343                     toolBar = toolBars.takeAt(x);
       
  1344                     break;
       
  1345                 }
       
  1346             }
       
  1347             if (toolBar == 0) {
       
  1348                 continue;
       
  1349             }
       
  1350 
       
  1351             if (!testing) {
       
  1352                 item.widgetItem = new QWidgetItemV2(toolBar);
       
  1353                 toolBar->setOrientation(floating ? ((shown & 2) ? Qt::Vertical : Qt::Horizontal) : dock.o);
       
  1354                 toolBar->setVisible(shown & 1);
       
  1355                 toolBar->d_func()->setWindowState(floating, true, rect);
       
  1356 
       
  1357                 item.preferredSize = item.size;
       
  1358                 line.toolBarItems.append(item);
       
  1359             }
       
  1360         }
       
  1361 
       
  1362         if (!testing) {
       
  1363             dock.lines.append(line);
       
  1364         }
       
  1365     }
       
  1366 
       
  1367 
       
  1368     return stream.status() == QDataStream::Ok;
       
  1369 }
       
  1370 
       
  1371 bool QToolBarAreaLayout::isEmpty() const
       
  1372 {
       
  1373     for (int i = 0; i < QInternal::DockCount; ++i) {
       
  1374         if (!docks[i].lines.isEmpty())
       
  1375             return false;
       
  1376     }
       
  1377     return true;
       
  1378 }
       
  1379 
       
  1380 QT_END_NAMESPACE
       
  1381 
       
  1382 #endif // QT_NO_TOOLBAR