src/gui/graphicsview/qgridlayoutengine.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 "qglobal.h"
       
    43 
       
    44 #ifndef QT_NO_GRAPHICSVIEW
       
    45 
       
    46 #include <math.h>
       
    47 
       
    48 #include "qgraphicslayoutitem.h"
       
    49 #include "qgridlayoutengine_p.h"
       
    50 #include "qstyleoption.h"
       
    51 #include "qvarlengtharray.h"
       
    52 
       
    53 #include <QtDebug>
       
    54 
       
    55 QT_BEGIN_NAMESPACE
       
    56 
       
    57 template <typename T>
       
    58 static void insertOrRemoveItems(QVector<T> &items, int index, int delta)
       
    59 {
       
    60     int count = items.count();
       
    61     if (index < count) {
       
    62         if (delta > 0) {
       
    63             items.insert(index, delta, T());
       
    64         } else if (delta < 0) {
       
    65             items.remove(index, qMin(-delta, count - index));
       
    66         }
       
    67     }
       
    68 }
       
    69 
       
    70 static qreal growthFactorBelowPreferredSize(qreal desired, qreal sumAvailable, qreal sumDesired)
       
    71 {
       
    72     Q_ASSERT(sumDesired != 0.0);
       
    73     return desired * ::pow(sumAvailable / sumDesired, desired / sumDesired);
       
    74 }
       
    75 
       
    76 static qreal fixedDescent(qreal descent, qreal ascent, qreal targetSize)
       
    77 {
       
    78     if (descent < 0.0)
       
    79         return -1.0;
       
    80 
       
    81     Q_ASSERT(descent >= 0.0);
       
    82     Q_ASSERT(ascent >= 0.0);
       
    83     Q_ASSERT(targetSize >= ascent + descent);
       
    84 
       
    85     qreal extra = targetSize - (ascent + descent);
       
    86     return descent + (extra / 2.0);
       
    87 }
       
    88 
       
    89 static qreal compare(const QGridLayoutBox &box1, const QGridLayoutBox &box2, int which)
       
    90 {
       
    91     qreal size1 = box1.q_sizes(which);
       
    92     qreal size2 = box2.q_sizes(which);
       
    93 
       
    94     if (which == MaximumSize) {
       
    95         return size2 - size1;
       
    96     } else {
       
    97         return size1 - size2;
       
    98     }
       
    99 }
       
   100 
       
   101 void QGridLayoutBox::add(const QGridLayoutBox &other, int stretch, qreal spacing)
       
   102 {
       
   103     Q_ASSERT(q_minimumDescent < 0.0);
       
   104 
       
   105     q_minimumSize += other.q_minimumSize + spacing;
       
   106     q_preferredSize += other.q_preferredSize + spacing;
       
   107     q_maximumSize += ((stretch == 0) ? other.q_preferredSize : other.q_maximumSize) + spacing;
       
   108 }
       
   109 
       
   110 void QGridLayoutBox::combine(const QGridLayoutBox &other)
       
   111 {
       
   112     q_minimumDescent = qMax(q_minimumDescent, other.q_minimumDescent);
       
   113     q_minimumAscent = qMax(q_minimumAscent, other.q_minimumAscent);
       
   114 
       
   115     q_minimumSize = qMax(q_minimumAscent + q_minimumDescent,
       
   116                          qMax(q_minimumSize, other.q_minimumSize));
       
   117     qreal maxMax;
       
   118     if (q_maximumSize == FLT_MAX && other.q_maximumSize != FLT_MAX)
       
   119         maxMax = other.q_maximumSize;
       
   120     else if (other.q_maximumSize == FLT_MAX && q_maximumSize != FLT_MAX)
       
   121         maxMax = q_maximumSize;
       
   122     else
       
   123         maxMax = qMax(q_maximumSize, other.q_maximumSize);
       
   124 
       
   125     q_maximumSize = qMax(q_minimumSize, maxMax);
       
   126     q_preferredSize = qBound(q_minimumSize, qMax(q_preferredSize, other.q_preferredSize),
       
   127                              q_maximumSize);
       
   128 }
       
   129 
       
   130 void QGridLayoutBox::normalize()
       
   131 {
       
   132     q_maximumSize = qMax(qreal(0.0), q_maximumSize);
       
   133     q_minimumSize = qBound(qreal(0.0), q_minimumSize, q_maximumSize);
       
   134     q_preferredSize = qBound(q_minimumSize, q_preferredSize, q_maximumSize);
       
   135     q_minimumDescent = qMin(q_minimumDescent, q_minimumSize);
       
   136 
       
   137     Q_ASSERT((q_minimumDescent < 0.0) == (q_minimumAscent < 0.0));
       
   138 }
       
   139 
       
   140 #ifdef QT_DEBUG
       
   141 void QGridLayoutBox::dump(int indent) const
       
   142 {
       
   143     qDebug("%*sBox (%g <= %g <= %g [%g/%g])", indent, "", q_minimumSize, q_preferredSize,
       
   144            q_maximumSize, q_minimumAscent, q_minimumDescent);
       
   145 }
       
   146 #endif
       
   147 
       
   148 bool operator==(const QGridLayoutBox &box1, const QGridLayoutBox &box2)
       
   149 {
       
   150     for (int i = 0; i < NSizes; ++i) {
       
   151         if (box1.q_sizes(i) != box2.q_sizes(i))
       
   152             return false;
       
   153     }
       
   154     return box1.q_minimumDescent == box2.q_minimumDescent
       
   155            && box1.q_minimumAscent == box2.q_minimumAscent;
       
   156 }
       
   157 
       
   158 void QGridLayoutRowData::reset(int count)
       
   159 {
       
   160     ignore.fill(false, count);
       
   161     boxes.fill(QGridLayoutBox(), count);
       
   162     multiCellMap.clear();
       
   163     stretches.fill(0, count);
       
   164     spacings.fill(0.0, count);
       
   165     hasIgnoreFlag = false;
       
   166 }
       
   167 
       
   168 void QGridLayoutRowData::distributeMultiCells()
       
   169 {
       
   170     MultiCellMap::const_iterator i = multiCellMap.constBegin();
       
   171     for (; i != multiCellMap.constEnd(); ++i) {
       
   172         int start = i.key().first;
       
   173         int span = i.key().second;
       
   174         int end = start + span;
       
   175         const QGridLayoutBox &box = i.value().q_box;
       
   176         int stretch = i.value().q_stretch;
       
   177 
       
   178         QGridLayoutBox totalBox = this->totalBox(start, end);
       
   179         QVarLengthArray<QGridLayoutBox> extras(span);
       
   180         QVarLengthArray<qreal> dummy(span);
       
   181         QVarLengthArray<qreal> newSizes(span);
       
   182 
       
   183         for (int j = 0; j < NSizes; ++j) {
       
   184             qreal extra = compare(totalBox, box, j);
       
   185             if (extra > 0.0) {
       
   186                 calculateGeometries(start, end, totalBox.q_sizes(j), dummy.data(), newSizes.data(),
       
   187                                     0, totalBox);
       
   188 
       
   189                 for (int k = 0; k < span; ++k)
       
   190                     extras[k].q_sizes(j) = newSizes[k];
       
   191             }
       
   192         }
       
   193 
       
   194         for (int k = 0; k < span; ++k) {
       
   195             boxes[start + k].combine(extras[k]);
       
   196             stretches[start + k] = qMax(stretches[start + k], stretch);
       
   197         }
       
   198     }
       
   199     multiCellMap.clear();
       
   200 }
       
   201 
       
   202 void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSize, qreal *positions,
       
   203                                              qreal *sizes, qreal *descents,
       
   204                                              const QGridLayoutBox &totalBox)
       
   205 {
       
   206     Q_ASSERT(end > start);
       
   207 
       
   208     targetSize = qBound(totalBox.q_minimumSize, targetSize, totalBox.q_maximumSize);
       
   209 
       
   210     int n = end - start;
       
   211     QVarLengthArray<qreal> newSizes(n);
       
   212     QVarLengthArray<qreal> factors(n);
       
   213     qreal sumFactors = 0.0;
       
   214     int sumStretches = 0;
       
   215     qreal sumAvailable;
       
   216 
       
   217     for (int i = 0; i < n; ++i) {
       
   218         if (stretches[start + i] > 0)
       
   219             sumStretches += stretches[start + i];
       
   220     }
       
   221 
       
   222     if (targetSize < totalBox.q_preferredSize) {
       
   223         stealBox(start, end, MinimumSize, positions, sizes);
       
   224 
       
   225         sumAvailable = targetSize - totalBox.q_minimumSize;
       
   226         if (sumAvailable > 0.0) {
       
   227             qreal sumDesired = totalBox.q_preferredSize - totalBox.q_minimumSize;
       
   228 
       
   229             for (int i = 0; i < n; ++i) {
       
   230                 if (ignore.testBit(start + i)) {
       
   231                     factors[i] = 0.0;
       
   232                     continue;
       
   233                 }
       
   234 
       
   235                 const QGridLayoutBox &box = boxes.at(start + i);
       
   236                 qreal desired = box.q_preferredSize - box.q_minimumSize;
       
   237                 factors[i] = growthFactorBelowPreferredSize(desired, sumAvailable, sumDesired);
       
   238                 sumFactors += factors[i];
       
   239             }
       
   240 
       
   241             for (int i = 0; i < n; ++i) {
       
   242                 Q_ASSERT(sumFactors > 0.0);
       
   243                 qreal delta = sumAvailable * factors[i] / sumFactors;
       
   244                 newSizes[i] = sizes[i] + delta;
       
   245             }
       
   246         }
       
   247     } else {
       
   248         stealBox(start, end, PreferredSize, positions, sizes);
       
   249 
       
   250         sumAvailable = targetSize - totalBox.q_preferredSize;
       
   251         if (sumAvailable > 0.0) {
       
   252             bool somethingHasAMaximumSize = false;
       
   253 
       
   254             qreal sumPreferredSizes = 0.0;
       
   255             for (int i = 0; i < n; ++i)
       
   256                 sumPreferredSizes += sizes[i];
       
   257 
       
   258             for (int i = 0; i < n; ++i) {
       
   259                 if (ignore.testBit(start + i)) {
       
   260                     newSizes[i] = 0.0;
       
   261                     factors[i] = 0.0;
       
   262                     continue;
       
   263                 }
       
   264 
       
   265                 const QGridLayoutBox &box = boxes.at(start + i);
       
   266                 qreal desired = box.q_maximumSize - box.q_preferredSize;
       
   267                 if (desired == 0.0) {
       
   268                     newSizes[i] = sizes[i];
       
   269                     factors[i] = 0.0;
       
   270                 } else {
       
   271                     Q_ASSERT(desired > 0.0);
       
   272 
       
   273                     int stretch = stretches[start + i];
       
   274                     if (sumStretches == 0) {
       
   275                         if (hasIgnoreFlag) {
       
   276                             factors[i] = (stretch < 0) ? 1.0 : 0.0;
       
   277                         } else {
       
   278                             factors[i] = (stretch < 0) ? sizes[i] : 0.0;
       
   279                         }
       
   280                     } else if (stretch == sumStretches) {
       
   281                         factors[i] = 1.0;
       
   282                     } else if (stretch <= 0) {
       
   283                         factors[i] = 0.0;
       
   284                     } else {
       
   285                         qreal ultimatePreferredSize;
       
   286                         qreal ultimateSumPreferredSizes;
       
   287                         qreal x = ((stretch * sumPreferredSizes)
       
   288                                    - (sumStretches * box.q_preferredSize))
       
   289                                   / (sumStretches - stretch);
       
   290                         if (x >= 0.0) {
       
   291                             ultimatePreferredSize = box.q_preferredSize + x;
       
   292                             ultimateSumPreferredSizes = sumPreferredSizes + x;
       
   293                         } else {
       
   294                             ultimatePreferredSize = box.q_preferredSize;
       
   295                             ultimateSumPreferredSizes = (sumStretches * box.q_preferredSize)
       
   296                                                         / stretch;
       
   297                         }
       
   298 
       
   299                         /*
       
   300                             We multiply these by 1.5 to give some space for a smooth transition
       
   301                             (at the expense of the stretch factors, which are not fully respected
       
   302                             during the transition).
       
   303                         */
       
   304                         ultimatePreferredSize = ultimatePreferredSize * 3 / 2;
       
   305                         ultimateSumPreferredSizes = ultimateSumPreferredSizes * 3 / 2;
       
   306 
       
   307                         qreal ultimateFactor = (stretch * ultimateSumPreferredSizes
       
   308                                                 / sumStretches)
       
   309                                                - (box.q_preferredSize);
       
   310                         qreal transitionalFactor = sumAvailable
       
   311                                                    * (ultimatePreferredSize - box.q_preferredSize)
       
   312                                                    / (ultimateSumPreferredSizes
       
   313                                                       - sumPreferredSizes);
       
   314 
       
   315                         qreal alpha = qMin(sumAvailable,
       
   316                                            ultimateSumPreferredSizes - sumPreferredSizes);
       
   317                         qreal beta = ultimateSumPreferredSizes - sumPreferredSizes;
       
   318 
       
   319                         factors[i] = ((alpha * ultimateFactor)
       
   320                                       + ((beta - alpha) * transitionalFactor)) / beta;
       
   321                     }
       
   322                     sumFactors += factors[i];
       
   323                     if (desired < sumAvailable)
       
   324                         somethingHasAMaximumSize = true;
       
   325 
       
   326                     newSizes[i] = -1.0;
       
   327                 }
       
   328             }
       
   329 
       
   330             bool keepGoing = somethingHasAMaximumSize;
       
   331             while (keepGoing) {
       
   332                 keepGoing = false;
       
   333 
       
   334                 for (int i = 0; i < n; ++i) {
       
   335                     if (newSizes[i] >= 0.0)
       
   336                         continue;
       
   337 
       
   338                     const QGridLayoutBox &box = boxes.at(start + i);
       
   339                     qreal avail = sumAvailable * factors[i] / sumFactors;
       
   340                     if (sizes[i] + avail >= box.q_maximumSize) {
       
   341                         newSizes[i] = box.q_maximumSize;
       
   342                         sumAvailable -= box.q_maximumSize - sizes[i];
       
   343                         sumFactors -= factors[i];
       
   344                         keepGoing = (sumAvailable > 0.0);
       
   345                         if (!keepGoing)
       
   346                             break;
       
   347                     }
       
   348                 }
       
   349             }
       
   350 
       
   351             for (int i = 0; i < n; ++i) {
       
   352                 if (newSizes[i] < 0.0) {
       
   353                     qreal delta = (sumFactors == 0.0) ? 0.0
       
   354                                                       : sumAvailable * factors[i] / sumFactors;
       
   355                     newSizes[i] = sizes[i] + delta;
       
   356                 }
       
   357             }
       
   358         }
       
   359     }
       
   360 
       
   361     if (sumAvailable > 0) {
       
   362         qreal offset = 0;
       
   363         for (int i = 0; i < n; ++i) {
       
   364             qreal delta = newSizes[i] - sizes[i];
       
   365             positions[i] += offset;
       
   366             sizes[i] += delta;
       
   367             offset += delta;
       
   368         }
       
   369 
       
   370 #if 0 // some "pixel allocation"
       
   371         int surplus = targetSize - (positions[n - 1] + sizes[n - 1]);
       
   372         Q_ASSERT(surplus >= 0 && surplus <= n);
       
   373 
       
   374         int prevSurplus = -1;
       
   375         while (surplus > 0 && surplus != prevSurplus) {
       
   376             prevSurplus = surplus;
       
   377 
       
   378             int offset = 0;
       
   379             for (int i = 0; i < n; ++i) {
       
   380                 const QGridLayoutBox &box = boxes.at(start + i);
       
   381                 int delta = (!ignore.testBit(start + i) && surplus > 0
       
   382                              && factors[i] > 0 && sizes[i] < box.q_maximumSize)
       
   383                     ? 1 : 0;
       
   384 
       
   385                 positions[i] += offset;
       
   386                 sizes[i] += delta;
       
   387                 offset += delta;
       
   388                 surplus -= delta;
       
   389             }
       
   390         }
       
   391         Q_ASSERT(surplus == 0);
       
   392 #endif
       
   393     }
       
   394 
       
   395     if (descents) {
       
   396         for (int i = 0; i < n; ++i) {
       
   397             if (ignore.testBit(start + i))
       
   398                 continue;
       
   399             const QGridLayoutBox &box = boxes.at(start + i);
       
   400             descents[i] = fixedDescent(box.q_minimumDescent, box.q_minimumAscent, sizes[i]);
       
   401         }
       
   402     }
       
   403 }
       
   404 
       
   405 QGridLayoutBox QGridLayoutRowData::totalBox(int start, int end) const
       
   406 {
       
   407     QGridLayoutBox result;
       
   408     if (start < end) {
       
   409         result.q_maximumSize = 0.0;
       
   410         qreal nextSpacing = 0.0;
       
   411         for (int i = start; i < end; ++i) {
       
   412             result.add(boxes.at(i), stretches.at(i), nextSpacing);
       
   413             nextSpacing = spacings.at(i);
       
   414         }
       
   415     }
       
   416     return result;
       
   417 }
       
   418 
       
   419 void QGridLayoutRowData::stealBox(int start, int end, int which, qreal *positions, qreal *sizes)
       
   420 {
       
   421     qreal offset = 0.0;
       
   422     qreal nextSpacing = 0.0;
       
   423 
       
   424     for (int i = start; i < end; ++i) {
       
   425         qreal avail = 0.0;
       
   426 
       
   427         if (!ignore.testBit(i)) {
       
   428             const QGridLayoutBox &box = boxes.at(i);
       
   429             avail = box.q_sizes(which);
       
   430             offset += nextSpacing;
       
   431             nextSpacing = spacings.at(i);
       
   432         }
       
   433 
       
   434         *positions++ = offset;
       
   435         *sizes++ = avail;
       
   436         offset += avail;
       
   437     }
       
   438 }
       
   439 
       
   440 #ifdef QT_DEBUG
       
   441 void QGridLayoutRowData::dump(int indent) const
       
   442 {
       
   443     qDebug("%*sData", indent, "");
       
   444 
       
   445     for (int i = 0; i < ignore.count(); ++i) {
       
   446         qDebug("%*s Row %d (stretch %d, spacing %g)", indent, "", i, stretches.at(i),
       
   447                spacings.at(i));
       
   448         if (ignore.testBit(i))
       
   449             qDebug("%*s  Ignored", indent, "");
       
   450         boxes.at(i).dump(indent + 2);
       
   451     }
       
   452 
       
   453     MultiCellMap::const_iterator it = multiCellMap.constBegin();
       
   454     while (it != multiCellMap.constEnd()) {
       
   455         qDebug("%*s Multi-cell entry <%d, %d> (stretch %d)", indent, "", it.key().first,
       
   456                it.key().second, it.value().q_stretch);
       
   457         it.value().q_box.dump(indent + 2);
       
   458     }
       
   459 }
       
   460 #endif
       
   461 
       
   462 QGridLayoutItem::QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem *layoutItem,
       
   463                                  int row, int column, int rowSpan, int columnSpan,
       
   464                                  Qt::Alignment alignment, int itemAtIndex)
       
   465     : q_engine(engine), q_layoutItem(layoutItem), q_alignment(alignment)
       
   466 {
       
   467     q_firstRows[Hor] = column;
       
   468     q_firstRows[Ver] = row;
       
   469     q_rowSpans[Hor] = columnSpan;
       
   470     q_rowSpans[Ver] = rowSpan;
       
   471     q_stretches[Hor] = -1;
       
   472     q_stretches[Ver] = -1;
       
   473 
       
   474     q_engine->insertItem(this, itemAtIndex);
       
   475 }
       
   476 
       
   477 int QGridLayoutItem::firstRow(Qt::Orientation orientation) const
       
   478 {
       
   479     return q_firstRows[orientation == Qt::Vertical];
       
   480 }
       
   481 
       
   482 int QGridLayoutItem::firstColumn(Qt::Orientation orientation) const
       
   483 {
       
   484     return q_firstRows[orientation == Qt::Horizontal];
       
   485 }
       
   486 
       
   487 int QGridLayoutItem::lastRow(Qt::Orientation orientation) const
       
   488 {
       
   489     return firstRow(orientation) + rowSpan(orientation) - 1;
       
   490 }
       
   491 
       
   492 int QGridLayoutItem::lastColumn(Qt::Orientation orientation) const
       
   493 {
       
   494     return firstColumn(orientation) + columnSpan(orientation) - 1;
       
   495 }
       
   496 
       
   497 int QGridLayoutItem::rowSpan(Qt::Orientation orientation) const
       
   498 {
       
   499     return q_rowSpans[orientation == Qt::Vertical];
       
   500 }
       
   501 
       
   502 int QGridLayoutItem::columnSpan(Qt::Orientation orientation) const
       
   503 {
       
   504     return q_rowSpans[orientation == Qt::Horizontal];
       
   505 }
       
   506 
       
   507 void QGridLayoutItem::setFirstRow(int row, Qt::Orientation orientation)
       
   508 {
       
   509     q_firstRows[orientation == Qt::Vertical] = row;
       
   510 }
       
   511 
       
   512 void QGridLayoutItem::setRowSpan(int rowSpan, Qt::Orientation orientation)
       
   513 {
       
   514     q_rowSpans[orientation == Qt::Vertical] = rowSpan;
       
   515 }
       
   516 
       
   517 int QGridLayoutItem::stretchFactor(Qt::Orientation orientation) const
       
   518 {
       
   519     int stretch = q_stretches[orientation == Qt::Vertical];
       
   520     if (stretch >= 0)
       
   521         return stretch;
       
   522 
       
   523     QSizePolicy::Policy policy = sizePolicy(orientation);
       
   524 
       
   525     if (policy & QSizePolicy::ExpandFlag) {
       
   526         return 1;
       
   527     } else if (policy & QSizePolicy::GrowFlag) {
       
   528         return -1;  // because we max it up
       
   529     } else {
       
   530         return 0;
       
   531     }
       
   532 }
       
   533 
       
   534 void QGridLayoutItem::setStretchFactor(int stretch, Qt::Orientation orientation)
       
   535 {
       
   536     Q_ASSERT(stretch >= 0); // ### deal with too big stretches
       
   537     q_stretches[orientation == Qt::Vertical] = stretch;
       
   538 }
       
   539 
       
   540 QSizePolicy::Policy QGridLayoutItem::sizePolicy(Qt::Orientation orientation) const
       
   541 {
       
   542     QSizePolicy sizePolicy(q_layoutItem->sizePolicy());
       
   543     return (orientation == Qt::Horizontal) ? sizePolicy.horizontalPolicy()
       
   544                                            : sizePolicy.verticalPolicy();
       
   545 }
       
   546 
       
   547 QSizePolicy::ControlTypes QGridLayoutItem::controlTypes(LayoutSide /* side */) const
       
   548 {
       
   549     return q_layoutItem->sizePolicy().controlType();
       
   550 }
       
   551 
       
   552 QSizeF QGridLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
       
   553 {
       
   554     return q_layoutItem->effectiveSizeHint(which, constraint);
       
   555 }
       
   556 
       
   557 QGridLayoutBox QGridLayoutItem::box(Qt::Orientation orientation, qreal constraint) const
       
   558 {
       
   559     QGridLayoutBox result;
       
   560     QSizePolicy::Policy policy = sizePolicy(orientation);
       
   561 
       
   562     if (orientation == Qt::Horizontal) {
       
   563         QSizeF constraintSize(-1.0, constraint);
       
   564 
       
   565         result.q_preferredSize = sizeHint(Qt::PreferredSize, constraintSize).width();
       
   566 
       
   567         if (policy & QSizePolicy::ShrinkFlag) {
       
   568             result.q_minimumSize = sizeHint(Qt::MinimumSize, constraintSize).width();
       
   569         } else {
       
   570             result.q_minimumSize = result.q_preferredSize;
       
   571         }
       
   572 
       
   573         if (policy & (QSizePolicy::GrowFlag | QSizePolicy::ExpandFlag)) {
       
   574             result.q_maximumSize = sizeHint(Qt::MaximumSize, constraintSize).width();
       
   575         } else {
       
   576             result.q_maximumSize = result.q_preferredSize;
       
   577         }
       
   578     } else {
       
   579         QSizeF constraintSize(constraint, -1.0);
       
   580 
       
   581         result.q_preferredSize = sizeHint(Qt::PreferredSize, constraintSize).height();
       
   582 
       
   583         if (policy & QSizePolicy::ShrinkFlag) {
       
   584             result.q_minimumSize = sizeHint(Qt::MinimumSize, constraintSize).height();
       
   585         } else {
       
   586             result.q_minimumSize = result.q_preferredSize;
       
   587         }
       
   588 
       
   589         if (policy & (QSizePolicy::GrowFlag | QSizePolicy::ExpandFlag)) {
       
   590             result.q_maximumSize = sizeHint(Qt::MaximumSize, constraintSize).height();
       
   591         } else {
       
   592             result.q_maximumSize = result.q_preferredSize;
       
   593         }
       
   594 
       
   595         result.q_minimumDescent = sizeHint(Qt::MinimumDescent, constraintSize).height();
       
   596         if (result.q_minimumDescent >= 0.0)
       
   597             result.q_minimumAscent = result.q_minimumSize - result.q_minimumDescent;
       
   598     }
       
   599     if (policy & QSizePolicy::IgnoreFlag)
       
   600         result.q_preferredSize = result.q_minimumSize;
       
   601 
       
   602     return result;
       
   603 }
       
   604 
       
   605 QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal height,
       
   606                                        qreal rowDescent) const
       
   607 {
       
   608     rowDescent = -1.0; // ### This disables the descent
       
   609 
       
   610     QGridLayoutBox vBox = box(Qt::Vertical);
       
   611     if (vBox.q_minimumDescent < 0.0 || rowDescent < 0.0) {
       
   612         qreal cellWidth = width;
       
   613         qreal cellHeight = height;
       
   614 
       
   615         QSizeF size = effectiveMaxSize().boundedTo(QSizeF(cellWidth, cellHeight));
       
   616         width = size.width();
       
   617         height = size.height();
       
   618 
       
   619         Qt::Alignment align = q_engine->effectiveAlignment(this);
       
   620         switch (align & Qt::AlignHorizontal_Mask) {
       
   621         case Qt::AlignHCenter:
       
   622             x += (cellWidth - width)/2;
       
   623             break;
       
   624         case Qt::AlignRight:
       
   625             x += cellWidth - width;
       
   626             break;
       
   627         default:
       
   628             break;
       
   629         }
       
   630         switch (align & Qt::AlignVertical_Mask) {
       
   631         case Qt::AlignVCenter:
       
   632             y += (cellHeight - height)/2;
       
   633             break;
       
   634         case Qt::AlignBottom:
       
   635             y += cellHeight - height;
       
   636             break;
       
   637         default:
       
   638             break;
       
   639         }
       
   640         return QRectF(x, y, width, height);
       
   641     } else {
       
   642         qreal descent = vBox.q_minimumDescent;
       
   643         qreal ascent = vBox.q_minimumSize - descent;
       
   644         return QRectF(x, y + height - rowDescent - ascent, width, ascent + descent);
       
   645     }
       
   646 }
       
   647 
       
   648 void QGridLayoutItem::setGeometry(const QRectF &rect)
       
   649 {
       
   650     q_layoutItem->setGeometry(rect);
       
   651 }
       
   652 
       
   653 void QGridLayoutItem::transpose()
       
   654 {
       
   655     qSwap(q_firstRows[Hor], q_firstRows[Ver]);
       
   656     qSwap(q_rowSpans[Hor], q_rowSpans[Ver]);
       
   657     qSwap(q_stretches[Hor], q_stretches[Ver]);
       
   658 }
       
   659 
       
   660 void QGridLayoutItem::insertOrRemoveRows(int row, int delta, Qt::Orientation orientation)
       
   661 {
       
   662     int oldFirstRow = firstRow(orientation);
       
   663     if (oldFirstRow >= row) {
       
   664         setFirstRow(oldFirstRow + delta, orientation);
       
   665     } else if (lastRow(orientation) >= row) {
       
   666         setRowSpan(rowSpan(orientation) + delta, orientation);
       
   667     }
       
   668 }
       
   669 /*!
       
   670     \internal
       
   671     returns the effective maximumSize, will take the sizepolicy into
       
   672     consideration. (i.e. if sizepolicy does not have QSizePolicy::Grow, then
       
   673     maxSizeHint will be the preferredSize)
       
   674     Note that effectiveSizeHint does not take sizePolicy into consideration,
       
   675     (since it only evaluates the hints, as the name implies)
       
   676 */
       
   677 QSizeF QGridLayoutItem::effectiveMaxSize() const
       
   678 {
       
   679     QSizeF size;
       
   680     bool vGrow = (sizePolicy(Qt::Vertical) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag;
       
   681     bool hGrow = (sizePolicy(Qt::Horizontal) & QSizePolicy::GrowFlag) == QSizePolicy::GrowFlag;
       
   682     if (!vGrow || !hGrow) {
       
   683         QSizeF pref = layoutItem()->effectiveSizeHint(Qt::PreferredSize);
       
   684         if (!vGrow)
       
   685             size.setHeight(pref.height());
       
   686         if (!hGrow)
       
   687             size.setWidth(pref.width());
       
   688     }
       
   689 
       
   690     if (!size.isValid()) {
       
   691         QSizeF maxSize = layoutItem()->effectiveSizeHint(Qt::MaximumSize);
       
   692         if (size.width() == -1)
       
   693             size.setWidth(maxSize.width());
       
   694         if (size.height() == -1)
       
   695             size.setHeight(maxSize.height());
       
   696     }
       
   697     return size;
       
   698 }
       
   699 
       
   700 #ifdef QT_DEBUG
       
   701 void QGridLayoutItem::dump(int indent) const
       
   702 {
       
   703     qDebug("%*s%p (%d, %d) %d x %d", indent, "", q_layoutItem, firstRow(), firstColumn(),
       
   704            rowSpan(), columnSpan());
       
   705 
       
   706     if (q_stretches[Hor] >= 0)
       
   707         qDebug("%*s Horizontal stretch: %d", indent, "", q_stretches[Hor]);
       
   708     if (q_stretches[Ver] >= 0)
       
   709         qDebug("%*s Vertical stretch: %d", indent, "", q_stretches[Ver]);
       
   710     if (q_alignment != 0)
       
   711         qDebug("%*s Alignment: %x", indent, "", uint(q_alignment));
       
   712     qDebug("%*s Horizontal size policy: %x Vertical size policy: %x",
       
   713         indent, "", sizePolicy(Qt::Horizontal), sizePolicy(Qt::Vertical));
       
   714 }
       
   715 #endif
       
   716 
       
   717 void QGridLayoutRowInfo::insertOrRemoveRows(int row, int delta)
       
   718 {
       
   719     count += delta;
       
   720 
       
   721     insertOrRemoveItems(stretches, row, delta);
       
   722     insertOrRemoveItems(spacings, row, delta);
       
   723     insertOrRemoveItems(alignments, row, delta);
       
   724     insertOrRemoveItems(boxes, row, delta);
       
   725 }
       
   726 
       
   727 #ifdef QT_DEBUG
       
   728 void QGridLayoutRowInfo::dump(int indent) const
       
   729 {
       
   730     qDebug("%*sInfo (count: %d)", indent, "", count);
       
   731     for (int i = 0; i < count; ++i) {
       
   732         QString message;
       
   733 
       
   734         if (stretches.value(i).value() >= 0)
       
   735             message += QString::fromAscii(" stretch %1").arg(stretches.value(i).value());
       
   736         if (spacings.value(i).value() >= 0.0)
       
   737             message += QString::fromAscii(" spacing %1").arg(spacings.value(i).value());
       
   738         if (alignments.value(i) != 0)
       
   739             message += QString::fromAscii(" alignment %1").arg(int(alignments.value(i)), 16);
       
   740 
       
   741         if (!message.isEmpty() || boxes.value(i) != QGridLayoutBox()) {
       
   742             qDebug("%*s Row %d:%s", indent, "", i, qPrintable(message));
       
   743             if (boxes.value(i) != QGridLayoutBox())
       
   744                 boxes.value(i).dump(indent + 1);
       
   745         }
       
   746     }
       
   747 }
       
   748 #endif
       
   749 
       
   750 QGridLayoutEngine::QGridLayoutEngine()
       
   751 {
       
   752     m_visualDirection = Qt::LeftToRight;
       
   753     invalidate();
       
   754 }
       
   755 
       
   756 int QGridLayoutEngine::rowCount(Qt::Orientation orientation) const
       
   757 {
       
   758     return q_infos[orientation == Qt::Vertical].count;
       
   759 }
       
   760 
       
   761 int QGridLayoutEngine::columnCount(Qt::Orientation orientation) const
       
   762 {
       
   763     return q_infos[orientation == Qt::Horizontal].count;
       
   764 }
       
   765 
       
   766 int QGridLayoutEngine::itemCount() const
       
   767 {
       
   768     return q_items.count();
       
   769 }
       
   770 
       
   771 QGridLayoutItem *QGridLayoutEngine::itemAt(int index) const
       
   772 {
       
   773     Q_ASSERT(index >= 0 && index < itemCount());
       
   774     return q_items.at(index);
       
   775 }
       
   776 
       
   777 int QGridLayoutEngine::effectiveFirstRow(Qt::Orientation orientation) const
       
   778 {
       
   779     ensureEffectiveFirstAndLastRows();
       
   780     return q_cachedEffectiveFirstRows[orientation == Qt::Vertical];
       
   781 }
       
   782 
       
   783 int QGridLayoutEngine::effectiveLastRow(Qt::Orientation orientation) const
       
   784 {
       
   785     ensureEffectiveFirstAndLastRows();
       
   786     return q_cachedEffectiveLastRows[orientation == Qt::Vertical];
       
   787 }
       
   788 
       
   789 void QGridLayoutEngine::setSpacing(qreal spacing, Qt::Orientations orientations)
       
   790 {
       
   791     Q_ASSERT(spacing >= 0.0);
       
   792     if (orientations & Qt::Horizontal)
       
   793         q_defaultSpacings[Hor].setUserValue(spacing);
       
   794     if (orientations & Qt::Vertical)
       
   795         q_defaultSpacings[Ver].setUserValue(spacing);
       
   796 
       
   797     invalidate();
       
   798 }
       
   799 
       
   800 qreal QGridLayoutEngine::spacing(const QLayoutStyleInfo &styleInfo, Qt::Orientation orientation) const
       
   801 {
       
   802     if (q_defaultSpacings[orientation == Qt::Vertical].isDefault()) {
       
   803         QStyle *style = styleInfo.style();
       
   804         QStyleOption option;
       
   805         option.initFrom(styleInfo.widget());
       
   806         qreal defaultSpacing = (qreal)style->pixelMetric(orientation == Qt::Vertical ? QStyle::PM_LayoutVerticalSpacing
       
   807                                                : QStyle::PM_LayoutHorizontalSpacing, &option, styleInfo.widget());
       
   808         q_defaultSpacings[orientation == Qt::Vertical].setCachedValue(defaultSpacing);
       
   809     }
       
   810     return q_defaultSpacings[orientation == Qt::Vertical].value();
       
   811 }
       
   812 
       
   813 void QGridLayoutEngine::setRowSpacing(int row, qreal spacing, Qt::Orientation orientation)
       
   814 {
       
   815     Q_ASSERT(row >= 0);
       
   816 
       
   817     QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical];
       
   818     if (row >= rowInfo.spacings.count())
       
   819         rowInfo.spacings.resize(row + 1);
       
   820     if (spacing >= 0)
       
   821         rowInfo.spacings[row].setUserValue(spacing);
       
   822     else
       
   823         rowInfo.spacings[row] = QLayoutParameter<qreal>();
       
   824     invalidate();
       
   825 }
       
   826 
       
   827 qreal QGridLayoutEngine::rowSpacing(int row, Qt::Orientation orientation) const
       
   828 {
       
   829     QLayoutParameter<qreal> spacing = q_infos[orientation == Qt::Vertical].spacings.value(row);
       
   830     if (!spacing.isDefault())
       
   831         return spacing.value();
       
   832     return q_defaultSpacings[orientation == Qt::Vertical].value();
       
   833 }
       
   834 
       
   835 void QGridLayoutEngine::setRowStretchFactor(int row, int stretch, Qt::Orientation orientation)
       
   836 {
       
   837     Q_ASSERT(row >= 0);
       
   838     Q_ASSERT(stretch >= 0);
       
   839 
       
   840     maybeExpandGrid(row, -1, orientation);
       
   841 
       
   842     QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical];
       
   843     if (row >= rowInfo.stretches.count())
       
   844         rowInfo.stretches.resize(row + 1);
       
   845     rowInfo.stretches[row].setUserValue(stretch);
       
   846 }
       
   847 
       
   848 int QGridLayoutEngine::rowStretchFactor(int row, Qt::Orientation orientation) const
       
   849 {
       
   850     QStretchParameter stretch = q_infos[orientation == Qt::Vertical].stretches.value(row);
       
   851     if (!stretch.isDefault())
       
   852         return stretch.value();
       
   853     return 0;
       
   854 }
       
   855 
       
   856 void QGridLayoutEngine::setStretchFactor(QGraphicsLayoutItem *layoutItem, int stretch,
       
   857                                          Qt::Orientation orientation)
       
   858 {
       
   859     Q_ASSERT(stretch >= 0);
       
   860 
       
   861     if (QGridLayoutItem *item = findLayoutItem(layoutItem))
       
   862         item->setStretchFactor(stretch, orientation);
       
   863 }
       
   864 
       
   865 int QGridLayoutEngine::stretchFactor(QGraphicsLayoutItem *layoutItem, Qt::Orientation orientation) const
       
   866 {
       
   867     if (QGridLayoutItem *item = findLayoutItem(layoutItem))
       
   868         return item->stretchFactor(orientation);
       
   869     return 0;
       
   870 }
       
   871 
       
   872 void QGridLayoutEngine::setRowSizeHint(Qt::SizeHint which, int row, qreal size,
       
   873                                        Qt::Orientation orientation)
       
   874 {
       
   875     Q_ASSERT(row >= 0);
       
   876     Q_ASSERT(size >= 0.0);
       
   877 
       
   878     maybeExpandGrid(row, -1, orientation);
       
   879 
       
   880     QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical];
       
   881     if (row >= rowInfo.boxes.count())
       
   882         rowInfo.boxes.resize(row + 1);
       
   883     rowInfo.boxes[row].q_sizes(which) = size;
       
   884 }
       
   885 
       
   886 qreal QGridLayoutEngine::rowSizeHint(Qt::SizeHint which, int row, Qt::Orientation orientation) const
       
   887 {
       
   888     return q_infos[orientation == Qt::Vertical].boxes.value(row).q_sizes(which);
       
   889 }
       
   890 
       
   891 void QGridLayoutEngine::setRowAlignment(int row, Qt::Alignment alignment,
       
   892                                         Qt::Orientation orientation)
       
   893 {
       
   894     Q_ASSERT(row >= 0);
       
   895 
       
   896     maybeExpandGrid(row, -1, orientation);
       
   897 
       
   898     QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical];
       
   899     if (row >= rowInfo.alignments.count())
       
   900         rowInfo.alignments.resize(row + 1);
       
   901     rowInfo.alignments[row] = alignment;
       
   902 }
       
   903 
       
   904 Qt::Alignment QGridLayoutEngine::rowAlignment(int row, Qt::Orientation orientation) const
       
   905 {
       
   906     Q_ASSERT(row >= 0);
       
   907     return q_infos[orientation == Qt::Vertical].alignments.value(row);
       
   908 }
       
   909 
       
   910 void QGridLayoutEngine::setAlignment(QGraphicsLayoutItem *layoutItem, Qt::Alignment alignment)
       
   911 {
       
   912     if (QGridLayoutItem *item = findLayoutItem(layoutItem))
       
   913         item->setAlignment(alignment);
       
   914     invalidate();
       
   915 }
       
   916 
       
   917 Qt::Alignment QGridLayoutEngine::alignment(QGraphicsLayoutItem *layoutItem) const
       
   918 {
       
   919     if (QGridLayoutItem *item = findLayoutItem(layoutItem))
       
   920         return item->alignment();
       
   921     return 0;
       
   922 }
       
   923 
       
   924 Qt::Alignment QGridLayoutEngine::effectiveAlignment(const QGridLayoutItem *layoutItem) const
       
   925 {
       
   926     Qt::Alignment align = layoutItem->alignment();
       
   927     if (!(align & Qt::AlignVertical_Mask)) {
       
   928         // no vertical alignment, respect the row alignment
       
   929         int y = layoutItem->firstRow();
       
   930         align |= (rowAlignment(y, Qt::Vertical) & Qt::AlignVertical_Mask);
       
   931     }
       
   932     if (!(align & Qt::AlignHorizontal_Mask)) {
       
   933         // no horizontal alignment, respect the column alignment
       
   934         int x = layoutItem->firstColumn();
       
   935         align |= (rowAlignment(x, Qt::Horizontal) & Qt::AlignHorizontal_Mask);
       
   936     }
       
   937     return align;
       
   938 }
       
   939 
       
   940 /*!
       
   941     \internal
       
   942     The \a index is only used by QGraphicsLinearLayout to ensure that itemAt() reflects the order
       
   943     of visual arrangement. Strictly speaking it does not have to, but most people expect it to.
       
   944     (And if it didn't we would have to add itemArrangedAt(int index) or something..)
       
   945  */
       
   946 void QGridLayoutEngine::insertItem(QGridLayoutItem *item, int index)
       
   947 {
       
   948     maybeExpandGrid(item->lastRow(), item->lastColumn());
       
   949 
       
   950     if (index == -1)
       
   951         q_items.append(item);
       
   952     else
       
   953         q_items.insert(index, item);
       
   954 
       
   955     for (int i = item->firstRow(); i <= item->lastRow(); ++i) {
       
   956         for (int j = item->firstColumn(); j <= item->lastColumn(); ++j) {
       
   957             if (itemAt(i, j))
       
   958                 qWarning("QGridLayoutEngine::addItem: Cell (%d, %d) already taken", i, j);
       
   959             setItemAt(i, j, item);
       
   960         }
       
   961     }
       
   962 }
       
   963 
       
   964 void QGridLayoutEngine::addItem(QGridLayoutItem *item)
       
   965 {
       
   966     insertItem(item, -1);
       
   967 }
       
   968 
       
   969 void QGridLayoutEngine::removeItem(QGridLayoutItem *item)
       
   970 {
       
   971     Q_ASSERT(q_items.contains(item));
       
   972 
       
   973     invalidate();
       
   974 
       
   975     for (int i = item->firstRow(); i <= item->lastRow(); ++i) {
       
   976         for (int j = item->firstColumn(); j <= item->lastColumn(); ++j) {
       
   977             if (itemAt(i, j) == item)
       
   978                 setItemAt(i, j, 0);
       
   979         }
       
   980     }
       
   981 
       
   982     q_items.removeAll(item);
       
   983 }
       
   984 
       
   985 QGridLayoutItem *QGridLayoutEngine::findLayoutItem(QGraphicsLayoutItem *layoutItem) const
       
   986 {
       
   987     for (int i = q_items.count() - 1; i >= 0; --i) {
       
   988         QGridLayoutItem *item = q_items.at(i);
       
   989         if (item->layoutItem() == layoutItem)
       
   990             return item;
       
   991     }
       
   992     return 0;
       
   993 }
       
   994 
       
   995 QGridLayoutItem *QGridLayoutEngine::itemAt(int row, int column, Qt::Orientation orientation) const
       
   996 {
       
   997     if (orientation == Qt::Horizontal)
       
   998         qSwap(row, column);
       
   999     if (uint(row) >= uint(rowCount()) || uint(column) >= uint(columnCount()))
       
  1000         return 0;
       
  1001     return q_grid.at((row * internalGridColumnCount()) + column);
       
  1002 }
       
  1003 
       
  1004 void QGridLayoutEngine::invalidate()
       
  1005 {
       
  1006     q_cachedEffectiveFirstRows[Hor] = -1;
       
  1007     q_cachedEffectiveFirstRows[Ver] = -1;
       
  1008     q_cachedEffectiveLastRows[Hor] = -1;
       
  1009     q_cachedEffectiveLastRows[Ver] = -1;
       
  1010     q_cachedDataForStyleInfo.invalidate();
       
  1011     q_cachedSize = QSizeF();
       
  1012 }
       
  1013 
       
  1014 static void visualRect(QRectF *geom, Qt::LayoutDirection dir, const QRectF &contentsRect)
       
  1015 {
       
  1016     if (dir == Qt::RightToLeft)
       
  1017         geom->moveRight(contentsRect.right() - (geom->left() - contentsRect.left()));
       
  1018 }
       
  1019 
       
  1020 void QGridLayoutEngine::setGeometries(const QLayoutStyleInfo &styleInfo,
       
  1021                                       const QRectF &contentsGeometry)
       
  1022 {
       
  1023     if (rowCount() < 1 || columnCount() < 1)
       
  1024         return;
       
  1025 
       
  1026     ensureGeometries(styleInfo, contentsGeometry.size());
       
  1027 
       
  1028     for (int i = q_items.count() - 1; i >= 0; --i) {
       
  1029         QGridLayoutItem *item = q_items.at(i);
       
  1030 
       
  1031         qreal x = q_xx[item->firstColumn()];
       
  1032         qreal y = q_yy[item->firstRow()];
       
  1033         qreal width = q_widths[item->lastColumn()];
       
  1034         qreal height = q_heights[item->lastRow()];
       
  1035 
       
  1036         if (item->columnSpan() != 1)
       
  1037             width += q_xx[item->lastColumn()] - x;
       
  1038         if (item->rowSpan() != 1)
       
  1039             height += q_yy[item->lastRow()] - y;
       
  1040 
       
  1041         QRectF geom = item->geometryWithin(contentsGeometry.x() + x, contentsGeometry.y() + y,
       
  1042                                                width, height, q_descents[item->lastRow()]);
       
  1043         visualRect(&geom, visualDirection(), contentsGeometry);
       
  1044         item->setGeometry(geom);
       
  1045     }
       
  1046 }
       
  1047 
       
  1048 // ### candidate for deletion
       
  1049 QRectF QGridLayoutEngine::cellRect(const QLayoutStyleInfo &styleInfo,
       
  1050                                    const QRectF &contentsGeometry, int row, int column, int rowSpan,
       
  1051                                    int columnSpan) const
       
  1052 {
       
  1053     if (uint(row) >= uint(rowCount()) || uint(column) >= uint(columnCount())
       
  1054             || rowSpan < 1 || columnSpan < 1)
       
  1055         return QRectF();
       
  1056 
       
  1057     ensureGeometries(styleInfo, contentsGeometry.size());
       
  1058 
       
  1059     int lastColumn = qMax(column + columnSpan, columnCount()) - 1;
       
  1060     int lastRow = qMax(row + rowSpan, rowCount()) - 1;
       
  1061 
       
  1062     qreal x = q_xx[column];
       
  1063     qreal y = q_yy[row];
       
  1064     qreal width = q_widths[lastColumn];
       
  1065     qreal height = q_heights[lastRow];
       
  1066 
       
  1067     if (columnSpan != 1)
       
  1068         width += q_xx[lastColumn] - x;
       
  1069     if (rowSpan != 1)
       
  1070         height += q_yy[lastRow] - y;
       
  1071 
       
  1072     return QRectF(contentsGeometry.x() + x, contentsGeometry.y() + y, width, height);
       
  1073 }
       
  1074 
       
  1075 QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHint which,
       
  1076                                    const QSizeF & /* constraint */) const
       
  1077 {
       
  1078     ensureColumnAndRowData(styleInfo);
       
  1079 
       
  1080     switch (which) {
       
  1081     case Qt::MinimumSize:
       
  1082         return QSizeF(q_totalBoxes[Hor].q_minimumSize, q_totalBoxes[Ver].q_minimumSize);
       
  1083     case Qt::PreferredSize:
       
  1084         return QSizeF(q_totalBoxes[Hor].q_preferredSize, q_totalBoxes[Ver].q_preferredSize);
       
  1085     case Qt::MaximumSize:
       
  1086         return QSizeF(q_totalBoxes[Hor].q_maximumSize, q_totalBoxes[Ver].q_maximumSize);
       
  1087     case Qt::MinimumDescent:
       
  1088         return QSizeF(-1.0, q_totalBoxes[Hor].q_minimumDescent);    // ### doesn't work
       
  1089     default:
       
  1090         break;
       
  1091     }
       
  1092     return QSizeF();
       
  1093 }
       
  1094 
       
  1095 QSizePolicy::ControlTypes QGridLayoutEngine::controlTypes(LayoutSide side) const
       
  1096 {
       
  1097     Qt::Orientation orientation = (side == Top || side == Bottom) ? Qt::Vertical : Qt::Horizontal;
       
  1098     int row = (side == Top || side == Left) ? effectiveFirstRow(orientation)
       
  1099                                             : effectiveLastRow(orientation);
       
  1100     QSizePolicy::ControlTypes result = 0;
       
  1101 
       
  1102     for (int column = columnCount(orientation) - 1; column >= 0; --column) {
       
  1103         if (QGridLayoutItem *item = itemAt(row, column, orientation))
       
  1104             result |= item->controlTypes(side);
       
  1105     }
       
  1106     return result;
       
  1107 }
       
  1108 
       
  1109 void QGridLayoutEngine::transpose()
       
  1110 {
       
  1111     invalidate();
       
  1112 
       
  1113     for (int i = q_items.count() - 1; i >= 0; --i)
       
  1114         q_items.at(i)->transpose();
       
  1115 
       
  1116     qSwap(q_defaultSpacings[Hor], q_defaultSpacings[Ver]);
       
  1117     qSwap(q_infos[Hor], q_infos[Ver]);
       
  1118 
       
  1119     regenerateGrid();
       
  1120 }
       
  1121 
       
  1122 void QGridLayoutEngine::setVisualDirection(Qt::LayoutDirection direction)
       
  1123 {
       
  1124     m_visualDirection = direction;
       
  1125 }
       
  1126 
       
  1127 Qt::LayoutDirection QGridLayoutEngine::visualDirection() const
       
  1128 {
       
  1129     return m_visualDirection;
       
  1130 }
       
  1131 
       
  1132 #ifdef QT_DEBUG
       
  1133 void QGridLayoutEngine::dump(int indent) const
       
  1134 {
       
  1135     qDebug("%*sEngine", indent, "");
       
  1136 
       
  1137     qDebug("%*s Items (%d)", indent, "", q_items.count());
       
  1138     int i;
       
  1139     for (i = 0; i < q_items.count(); ++i)
       
  1140         q_items.at(i)->dump(indent + 2);
       
  1141 
       
  1142     qDebug("%*s Grid (%d x %d)", indent, "", internalGridRowCount(),
       
  1143            internalGridColumnCount());
       
  1144     for (int row = 0; row < internalGridRowCount(); ++row) {
       
  1145         QString message = QLatin1String("[ ");
       
  1146         for (int column = 0; column < internalGridColumnCount(); ++column) {
       
  1147             message += QString::number(q_items.indexOf(itemAt(row, column))).rightJustified(3);
       
  1148             message += QLatin1Char(' ');
       
  1149         }
       
  1150         message += QLatin1Char(']');
       
  1151         qDebug("%*s  %s", indent, "", qPrintable(message));
       
  1152     }
       
  1153 
       
  1154     if (q_defaultSpacings[Hor].value() >= 0.0 || q_defaultSpacings[Ver].value() >= 0.0)
       
  1155         qDebug("%*s Default spacings: %g %g", indent, "", q_defaultSpacings[Hor].value(),
       
  1156                q_defaultSpacings[Ver].value());
       
  1157 
       
  1158     qDebug("%*s Column and row info", indent, "");
       
  1159     q_infos[Hor].dump(indent + 2);
       
  1160     q_infos[Ver].dump(indent + 2);
       
  1161 
       
  1162     qDebug("%*s Column and row data", indent, "");
       
  1163     q_columnData.dump(indent + 2);
       
  1164     q_rowData.dump(indent + 2);
       
  1165 
       
  1166     qDebug("%*s Geometries output", indent, "");
       
  1167     QVector<qreal> *cellPos = &q_yy;
       
  1168     for (int pass = 0; pass < 2; ++pass) {
       
  1169         QString message;
       
  1170         for (i = 0; i < cellPos->count(); ++i) {
       
  1171             message += QLatin1String((message.isEmpty() ? "[" : ", "));
       
  1172             message += QString::number(cellPos->at(i));
       
  1173         }
       
  1174         message += QLatin1Char(']');
       
  1175         qDebug("%*s %s %s", indent, "", (pass == 0 ? "rows:" : "columns:"), qPrintable(message));
       
  1176         cellPos = &q_xx;
       
  1177     }
       
  1178 }
       
  1179 #endif
       
  1180 
       
  1181 void QGridLayoutEngine::maybeExpandGrid(int row, int column, Qt::Orientation orientation)
       
  1182 {
       
  1183     invalidate();   // ### move out of here?
       
  1184 
       
  1185     if (orientation == Qt::Horizontal)
       
  1186         qSwap(row, column);
       
  1187 
       
  1188     if (row < rowCount() && column < columnCount())
       
  1189         return;
       
  1190 
       
  1191     int oldGridRowCount = internalGridRowCount();
       
  1192     int oldGridColumnCount = internalGridColumnCount();
       
  1193 
       
  1194     q_infos[Ver].count = qMax(row + 1, rowCount());
       
  1195     q_infos[Hor].count = qMax(column + 1, columnCount());
       
  1196 
       
  1197     int newGridRowCount = internalGridRowCount();
       
  1198     int newGridColumnCount = internalGridColumnCount();
       
  1199 
       
  1200     int newGridSize = newGridRowCount * newGridColumnCount;
       
  1201     if (newGridSize != q_grid.count()) {
       
  1202         q_grid.resize(newGridSize);
       
  1203 
       
  1204         if (newGridColumnCount != oldGridColumnCount) {
       
  1205             for (int i = oldGridRowCount - 1; i >= 1; --i) {
       
  1206                 for (int j = oldGridColumnCount - 1; j >= 0; --j) {
       
  1207                     int oldIndex = (i * oldGridColumnCount) + j;
       
  1208                     int newIndex = (i * newGridColumnCount) + j;
       
  1209 
       
  1210                     Q_ASSERT(newIndex > oldIndex);
       
  1211                     q_grid[newIndex] = q_grid[oldIndex];
       
  1212                     q_grid[oldIndex] = 0;
       
  1213                 }
       
  1214             }
       
  1215         }
       
  1216     }
       
  1217 }
       
  1218 
       
  1219 void QGridLayoutEngine::regenerateGrid()
       
  1220 {
       
  1221     q_grid.fill(0);
       
  1222 
       
  1223     for (int i = q_items.count() - 1; i >= 0; --i) {
       
  1224         QGridLayoutItem *item = q_items.at(i);
       
  1225 
       
  1226         for (int j = item->firstRow(); j <= item->lastRow(); ++j) {
       
  1227             for (int k = item->firstColumn(); k <= item->lastColumn(); ++k) {
       
  1228                 setItemAt(j, k, item);
       
  1229             }
       
  1230         }
       
  1231     }
       
  1232 }
       
  1233 
       
  1234 void QGridLayoutEngine::setItemAt(int row, int column, QGridLayoutItem *item)
       
  1235 {
       
  1236     Q_ASSERT(row >= 0 && row < rowCount());
       
  1237     Q_ASSERT(column >= 0 && column < columnCount());
       
  1238     q_grid[(row * internalGridColumnCount()) + column] = item;
       
  1239 }
       
  1240 
       
  1241 void QGridLayoutEngine::insertOrRemoveRows(int row, int delta, Qt::Orientation orientation)
       
  1242 {
       
  1243     int oldRowCount = rowCount(orientation);
       
  1244     Q_ASSERT(uint(row) <= uint(oldRowCount));
       
  1245 
       
  1246     invalidate();
       
  1247 
       
  1248     // appending rows (or columns) is easy
       
  1249     if (row == oldRowCount && delta > 0) {
       
  1250         maybeExpandGrid(oldRowCount + delta - 1, -1, orientation);
       
  1251         return;
       
  1252     }
       
  1253 
       
  1254     q_infos[orientation == Qt::Vertical].insertOrRemoveRows(row, delta);
       
  1255 
       
  1256     for (int i = q_items.count() - 1; i >= 0; --i)
       
  1257         q_items.at(i)->insertOrRemoveRows(row, delta, orientation);
       
  1258 
       
  1259     q_grid.resize(internalGridRowCount() * internalGridColumnCount());
       
  1260     regenerateGrid();
       
  1261 }
       
  1262 
       
  1263 void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutStyleInfo &styleInfo,
       
  1264                                     Qt::Orientation orientation) const
       
  1265 {
       
  1266     const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton;
       
  1267     const QGridLayoutRowInfo &rowInfo = q_infos[orientation == Qt::Vertical];
       
  1268     const QGridLayoutRowInfo &columnInfo = q_infos[orientation == Qt::Horizontal];
       
  1269     LayoutSide top = (orientation == Qt::Vertical) ? Top : Left;
       
  1270     LayoutSide bottom = (orientation == Qt::Vertical) ? Bottom : Right;
       
  1271 
       
  1272     QStyle *style = styleInfo.style();
       
  1273     QStyleOption option;
       
  1274     option.initFrom(styleInfo.widget());
       
  1275 
       
  1276     const QLayoutParameter<qreal> &defaultSpacing = q_defaultSpacings[orientation == Qt::Vertical];
       
  1277     qreal innerSpacing = 0.0;
       
  1278     if (style)
       
  1279         innerSpacing = (qreal)style->pixelMetric(orientation == Qt::Vertical ? QStyle::PM_LayoutVerticalSpacing
       
  1280                                                        : QStyle::PM_LayoutHorizontalSpacing,
       
  1281                            &option, styleInfo.widget());
       
  1282     if (innerSpacing >= 0.0)
       
  1283         defaultSpacing.setCachedValue(innerSpacing);
       
  1284 
       
  1285     for (int row = 0; row < rowInfo.count; ++row) {
       
  1286         bool rowIsEmpty = true;
       
  1287         bool rowIsIdenticalToPrevious = (row > 0);
       
  1288 
       
  1289         for (int column = 0; column < columnInfo.count; ++column) {
       
  1290             QGridLayoutItem *item = itemAt(row, column, orientation);
       
  1291 
       
  1292             if (rowIsIdenticalToPrevious && item != itemAt(row - 1, column, orientation))
       
  1293                 rowIsIdenticalToPrevious = false;
       
  1294 
       
  1295             if (item)
       
  1296                 rowIsEmpty = false;
       
  1297         }
       
  1298 
       
  1299         if ((rowIsEmpty || rowIsIdenticalToPrevious)
       
  1300                 && rowInfo.spacings.value(row).isDefault()
       
  1301                 && rowInfo.stretches.value(row).isDefault()
       
  1302                 && rowInfo.boxes.value(row) == QGridLayoutBox())
       
  1303             rowData->ignore.setBit(row, true);
       
  1304 
       
  1305         if (rowInfo.spacings.value(row).isUser()) {
       
  1306             rowData->spacings[row] = rowInfo.spacings.at(row).value();
       
  1307         } else if (!defaultSpacing.isDefault()) {
       
  1308             rowData->spacings[row] = defaultSpacing.value();
       
  1309         }
       
  1310 
       
  1311         rowData->stretches[row] = rowInfo.stretches.value(row).value();
       
  1312     }
       
  1313 
       
  1314     struct RowAdHocData {
       
  1315         int q_row;
       
  1316         unsigned int q_hasButtons : 8;
       
  1317         unsigned int q_hasNonButtons : 8;
       
  1318 
       
  1319         inline RowAdHocData() : q_row(-1), q_hasButtons(false), q_hasNonButtons(false) {}
       
  1320         inline void init(int row) {
       
  1321             this->q_row = row;
       
  1322             q_hasButtons = false;
       
  1323             q_hasNonButtons = false;
       
  1324         }
       
  1325         inline bool hasOnlyButtons() const { return q_hasButtons && !q_hasNonButtons; }
       
  1326         inline bool hasOnlyNonButtons() const { return q_hasNonButtons && !q_hasButtons; }
       
  1327     };
       
  1328     RowAdHocData lastRowAdHocData;
       
  1329     RowAdHocData nextToLastRowAdHocData;
       
  1330     RowAdHocData nextToNextToLastRowAdHocData;
       
  1331 
       
  1332     rowData->hasIgnoreFlag = false;
       
  1333     for (int row = 0; row < rowInfo.count; ++row) {
       
  1334         if (rowData->ignore.testBit(row))
       
  1335             continue;
       
  1336 
       
  1337         QGridLayoutBox &rowBox = rowData->boxes[row];
       
  1338         if (option.state & QStyle::State_Window) {
       
  1339             nextToNextToLastRowAdHocData = nextToLastRowAdHocData;
       
  1340             nextToLastRowAdHocData = lastRowAdHocData;
       
  1341             lastRowAdHocData.init(row);
       
  1342         }
       
  1343 
       
  1344         bool userRowStretch = rowInfo.stretches.value(row).isUser();
       
  1345         int &rowStretch = rowData->stretches[row];
       
  1346 
       
  1347         bool hasIgnoreFlag = true;
       
  1348         for (int column = 0; column < columnInfo.count; ++column) {
       
  1349             QGridLayoutItem *item = itemAt(row, column, orientation);
       
  1350             if (item) {
       
  1351                 int itemRow = item->firstRow(orientation);
       
  1352                 int itemColumn = item->firstColumn(orientation);
       
  1353 
       
  1354                 if (itemRow == row && itemColumn == column) {
       
  1355                     int itemStretch = item->stretchFactor(orientation);
       
  1356                     if (!(item->sizePolicy(orientation) & QSizePolicy::IgnoreFlag))
       
  1357                         hasIgnoreFlag = false;
       
  1358                     int itemRowSpan = item->rowSpan(orientation);
       
  1359 
       
  1360                     int effectiveRowSpan = 1;
       
  1361                     for (int i = 1; i < itemRowSpan; ++i) {
       
  1362                         if (!rowData->ignore.testBit(i))
       
  1363                             ++effectiveRowSpan;
       
  1364                     }
       
  1365 
       
  1366                     QGridLayoutBox *box;
       
  1367                     if (effectiveRowSpan == 1) {
       
  1368                         box = &rowBox;
       
  1369                         if (!userRowStretch)
       
  1370                             rowStretch = qMax(rowStretch, itemStretch);
       
  1371                     } else {
       
  1372                         QGridLayoutMultiCellData &multiCell =
       
  1373                                 rowData->multiCellMap[qMakePair(row, effectiveRowSpan)];
       
  1374                         box = &multiCell.q_box;
       
  1375                         multiCell.q_stretch = itemStretch;
       
  1376                     }
       
  1377                     box->combine(item->box(orientation));
       
  1378 
       
  1379                     if (effectiveRowSpan == 1) {
       
  1380                         QSizePolicy::ControlTypes controls = item->controlTypes(top);
       
  1381                         if (controls & ButtonMask)
       
  1382                             lastRowAdHocData.q_hasButtons = true;
       
  1383                         if (controls & ~ButtonMask)
       
  1384                             lastRowAdHocData.q_hasNonButtons = true;
       
  1385                     }
       
  1386                 }
       
  1387             }
       
  1388         }
       
  1389         if (row < rowInfo.boxes.count()) {
       
  1390             QGridLayoutBox rowBoxInfo = rowInfo.boxes.at(row);
       
  1391             rowBoxInfo.normalize();
       
  1392             rowBox.q_minimumSize = qMax(rowBox.q_minimumSize, rowBoxInfo.q_minimumSize);
       
  1393             rowBox.q_maximumSize = qMax(rowBox.q_minimumSize,
       
  1394                                         (rowBoxInfo.q_maximumSize != FLT_MAX ?
       
  1395                                         rowBoxInfo.q_maximumSize : rowBox.q_maximumSize));
       
  1396             rowBox.q_preferredSize = qBound(rowBox.q_minimumSize,
       
  1397                                             qMax(rowBox.q_preferredSize, rowBoxInfo.q_preferredSize),
       
  1398                                             rowBox.q_maximumSize);
       
  1399         }
       
  1400         if (hasIgnoreFlag)
       
  1401             rowData->hasIgnoreFlag = true;
       
  1402     }
       
  1403 
       
  1404     /*
       
  1405         Heuristic: Detect button boxes that don't use QSizePolicy::ButtonBox.
       
  1406         This is somewhat ad hoc but it usually does the trick.
       
  1407     */
       
  1408     bool lastRowIsButtonBox = (lastRowAdHocData.hasOnlyButtons()
       
  1409                                && nextToLastRowAdHocData.hasOnlyNonButtons());
       
  1410     bool lastTwoRowsIsButtonBox = (lastRowAdHocData.hasOnlyButtons()
       
  1411                                    && nextToLastRowAdHocData.hasOnlyButtons()
       
  1412                                    && nextToNextToLastRowAdHocData.hasOnlyNonButtons()
       
  1413                                    && orientation == Qt::Vertical);
       
  1414 
       
  1415     if (defaultSpacing.isDefault()) {
       
  1416         int prevRow = -1;
       
  1417         for (int row = 0; row < rowInfo.count; ++row) {
       
  1418             if (rowData->ignore.testBit(row))
       
  1419                 continue;
       
  1420 
       
  1421             if (prevRow != -1 && !rowInfo.spacings.value(prevRow).isUser()) {
       
  1422                 qreal &rowSpacing = rowData->spacings[prevRow];
       
  1423                 for (int column = 0; column < columnInfo.count; ++column) {
       
  1424                     QGridLayoutItem *item1 = itemAt(prevRow, column, orientation);
       
  1425                     QGridLayoutItem *item2 = itemAt(row, column, orientation);
       
  1426 
       
  1427                     if (item1 && item2 && item1 != item2) {
       
  1428                         QSizePolicy::ControlTypes controls1 = item1->controlTypes(bottom);
       
  1429                         QSizePolicy::ControlTypes controls2 = item2->controlTypes(top);
       
  1430 
       
  1431                         if (controls2 & QSizePolicy::PushButton) {
       
  1432                             if ((row == nextToLastRowAdHocData.q_row && lastTwoRowsIsButtonBox)
       
  1433                                     || (row == lastRowAdHocData.q_row && lastRowIsButtonBox)) {
       
  1434                                 controls2 &= ~QSizePolicy::PushButton;
       
  1435                                 controls2 |= QSizePolicy::ButtonBox;
       
  1436                             }
       
  1437                         }
       
  1438 
       
  1439                         qreal spacing = style->combinedLayoutSpacing(controls1, controls2,
       
  1440                                                                      orientation, &option,
       
  1441                                                                      styleInfo.widget());
       
  1442                         if (orientation == Qt::Horizontal) {
       
  1443                             qreal width1 = rowData->boxes.at(prevRow).q_minimumSize;
       
  1444                             qreal width2 = rowData->boxes.at(row).q_minimumSize;
       
  1445                             QRectF rect1 = item1->geometryWithin(0.0, 0.0, width1, FLT_MAX, -1.0);
       
  1446                             QRectF rect2 = item2->geometryWithin(0.0, 0.0, width2, FLT_MAX, -1.0);
       
  1447                             spacing -= (width1 - (rect1.x() + rect1.width())) + rect2.x();
       
  1448                         } else {
       
  1449                             const QGridLayoutBox &box1 = rowData->boxes.at(prevRow);
       
  1450                             const QGridLayoutBox &box2 = rowData->boxes.at(row);
       
  1451                             qreal height1 = box1.q_minimumSize;
       
  1452                             qreal height2 = box2.q_minimumSize;
       
  1453                             qreal rowDescent1 = fixedDescent(box1.q_minimumDescent,
       
  1454                                                              box1.q_minimumAscent, height1);
       
  1455                             qreal rowDescent2 = fixedDescent(box2.q_minimumDescent,
       
  1456                                                              box2.q_minimumAscent, height2);
       
  1457                             QRectF rect1 = item1->geometryWithin(0.0, 0.0, FLT_MAX, height1,
       
  1458                                                                  rowDescent1);
       
  1459                             QRectF rect2 = item2->geometryWithin(0.0, 0.0, FLT_MAX, height2,
       
  1460                                                                  rowDescent2);
       
  1461                             spacing -= (height1 - (rect1.y() + rect1.height())) + rect2.y();
       
  1462                         }
       
  1463                         rowSpacing = qMax(spacing, rowSpacing);
       
  1464                     }
       
  1465                 }
       
  1466             }
       
  1467             prevRow = row;
       
  1468         }
       
  1469     } else if (lastRowIsButtonBox || lastTwoRowsIsButtonBox) {
       
  1470         /*
       
  1471             Even for styles that define a uniform spacing, we cheat a
       
  1472             bit and use the window margin as the spacing. This
       
  1473             significantly improves the look of dialogs.
       
  1474         */
       
  1475         int prevRow = lastRowIsButtonBox ? nextToLastRowAdHocData.q_row
       
  1476                                          : nextToNextToLastRowAdHocData.q_row;
       
  1477         if (!defaultSpacing.isUser() && !rowInfo.spacings.value(prevRow).isUser()) {
       
  1478             qreal windowMargin = style->pixelMetric(orientation == Qt::Vertical
       
  1479                                                           ? QStyle::PM_LayoutBottomMargin
       
  1480                                                           : QStyle::PM_LayoutRightMargin,
       
  1481                                                   &option, styleInfo.widget());
       
  1482 
       
  1483             qreal &rowSpacing = rowData->spacings[prevRow];
       
  1484             rowSpacing = qMax(windowMargin, rowSpacing);
       
  1485         }
       
  1486     }
       
  1487 }
       
  1488 
       
  1489 void QGridLayoutEngine::ensureEffectiveFirstAndLastRows() const
       
  1490 {
       
  1491     if (q_cachedEffectiveFirstRows[Hor] == -1 && !q_items.isEmpty()) {
       
  1492         int rowCount = this->rowCount();
       
  1493         int columnCount = this->columnCount();
       
  1494 
       
  1495         q_cachedEffectiveFirstRows[Ver] = rowCount;
       
  1496         q_cachedEffectiveFirstRows[Hor] = columnCount;
       
  1497         q_cachedEffectiveLastRows[Ver] = -1;
       
  1498         q_cachedEffectiveLastRows[Hor] = -1;
       
  1499 
       
  1500         for (int i = q_items.count() - 1; i >= 0; --i) {
       
  1501             const QGridLayoutItem *item = q_items.at(i);
       
  1502 
       
  1503             for (int j = 0; j < NOrientations; ++j) {
       
  1504                 Qt::Orientation orientation = (j == Hor) ? Qt::Horizontal : Qt::Vertical;
       
  1505                 if (item->firstRow(orientation) < q_cachedEffectiveFirstRows[j])
       
  1506                     q_cachedEffectiveFirstRows[j] = item->firstRow(orientation);
       
  1507                 if (item->lastRow(orientation) > q_cachedEffectiveLastRows[j])
       
  1508                     q_cachedEffectiveLastRows[j] = item->lastRow(orientation);
       
  1509             }
       
  1510         }
       
  1511     }
       
  1512 }
       
  1513 
       
  1514 void QGridLayoutEngine::ensureColumnAndRowData(const QLayoutStyleInfo &styleInfo) const
       
  1515 {
       
  1516     if (q_cachedDataForStyleInfo == styleInfo)
       
  1517         return;
       
  1518 
       
  1519     q_columnData.reset(columnCount());
       
  1520     q_rowData.reset(rowCount());
       
  1521 
       
  1522     fillRowData(&q_columnData, styleInfo, Qt::Horizontal);
       
  1523     fillRowData(&q_rowData, styleInfo, Qt::Vertical);
       
  1524 
       
  1525     q_columnData.distributeMultiCells();
       
  1526     q_rowData.distributeMultiCells();
       
  1527 
       
  1528     q_totalBoxes[Hor] = q_columnData.totalBox(0, columnCount());
       
  1529     q_totalBoxes[Ver] = q_rowData.totalBox(0, rowCount());
       
  1530 
       
  1531     q_cachedDataForStyleInfo = styleInfo;
       
  1532 }
       
  1533 
       
  1534 void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo,
       
  1535                                          const QSizeF &size) const
       
  1536 {
       
  1537     ensureColumnAndRowData(styleInfo);
       
  1538     if (q_cachedSize == size)
       
  1539         return;
       
  1540 
       
  1541     q_xx.resize(columnCount());
       
  1542     q_yy.resize(rowCount());
       
  1543     q_widths.resize(columnCount());
       
  1544     q_heights.resize(rowCount());
       
  1545     q_descents.resize(rowCount());
       
  1546     q_columnData.calculateGeometries(0, columnCount(), size.width(), q_xx.data(), q_widths.data(),
       
  1547                                      0, q_totalBoxes[Hor]);
       
  1548     q_rowData.calculateGeometries(0, rowCount(), size.height(), q_yy.data(), q_heights.data(),
       
  1549                                   q_descents.data(), q_totalBoxes[Ver]);
       
  1550 
       
  1551     q_cachedSize = size;
       
  1552 }
       
  1553 
       
  1554 QT_END_NAMESPACE
       
  1555 
       
  1556 #endif //QT_NO_GRAPHICSVIEW