src/gui/widgets/qtoolbarlayout.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 <qaction.h>
       
    43 #include <qwidgetaction.h>
       
    44 #include <qtoolbar.h>
       
    45 #include <qstyleoption.h>
       
    46 #include <qtoolbutton.h>
       
    47 #include <qmenu.h>
       
    48 #include <qdebug.h>
       
    49 #include <qmath.h>
       
    50 
       
    51 #include "qmainwindowlayout_p.h"
       
    52 #include "qtoolbarextension_p.h"
       
    53 #include "qtoolbarlayout_p.h"
       
    54 #include "qtoolbarseparator_p.h"
       
    55 
       
    56 #ifndef QT_NO_TOOLBAR
       
    57 
       
    58 QT_BEGIN_NAMESPACE
       
    59 
       
    60 /******************************************************************************
       
    61 ** QToolBarItem
       
    62 */
       
    63 
       
    64 QToolBarItem::QToolBarItem(QWidget *widget)
       
    65     : QWidgetItem(widget), action(0), customWidget(false)
       
    66 {
       
    67 }
       
    68 
       
    69 bool QToolBarItem::isEmpty() const
       
    70 {
       
    71     return action == 0 || !action->isVisible();
       
    72 }
       
    73 
       
    74 /******************************************************************************
       
    75 ** QToolBarLayout
       
    76 */
       
    77 
       
    78 QToolBarLayout::QToolBarLayout(QWidget *parent)
       
    79     : QLayout(parent), expanded(false), animating(false), dirty(true),
       
    80         expanding(false), empty(true), expandFlag(false), popupMenu(0)
       
    81 {
       
    82     QToolBar *tb = qobject_cast<QToolBar*>(parent);
       
    83     if (!tb)
       
    84         return;
       
    85 
       
    86     extension = new QToolBarExtension(tb);
       
    87     extension->setFocusPolicy(Qt::NoFocus);
       
    88     extension->hide();
       
    89     QObject::connect(tb, SIGNAL(orientationChanged(Qt::Orientation)),
       
    90                      extension, SLOT(setOrientation(Qt::Orientation)));
       
    91 
       
    92     setUsePopupMenu(qobject_cast<QMainWindow*>(tb->parentWidget()) == 0);
       
    93 }
       
    94 
       
    95 QToolBarLayout::~QToolBarLayout()
       
    96 {
       
    97     while (!items.isEmpty()) {
       
    98         QToolBarItem *item = items.takeFirst();
       
    99         if (QWidgetAction *widgetAction = qobject_cast<QWidgetAction*>(item->action)) {
       
   100             if (item->customWidget)
       
   101                 widgetAction->releaseWidget(item->widget());
       
   102         }
       
   103         delete item;
       
   104     }
       
   105 }
       
   106 
       
   107 void QToolBarLayout::updateMarginAndSpacing()
       
   108 {
       
   109     QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
       
   110     if (!tb)
       
   111         return;
       
   112     QStyle *style = tb->style();
       
   113     QStyleOptionToolBar opt;
       
   114     tb->initStyleOption(&opt);
       
   115     setMargin(style->pixelMetric(QStyle::PM_ToolBarItemMargin, &opt, tb)
       
   116                 + style->pixelMetric(QStyle::PM_ToolBarFrameWidth, &opt, tb));
       
   117     setSpacing(style->pixelMetric(QStyle::PM_ToolBarItemSpacing, &opt, tb));
       
   118 }
       
   119 
       
   120 bool QToolBarLayout::hasExpandFlag() const
       
   121 {
       
   122     return expandFlag;
       
   123 }
       
   124 
       
   125 void QToolBarLayout::setUsePopupMenu(bool set)
       
   126 {
       
   127     if (!dirty && ((popupMenu == 0) == set))
       
   128         invalidate();
       
   129     if (!set) {
       
   130         QObject::connect(extension, SIGNAL(clicked(bool)),
       
   131                         this, SLOT(setExpanded(bool)), Qt::UniqueConnection);
       
   132         extension->setPopupMode(QToolButton::DelayedPopup);
       
   133         extension->setMenu(0);
       
   134         delete popupMenu;
       
   135         popupMenu = 0;
       
   136     } else {
       
   137         QObject::disconnect(extension, SIGNAL(clicked(bool)),
       
   138                             this, SLOT(setExpanded(bool)));
       
   139         extension->setPopupMode(QToolButton::InstantPopup);
       
   140         if (!popupMenu) {
       
   141             popupMenu = new QMenu(extension);
       
   142         }
       
   143         extension->setMenu(popupMenu);
       
   144     }
       
   145 }
       
   146 
       
   147 void QToolBarLayout::checkUsePopupMenu()
       
   148 {
       
   149     QToolBar *tb = static_cast<QToolBar *>(parent());
       
   150     QMainWindow *mw = qobject_cast<QMainWindow *>(tb->parent());
       
   151     Qt::Orientation o = tb->orientation();
       
   152     setUsePopupMenu(!mw || tb->isFloating() || perp(o, expandedSize(mw->size())) >= perp(o, mw->size()));
       
   153 }
       
   154 
       
   155 void QToolBarLayout::addItem(QLayoutItem*)
       
   156 {
       
   157     qWarning() << "QToolBarLayout::addItem(): please use addAction() instead";
       
   158     return;
       
   159 }
       
   160 
       
   161 QLayoutItem *QToolBarLayout::itemAt(int index) const
       
   162 {
       
   163     if (index < 0 || index >= items.count())
       
   164         return 0;
       
   165     return items.at(index);
       
   166 }
       
   167 
       
   168 QLayoutItem *QToolBarLayout::takeAt(int index)
       
   169 {
       
   170     if (index < 0 || index >= items.count())
       
   171         return 0;
       
   172     QToolBarItem *item = items.takeAt(index);
       
   173 
       
   174     if (popupMenu)
       
   175         popupMenu->removeAction(item->action);
       
   176 
       
   177     QWidgetAction *widgetAction = qobject_cast<QWidgetAction*>(item->action);
       
   178     if (widgetAction != 0 && item->customWidget) {
       
   179         widgetAction->releaseWidget(item->widget());
       
   180     } else {
       
   181         // destroy the QToolButton/QToolBarSeparator
       
   182         item->widget()->hide();
       
   183         item->widget()->deleteLater();
       
   184     }
       
   185 
       
   186     invalidate();
       
   187     return item;
       
   188 }
       
   189 
       
   190 void QToolBarLayout::insertAction(int index, QAction *action)
       
   191 {
       
   192     index = qMax(0, index);
       
   193     index = qMin(items.count(), index);
       
   194 
       
   195     QToolBarItem *item = createItem(action);
       
   196     if (item) {
       
   197         items.insert(index, item);
       
   198         invalidate();
       
   199     }
       
   200 }
       
   201 
       
   202 int QToolBarLayout::indexOf(QAction *action) const
       
   203 {
       
   204     for (int i = 0; i < items.count(); ++i) {
       
   205         if (items.at(i)->action == action)
       
   206             return i;
       
   207     }
       
   208     return -1;
       
   209 }
       
   210 
       
   211 int QToolBarLayout::count() const
       
   212 {
       
   213     return items.count();
       
   214 }
       
   215 
       
   216 bool QToolBarLayout::isEmpty() const
       
   217 {
       
   218     if (dirty)
       
   219         updateGeomArray();
       
   220     return empty;
       
   221 }
       
   222 
       
   223 void QToolBarLayout::invalidate()
       
   224 {
       
   225     dirty = true;
       
   226     QLayout::invalidate();
       
   227 }
       
   228 
       
   229 Qt::Orientations QToolBarLayout::expandingDirections() const
       
   230 {
       
   231     if (dirty)
       
   232         updateGeomArray();
       
   233     QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
       
   234     if (!tb)
       
   235         return Qt::Orientations(0);
       
   236     Qt::Orientation o = tb->orientation();
       
   237     return expanding ? Qt::Orientations(o) : Qt::Orientations(0);
       
   238 }
       
   239 
       
   240 bool QToolBarLayout::movable() const
       
   241 {
       
   242     QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
       
   243     if (!tb)
       
   244         return false;
       
   245     QMainWindow *win = qobject_cast<QMainWindow*>(tb->parentWidget());
       
   246     return tb->isMovable() && win != 0;
       
   247 }
       
   248 
       
   249 void QToolBarLayout::updateGeomArray() const
       
   250 {
       
   251     if (!dirty)
       
   252         return;
       
   253 
       
   254     QToolBarLayout *that = const_cast<QToolBarLayout*>(this);
       
   255 
       
   256     QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
       
   257     if (!tb)
       
   258         return;
       
   259     QStyle *style = tb->style();
       
   260     QStyleOptionToolBar opt;
       
   261     tb->initStyleOption(&opt);
       
   262     const int handleExtent = movable()
       
   263             ? style->pixelMetric(QStyle::PM_ToolBarHandleExtent, &opt, tb) : 0;
       
   264     const int margin = this->margin();
       
   265     const int spacing = this->spacing();
       
   266     const int extensionExtent = style->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, tb);
       
   267     Qt::Orientation o = tb->orientation();
       
   268 
       
   269     that->minSize = QSize(0, 0);
       
   270     that->hint = QSize(0, 0);
       
   271     rperp(o, that->minSize) = style->pixelMetric(QStyle::PM_ToolBarHandleExtent, &opt, tb);
       
   272     rperp(o, that->hint) = style->pixelMetric(QStyle::PM_ToolBarHandleExtent, &opt, tb);
       
   273 
       
   274     that->expanding = false;
       
   275     that->empty = false;
       
   276 
       
   277     QVector<QLayoutStruct> a(items.count() + 1); // + 1 for the stretch
       
   278 
       
   279     int count = 0;
       
   280     for (int i = 0; i < items.count(); ++i) {
       
   281         QToolBarItem *item = items.at(i);
       
   282 
       
   283         QSize max = item->maximumSize();
       
   284         QSize min = item->minimumSize();
       
   285         QSize hint = item->sizeHint();
       
   286         Qt::Orientations exp = item->expandingDirections();
       
   287         bool empty = item->isEmpty();
       
   288 
       
   289         that->expanding = expanding || exp & o;
       
   290 
       
   291 
       
   292         if (item->widget()) {
       
   293             if ((item->widget()->sizePolicy().horizontalPolicy() & QSizePolicy::ExpandFlag)) {
       
   294                 that->expandFlag = true;
       
   295             }
       
   296         }
       
   297 
       
   298         if (!empty) {
       
   299             if (count == 0) // the minimum size only displays one widget
       
   300                 rpick(o, that->minSize) += pick(o, min);
       
   301             int s = perp(o, minSize);
       
   302             rperp(o, that->minSize) = qMax(s, perp(o, min));
       
   303 
       
   304             //we only add spacing before item (ie never before the first one)
       
   305             rpick(o, that->hint) += (count == 0 ? 0 : spacing) + pick(o, hint);
       
   306             s = perp(o, that->hint);
       
   307             rperp(o, that->hint) = qMax(s, perp(o, hint));
       
   308             ++count;
       
   309         }
       
   310 
       
   311         a[i].sizeHint = pick(o, hint);
       
   312         a[i].maximumSize = pick(o, max);
       
   313         a[i].minimumSize = pick(o, min);
       
   314         a[i].expansive = exp & o;
       
   315         if (o == Qt::Horizontal)
       
   316             a[i].stretch = item->widget()->sizePolicy().horizontalStretch();
       
   317         else
       
   318             a[i].stretch = item->widget()->sizePolicy().verticalStretch();
       
   319         a[i].empty = empty;
       
   320     }
       
   321 
       
   322     that->geomArray = a;
       
   323     that->empty = count == 0;
       
   324 
       
   325     rpick(o, that->minSize) += handleExtent;
       
   326     that->minSize += QSize(2*margin, 2*margin);
       
   327     if (items.count() > 1)
       
   328         rpick(o, that->minSize) += spacing + extensionExtent;
       
   329 
       
   330     rpick(o, that->hint) += handleExtent;
       
   331     that->hint += QSize(2*margin, 2*margin);
       
   332     that->dirty = false;
       
   333 #ifdef Q_WS_MAC
       
   334     if (QMainWindow *mw = qobject_cast<QMainWindow *>(parentWidget()->parentWidget())) {
       
   335         if (mw->unifiedTitleAndToolBarOnMac()
       
   336                 && mw->toolBarArea(static_cast<QToolBar *>(parentWidget())) == Qt::TopToolBarArea) {
       
   337             if (expandFlag) {
       
   338                 tb->setMaximumSize(0xFFFFFF, 0xFFFFFF);
       
   339             } else {
       
   340                tb->setMaximumSize(hint);
       
   341             }
       
   342         }
       
   343     }
       
   344 #endif
       
   345 
       
   346     that->dirty = false;
       
   347 }
       
   348 
       
   349 static bool defaultWidgetAction(QToolBarItem *item)
       
   350 {
       
   351     QWidgetAction *a = qobject_cast<QWidgetAction*>(item->action);
       
   352     return a != 0 && a->defaultWidget() == item->widget();
       
   353 }
       
   354 
       
   355 void QToolBarLayout::setGeometry(const QRect &rect)
       
   356 {
       
   357     QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
       
   358     if (!tb)
       
   359         return;
       
   360     QStyle *style = tb->style();
       
   361     QStyleOptionToolBar opt;
       
   362     tb->initStyleOption(&opt);
       
   363     const int margin = this->margin();
       
   364     const int extensionExtent = style->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, tb);
       
   365     Qt::Orientation o = tb->orientation();
       
   366 
       
   367     QLayout::setGeometry(rect);
       
   368 
       
   369     bool ranOutOfSpace = false;
       
   370     if (!animating)
       
   371         ranOutOfSpace = layoutActions(rect.size());
       
   372 
       
   373     if (expanded || animating || ranOutOfSpace) {
       
   374         Qt::ToolBarArea area = Qt::TopToolBarArea;
       
   375         if (QMainWindow *win = qobject_cast<QMainWindow*>(tb->parentWidget()))
       
   376             area = win->toolBarArea(tb);
       
   377         QSize hint = sizeHint();
       
   378 
       
   379         QPoint pos;
       
   380         rpick(o, pos) = pick(o, rect.bottomRight()) - margin - extensionExtent + 2;
       
   381         if (area == Qt::LeftToolBarArea || area == Qt::TopToolBarArea)
       
   382             rperp(o, pos) = perp(o, rect.topLeft()) + margin;
       
   383         else
       
   384             rperp(o, pos) = perp(o, rect.bottomRight()) - margin - (perp(o, hint) - 2*margin) + 1;
       
   385         QSize size;
       
   386         rpick(o, size) = extensionExtent;
       
   387         rperp(o, size) = perp(o, hint) - 2*margin;
       
   388         QRect r(pos, size);
       
   389 
       
   390         if (o == Qt::Horizontal)
       
   391             r = QStyle::visualRect(parentWidget()->layoutDirection(), rect, r);
       
   392 
       
   393         extension->setGeometry(r);
       
   394 
       
   395         if (extension->isHidden())
       
   396             extension->show();
       
   397     } else {
       
   398         if (!extension->isHidden())
       
   399             extension->hide();
       
   400     }
       
   401 #ifdef Q_WS_MAC
       
   402     // Nothing to do for Carbon... probably   
       
   403 #  ifdef QT_MAC_USE_COCOA
       
   404     if (QMainWindow *win = qobject_cast<QMainWindow*>(tb->parentWidget())) {
       
   405         Qt::ToolBarArea area = win->toolBarArea(tb);
       
   406         if (win->unifiedTitleAndToolBarOnMac() && area == Qt::TopToolBarArea) {
       
   407             static_cast<QMainWindowLayout *>(win->layout())->fixSizeInUnifiedToolbar(tb);
       
   408         }
       
   409     }
       
   410 #  endif
       
   411 #endif
       
   412     
       
   413 }
       
   414 
       
   415 bool QToolBarLayout::layoutActions(const QSize &size)
       
   416 {
       
   417     if (dirty)
       
   418         updateGeomArray();
       
   419 
       
   420     QRect rect(0, 0, size.width(), size.height());
       
   421 
       
   422     QList<QWidget*> showWidgets, hideWidgets;
       
   423 
       
   424     QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
       
   425     if (!tb)
       
   426         return false;
       
   427     QStyle *style = tb->style();
       
   428     QStyleOptionToolBar opt;
       
   429     tb->initStyleOption(&opt);
       
   430     const int handleExtent = movable()
       
   431             ? style->pixelMetric(QStyle::PM_ToolBarHandleExtent, &opt, tb) : 0;
       
   432     const int margin = this->margin();
       
   433     const int spacing = this->spacing();
       
   434     const int extensionExtent = style->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, tb);
       
   435     Qt::Orientation o = tb->orientation();
       
   436     bool extensionMenuContainsOnlyWidgetActions = true;
       
   437 
       
   438     int space = pick(o, rect.size()) - 2*margin - handleExtent;
       
   439     if (space <= 0)
       
   440         return false;  // nothing to do.
       
   441 
       
   442     if(popupMenu)
       
   443         popupMenu->clear();
       
   444 
       
   445     bool ranOutOfSpace = false;
       
   446     int rows = 0;
       
   447     int rowPos = perp(o, rect.topLeft()) + margin;
       
   448     int i = 0;
       
   449     while (i < items.count()) {
       
   450         QVector<QLayoutStruct> a = geomArray;
       
   451 
       
   452         int start = i;
       
   453         int size = 0;
       
   454         int prev = -1;
       
   455         int rowHeight = 0;
       
   456         int count = 0;
       
   457         int maximumSize = 0;
       
   458         bool expansiveRow = false;
       
   459         for (; i < items.count(); ++i) {
       
   460             if (a[i].empty)
       
   461                 continue;
       
   462 
       
   463             int newSize = size + (count == 0 ? 0 : spacing) + a[i].minimumSize;
       
   464             if (prev != -1 && newSize > space) {
       
   465                 if (rows == 0)
       
   466                     ranOutOfSpace = true;
       
   467                 // do we have to move the previous item to the next line to make space for
       
   468                 // the extension button?
       
   469                 if (count > 1 && size + spacing + extensionExtent > space)
       
   470                     i = prev;
       
   471                 break;
       
   472             }
       
   473 
       
   474             if (expanded)
       
   475                 rowHeight = qMax(rowHeight, perp(o, items.at(i)->sizeHint()));
       
   476             expansiveRow = expansiveRow || a[i].expansive;
       
   477             size = newSize;
       
   478             maximumSize += spacing + (a[i].expansive ? a[i].maximumSize : a[i].smartSizeHint());
       
   479             prev = i;
       
   480             ++count;
       
   481         }
       
   482 
       
   483         // stretch at the end
       
   484         a[i].sizeHint = 0;
       
   485         a[i].maximumSize = QWIDGETSIZE_MAX;
       
   486         a[i].minimumSize = 0;
       
   487         a[i].expansive = true;
       
   488         a[i].stretch = 0;
       
   489         a[i].empty = true;
       
   490 
       
   491         if (expansiveRow && maximumSize < space) {
       
   492             expansiveRow = false;
       
   493             a[i].maximumSize = space - maximumSize;
       
   494         }
       
   495 
       
   496         qGeomCalc(a, start, i - start + (expansiveRow ? 0 : 1), 0,
       
   497                     space - (ranOutOfSpace ? (extensionExtent + spacing) : 0),
       
   498                     spacing);
       
   499 
       
   500         for (int j = start; j < i; ++j) {
       
   501             QToolBarItem *item = items.at(j);
       
   502 
       
   503             if (a[j].empty) {
       
   504                 if (!item->widget()->isHidden())
       
   505                     hideWidgets << item->widget();
       
   506                 continue;
       
   507             }
       
   508 
       
   509             QPoint pos;
       
   510             rpick(o, pos) = margin + handleExtent + a[j].pos;
       
   511             rperp(o, pos) = rowPos;
       
   512             QSize size;
       
   513             rpick(o, size) = a[j].size;
       
   514             if (expanded)
       
   515                 rperp(o, size) = rowHeight;
       
   516             else
       
   517                 rperp(o, size) = perp(o, rect.size()) - 2*margin;
       
   518             QRect r(pos, size);
       
   519 
       
   520             if (o == Qt::Horizontal)
       
   521                 r = QStyle::visualRect(parentWidget()->layoutDirection(), rect, r);
       
   522 
       
   523             item->setGeometry(r);
       
   524 
       
   525             if (item->widget()->isHidden())
       
   526                 showWidgets << item->widget();
       
   527         }
       
   528 
       
   529         if (!expanded) {
       
   530             for (int j = i; j < items.count(); ++j) {
       
   531                 QToolBarItem *item = items.at(j);
       
   532                 if (!item->widget()->isHidden())
       
   533                     hideWidgets << item->widget();
       
   534                 if (popupMenu) {
       
   535                     if (!defaultWidgetAction(item)) {
       
   536                         popupMenu->addAction(item->action);
       
   537                         extensionMenuContainsOnlyWidgetActions = false;
       
   538                     }
       
   539                 }
       
   540             }
       
   541             break;
       
   542         }
       
   543 
       
   544         rowPos += rowHeight + spacing;
       
   545         ++rows;
       
   546     }
       
   547 
       
   548     // if we are using a popup menu, not the expadning toolbar effect, we cannot move custom
       
   549     // widgets into the menu. If only custom widget actions are chopped off, the popup menu
       
   550     // is empty. So we show the little extension button to show something is chopped off,
       
   551     // but we make it disabled.
       
   552     extension->setEnabled(popupMenu == 0 || !extensionMenuContainsOnlyWidgetActions);
       
   553 
       
   554     // we have to do the show/hide here, because it triggers more calls to setGeometry :(
       
   555     for (int i = 0; i < showWidgets.count(); ++i)
       
   556         showWidgets.at(i)->show();
       
   557     for (int i = 0; i < hideWidgets.count(); ++i)
       
   558         hideWidgets.at(i)->hide();
       
   559 
       
   560     return ranOutOfSpace;
       
   561 }
       
   562 
       
   563 QSize QToolBarLayout::expandedSize(const QSize &size) const
       
   564 {
       
   565     if (dirty)
       
   566         updateGeomArray();
       
   567 
       
   568     QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
       
   569     if (!tb)
       
   570         return QSize(0, 0);
       
   571     QMainWindow *win = qobject_cast<QMainWindow*>(tb->parentWidget());
       
   572     Qt::Orientation o = tb->orientation();
       
   573     QStyle *style = tb->style();
       
   574     QStyleOptionToolBar opt;
       
   575     tb->initStyleOption(&opt);
       
   576     const int handleExtent = movable()
       
   577             ? style->pixelMetric(QStyle::PM_ToolBarHandleExtent, &opt, tb) : 0;
       
   578     const int margin = this->margin();
       
   579     const int spacing = this->spacing();
       
   580     const int extensionExtent = style->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, tb);
       
   581 
       
   582     int total_w = 0;
       
   583     int count = 0;
       
   584     for (int x = 0; x < items.count(); ++x) {
       
   585         if (!geomArray[x].empty) {
       
   586             total_w += (count == 0 ? 0 : spacing) + geomArray[x].minimumSize;
       
   587             ++count;
       
   588         }
       
   589     }
       
   590     if (count == 0)
       
   591         return QSize(0, 0);
       
   592 
       
   593     int min_w = pick(o, size);
       
   594     int rows = (int)qSqrt(qreal(count));
       
   595     if (rows == 1)
       
   596         ++rows;      // we want to expand to at least two rows
       
   597     int space = total_w/rows + spacing + extensionExtent;
       
   598     space = qMax(space, min_w - 2*margin - handleExtent);
       
   599     if (win != 0)
       
   600         space = qMin(space, pick(o, win->size()) - 2*margin - handleExtent);
       
   601 
       
   602     int w = 0;
       
   603     int h = 0;
       
   604     int i = 0;
       
   605     while (i < items.count()) {
       
   606         int count = 0;
       
   607         int size = 0;
       
   608         int prev = -1;
       
   609         int rowHeight = 0;
       
   610         for (; i < items.count(); ++i) {
       
   611             if (geomArray[i].empty)
       
   612                 continue;
       
   613 
       
   614             int newSize = size + (count == 0 ? 0 : spacing) + geomArray[i].minimumSize;
       
   615             rowHeight = qMax(rowHeight, perp(o, items.at(i)->sizeHint()));
       
   616             if (prev != -1 && newSize > space) {
       
   617                 if (count > 1 && size + spacing + extensionExtent > space) {
       
   618                     size -= spacing + geomArray[prev].minimumSize;
       
   619                     i = prev;
       
   620                 }
       
   621                 break;
       
   622             }
       
   623 
       
   624             size = newSize;
       
   625             prev = i;
       
   626             ++count;
       
   627         }
       
   628 
       
   629         w = qMax(size, w);
       
   630         h += rowHeight + spacing;
       
   631     }
       
   632 
       
   633     w += 2*margin + handleExtent + spacing + extensionExtent;
       
   634     w = qMax(w, min_w);
       
   635     if (win != 0)
       
   636         w = qMin(w, pick(o, win->size()));
       
   637     h += 2*margin - spacing; //there is no spacing before the first row
       
   638 
       
   639     QSize result;
       
   640     rpick(o, result) = w;
       
   641     rperp(o, result) = h;
       
   642     return result;
       
   643 }
       
   644 
       
   645 void QToolBarLayout::setExpanded(bool exp, bool animated)
       
   646 {
       
   647     if (exp == expanded)
       
   648         return;
       
   649 
       
   650     expanded = exp;
       
   651     extension->setChecked(expanded);
       
   652 
       
   653     QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
       
   654     if (!tb)
       
   655         return;
       
   656     if (QMainWindow *win = qobject_cast<QMainWindow*>(tb->parentWidget())) {
       
   657         animating = true;
       
   658         QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
       
   659         if (expanded) {
       
   660             tb->raise();
       
   661         } else {
       
   662             QList<int> path = layout->layoutState.indexOf(tb);
       
   663             if (!path.isEmpty()) {
       
   664                 QRect rect = layout->layoutState.itemRect(path);
       
   665                 layoutActions(rect.size());
       
   666             }
       
   667         }
       
   668         layout->layoutState.toolBarAreaLayout.apply(animated);
       
   669     }
       
   670 }
       
   671 
       
   672 QSize QToolBarLayout::minimumSize() const
       
   673 {
       
   674     if (dirty)
       
   675         updateGeomArray();
       
   676     return minSize;
       
   677 }
       
   678 
       
   679 QSize QToolBarLayout::sizeHint() const
       
   680 {
       
   681     if (dirty)
       
   682         updateGeomArray();
       
   683     return hint;
       
   684 }
       
   685 
       
   686 QToolBarItem *QToolBarLayout::createItem(QAction *action)
       
   687 {
       
   688     bool customWidget = false;
       
   689     bool standardButtonWidget = false;
       
   690     QWidget *widget = 0;
       
   691     QToolBar *tb = qobject_cast<QToolBar*>(parentWidget());
       
   692     if (!tb)
       
   693         return (QToolBarItem *)0;
       
   694 
       
   695     if (QWidgetAction *widgetAction = qobject_cast<QWidgetAction *>(action)) {
       
   696         widget = widgetAction->requestWidget(tb);
       
   697         if (widget != 0) {
       
   698             widget->setAttribute(Qt::WA_LayoutUsesWidgetRect);
       
   699             customWidget = true;
       
   700         }
       
   701     } else if (action->isSeparator()) {
       
   702         QToolBarSeparator *sep = new QToolBarSeparator(tb);
       
   703         connect(tb, SIGNAL(orientationChanged(Qt::Orientation)),
       
   704                 sep, SLOT(setOrientation(Qt::Orientation)));
       
   705         widget = sep;
       
   706     }
       
   707 
       
   708     if (!widget) {
       
   709         QToolButton *button = new QToolButton(tb);
       
   710         button->setAutoRaise(true);
       
   711         button->setFocusPolicy(Qt::NoFocus);
       
   712         button->setIconSize(tb->iconSize());
       
   713         button->setToolButtonStyle(tb->toolButtonStyle());
       
   714         QObject::connect(tb, SIGNAL(iconSizeChanged(QSize)),
       
   715                          button, SLOT(setIconSize(QSize)));
       
   716         QObject::connect(tb, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
       
   717                          button, SLOT(setToolButtonStyle(Qt::ToolButtonStyle)));
       
   718         button->setDefaultAction(action);
       
   719         QObject::connect(button, SIGNAL(triggered(QAction*)), tb, SIGNAL(actionTriggered(QAction*)));
       
   720         widget = button;
       
   721         standardButtonWidget = true;
       
   722     }
       
   723 
       
   724     widget->hide();
       
   725     QToolBarItem *result = new QToolBarItem(widget);
       
   726     if (standardButtonWidget)
       
   727         result->setAlignment(Qt::AlignJustify);
       
   728     result->customWidget = customWidget;
       
   729     result->action = action;
       
   730     return result;
       
   731 }
       
   732 
       
   733 QT_END_NAMESPACE
       
   734 
       
   735 #endif // QT_NO_TOOLBAR