src/gui/kernel/qgridlayout.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtGui module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qgridlayout.h"
00025 
00026 
00027 #include "qapplication.h"
00028 #include "qwidget.h"
00029 #include "qlist.h"
00030 #include "qsizepolicy.h"
00031 #include "qvector.h"
00032 
00033 #include "qlayoutengine_p.h"
00034 #include "qlayout_p.h"
00035 
00036 /*
00037   Three internal classes related to QGridLayout: (1) QGridBox is a
00038   QLayoutItem with (row, column) information and (torow, tocolumn) information; (3) QGridLayoutData is
00039   the internal representation of a QGridLayout.
00040 */
00041 
00042 class QGridBox
00043 {
00044 public:
00045     QGridBox(QLayoutItem *lit) { item_ = lit; }
00046 
00047     QGridBox(QWidget *wid) { item_ = new QWidgetItem(wid); }
00048     ~QGridBox() { delete item_; }
00049 
00050     QSize sizeHint() const { return item_->sizeHint(); }
00051     QSize minimumSize() const { return item_->minimumSize(); }
00052     QSize maximumSize() const { return item_->maximumSize(); }
00053     Qt::Orientations expandingDirections() const { return item_->expandingDirections(); }
00054     bool isEmpty() const { return item_->isEmpty(); }
00055 
00056     bool hasHeightForWidth() const { return item_->hasHeightForWidth(); }
00057     int heightForWidth(int w) const { return item_->heightForWidth(w); }
00058 
00059     void setAlignment(Qt::Alignment a) { item_->setAlignment(a); }
00060     void setGeometry(const QRect &r) { item_->setGeometry(r); }
00061     Qt::Alignment alignment() const { return item_->alignment(); }
00062     QLayoutItem *item() { return item_; }
00063     QLayoutItem *takeItem() { QLayoutItem *i = item_; item_ = 0; return i; }
00064 
00065     int hStretch() { return item_->widget() ?
00066                          item_->widget()->sizePolicy().horizontalStretch() : 0; }
00067     int vStretch() { return item_->widget() ?
00068                          item_->widget()->sizePolicy().verticalStretch() : 0; }
00069 
00070 private:
00071     friend class QGridLayoutPrivate;
00072 
00073     QLayoutItem *item_;
00074     int row, col;
00075     int torow, tocol;
00076 };
00077 
00078 class QGridLayoutPrivate : public QLayoutPrivate
00079 {
00080     Q_DECLARE_PUBLIC(QGridLayout)
00081 public:
00082     QGridLayoutPrivate();
00083 
00084     void add(QGridBox*, int row, int col);
00085     void add(QGridBox*, int row1, int row2, int col1, int col2);
00086     QSize sizeHint(int) const;
00087     QSize minimumSize(int) const;
00088     QSize maximumSize(int) const;
00089 
00090     Qt::Orientations expandingDirections(int spacing) const;
00091 
00092     void distribute(QRect, int);
00093     inline int numRows() const { return rr; }
00094     inline int numCols() const { return cc; }
00095     inline void expand(int rows, int cols)
00096         { setSize(qMax(rows, rr), qMax(cols, cc)); }
00097     inline void setRowStretch(int r, int s)
00098         { expand(r + 1, 0); rStretch[r] = s; setDirty(); }
00099     inline void setColStretch(int c, int s)
00100         { expand(0, c + 1); cStretch[c] = s; setDirty(); }
00101     inline int rowStretch(int r) const { return rStretch[r]; }
00102     inline int colStretch(int c) const { return cStretch[c]; }
00103     inline void setRowSpacing(int r, int s)
00104         { expand(r + 1, 0); rSpacing[r] = s; setDirty(); }
00105     inline void setColSpacing(int c, int s)
00106         { expand(0, c + 1); cSpacing[c] = s; setDirty(); }
00107     inline int rowSpacing(int r) const { return rSpacing[r]; }
00108     inline int colSpacing(int c) const { return cSpacing[c]; }
00109 
00110     inline void setReversed(bool r, bool c) { hReversed = c; vReversed = r; }
00111     inline bool horReversed() const { return hReversed; }
00112     inline bool verReversed() const { return vReversed; }
00113     inline void setDirty() { needRecalc = true; hfw_width = -1; }
00114     inline bool isDirty() const { return needRecalc; }
00115     bool hasHeightForWidth(int space);
00116     int heightForWidth(int, int, int);
00117     int minimumHeightForWidth(int, int, int);
00118 
00119     inline void getNextPos(int &row, int &col) { row = nextR; col = nextC; }
00120     inline int count() const { return things.count(); }
00121     QRect cellRect(int row, int col) const;
00122 
00123     inline QLayoutItem *itemAt(int index) const {
00124         if (index < things.count())
00125             return things.at(index)->item();
00126         else
00127             return 0;
00128     }
00129     inline QLayoutItem *takeAt(int index) {
00130         QLayoutItem *item = 0;
00131         if (index < things.count()) {
00132             QGridBox *b = things.takeAt(index);
00133             if (b) {
00134                 item = b->takeItem();
00135                 delete b;
00136             }
00137         }
00138         return item;
00139     }
00140 
00141     void getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan) {
00142         if (index < things.count()) {
00143             QGridBox *b =  things.at(index);
00144             int toRow = b->torow < 0 ? rr-1 : b->torow;
00145             int toCol = b->tocol  < 0 ? cc-1 : b->tocol;
00146             *row = b->row;
00147             *column = b->col;
00148             *rowSpan = toRow - *row + 1;
00149             *columnSpan = toCol - *column +1;
00150         }
00151     }
00152     void deleteAll();
00153 
00154 private:
00155     void setNextPosAfter(int r, int c);
00156     void recalcHFW(int w, int s);
00157     void addHfwData(QGridBox *box, int width);
00158     void init();
00159     QSize findSize(int QLayoutStruct::*, int) const;
00160     void addData(QGridBox *b, bool r = true, bool c = true);
00161     void setSize(int rows, int cols);
00162     void setupLayoutData(int space);
00163     void setupHfwLayoutData(int space);
00164 
00165     int rr;
00166     int cc;
00167     QVector<QLayoutStruct> rowData;
00168     QVector<QLayoutStruct> colData;
00169     QVector<QLayoutStruct> *hfwData;
00170     QVector<int> rStretch;
00171     QVector<int> cStretch;
00172     QVector<int> rSpacing;
00173     QVector<int> cSpacing;
00174     QList<QGridBox *> things;
00175 
00176     int hfw_width;
00177     int hfw_height;
00178     int hfw_minheight;
00179     int nextR;
00180     int nextC;
00181 
00182     uint hReversed        : 1;
00183     uint vReversed        : 1;
00184     uint needRecalc        : 1;
00185     uint has_hfw        : 1;
00186     uint addVertical        : 1;
00187 };
00188 
00189 QGridLayoutPrivate::QGridLayoutPrivate()
00190 {
00191     addVertical = false;
00192     setDirty();
00193     rr = cc = 0;
00194     nextR = nextC = 0;
00195     hfwData = 0;
00196     hReversed = false;
00197     vReversed = false;
00198 }
00199 
00200 #if 0
00201 QGridLayoutPrivate::QGridLayoutPrivate(int nRows, int nCols)
00202     : rowData(0), colData(0)
00203 {
00204     init();
00205     if (nRows  < 0) {
00206         nRows = 1;
00207         addVertical = false;
00208     }
00209     if (nCols  < 0) {
00210         nCols = 1;
00211         addVertical = true;
00212     }
00213     setSize(nRows, nCols);
00214 }
00215 #endif
00216 
00217 void QGridLayoutPrivate::deleteAll()
00218 {
00219     while (!things.isEmpty())
00220         delete things.takeFirst();
00221     delete hfwData;
00222 }
00223 
00224 bool QGridLayoutPrivate::hasHeightForWidth(int spacing)
00225 {
00226     setupLayoutData(spacing);
00227     return has_hfw;
00228 }
00229 
00230 /*
00231   Assumes that setupLayoutData() has been called, and that
00232   qGeomCalc() has filled in colData with appropriate values.
00233 */
00234 void QGridLayoutPrivate::recalcHFW(int w, int spacing)
00235 {
00236     /*
00237       Go through all children, using colData and heightForWidth()
00238       and put the results in hfwData.
00239     */
00240     if (!hfwData)
00241         hfwData = new QVector<QLayoutStruct>(rr);
00242     setupHfwLayoutData(spacing);
00243     QVector<QLayoutStruct> &rData = *hfwData;
00244 
00245     int h = 0;
00246     int mh = 0;
00247     int n = 0;
00248     for (int r = 0; r < rr; r++) {
00249         h += rData[r].sizeHint;
00250         mh += rData[r].minimumSize;
00251         if (!rData[r].empty)
00252             n++;
00253     }
00254     if (n) {
00255         h += (n - 1) * spacing;
00256         mh += (n - 1) * spacing;
00257     }
00258 
00259     hfw_width = w;
00260     hfw_height = qMin(QLAYOUTSIZE_MAX, h);
00261     hfw_minheight = qMin(QLAYOUTSIZE_MAX, mh);
00262 }
00263 
00264 int QGridLayoutPrivate::heightForWidth(int w, int margin, int spacing)
00265 {
00266     setupLayoutData(spacing);
00267     if (!has_hfw)
00268         return -1;
00269     if (w + 2*margin != hfw_width) {
00270         qGeomCalc(colData, 0, cc, 0, w - 2*margin, spacing);
00271         recalcHFW(w - 2*margin, spacing);
00272     }
00273     return hfw_height + 2*margin;
00274 }
00275 
00276 int QGridLayoutPrivate::minimumHeightForWidth(int w, int margin, int spacing)
00277 {
00278     (void) heightForWidth(w, margin, spacing);
00279     return has_hfw ? (hfw_minheight + 2*margin) : -1;
00280 }
00281 
00282 QSize QGridLayoutPrivate::findSize(int QLayoutStruct::*size, int spacer) const
00283 {
00284     QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this);
00285     that->setupLayoutData(spacer);
00286 
00287     int w = 0;
00288     int h = 0;
00289     int n = 0;
00290 
00291     for (int r = 0; r < rr; r++) {
00292         h = h + rowData[r].*size;
00293         if (!rowData[r].empty)
00294             n++;
00295     }
00296     if (n)
00297         h += (n - 1) * spacer;
00298 
00299     n = 0;
00300     for (int c = 0; c < cc; c++) {
00301         w = w + colData[c].*size;
00302         if (!colData[c].empty)
00303             n++;
00304     }
00305     if (n)
00306         w += (n - 1) * spacer;
00307 
00308     w = qMin(QLAYOUTSIZE_MAX, w);
00309     h = qMin(QLAYOUTSIZE_MAX, h);
00310 
00311     return QSize(w, h);
00312 }
00313 
00314 Qt::Orientations QGridLayoutPrivate::expandingDirections(int spacing) const
00315 {
00316     QGridLayoutPrivate *that = const_cast<QGridLayoutPrivate*>(this);
00317     that->setupLayoutData(spacing);
00318     Qt::Orientations ret;
00319 
00320     for (int r = 0; r < rr; r++) {
00321         if (rowData[r].expansive) {
00322             ret |= Qt::Vertical;
00323             break;
00324         }
00325     }
00326     for (int c = 0; c < cc; c++) {
00327         if (colData[c].expansive) {
00328             ret |= Qt::Horizontal;
00329             break;
00330         }
00331     }
00332     return ret;
00333 }
00334 
00335 QSize QGridLayoutPrivate::sizeHint(int spacer) const
00336 {
00337     return findSize(&QLayoutStruct::sizeHint, spacer);
00338 }
00339 
00340 QSize QGridLayoutPrivate::maximumSize(int spacer) const
00341 {
00342     return findSize(&QLayoutStruct::maximumSize, spacer);
00343 }
00344 
00345 QSize QGridLayoutPrivate::minimumSize(int spacer) const
00346 {
00347     return findSize(&QLayoutStruct::minimumSize, spacer);
00348 }
00349 
00350 void QGridLayoutPrivate::setSize(int r, int c)
00351 {
00352     if ((int)rowData.size() < r) {
00353         int newR = qMax(r, rr * 2);
00354         rowData.resize(newR);
00355         rStretch.resize(newR);
00356         rSpacing.resize(newR);
00357         for (int i = rr; i < newR; i++) {
00358             rowData[i].init();
00359             rowData[i].maximumSize = 0;
00360             rowData[i].pos = 0;
00361             rowData[i].size = 0;
00362             rStretch[i] = 0;
00363             rSpacing[i] = 0;
00364         }
00365     }
00366     if ((int)colData.size() < c) {
00367         int newC = qMax(c, cc * 2);
00368         colData.resize(newC);
00369         cStretch.resize(newC);
00370         cSpacing.resize(newC);
00371         for (int i = cc; i < newC; i++) {
00372             colData[i].init();
00373             colData[i].maximumSize = 0;
00374             colData[i].pos = 0;
00375             colData[i].size = 0;
00376             cStretch[i] = 0;
00377             cSpacing[i] = 0;
00378         }
00379     }
00380 
00381     if (hfwData && (int)hfwData->size() < r) {
00382         delete hfwData;
00383         hfwData = 0;
00384         hfw_width = -1;
00385     }
00386     rr = r;
00387     cc = c;
00388 }
00389 
00390 void QGridLayoutPrivate::setNextPosAfter(int row, int col)
00391 {
00392     if (addVertical) {
00393         if (col > nextC || col == nextC && row >= nextR) {
00394             nextR = row + 1;
00395             nextC = col;
00396             if (nextR >= rr) {
00397                 nextR = 0;
00398                 nextC++;
00399             }
00400         }
00401     } else {
00402         if (row > nextR || row == nextR && col >= nextC) {
00403             nextR = row;
00404             nextC = col + 1;
00405             if (nextC >= cc) {
00406                 nextC = 0;
00407                 nextR++;
00408             }
00409         }
00410     }
00411 }
00412 
00413 void QGridLayoutPrivate::add(QGridBox *box, int row, int col)
00414 {
00415     expand(row+1, col+1);
00416     box->row = box->torow = row;
00417     box->col = box->tocol = col;
00418     things.append(box);
00419     setDirty();
00420     setNextPosAfter(row, col);
00421 }
00422 
00423 void QGridLayoutPrivate::add(QGridBox *box, int row1, int row2, int col1,
00424                            int col2 )
00425 {
00426     if (row2 >= 0 && row2 < row1)
00427         qWarning("QGridLayout: Multi-cell fromRow greater than toRow");
00428     if (col2 >= 0 && col2 < col1)
00429         qWarning("QGridLayout: Multi-cell fromCol greater than toCol");
00430     if (row1 == row2 && col1 == col2) {
00431         add(box, row1, col1);
00432         return;
00433     }
00434     expand(row2+1, col2+1);
00435     box->row = row1;
00436     box->col = col1;
00437 
00438     box->torow = row2;
00439     box->tocol = col2;
00440 
00441     things.append(box);
00442     setDirty();
00443     if (col2 < 0)
00444         col2 = cc - 1;
00445 
00446     setNextPosAfter(row2, col2);
00447 }
00448 
00449 void QGridLayoutPrivate::addData(QGridBox *box, bool r, bool c)
00450 {
00451     QSize hint = box->sizeHint();
00452     QSize minS = box->minimumSize();
00453     QSize maxS = box->maximumSize();
00454     const QWidget *widget = box->item()->widget();
00455 
00456     if (box->isEmpty() && widget)
00457         return;
00458 
00459     if (c) {
00460         if (!cStretch[box->col])
00461             colData[box->col].stretch = qMax(colData[box->col].stretch,
00462                                               box->hStretch());
00463         colData[box->col].sizeHint = qMax(hint.width(),
00464                                            colData[box->col].sizeHint);
00465         colData[box->col].minimumSize = qMax(minS.width(),
00466                                               colData[box->col].minimumSize);
00467 
00468         qMaxExpCalc(colData[box->col].maximumSize, colData[box->col].expansive, colData[box->col].empty,
00469                     maxS.width(), box->expandingDirections() & Qt::Horizontal, box->isEmpty());
00470     }
00471     if (r) {
00472         if (!rStretch[box->row])
00473             rowData[box->row].stretch = qMax(rowData[box->row].stretch,
00474                                               box->vStretch());
00475         rowData[box->row].sizeHint = qMax(hint.height(),
00476                                            rowData[box->row].sizeHint);
00477         rowData[box->row].minimumSize = qMax(minS.height(),
00478                                               rowData[box->row].minimumSize);
00479 
00480         qMaxExpCalc(rowData[box->row].maximumSize, rowData[box->row].expansive, rowData[box->row].empty,
00481                     maxS.height(), box->expandingDirections() & Qt::Vertical, box->isEmpty());
00482     }
00483 }
00484 
00485 static void distributeMultiBox(QVector<QLayoutStruct> &chain, int spacing, int start, int end,
00486                                int minSize, int sizeHint, QVector<int> &stretchArray, int stretch)
00487 {
00488     int i;
00489     int w = 0;
00490     int wh = 0;
00491     int max = 0;
00492     for (i = start; i <= end; i++) {
00493         w += chain[i].minimumSize;
00494         wh += chain[i].sizeHint;
00495         if (chain[i].empty)
00496             chain[i].maximumSize = QWIDGETSIZE_MAX;
00497         max += chain[i].maximumSize;
00498         chain[i].empty = false;
00499         if (stretchArray[i] == 0)
00500             chain[i].stretch = qMax(chain[i].stretch,stretch);
00501     }
00502     w += spacing * (end - start);
00503     wh += spacing * (end - start);
00504     max += spacing * (end - start);
00505 
00506     if (max < minSize) { // implies w < minSize
00507         /*
00508           We must increase the maximum size of at least one of the
00509           items. qGeomCalc() will put the extra space in between the
00510           items. We must recover that extra space and put it
00511           somewhere. It does not really matter where, since the user
00512           can always specify stretch factors and avoid this code.
00513         */
00514         qGeomCalc(chain, start, end - start + 1, 0, minSize, spacing);
00515         int pos = 0;
00516         for (i = start; i <= end; i++) {
00517             int nextPos = (i == end) ? minSize - 1 : chain[i + 1].pos;
00518             int realSize = nextPos - pos;
00519             if (i != end)
00520                 realSize -= spacing;
00521             if (chain[i].minimumSize < realSize)
00522                 chain[i].minimumSize = realSize;
00523             if (chain[i].maximumSize < chain[i].minimumSize)
00524                 chain[i].maximumSize = chain[i].minimumSize;
00525             pos = nextPos;
00526         }
00527     } else if (w < minSize) {
00528         qGeomCalc(chain, start, end - start + 1, 0, minSize, spacing);
00529         for (i = start; i <= end; i++) {
00530             if (chain[i].minimumSize < chain[i].size)
00531                 chain[i].minimumSize = chain[i].size;
00532         }
00533     }
00534 
00535     if (wh < sizeHint) {
00536         qGeomCalc(chain, start, end - start + 1, 0, sizeHint, spacing);
00537         for (i = start; i <= end; i++) {
00538             if (chain[i].sizeHint < chain[i].size)
00539                 chain[i].sizeHint = chain[i].size;
00540         }
00541     }
00542 }
00543 
00544 //#define QT_LAYOUT_DISABLE_CACHING
00545 
00546 void QGridLayoutPrivate::setupLayoutData(int spacing)
00547 {
00548 #ifndef QT_LAYOUT_DISABLE_CACHING
00549     if (!needRecalc)
00550         return;
00551 #endif
00552     has_hfw = false;
00553     int i;
00554 
00555     for (i = 0; i < rr; i++) {
00556         rowData[i].init(rStretch[i], rSpacing[i]);
00557         rowData[i].maximumSize = rStretch[i] ? QLAYOUTSIZE_MAX : rSpacing[i];
00558     }
00559     for (i = 0; i < cc; i++) {
00560         colData[i].init(cStretch[i], cSpacing[i]);
00561         colData[i].maximumSize = cStretch[i] ? QLAYOUTSIZE_MAX : cSpacing[i];
00562     }
00563     for (int pass = 0; pass < 2; ++pass) {
00564         for (i = 0; i < things.size(); ++i) {
00565             QGridBox *box = things.at(i);
00566             int r1 = box->row;
00567             int c1 = box->col;
00568             int r2 = box->torow;
00569             int c2 = box->tocol;
00570             if (r2 < 0)
00571                 r2 = rr - 1;
00572             if (c2 < 0)
00573                 c2 = cc - 1;
00574 
00575             QSize hint = box->sizeHint();
00576             QSize min = box->minimumSize();
00577             if (box->hasHeightForWidth())
00578                 has_hfw = true;
00579 
00580             if (r1 == r2) {
00581                 if (pass == 0)
00582                     addData(box, true, false);
00583             } else {
00584                 if (pass == 1)
00585                     distributeMultiBox(rowData, spacing, r1, r2, min.height(), hint.height(),
00586                                        rStretch, box->vStretch());
00587             }
00588             if (c1 == c2) {
00589                 if (pass == 0)
00590                     addData(box, false, true);
00591             } else {
00592                 if (pass == 1)
00593                     distributeMultiBox(colData, spacing, c1, c2, min.width(), hint.width(),
00594                                        cStretch, box->hStretch());
00595             }
00596         }
00597     }
00598 
00599     for (i = 0; i < rr; i++)
00600         rowData[i].expansive = rowData[i].expansive || rowData[i].stretch > 0;
00601     for (i = 0; i < cc; i++)
00602         colData[i].expansive = colData[i].expansive || colData[i].stretch > 0;
00603 
00604     needRecalc = false;
00605 }
00606 
00607 void QGridLayoutPrivate::addHfwData(QGridBox *box, int width)
00608 {
00609     QVector<QLayoutStruct> &rData = *hfwData;
00610     if (box->hasHeightForWidth()) {
00611         int hint = box->heightForWidth(width);
00612         rData[box->row].sizeHint = qMax(hint, rData[box->row].sizeHint);
00613         rData[box->row].minimumSize = qMax(hint, rData[box->row].minimumSize);
00614     } else {
00615         QSize hint = box->sizeHint();
00616         QSize minS = box->minimumSize();
00617         rData[box->row].sizeHint = qMax(hint.height(), rData[box->row].sizeHint);
00618         rData[box->row].minimumSize = qMax(minS.height(), rData[box->row].minimumSize);
00619     }
00620 }
00621 
00622 /*
00623   Similar to setupLayoutData(), but uses heightForWidth(colData)
00624   instead of sizeHint(). Assumes that setupLayoutData() and
00625   qGeomCalc(colData) has been called.
00626 */
00627 void QGridLayoutPrivate::setupHfwLayoutData(int spacing)
00628 {
00629     QVector<QLayoutStruct> &rData = *hfwData;
00630     for (int i = 0; i < rr; i++) {
00631         rData[i] = rowData[i];
00632         rData[i].minimumSize = rData[i].sizeHint = rSpacing[i];
00633     }
00634 
00635     for (int pass = 0; pass < 2; ++pass) {
00636         for (int i = 0; i < things.size(); ++i) {
00637             QGridBox *box = things.at(i);
00638             int r1 = box->row;
00639             int c1 = box->col;
00640             int r2 = box->torow;
00641             int c2 = box->tocol;
00642             if (r2 < 0)
00643                 r2 = rr-1;
00644             if (c2 < 0)
00645                 c2 = cc-1;
00646             int w = colData[c2].pos + colData[c2].size - colData[c1].pos;
00647 
00648             if (r1 == r2) {
00649                 if (pass == 0)
00650                     addHfwData(box, w);
00651             } else {
00652                 if (pass == 1) {
00653                     QSize hint = box->sizeHint();
00654                     QSize min = box->minimumSize();
00655                     if (box->hasHeightForWidth()) {
00656                         int hfwh = box->heightForWidth(w);
00657                         if (hfwh > hint.height())
00658                             hint.setHeight(hfwh);
00659                         if (hfwh > min.height())
00660                             min.setHeight(hfwh);
00661                     }
00662                     distributeMultiBox(rData, spacing, r1, r2,
00663                                        min.height(), hint.height(),
00664                                        rStretch, box->vStretch());
00665                 }
00666             }
00667         }
00668     }
00669     for (int i = 0; i < rr; i++)
00670         rData[i].expansive = rData[i].expansive || rData[i].stretch > 0;
00671 }
00672 
00673 void QGridLayoutPrivate::distribute(QRect r, int spacing)
00674 {
00675     Q_Q(QGridLayout);
00676     bool visualHReversed = hReversed;
00677     QWidget *parent = q->parentWidget();
00678     if (parent && parent->isRightToLeft())
00679         visualHReversed = !visualHReversed;
00680 
00681     setupLayoutData(spacing);
00682 
00683     qGeomCalc(colData, 0, cc, r.x(), r.width(), spacing);
00684     QVector<QLayoutStruct> *rDataPtr;
00685     if (has_hfw) {
00686         recalcHFW(r.width(), spacing);
00687         qGeomCalc(*hfwData, 0, rr, r.y(), r.height(), spacing);
00688         rDataPtr = hfwData;
00689     } else {
00690         qGeomCalc(rowData, 0, rr, r.y(), r.height(), spacing);
00691         rDataPtr = &rowData;
00692     }
00693     QVector<QLayoutStruct> &rData = *rDataPtr;
00694     int i;
00695 
00696     bool reverse = ((r.bottom() > rect.bottom()) || (r.bottom() == rect.bottom()
00697                                                      && ((r.right() > rect.right()) != visualHReversed)));
00698     int n = things.size();
00699     for (i = 0; i < n; ++i) {
00700         QGridBox *box = things.at(reverse ? n-i-1 : i);
00701         int r2 = box->torow;
00702         int c2 = box->tocol;
00703         if (r2 < 0)
00704             r2 = rr-1;
00705         if (c2 < 0)
00706             c2 = cc-1;
00707 
00708         int x = colData[box->col].pos;
00709         int y = rData[box->row].pos;
00710         int x2p = colData[c2].pos + colData[c2].size; // x2+1
00711         int y2p = rData[r2].pos + rData[r2].size;    // y2+1
00712         int w = x2p - x;
00713         int h = y2p - y;
00714 
00715         if (visualHReversed)
00716             x = r.left() + r.right() - x - w + 1;
00717         if (vReversed)
00718             y = r.top() + r.bottom() - y - h + 1;
00719         box->setGeometry(QRect(x, y, w, h));
00720     }
00721 }
00722 
00723 QRect QGridLayoutPrivate::cellRect(int row, int col) const
00724 {
00725     if (row < 0 || row >= rr || col < 0 || col >= cc)
00726         return QRect();
00727 
00728     const QVector<QLayoutStruct> *rDataPtr;
00729     if (has_hfw && hfwData)
00730         rDataPtr = hfwData;
00731     else
00732         rDataPtr = &rowData;
00733     return QRect(colData[col].pos, (*rDataPtr)[row].pos, colData[col].size, (*rDataPtr)[row].size);
00734 }
00735 
00817 QGridLayout::QGridLayout(QWidget *parent)
00818     : QLayout(*new QGridLayoutPrivate, 0, parent)
00819 {
00820     Q_D(QGridLayout);
00821     d->expand(1, 1);
00822 }
00823 
00831 QGridLayout::QGridLayout()
00832     : QLayout(*new QGridLayoutPrivate, 0, 0)
00833 {
00834     Q_D(QGridLayout);
00835     d->expand(1, 1);
00836 }
00837 
00838 
00839 #ifdef QT3_SUPPORT
00840 
00850 QGridLayout::QGridLayout(QWidget *parent, int nRows, int nCols, int margin,
00851                           int space, const char *name)
00852     : QLayout(*new QGridLayoutPrivate, 0, parent)
00853 {
00854     Q_D(QGridLayout);
00855     d->expand(nRows, nCols);
00856     setMargin(margin);
00857     setSpacing(space<0 ? margin : space);
00858     setObjectName(QString::fromAscii(name));
00859 }
00860 
00872 QGridLayout::QGridLayout(QLayout *parentLayout, int nRows, int nCols,
00873                           int spacing, const char *name)
00874     : QLayout(*new QGridLayoutPrivate, parentLayout, 0)
00875 {
00876     Q_D(QGridLayout);
00877     d->expand(nRows, nCols);
00878     setSpacing(spacing);
00879     setObjectName(QString::fromAscii(name));
00880 }
00881 
00893 QGridLayout::QGridLayout(int nRows, int nCols,
00894                           int spacing, const char *name)
00895     : QLayout(*new QGridLayoutPrivate, 0, 0)
00896 {
00897     Q_D(QGridLayout);
00898     d->expand(nRows, nCols);
00899     setSpacing(spacing);
00900     setObjectName(QString::fromAscii(name));
00901 }
00902 #endif
00903 
00904 
00914 void QGridLayout::setDefaultPositioning(int n, Qt::Orientation orient)
00915 {
00916     Q_D(QGridLayout);
00917     if (orient == Qt::Horizontal) {
00918         d->expand(1, n);
00919         d->addVertical = false;
00920     } else {
00921         d->expand(n,1);
00922         d->addVertical = true;
00923     }
00924 }
00925 
00926 
00933 QGridLayout::~QGridLayout()
00934 {
00935     Q_D(QGridLayout);
00936     d->deleteAll();
00937 }
00938 
00942 int QGridLayout::rowCount() const
00943 {
00944     Q_D(const QGridLayout);
00945     return d->numRows();
00946 }
00947 
00951 int QGridLayout::columnCount() const
00952 {
00953     Q_D(const QGridLayout);
00954     return d->numCols();
00955 }
00956 
00960 QSize QGridLayout::sizeHint() const
00961 {
00962     Q_D(const QGridLayout);
00963     int m = margin();
00964     return d->sizeHint(spacing()) + QSize(2 * m, 2 * m);
00965 }
00966 
00970 QSize QGridLayout::minimumSize() const
00971 {
00972     Q_D(const QGridLayout);
00973     int m = margin();
00974     return d->minimumSize(spacing()) + QSize(2 * m, 2 * m);
00975 }
00976 
00980 QSize QGridLayout::maximumSize() const
00981 {
00982     Q_D(const QGridLayout);
00983     int m = margin();
00984     QSize s = d->maximumSize(spacing()) +
00985               QSize(2 * m, 2 * m);
00986     s = s.boundedTo(QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX));
00987     if (alignment() & Qt::AlignHorizontal_Mask)
00988         s.setWidth(QLAYOUTSIZE_MAX);
00989     if (alignment() & Qt::AlignVertical_Mask)
00990         s.setHeight(QLAYOUTSIZE_MAX);
00991     return s;
00992 }
00993 
00997 bool QGridLayout::hasHeightForWidth() const
00998 {
00999     return ((QGridLayout*)this)->d_func()->hasHeightForWidth(spacing());
01000 }
01001 
01005 int QGridLayout::heightForWidth(int w) const
01006 {
01007     QGridLayout *that = (QGridLayout*)this;
01008     return that->d_func()->heightForWidth(w, margin(), spacing());
01009 }
01010 
01014 int QGridLayout::minimumHeightForWidth(int w) const
01015 {
01016     QGridLayout *that = (QGridLayout*)this;
01017     return that->d_func()->minimumHeightForWidth(w, margin(), spacing());
01018 }
01019 
01020 #ifdef QT3_SUPPORT
01021 
01034 bool QGridLayout::findWidget(QWidget* w, int *row, int *column)
01035 {
01036     Q_D(QGridLayout);
01037     int index = indexOf(w);
01038     if (index < 0)
01039         return false;
01040     int dummy1, dummy2;
01041     d->getItemPosition(index, row, column, &dummy1, &dummy2);
01042     return true;
01043 }
01044 #endif
01045 
01048 int QGridLayout::count() const
01049 {
01050     Q_D(const QGridLayout);
01051     return d->count();
01052 }
01053 
01054 
01058 QLayoutItem *QGridLayout::itemAt(int index) const
01059 {
01060     Q_D(const QGridLayout);
01061     return d->itemAt(index);
01062 }
01063 
01064 
01068 QLayoutItem *QGridLayout::takeAt(int index)
01069 {
01070     Q_D(QGridLayout);
01071     return d->takeAt(index);
01072 }
01073 
01081 void QGridLayout::getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan)
01082 {
01083     Q_D(QGridLayout);
01084     d->getItemPosition(index, row, column, rowSpan, columnSpan);
01085 }
01086 
01087 
01091 void QGridLayout::setGeometry(const QRect &rect)
01092 {
01093     Q_D(QGridLayout);
01094     if (d->isDirty() || rect != geometry()) {
01095         QRect cr = alignment() ? alignmentRect(rect) : rect;
01096         int m = margin();
01097         QRect s(cr.x() + m, cr.y() + m,
01098                  cr.width() - 2 * m, cr.height() - 2 * m);
01099         d->distribute(s, spacing());
01100         QLayout::setGeometry(rect);
01101     }
01102 }
01103 
01113 QRect QGridLayout::cellRect(int row, int column) const
01114 {
01115     Q_D(const QGridLayout);
01116     return d->cellRect(row, column);
01117 }
01118 #ifdef QT3_SUPPORT
01119 
01126 void QGridLayout::expand(int nRows, int nCols)
01127 {
01128     Q_D(QGridLayout);
01129     d->expand(nRows, nCols);
01130 }
01131 #endif
01132 
01136 void QGridLayout::addItem(QLayoutItem *item)
01137 {
01138     Q_D(QGridLayout);
01139     int r, c;
01140     d->getNextPos(r, c);
01141     addItem(item, r, c);
01142 }
01143 
01154 void QGridLayout::addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
01155 {
01156     Q_D(QGridLayout);
01157     QGridBox *b = new QGridBox(item);
01158     b->setAlignment(alignment);
01159     d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
01160     invalidate();
01161 }
01162 
01163 /*
01164   Returns true if the widget \a w can be added to the layout \a l;
01165   otherwise returns false.
01166 */
01167 static bool checkWidget(QLayout *l, QWidget *w)
01168 {
01169     if (!w) {
01170         qWarning("QLayout: Cannot add null widget to %s/%s", l->metaObject()->className(),
01171                   l->objectName().toLocal8Bit().data());
01172         return false;
01173     }
01174     return true;
01175 }
01176 
01185 void QGridLayout::addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
01186 {
01187     if (!checkWidget(this, widget))
01188         return;
01189     if (row < 0 || column < 0) {
01190         qWarning("QGridLayout: Cannot add %s/%s to %s/%s at row %d column %d",
01191                  widget->metaObject()->className(), widget->objectName().toLocal8Bit().data(),
01192                  metaObject()->className(), objectName().toLocal8Bit().data(), row, column);
01193         return;
01194     }
01195     addChildWidget(widget);
01196     QWidgetItem *b = new QWidgetItem(widget);
01197     addItem(b, row, column, 1, 1, alignment);
01198 }
01199 
01212 void QGridLayout::addWidget(QWidget *widget, int fromRow, int fromColumn,
01213                             int rowSpan, int columnSpan, Qt::Alignment alignment)
01214 {
01215     Q_D(QGridLayout);
01216     if (!checkWidget(this, widget))
01217         return;
01218     int toRow = (rowSpan < 0) ? -1 : fromRow + rowSpan - 1;
01219     int toColumn = (columnSpan < 0) ? -1 : fromColumn + columnSpan - 1;
01220     addChildWidget(widget);
01221     QGridBox *b = new QGridBox(widget);
01222     b->setAlignment(alignment);
01223     d->add(b, fromRow, toRow, fromColumn, toColumn);
01224     invalidate();
01225 }
01226 
01248 void QGridLayout::addLayout(QLayout *layout, int row, int column, Qt::Alignment alignment)
01249 {
01250     Q_D(QGridLayout);
01251     addChildLayout(layout);
01252     QGridBox *b = new QGridBox(layout);
01253     b->setAlignment(alignment);
01254     d->add(b, row, column);
01255 }
01256 
01266 void QGridLayout::addLayout(QLayout *layout, int row, int column,
01267                                       int rowSpan, int columnSpan, Qt::Alignment alignment)
01268 {
01269     Q_D(QGridLayout);
01270     addChildLayout(layout);
01271     QGridBox *b = new QGridBox(layout);
01272     b->setAlignment(alignment);
01273     d->add(b, row, (rowSpan < 0) ? -1 : row + rowSpan - 1, column, (columnSpan < 0) ? -1 : column + columnSpan - 1);
01274 }
01275 
01289 void QGridLayout::setRowStretch(int row, int stretch)
01290 {
01291     Q_D(QGridLayout);
01292     d->setRowStretch(row, stretch);
01293     invalidate();
01294 }
01295 
01301 int QGridLayout::rowStretch(int row) const
01302 {
01303     Q_D(const QGridLayout);
01304     return d->rowStretch(row);
01305 }
01306 
01312 int QGridLayout::columnStretch(int column) const
01313 {
01314     Q_D(const QGridLayout);
01315     return d->colStretch(column);
01316 }
01317 
01335 void QGridLayout::setColumnStretch(int column, int stretch)
01336 {
01337     Q_D(QGridLayout);
01338     d->setColStretch(column, stretch);
01339     invalidate();
01340 }
01341 
01342 
01343 
01349 void QGridLayout::setRowMinimumHeight(int row, int minSize)
01350 {
01351     Q_D(QGridLayout);
01352     d->setRowSpacing(row, minSize);
01353     invalidate();
01354 }
01355 
01361 int QGridLayout::rowMinimumHeight(int row) const
01362 {
01363     Q_D(const QGridLayout);
01364     return d->rowSpacing(row);
01365 }
01366 
01372 void QGridLayout::setColumnMinimumWidth(int column, int minSize)
01373 {
01374     Q_D(QGridLayout);
01375     d->setColSpacing(column, minSize);
01376     invalidate();
01377 }
01378 
01384 int QGridLayout::columnMinimumWidth(int column) const
01385 {
01386     Q_D(const QGridLayout);
01387     return d->colSpacing(column);
01388 }
01389 
01393 Qt::Orientations QGridLayout::expandingDirections() const
01394 {
01395     Q_D(const QGridLayout);
01396     return d->expandingDirections(spacing());
01397 }
01398 
01402 void QGridLayout::setOriginCorner(Qt::Corner corner)
01403 {
01404     Q_D(QGridLayout);
01405     d->setReversed(corner == Qt::BottomLeftCorner || corner == Qt::BottomRightCorner,
01406                    corner == Qt::TopRightCorner || corner == Qt::BottomRightCorner);
01407 }
01408 
01413 Qt::Corner QGridLayout::originCorner() const
01414 {
01415     Q_D(const QGridLayout);
01416     if (d->horReversed()) {
01417         return d->verReversed() ? Qt::BottomRightCorner : Qt::TopRightCorner;
01418     } else {
01419         return d->verReversed() ? Qt::BottomLeftCorner : Qt::TopLeftCorner;
01420     }
01421 }
01422 
01426 void QGridLayout::invalidate()
01427 {
01428     Q_D(QGridLayout);
01429     d->setDirty();
01430     QLayout::invalidate();
01431 }
01432 

Generated on Thu Mar 15 11:55:08 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1