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