| 1 | /****************************************************************************
|
|---|
| 2 | ** $Id: qlayout.cpp 2 2005-11-16 15:49:26Z dmik $
|
|---|
| 3 | **
|
|---|
| 4 | ** Implementation of layout classes
|
|---|
| 5 | **
|
|---|
| 6 | ** Created : 960416
|
|---|
| 7 | **
|
|---|
| 8 | ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
|
|---|
| 9 | **
|
|---|
| 10 | ** This file is part of the kernel module of the Qt GUI Toolkit.
|
|---|
| 11 | **
|
|---|
| 12 | ** This file may be distributed under the terms of the Q Public License
|
|---|
| 13 | ** as defined by Trolltech AS of Norway and appearing in the file
|
|---|
| 14 | ** LICENSE.QPL included in the packaging of this file.
|
|---|
| 15 | **
|
|---|
| 16 | ** This file may be distributed and/or modified under the terms of the
|
|---|
| 17 | ** GNU General Public License version 2 as published by the Free Software
|
|---|
| 18 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
|---|
| 19 | ** packaging of this file.
|
|---|
| 20 | **
|
|---|
| 21 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
|---|
| 22 | ** licenses may use this file in accordance with the Qt Commercial License
|
|---|
| 23 | ** Agreement provided with the Software.
|
|---|
| 24 | **
|
|---|
| 25 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|---|
| 26 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|---|
| 27 | **
|
|---|
| 28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
|---|
| 29 | ** information about Qt Commercial License Agreements.
|
|---|
| 30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
|---|
| 31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
|---|
| 32 | **
|
|---|
| 33 | ** Contact info@trolltech.com if any conditions of this licensing are
|
|---|
| 34 | ** not clear to you.
|
|---|
| 35 | **
|
|---|
| 36 | **********************************************************************/
|
|---|
| 37 |
|
|---|
| 38 | #include "qlayout.h"
|
|---|
| 39 |
|
|---|
| 40 | #ifndef QT_NO_LAYOUT
|
|---|
| 41 |
|
|---|
| 42 | #include "qapplication.h"
|
|---|
| 43 | #include "qwidget.h"
|
|---|
| 44 | #include "qptrlist.h"
|
|---|
| 45 | #include "qsizepolicy.h"
|
|---|
| 46 |
|
|---|
| 47 | #include "qlayoutengine_p.h"
|
|---|
| 48 |
|
|---|
| 49 | /*
|
|---|
| 50 | Three internal classes related to QGridLayout: (1) QGridBox is a
|
|---|
| 51 | QLayoutItem with (row, column) information; (2) QGridMultiBox is a
|
|---|
| 52 | QGridBox with (torow, tocolumn) information; (3) QGridLayoutData is
|
|---|
| 53 | the internal representation of a QGridLayout.
|
|---|
| 54 | */
|
|---|
| 55 |
|
|---|
| 56 | class QGridBox
|
|---|
| 57 | {
|
|---|
| 58 | public:
|
|---|
| 59 | QGridBox( QLayoutItem *lit ) { item_ = lit; }
|
|---|
| 60 |
|
|---|
| 61 | QGridBox( QWidget *wid ) { item_ = new QWidgetItem( wid ); }
|
|---|
| 62 | QGridBox( int w, int h, QSizePolicy::SizeType hData = QSizePolicy::Minimum,
|
|---|
| 63 | QSizePolicy::SizeType vData = QSizePolicy::Minimum )
|
|---|
| 64 | { item_ = new QSpacerItem( w, h, hData, vData ); }
|
|---|
| 65 | ~QGridBox() { delete item_; }
|
|---|
| 66 |
|
|---|
| 67 | QSize sizeHint() const { return item_->sizeHint(); }
|
|---|
| 68 | QSize minimumSize() const { return item_->minimumSize(); }
|
|---|
| 69 | QSize maximumSize() const { return item_->maximumSize(); }
|
|---|
| 70 | QSizePolicy::ExpandData expanding() const { return item_->expanding(); }
|
|---|
| 71 | bool isEmpty() const { return item_->isEmpty(); }
|
|---|
| 72 |
|
|---|
| 73 | bool hasHeightForWidth() const { return item_->hasHeightForWidth(); }
|
|---|
| 74 | int heightForWidth( int w ) const { return item_->heightForWidth(w); }
|
|---|
| 75 |
|
|---|
| 76 | void setAlignment( int a ) { item_->setAlignment( a ); }
|
|---|
| 77 | void setGeometry( const QRect &r ) { item_->setGeometry( r ); }
|
|---|
| 78 | int alignment() const { return item_->alignment(); }
|
|---|
| 79 | QLayoutItem *item() { return item_; }
|
|---|
| 80 | QLayoutItem *takeItem() { QLayoutItem *i = item_; item_ = 0; return i; }
|
|---|
| 81 |
|
|---|
| 82 | int hStretch() { return item_->widget() ?
|
|---|
| 83 | item_->widget()->sizePolicy().horStretch() : 0; }
|
|---|
| 84 | int vStretch() { return item_->widget() ?
|
|---|
| 85 | item_->widget()->sizePolicy().verStretch() : 0; }
|
|---|
| 86 |
|
|---|
| 87 | private:
|
|---|
| 88 | friend class QGridLayoutData;
|
|---|
| 89 | friend class QGridLayoutDataIterator;
|
|---|
| 90 |
|
|---|
| 91 | QLayoutItem *item_;
|
|---|
| 92 | int row, col;
|
|---|
| 93 | };
|
|---|
| 94 |
|
|---|
| 95 | class QGridMultiBox
|
|---|
| 96 | {
|
|---|
| 97 | public:
|
|---|
| 98 | QGridMultiBox( QGridBox *box, int toRow, int toCol )
|
|---|
| 99 | : box_( box ), torow( toRow ), tocol( toCol ) { }
|
|---|
| 100 | ~QGridMultiBox() { delete box_; }
|
|---|
| 101 | QGridBox *box() { return box_; }
|
|---|
| 102 | QLayoutItem *takeItem() { return box_->takeItem(); }
|
|---|
| 103 |
|
|---|
| 104 | private:
|
|---|
| 105 | friend class QGridLayoutData;
|
|---|
| 106 | friend class QGridLayoutDataIterator;
|
|---|
| 107 |
|
|---|
| 108 | QGridBox *box_;
|
|---|
| 109 | int torow, tocol;
|
|---|
| 110 | };
|
|---|
| 111 |
|
|---|
| 112 | class QGridLayoutData
|
|---|
| 113 | {
|
|---|
| 114 | public:
|
|---|
| 115 | QGridLayoutData();
|
|---|
| 116 | QGridLayoutData( int nRows, int nCols );
|
|---|
| 117 | ~QGridLayoutData();
|
|---|
| 118 |
|
|---|
| 119 | void add( QGridBox*, int row, int col );
|
|---|
| 120 | void add( QGridBox*, int row1, int row2, int col1, int col2 );
|
|---|
| 121 | QSize sizeHint( int ) const;
|
|---|
| 122 | QSize minimumSize( int ) const;
|
|---|
| 123 | QSize maximumSize( int ) const;
|
|---|
| 124 |
|
|---|
| 125 | QSizePolicy::ExpandData expanding( int spacing );
|
|---|
| 126 |
|
|---|
| 127 | void distribute( QRect, int );
|
|---|
| 128 | inline int numRows() const { return rr; }
|
|---|
| 129 | inline int numCols() const { return cc; }
|
|---|
| 130 | inline void expand( int rows, int cols )
|
|---|
| 131 | { setSize( QMAX(rows, rr), QMAX(cols, cc) ); }
|
|---|
| 132 | inline void setRowStretch( int r, int s )
|
|---|
| 133 | { expand( r + 1, 0 ); rStretch[r] = s; setDirty(); }
|
|---|
| 134 | inline void setColStretch( int c, int s )
|
|---|
| 135 | { expand( 0, c + 1 ); cStretch[c] = s; setDirty(); }
|
|---|
| 136 | inline int rowStretch( int r ) const { return rStretch[r]; }
|
|---|
| 137 | inline int colStretch( int c ) const { return cStretch[c]; }
|
|---|
| 138 | inline void setRowSpacing( int r, int s )
|
|---|
| 139 | { expand( r + 1, 0 ); rSpacing[r] = s; setDirty(); }
|
|---|
| 140 | inline void setColSpacing( int c, int s )
|
|---|
| 141 | { expand( 0, c + 1 ); cSpacing[c] = s; setDirty(); }
|
|---|
| 142 | inline int rowSpacing( int r ) const { return rSpacing[r]; }
|
|---|
| 143 | inline int colSpacing( int c ) const { return cSpacing[c]; }
|
|---|
| 144 |
|
|---|
| 145 | inline void setReversed( bool r, bool c ) { hReversed = c; vReversed = r; }
|
|---|
| 146 | inline bool horReversed() const { return hReversed; }
|
|---|
| 147 | inline bool verReversed() const { return vReversed; }
|
|---|
| 148 | inline void setDirty() { needRecalc = TRUE; hfw_width = -1; }
|
|---|
| 149 | inline bool isDirty() const { return needRecalc; }
|
|---|
| 150 | bool hasHeightForWidth( int space );
|
|---|
| 151 | int heightForWidth( int, int, int );
|
|---|
| 152 | int minimumHeightForWidth( int, int, int );
|
|---|
| 153 |
|
|---|
| 154 | bool findWidget( QWidget* w, int *row, int *col );
|
|---|
| 155 |
|
|---|
| 156 | inline void getNextPos( int &row, int &col ) { row = nextR; col = nextC; }
|
|---|
| 157 | inline uint count() const
|
|---|
| 158 | { return things.count() + ( multi ? multi->count() : 0 ); }
|
|---|
| 159 | QRect cellGeometry( int row, int col ) const;
|
|---|
| 160 |
|
|---|
| 161 | private:
|
|---|
| 162 | void setNextPosAfter( int r, int c );
|
|---|
| 163 | void recalcHFW( int w, int s );
|
|---|
| 164 | void addHfwData ( QGridBox *box, int width );
|
|---|
| 165 | void init();
|
|---|
| 166 | QSize findSize( QCOORD QLayoutStruct::*, int ) const;
|
|---|
| 167 | void addData( QGridBox *b, bool r = TRUE, bool c = TRUE );
|
|---|
| 168 | void setSize( int rows, int cols );
|
|---|
| 169 | void setupLayoutData( int space );
|
|---|
| 170 | void setupHfwLayoutData( int space );
|
|---|
| 171 |
|
|---|
| 172 | int rr;
|
|---|
| 173 | int cc;
|
|---|
| 174 | QMemArray<QLayoutStruct> rowData;
|
|---|
| 175 | QMemArray<QLayoutStruct> colData;
|
|---|
| 176 | QMemArray<QLayoutStruct> *hfwData;
|
|---|
| 177 | QMemArray<int> rStretch;
|
|---|
| 178 | QMemArray<int> cStretch;
|
|---|
| 179 | QMemArray<int> rSpacing;
|
|---|
| 180 | QMemArray<int> cSpacing;
|
|---|
| 181 | QPtrList<QGridBox> things;
|
|---|
| 182 | QPtrList<QGridMultiBox> *multi;
|
|---|
| 183 |
|
|---|
| 184 | int hfw_width;
|
|---|
| 185 | int hfw_height;
|
|---|
| 186 | int hfw_minheight;
|
|---|
| 187 | int nextR;
|
|---|
| 188 | int nextC;
|
|---|
| 189 |
|
|---|
| 190 | uint hReversed : 1;
|
|---|
| 191 | uint vReversed : 1;
|
|---|
| 192 | uint needRecalc : 1;
|
|---|
| 193 | uint has_hfw : 1;
|
|---|
| 194 | uint addVertical : 1;
|
|---|
| 195 |
|
|---|
| 196 | friend class QGridLayoutDataIterator;
|
|---|
| 197 | };
|
|---|
| 198 |
|
|---|
| 199 | QGridLayoutData::QGridLayoutData()
|
|---|
| 200 | {
|
|---|
| 201 | init();
|
|---|
| 202 | }
|
|---|
| 203 |
|
|---|
| 204 | QGridLayoutData::QGridLayoutData( int nRows, int nCols )
|
|---|
| 205 | : rowData( 0 ), colData( 0 )
|
|---|
| 206 | {
|
|---|
| 207 | init();
|
|---|
| 208 | if ( nRows < 0 ) {
|
|---|
| 209 | nRows = 1;
|
|---|
| 210 | addVertical = FALSE;
|
|---|
| 211 | }
|
|---|
| 212 | if ( nCols < 0 ) {
|
|---|
| 213 | nCols = 1;
|
|---|
| 214 | addVertical = TRUE;
|
|---|
| 215 | }
|
|---|
| 216 | setSize( nRows, nCols );
|
|---|
| 217 | }
|
|---|
| 218 |
|
|---|
| 219 | QGridLayoutData::~QGridLayoutData()
|
|---|
| 220 | {
|
|---|
| 221 | // must be cleared while the data is still in a stable state
|
|---|
| 222 | things.clear();
|
|---|
| 223 |
|
|---|
| 224 | delete multi;
|
|---|
| 225 | delete hfwData;
|
|---|
| 226 | }
|
|---|
| 227 |
|
|---|
| 228 | void QGridLayoutData::init()
|
|---|
| 229 | {
|
|---|
| 230 | addVertical = FALSE;
|
|---|
| 231 | setDirty();
|
|---|
| 232 | multi = 0;
|
|---|
| 233 | rr = cc = 0;
|
|---|
| 234 | nextR = nextC = 0;
|
|---|
| 235 | hfwData = 0;
|
|---|
| 236 | things.setAutoDelete( TRUE );
|
|---|
| 237 | hReversed = FALSE;
|
|---|
| 238 | vReversed = FALSE;
|
|---|
| 239 | }
|
|---|
| 240 |
|
|---|
| 241 | bool QGridLayoutData::hasHeightForWidth( int spacing )
|
|---|
| 242 | {
|
|---|
| 243 | setupLayoutData( spacing );
|
|---|
| 244 | return has_hfw;
|
|---|
| 245 | }
|
|---|
| 246 |
|
|---|
| 247 | /*
|
|---|
| 248 | Assumes that setupLayoutData() has been called, and that
|
|---|
| 249 | qGeomCalc() has filled in colData with appropriate values.
|
|---|
| 250 | */
|
|---|
| 251 | void QGridLayoutData::recalcHFW( int w, int spacing )
|
|---|
| 252 | {
|
|---|
| 253 | /*
|
|---|
| 254 | Go through all children, using colData and heightForWidth()
|
|---|
| 255 | and put the results in hfw_rowData.
|
|---|
| 256 | */
|
|---|
| 257 | if ( !hfwData )
|
|---|
| 258 | hfwData = new QMemArray<QLayoutStruct>( rr );
|
|---|
| 259 | setupHfwLayoutData( spacing );
|
|---|
| 260 | QMemArray<QLayoutStruct> &rData = *hfwData;
|
|---|
| 261 |
|
|---|
| 262 | int h = 0;
|
|---|
| 263 | int mh = 0;
|
|---|
| 264 | int n = 0;
|
|---|
| 265 | for ( int r = 0; r < rr; r++ ) {
|
|---|
| 266 | h += rData[r].sizeHint;
|
|---|
| 267 | mh += rData[r].minimumSize;
|
|---|
| 268 | if ( !rData[r].empty )
|
|---|
| 269 | n++;
|
|---|
| 270 | }
|
|---|
| 271 | if ( n ) {
|
|---|
| 272 | h += ( n - 1 ) * spacing;
|
|---|
| 273 | mh += ( n - 1 ) * spacing;
|
|---|
| 274 | }
|
|---|
| 275 |
|
|---|
| 276 | hfw_width = w;
|
|---|
| 277 | hfw_height = QMIN( QLAYOUTSIZE_MAX, h );
|
|---|
| 278 | hfw_minheight = QMIN( QLAYOUTSIZE_MAX, h );
|
|---|
| 279 | }
|
|---|
| 280 |
|
|---|
| 281 | int QGridLayoutData::heightForWidth( int w, int margin, int spacing )
|
|---|
| 282 | {
|
|---|
| 283 | setupLayoutData( spacing );
|
|---|
| 284 | if ( !has_hfw )
|
|---|
| 285 | return -1;
|
|---|
| 286 | if ( w + 2*margin != hfw_width ) {
|
|---|
| 287 | qGeomCalc( colData, 0, cc, 0, w+2*margin, spacing );
|
|---|
| 288 | recalcHFW( w+2*margin, spacing );
|
|---|
| 289 | }
|
|---|
| 290 | return hfw_height + 2*margin;
|
|---|
| 291 | }
|
|---|
| 292 |
|
|---|
| 293 | int QGridLayoutData::minimumHeightForWidth( int w, int margin, int spacing )
|
|---|
| 294 | {
|
|---|
| 295 | (void) heightForWidth( w, margin, spacing );
|
|---|
| 296 | return has_hfw ? (hfw_minheight + 2*margin) : -1;
|
|---|
| 297 | }
|
|---|
| 298 |
|
|---|
| 299 | bool QGridLayoutData::findWidget( QWidget* w, int *row, int *col )
|
|---|
| 300 | {
|
|---|
| 301 | QPtrListIterator<QGridBox> it( things );
|
|---|
| 302 | QGridBox * box;
|
|---|
| 303 | while ( (box = it.current()) != 0 ) {
|
|---|
| 304 | ++it;
|
|---|
| 305 | if ( box->item()->widget() == w ) {
|
|---|
| 306 | if ( row )
|
|---|
| 307 | *row = box->row;
|
|---|
| 308 | if ( col )
|
|---|
| 309 | *col = box->col;
|
|---|
| 310 | return TRUE;
|
|---|
| 311 | }
|
|---|
| 312 | }
|
|---|
| 313 | if ( multi ) {
|
|---|
| 314 | QPtrListIterator<QGridMultiBox> it( *multi );
|
|---|
| 315 | QGridMultiBox * mbox;
|
|---|
| 316 | while ( (mbox = it.current()) != 0 ) {
|
|---|
| 317 | ++it;
|
|---|
| 318 | box = mbox->box();
|
|---|
| 319 | if ( box->item()->widget() == w ) {
|
|---|
| 320 | if ( row )
|
|---|
| 321 | *row = box->row;
|
|---|
| 322 | if ( col )
|
|---|
| 323 | *col = box->col;
|
|---|
| 324 | return TRUE;
|
|---|
| 325 | }
|
|---|
| 326 |
|
|---|
| 327 | }
|
|---|
| 328 | }
|
|---|
| 329 | return FALSE;
|
|---|
| 330 | }
|
|---|
| 331 |
|
|---|
| 332 | QSize QGridLayoutData::findSize( QCOORD QLayoutStruct::*size, int spacer ) const
|
|---|
| 333 | {
|
|---|
| 334 | QGridLayoutData *that = (QGridLayoutData *)this;
|
|---|
| 335 | that->setupLayoutData( spacer );
|
|---|
| 336 |
|
|---|
| 337 | int w = 0;
|
|---|
| 338 | int h = 0;
|
|---|
| 339 | int n = 0;
|
|---|
| 340 | for ( int r = 0; r < rr; r++ ) {
|
|---|
| 341 | h = h + rowData[r].*size;
|
|---|
| 342 | if ( !rowData[r].empty )
|
|---|
| 343 | n++;
|
|---|
| 344 | }
|
|---|
| 345 | if ( n )
|
|---|
| 346 | h += ( n - 1 ) * spacer;
|
|---|
| 347 | n = 0;
|
|---|
| 348 | for ( int c = 0; c < cc; c++ ) {
|
|---|
| 349 | w = w + colData[c].*size;
|
|---|
| 350 | if ( !colData[c].empty )
|
|---|
| 351 | n++;
|
|---|
| 352 | }
|
|---|
| 353 | if ( n )
|
|---|
| 354 | w += ( n - 1 ) * spacer;
|
|---|
| 355 | w = QMIN( QLAYOUTSIZE_MAX, w );
|
|---|
| 356 | h = QMIN( QLAYOUTSIZE_MAX, h );
|
|---|
| 357 |
|
|---|
| 358 | return QSize( w, h );
|
|---|
| 359 | }
|
|---|
| 360 |
|
|---|
| 361 | QSizePolicy::ExpandData QGridLayoutData::expanding( int spacing )
|
|---|
| 362 | {
|
|---|
| 363 | setupLayoutData( spacing );
|
|---|
| 364 | int ret = 0;
|
|---|
| 365 |
|
|---|
| 366 | for ( int r = 0; r < rr; r++ ) {
|
|---|
| 367 | if ( rowData[r].expansive ) {
|
|---|
| 368 | ret |= (int) QSizePolicy::Vertically;
|
|---|
| 369 | break;
|
|---|
| 370 | }
|
|---|
| 371 | }
|
|---|
| 372 | for ( int c = 0; c < cc; c++ ) {
|
|---|
| 373 | if ( colData[c].expansive ) {
|
|---|
| 374 | ret |= (int) QSizePolicy::Horizontally;
|
|---|
| 375 | break;
|
|---|
| 376 | }
|
|---|
| 377 | }
|
|---|
| 378 | return (QSizePolicy::ExpandData) ret;
|
|---|
| 379 | }
|
|---|
| 380 |
|
|---|
| 381 | QSize QGridLayoutData::sizeHint( int spacer ) const
|
|---|
| 382 | {
|
|---|
| 383 | return findSize( &QLayoutStruct::sizeHint, spacer );
|
|---|
| 384 | }
|
|---|
| 385 |
|
|---|
| 386 | QSize QGridLayoutData::maximumSize( int spacer ) const
|
|---|
| 387 | {
|
|---|
| 388 | return findSize( &QLayoutStruct::maximumSize, spacer );
|
|---|
| 389 | }
|
|---|
| 390 |
|
|---|
| 391 | QSize QGridLayoutData::minimumSize( int spacer ) const
|
|---|
| 392 | {
|
|---|
| 393 | return findSize( &QLayoutStruct::minimumSize, spacer );
|
|---|
| 394 | }
|
|---|
| 395 |
|
|---|
| 396 | void QGridLayoutData::setSize( int r, int c )
|
|---|
| 397 | {
|
|---|
| 398 | if ( (int)rowData.size() < r ) {
|
|---|
| 399 | int newR = QMAX( r, rr * 2 );
|
|---|
| 400 | rowData.resize( newR );
|
|---|
| 401 | rStretch.resize( newR );
|
|---|
| 402 | rSpacing.resize( newR );
|
|---|
| 403 | for ( int i = rr; i < newR; i++ ) {
|
|---|
| 404 | rowData[i].init();
|
|---|
| 405 | rStretch[i] = 0;
|
|---|
| 406 | rSpacing[i] = 0;
|
|---|
| 407 | }
|
|---|
| 408 | }
|
|---|
| 409 | if ( (int)colData.size() < c ) {
|
|---|
| 410 | int newC = QMAX( c, cc * 2 );
|
|---|
| 411 | colData.resize( newC );
|
|---|
| 412 | cStretch.resize( newC );
|
|---|
| 413 | cSpacing.resize( newC );
|
|---|
| 414 | for ( int i = cc; i < newC; i++ ) {
|
|---|
| 415 | colData[i].init();
|
|---|
| 416 | cStretch[i] = 0;
|
|---|
| 417 | cSpacing[i] = 0;
|
|---|
| 418 | }
|
|---|
| 419 | }
|
|---|
| 420 |
|
|---|
| 421 | if ( hfwData && (int)hfwData->size() < r ) {
|
|---|
| 422 | delete hfwData;
|
|---|
| 423 | hfwData = 0;
|
|---|
| 424 | hfw_width = -1;
|
|---|
| 425 | }
|
|---|
| 426 | rr = r;
|
|---|
| 427 | cc = c;
|
|---|
| 428 | }
|
|---|
| 429 |
|
|---|
| 430 | void QGridLayoutData::setNextPosAfter( int row, int col )
|
|---|
| 431 | {
|
|---|
| 432 | if ( addVertical ) {
|
|---|
| 433 | if ( col > nextC || col == nextC && row >= nextR ) {
|
|---|
| 434 | nextR = row + 1;
|
|---|
| 435 | nextC = col;
|
|---|
| 436 | if ( nextR >= rr ) {
|
|---|
| 437 | nextR = 0;
|
|---|
| 438 | nextC++;
|
|---|
| 439 | }
|
|---|
| 440 | }
|
|---|
| 441 | } else {
|
|---|
| 442 | if ( row > nextR || row == nextR && col >= nextC ) {
|
|---|
| 443 | nextR = row;
|
|---|
| 444 | nextC = col + 1;
|
|---|
| 445 | if ( nextC >= cc ) {
|
|---|
| 446 | nextC = 0;
|
|---|
| 447 | nextR++;
|
|---|
| 448 | }
|
|---|
| 449 | }
|
|---|
| 450 | }
|
|---|
| 451 | }
|
|---|
| 452 |
|
|---|
| 453 | void QGridLayoutData::add( QGridBox *box, int row, int col )
|
|---|
| 454 | {
|
|---|
| 455 | expand( row+1, col+1 );
|
|---|
| 456 | box->row = row;
|
|---|
| 457 | box->col = col;
|
|---|
| 458 | things.append( box );
|
|---|
| 459 | setDirty();
|
|---|
| 460 | setNextPosAfter( row, col );
|
|---|
| 461 | }
|
|---|
| 462 |
|
|---|
| 463 | void QGridLayoutData::add( QGridBox *box, int row1, int row2, int col1,
|
|---|
| 464 | int col2 )
|
|---|
| 465 | {
|
|---|
| 466 | #ifdef QT_CHECK_RANGE
|
|---|
| 467 | if ( row2 >= 0 && row2 < row1 )
|
|---|
| 468 | qWarning( "QGridLayout: Multi-cell fromRow greater than toRow" );
|
|---|
| 469 | if ( col2 >= 0 && col2 < col1 )
|
|---|
| 470 | qWarning( "QGridLayout: Multi-cell fromCol greater than toCol" );
|
|---|
| 471 | #endif
|
|---|
| 472 | if ( row1 == row2 && col1 == col2 ) {
|
|---|
| 473 | add( box, row1, col1 );
|
|---|
| 474 | return;
|
|---|
| 475 | }
|
|---|
| 476 | expand( row2+1, col2+1 );
|
|---|
| 477 | box->row = row1;
|
|---|
| 478 | box->col = col1;
|
|---|
| 479 | QGridMultiBox *mbox = new QGridMultiBox( box, row2, col2 );
|
|---|
| 480 | if ( !multi ) {
|
|---|
| 481 | multi = new QPtrList<QGridMultiBox>;
|
|---|
| 482 | multi->setAutoDelete( TRUE );
|
|---|
| 483 | }
|
|---|
| 484 | multi->append( mbox );
|
|---|
| 485 | setDirty();
|
|---|
| 486 | if ( col2 < 0 )
|
|---|
| 487 | col2 = cc - 1;
|
|---|
| 488 |
|
|---|
| 489 | setNextPosAfter( row2, col2 );
|
|---|
| 490 | }
|
|---|
| 491 |
|
|---|
| 492 | void QGridLayoutData::addData( QGridBox *box, bool r, bool c )
|
|---|
| 493 | {
|
|---|
| 494 | QSize hint = box->sizeHint();
|
|---|
| 495 | QSize minS = box->minimumSize();
|
|---|
| 496 | QSize maxS = box->maximumSize();
|
|---|
| 497 |
|
|---|
| 498 | if ( c ) {
|
|---|
| 499 | if ( !cStretch[box->col] )
|
|---|
| 500 | colData[box->col].stretch = QMAX( colData[box->col].stretch,
|
|---|
| 501 | box->hStretch() );
|
|---|
| 502 | colData[box->col].sizeHint = QMAX( hint.width(),
|
|---|
| 503 | colData[box->col].sizeHint );
|
|---|
| 504 | colData[box->col].minimumSize = QMAX( minS.width(),
|
|---|
| 505 | colData[box->col].minimumSize );
|
|---|
| 506 |
|
|---|
| 507 | qMaxExpCalc( colData[box->col].maximumSize, colData[box->col].expansive,
|
|---|
| 508 | maxS.width(),
|
|---|
| 509 | box->expanding() & QSizePolicy::Horizontally );
|
|---|
| 510 | }
|
|---|
| 511 | if ( r ) {
|
|---|
| 512 | if ( !rStretch[box->row] )
|
|---|
| 513 | rowData[box->row].stretch = QMAX( rowData[box->row].stretch,
|
|---|
| 514 | box->vStretch() );
|
|---|
| 515 | rowData[box->row].sizeHint = QMAX( hint.height(),
|
|---|
| 516 | rowData[box->row].sizeHint );
|
|---|
| 517 | rowData[box->row].minimumSize = QMAX( minS.height(),
|
|---|
| 518 | rowData[box->row].minimumSize );
|
|---|
| 519 |
|
|---|
| 520 | qMaxExpCalc( rowData[box->row].maximumSize, rowData[box->row].expansive,
|
|---|
| 521 | maxS.height(),
|
|---|
| 522 | box->expanding() & QSizePolicy::Vertically );
|
|---|
| 523 | }
|
|---|
| 524 | if ( box->isEmpty() ) {
|
|---|
| 525 | if ( box->item()->widget() != 0 ) {
|
|---|
| 526 | /*
|
|---|
| 527 | Hidden widgets should behave exactly the same as if
|
|---|
| 528 | there were no widgets at all in the cell. We could have
|
|---|
| 529 | QWidgetItem::maximumSize() to return
|
|---|
| 530 | QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX). However, that
|
|---|
| 531 | value is not suitable for QBoxLayouts. So let's fix it
|
|---|
| 532 | here.
|
|---|
| 533 | */
|
|---|
| 534 | if ( c )
|
|---|
| 535 | colData[box->col].maximumSize = QLAYOUTSIZE_MAX;
|
|---|
| 536 | if ( r )
|
|---|
| 537 | rowData[box->row].maximumSize = QLAYOUTSIZE_MAX;
|
|---|
| 538 | }
|
|---|
| 539 | } else {
|
|---|
| 540 | // Empty boxes (i.e. spacers) do not get borders. This is
|
|---|
| 541 | // hacky, but compatible.
|
|---|
| 542 | if ( c )
|
|---|
| 543 | colData[box->col].empty = FALSE;
|
|---|
| 544 | if ( r )
|
|---|
| 545 | rowData[box->row].empty = FALSE;
|
|---|
| 546 | }
|
|---|
| 547 | }
|
|---|
| 548 |
|
|---|
| 549 | static void distributeMultiBox( QMemArray<QLayoutStruct> &chain, int spacing,
|
|---|
| 550 | int start, int end,
|
|---|
| 551 | int minSize, int sizeHint,
|
|---|
| 552 | QMemArray<int> &stretchArray, int stretch )
|
|---|
| 553 | {
|
|---|
| 554 | int i;
|
|---|
| 555 | int w = 0;
|
|---|
| 556 | int wh = 0;
|
|---|
| 557 | int max = 0;
|
|---|
| 558 | for ( i = start; i <= end; i++ ) {
|
|---|
| 559 | w += chain[i].minimumSize;
|
|---|
| 560 | wh += chain[i].sizeHint;
|
|---|
| 561 | max += chain[i].maximumSize;
|
|---|
| 562 | chain[i].empty = FALSE;
|
|---|
| 563 | if ( stretchArray[i] == 0 )
|
|---|
| 564 | chain[i].stretch = QMAX(chain[i].stretch,stretch);
|
|---|
| 565 | }
|
|---|
| 566 | w += spacing * ( end - start );
|
|---|
| 567 | wh += spacing * ( end - start );
|
|---|
| 568 | max += spacing * ( end - start );
|
|---|
| 569 |
|
|---|
| 570 | if ( max < minSize ) { // implies w < minSize
|
|---|
| 571 | /*
|
|---|
| 572 | We must increase the maximum size of at least one of the
|
|---|
| 573 | items. qGeomCalc() will put the extra space in between the
|
|---|
| 574 | items. We must recover that extra space and put it
|
|---|
| 575 | somewhere. It does not really matter where, since the user
|
|---|
| 576 | can always specify stretch factors and avoid this code.
|
|---|
| 577 | */
|
|---|
| 578 | qGeomCalc( chain, start, end - start + 1, 0, minSize, spacing );
|
|---|
| 579 | int pos = 0;
|
|---|
| 580 | for ( i = start; i <= end; i++ ) {
|
|---|
| 581 | int nextPos = ( i == end ) ? minSize - 1 : chain[i + 1].pos;
|
|---|
| 582 | int realSize = nextPos - pos;
|
|---|
| 583 | if ( i != end )
|
|---|
| 584 | realSize -= spacing;
|
|---|
| 585 | if ( chain[i].minimumSize < realSize )
|
|---|
| 586 | chain[i].minimumSize = realSize;
|
|---|
| 587 | if ( chain[i].maximumSize < chain[i].minimumSize )
|
|---|
| 588 | chain[i].maximumSize = chain[i].minimumSize;
|
|---|
| 589 | pos = nextPos;
|
|---|
| 590 | }
|
|---|
| 591 | } else if ( w < minSize ) {
|
|---|
| 592 | qGeomCalc( chain, start, end - start + 1, 0, minSize, spacing );
|
|---|
| 593 | for ( i = start; i <= end; i++ ) {
|
|---|
| 594 | if ( chain[i].minimumSize < chain[i].size )
|
|---|
| 595 | chain[i].minimumSize = chain[i].size;
|
|---|
| 596 | }
|
|---|
| 597 | }
|
|---|
| 598 |
|
|---|
| 599 | if ( wh < sizeHint ) {
|
|---|
| 600 | qGeomCalc( chain, start, end - start + 1, 0, sizeHint, spacing );
|
|---|
| 601 | for ( i = start; i <= end; i++ ) {
|
|---|
| 602 | if ( chain[i].sizeHint < chain[i].size )
|
|---|
| 603 | chain[i].sizeHint = chain[i].size;
|
|---|
| 604 | }
|
|---|
| 605 | }
|
|---|
| 606 | }
|
|---|
| 607 |
|
|---|
| 608 | //#define QT_LAYOUT_DISABLE_CACHING
|
|---|
| 609 |
|
|---|
| 610 | void QGridLayoutData::setupLayoutData( int spacing )
|
|---|
| 611 | {
|
|---|
| 612 | #ifndef QT_LAYOUT_DISABLE_CACHING
|
|---|
| 613 | if ( !needRecalc )
|
|---|
| 614 | return;
|
|---|
| 615 | #endif
|
|---|
| 616 | has_hfw = FALSE;
|
|---|
| 617 | int i;
|
|---|
| 618 |
|
|---|
| 619 | for ( i = 0; i < rr; i++ )
|
|---|
| 620 | rowData[i].init( rStretch[i], rSpacing[i] );
|
|---|
| 621 | for ( i = 0; i < cc; i++ )
|
|---|
| 622 | colData[i].init( cStretch[i], cSpacing[i] );
|
|---|
| 623 |
|
|---|
| 624 | QPtrListIterator<QGridBox> it( things );
|
|---|
| 625 | QGridBox * box;
|
|---|
| 626 | while ( (box = it.current()) != 0 ) {
|
|---|
| 627 | ++it;
|
|---|
| 628 | addData( box );
|
|---|
| 629 | has_hfw = has_hfw || box->item()->hasHeightForWidth();
|
|---|
| 630 | }
|
|---|
| 631 |
|
|---|
| 632 | if ( multi ) {
|
|---|
| 633 | QPtrListIterator<QGridMultiBox> it( *multi );
|
|---|
| 634 | QGridMultiBox * mbox;
|
|---|
| 635 | while ( (mbox = it.current()) != 0 ) {
|
|---|
| 636 | ++it;
|
|---|
| 637 | QGridBox *box = mbox->box();
|
|---|
| 638 | int r1 = box->row;
|
|---|
| 639 | int c1 = box->col;
|
|---|
| 640 | int r2 = mbox->torow;
|
|---|
| 641 | int c2 = mbox->tocol;
|
|---|
| 642 | if ( r2 < 0 )
|
|---|
| 643 | r2 = rr - 1;
|
|---|
| 644 | if ( c2 < 0 )
|
|---|
| 645 | c2 = cc - 1;
|
|---|
| 646 |
|
|---|
| 647 | QSize hint = box->sizeHint();
|
|---|
| 648 | QSize min = box->minimumSize();
|
|---|
| 649 | if ( box->hasHeightForWidth() )
|
|---|
| 650 | has_hfw = TRUE;
|
|---|
| 651 |
|
|---|
| 652 | if ( r1 == r2 ) {
|
|---|
| 653 | addData( box, TRUE, FALSE );
|
|---|
| 654 | } else {
|
|---|
| 655 | distributeMultiBox( rowData, spacing, r1, r2,
|
|---|
| 656 | min.height(), hint.height(),
|
|---|
| 657 | rStretch, box->vStretch() );
|
|---|
| 658 | }
|
|---|
| 659 | if ( c1 == c2 ) {
|
|---|
| 660 | addData( box, FALSE, TRUE );
|
|---|
| 661 | } else {
|
|---|
| 662 | distributeMultiBox( colData, spacing, c1, c2,
|
|---|
| 663 | min.width(), hint.width(),
|
|---|
| 664 | cStretch, box->hStretch() );
|
|---|
| 665 | }
|
|---|
| 666 | }
|
|---|
| 667 | }
|
|---|
| 668 | for ( i = 0; i < rr; i++ )
|
|---|
| 669 | rowData[i].expansive = rowData[i].expansive || rowData[i].stretch > 0;
|
|---|
| 670 | for ( i = 0; i < cc; i++ )
|
|---|
| 671 | colData[i].expansive = colData[i].expansive || colData[i].stretch > 0;
|
|---|
| 672 |
|
|---|
| 673 | needRecalc = FALSE;
|
|---|
| 674 | }
|
|---|
| 675 |
|
|---|
| 676 | void QGridLayoutData::addHfwData( QGridBox *box, int width )
|
|---|
| 677 | {
|
|---|
| 678 | QMemArray<QLayoutStruct> &rData = *hfwData;
|
|---|
| 679 | if ( box->hasHeightForWidth() ) {
|
|---|
| 680 | int hint = box->heightForWidth( width );
|
|---|
| 681 | rData[box->row].sizeHint = QMAX( hint, rData[box->row].sizeHint );
|
|---|
| 682 | rData[box->row].minimumSize = QMAX( hint, rData[box->row].minimumSize );
|
|---|
| 683 | } else {
|
|---|
| 684 | QSize hint = box->sizeHint();
|
|---|
| 685 | QSize minS = box->minimumSize();
|
|---|
| 686 | rData[box->row].sizeHint = QMAX( hint.height(),
|
|---|
| 687 | rData[box->row].sizeHint );
|
|---|
| 688 | rData[box->row].minimumSize = QMAX( minS.height(),
|
|---|
| 689 | rData[box->row].minimumSize );
|
|---|
| 690 | }
|
|---|
| 691 | }
|
|---|
| 692 |
|
|---|
| 693 | /*
|
|---|
| 694 | Similar to setupLayoutData(), but uses heightForWidth(colData)
|
|---|
| 695 | instead of sizeHint(). Assumes that setupLayoutData() and
|
|---|
| 696 | qGeomCalc(colData) has been called.
|
|---|
| 697 | */
|
|---|
| 698 | void QGridLayoutData::setupHfwLayoutData( int spacing )
|
|---|
| 699 | {
|
|---|
| 700 | QMemArray<QLayoutStruct> &rData = *hfwData;
|
|---|
| 701 | int i;
|
|---|
| 702 | for ( i = 0; i < rr; i++ ) {
|
|---|
| 703 | rData[i] = rowData[i];
|
|---|
| 704 | rData[i].minimumSize = rData[i].sizeHint = 0;
|
|---|
| 705 | }
|
|---|
| 706 | QPtrListIterator<QGridBox> it( things );
|
|---|
| 707 | QGridBox * box;
|
|---|
| 708 | while ( (box=it.current()) != 0 ) {
|
|---|
| 709 | ++it;
|
|---|
| 710 | addHfwData( box, colData[box->col].size );
|
|---|
| 711 | }
|
|---|
| 712 | if ( multi ) {
|
|---|
| 713 | QPtrListIterator<QGridMultiBox> it( *multi );
|
|---|
| 714 | QGridMultiBox * mbox;
|
|---|
| 715 | while ( (mbox=it.current()) != 0 ) {
|
|---|
| 716 | ++it;
|
|---|
| 717 | QGridBox *box = mbox->box();
|
|---|
| 718 | int r1 = box->row;
|
|---|
| 719 | int c1 = box->col;
|
|---|
| 720 | int r2 = mbox->torow;
|
|---|
| 721 | int c2 = mbox->tocol;
|
|---|
| 722 | if ( r2 < 0 )
|
|---|
| 723 | r2 = rr-1;
|
|---|
| 724 | if ( c2 < 0 )
|
|---|
| 725 | c2 = cc-1;
|
|---|
| 726 | int w = colData[c2].pos + colData[c2].size - colData[c1].pos;
|
|---|
| 727 | if ( r1 == r2 ) {
|
|---|
| 728 | addHfwData( box, w );
|
|---|
| 729 | } else {
|
|---|
| 730 | QSize hint = box->sizeHint();
|
|---|
| 731 | QSize min = box->minimumSize();
|
|---|
| 732 | if ( box->hasHeightForWidth() ) {
|
|---|
| 733 | int hfwh = box->heightForWidth( w );
|
|---|
| 734 | if ( hfwh > hint.height() )
|
|---|
| 735 | hint.setHeight( hfwh );
|
|---|
| 736 | if ( hfwh > min.height() )
|
|---|
| 737 | min.setHeight( hfwh );
|
|---|
| 738 | }
|
|---|
| 739 | distributeMultiBox( rData, spacing, r1, r2,
|
|---|
| 740 | min.height(), hint.height(),
|
|---|
| 741 | rStretch, box->vStretch() );
|
|---|
| 742 | }
|
|---|
| 743 | }
|
|---|
| 744 | }
|
|---|
| 745 | for ( i = 0; i < rr; i++ )
|
|---|
| 746 | rData[i].expansive = rData[i].expansive || rData[i].stretch > 0;
|
|---|
| 747 | }
|
|---|
| 748 |
|
|---|
| 749 | void QGridLayoutData::distribute( QRect r, int spacing )
|
|---|
| 750 | {
|
|---|
| 751 | bool visualHReversed = hReversed;
|
|---|
| 752 | if ( QApplication::reverseLayout() )
|
|---|
| 753 | visualHReversed = !visualHReversed;
|
|---|
| 754 |
|
|---|
| 755 | setupLayoutData( spacing );
|
|---|
| 756 |
|
|---|
| 757 | qGeomCalc( colData, 0, cc, r.x(), r.width(), spacing );
|
|---|
| 758 | QMemArray<QLayoutStruct> *rDataPtr;
|
|---|
| 759 | if ( has_hfw ) {
|
|---|
| 760 | recalcHFW( r.width(), spacing );
|
|---|
| 761 | qGeomCalc( *hfwData, 0, rr, r.y(), r.height(), spacing );
|
|---|
| 762 | rDataPtr = hfwData;
|
|---|
| 763 | } else {
|
|---|
| 764 | qGeomCalc( rowData, 0, rr, r.y(), r.height(), spacing );
|
|---|
| 765 | rDataPtr = &rowData;
|
|---|
| 766 | }
|
|---|
| 767 | QMemArray<QLayoutStruct> &rData = *rDataPtr;
|
|---|
| 768 |
|
|---|
| 769 | QPtrListIterator<QGridBox> it( things );
|
|---|
| 770 | QGridBox * box;
|
|---|
| 771 | while ( (box=it.current()) != 0 ) {
|
|---|
| 772 | ++it;
|
|---|
| 773 | int x = colData[box->col].pos;
|
|---|
| 774 | int y = rData[box->row].pos;
|
|---|
| 775 | int w = colData[box->col].size;
|
|---|
| 776 | int h = rData[box->row].size;
|
|---|
| 777 | if ( visualHReversed )
|
|---|
| 778 | x = r.left() + r.right() - x - w + 1;
|
|---|
| 779 | if ( vReversed )
|
|---|
| 780 | y = r.top() + r.bottom() - y - h + 1;
|
|---|
| 781 | box->setGeometry( QRect( x, y, w, h ) );
|
|---|
| 782 | }
|
|---|
| 783 | if ( multi ) {
|
|---|
| 784 | QPtrListIterator<QGridMultiBox> it( *multi );
|
|---|
| 785 | QGridMultiBox * mbox;
|
|---|
| 786 | while ( (mbox=it.current()) != 0 ) {
|
|---|
| 787 | ++it;
|
|---|
| 788 | QGridBox *box = mbox->box();
|
|---|
| 789 | int r2 = mbox->torow;
|
|---|
| 790 | int c2 = mbox->tocol;
|
|---|
| 791 | if ( r2 < 0 )
|
|---|
| 792 | r2 = rr-1;
|
|---|
| 793 | if ( c2 < 0 )
|
|---|
| 794 | c2 = cc-1;
|
|---|
| 795 |
|
|---|
| 796 | int x = colData[box->col].pos;
|
|---|
| 797 | int y = rData[box->row].pos;
|
|---|
| 798 | int x2p = colData[c2].pos + colData[c2].size; // x2+1
|
|---|
| 799 | int y2p = rData[r2].pos + rData[r2].size; // y2+1
|
|---|
| 800 | int w = x2p - x;
|
|---|
| 801 | int h = y2p - y;
|
|---|
| 802 | // this code is copied from above:
|
|---|
| 803 | if ( visualHReversed )
|
|---|
| 804 | x = r.left() + r.right() - x - w + 1;
|
|---|
| 805 | if ( vReversed )
|
|---|
| 806 | y = r.top() + r.bottom() - y - h + 1;
|
|---|
| 807 | box->setGeometry( QRect( x, y, w, h ) );
|
|---|
| 808 | }
|
|---|
| 809 | }
|
|---|
| 810 | }
|
|---|
| 811 |
|
|---|
| 812 | QRect QGridLayoutData::cellGeometry( int row, int col ) const
|
|---|
| 813 | {
|
|---|
| 814 | if ( row < 0 || row >= rr || col < 0 || col >= cc )
|
|---|
| 815 | return QRect();
|
|---|
| 816 |
|
|---|
| 817 | const QMemArray<QLayoutStruct> *rDataPtr;
|
|---|
| 818 | if ( has_hfw )
|
|---|
| 819 | rDataPtr = hfwData;
|
|---|
| 820 | else
|
|---|
| 821 | rDataPtr = &rowData;
|
|---|
| 822 | return QRect( colData[col].pos, (*rDataPtr)[row].pos,
|
|---|
| 823 | colData[col].size, (*rDataPtr)[row].size );
|
|---|
| 824 | }
|
|---|
| 825 |
|
|---|
| 826 | class QGridLayoutDataIterator : public QGLayoutIterator
|
|---|
| 827 | {
|
|---|
| 828 | public:
|
|---|
| 829 | QGridLayoutDataIterator( QGridLayoutData *d );
|
|---|
| 830 | uint count() const { return data->count(); }
|
|---|
| 831 | QLayoutItem *current() {
|
|---|
| 832 | if ( multi ) {
|
|---|
| 833 | if ( !data->multi || idx >= (int)data->multi->count() )
|
|---|
| 834 | return 0;
|
|---|
| 835 | return data->multi->at( idx )->box()->item();
|
|---|
| 836 | } else {
|
|---|
| 837 | if ( idx >= (int)data->things.count() )
|
|---|
| 838 | return 0;
|
|---|
| 839 | return data->things.at( idx )->item();
|
|---|
| 840 | }
|
|---|
| 841 | }
|
|---|
| 842 | void toFirst() {
|
|---|
| 843 | multi = data->things.isEmpty();
|
|---|
| 844 | idx = 0;
|
|---|
| 845 | }
|
|---|
| 846 | QLayoutItem *next() {
|
|---|
| 847 | idx++;
|
|---|
| 848 | if ( !multi && idx >= (int)data->things.count() ) {
|
|---|
| 849 | multi = TRUE;
|
|---|
| 850 | idx = 0;
|
|---|
| 851 | }
|
|---|
| 852 | return current();
|
|---|
| 853 | }
|
|---|
| 854 | QLayoutItem *takeCurrent() {
|
|---|
| 855 | QLayoutItem *item = 0;
|
|---|
| 856 | if ( multi ) {
|
|---|
| 857 | if ( !data->multi || idx >= (int)data->multi->count() )
|
|---|
| 858 | return 0;
|
|---|
| 859 | QGridMultiBox *b = data->multi->take( idx );
|
|---|
| 860 | item = b->takeItem();
|
|---|
| 861 | delete b;
|
|---|
| 862 | } else {
|
|---|
| 863 | if ( idx >= (int)data->things.count() )
|
|---|
| 864 | return 0;
|
|---|
| 865 | QGridBox *b = data->things.take( idx );
|
|---|
| 866 | item = b->takeItem();
|
|---|
| 867 | delete b;
|
|---|
| 868 | }
|
|---|
| 869 | return item;
|
|---|
| 870 | }
|
|---|
| 871 |
|
|---|
| 872 | private:
|
|---|
| 873 | QGridLayoutData *data;
|
|---|
| 874 | bool multi;
|
|---|
| 875 | int idx;
|
|---|
| 876 | };
|
|---|
| 877 |
|
|---|
| 878 | inline QGridLayoutDataIterator::QGridLayoutDataIterator( QGridLayoutData *d )
|
|---|
| 879 | : data( d )
|
|---|
| 880 | {
|
|---|
| 881 | toFirst();
|
|---|
| 882 | }
|
|---|
| 883 |
|
|---|
| 884 | /*!
|
|---|
| 885 | \class QGridLayout
|
|---|
| 886 |
|
|---|
| 887 | \brief The QGridLayout class lays out widgets in a grid.
|
|---|
| 888 |
|
|---|
| 889 | \ingroup geomanagement
|
|---|
| 890 | \ingroup appearance
|
|---|
| 891 | \mainclass
|
|---|
| 892 |
|
|---|
| 893 | QGridLayout takes the space made available to it (by its parent
|
|---|
| 894 | layout or by the mainWidget()), divides it up into rows and
|
|---|
| 895 | columns, and puts each widget it manages into the correct cell.
|
|---|
| 896 |
|
|---|
| 897 | Columns and rows behave identically; we will discuss columns, but
|
|---|
| 898 | there are equivalent functions for rows.
|
|---|
| 899 |
|
|---|
| 900 | Each column has a minimum width and a stretch factor. The minimum
|
|---|
| 901 | width is the greatest of that set using addColSpacing() and the
|
|---|
| 902 | minimum width of each widget in that column. The stretch factor is
|
|---|
| 903 | set using setColStretch() and determines how much of the available
|
|---|
| 904 | space the column will get over and above its necessary minimum.
|
|---|
| 905 |
|
|---|
| 906 | Normally, each managed widget or layout is put into a cell of its
|
|---|
| 907 | own using addWidget(), addLayout() or by the \link
|
|---|
| 908 | QLayout::setAutoAdd() auto-add facility\endlink. It is also
|
|---|
| 909 | possible for a widget to occupy multiple cells using
|
|---|
| 910 | addMultiCellWidget(). If you do this, QGridLayout will guess how
|
|---|
| 911 | to distribute the size over the columns/rows (based on the stretch
|
|---|
| 912 | factors).
|
|---|
| 913 |
|
|---|
| 914 | To remove a widget from a layout, call remove(). Calling
|
|---|
| 915 | QWidget::hide() on a widget also effectively removes the widget
|
|---|
| 916 | from the layout until QWidget::show() is called.
|
|---|
| 917 |
|
|---|
| 918 | This illustration shows a fragment of a dialog with a five-column,
|
|---|
| 919 | three-row grid (the grid is shown overlaid in magenta):
|
|---|
| 920 |
|
|---|
| 921 | \img gridlayout.png
|
|---|
| 922 |
|
|---|
| 923 | Columns 0, 2 and 4 in this dialog fragment are made up of a
|
|---|
| 924 | QLabel, a QLineEdit, and a QListBox. Columns 1 and 3 are
|
|---|
| 925 | placeholders made with addColSpacing(). Row 0 consists of three
|
|---|
| 926 | QLabel objects, row 1 of three QLineEdit objects and row 2 of
|
|---|
| 927 | three QListBox objects. We used placeholder columns (1 and 3) to
|
|---|
| 928 | get the right amount of space between the columns.
|
|---|
| 929 |
|
|---|
| 930 | Note that the columns and rows are not equally wide or tall. If
|
|---|
| 931 | you want two columns to have the same width, you must set their
|
|---|
| 932 | minimum widths and stretch factors to be the same yourself. You do
|
|---|
| 933 | this using addColSpacing() and setColStretch().
|
|---|
| 934 |
|
|---|
| 935 | If the QGridLayout is not the top-level layout (i.e. does not
|
|---|
| 936 | manage all of the widget's area and children), you must add it to
|
|---|
| 937 | its parent layout when you create it, but before you do anything
|
|---|
| 938 | with it. The normal way to add a layout is by calling
|
|---|
| 939 | parentLayout-\>addLayout().
|
|---|
| 940 |
|
|---|
| 941 | Once you have added your layout you can start putting widgets and
|
|---|
| 942 | other layouts into the cells of your grid layout using
|
|---|
| 943 | addWidget(), addLayout() and addMultiCellWidget().
|
|---|
| 944 |
|
|---|
| 945 | QGridLayout also includes two margin widths: the border and the
|
|---|
| 946 | spacing. The border is the width of the reserved space along each
|
|---|
| 947 | of the QGridLayout's four sides. The spacing is the width of the
|
|---|
| 948 | automatically allocated spacing between neighboring boxes.
|
|---|
| 949 |
|
|---|
| 950 | Both the border and the spacing are parameters of the constructor
|
|---|
| 951 | and default to 0.
|
|---|
| 952 |
|
|---|
| 953 | \sa QGrid, \link layout.html Layout Overview \endlink
|
|---|
| 954 | */
|
|---|
| 955 |
|
|---|
| 956 | /*!
|
|---|
| 957 | \enum QGridLayout::Corner
|
|---|
| 958 |
|
|---|
| 959 | This enum identifies which corner is the origin (0, 0) of the
|
|---|
| 960 | layout.
|
|---|
| 961 |
|
|---|
| 962 | \value TopLeft the top-left corner
|
|---|
| 963 | \value TopRight the top-right corner
|
|---|
| 964 | \value BottomLeft the bottom-left corner
|
|---|
| 965 | \value BottomRight the bottom-right corner
|
|---|
| 966 | */
|
|---|
| 967 |
|
|---|
| 968 | /*!
|
|---|
| 969 | Constructs a new QGridLayout with \a nRows rows, \a nCols columns
|
|---|
| 970 | and parent widget, \a parent. \a parent may not be 0. The grid
|
|---|
| 971 | layout is called \a name.
|
|---|
| 972 |
|
|---|
| 973 | \a margin is the number of pixels between the edge of the widget
|
|---|
| 974 | and its managed children. \a space is the default number of pixels
|
|---|
| 975 | between cells. If \a space is -1, the value of \a margin is used.
|
|---|
| 976 | */
|
|---|
| 977 | QGridLayout::QGridLayout( QWidget *parent, int nRows, int nCols, int margin,
|
|---|
| 978 | int space, const char *name )
|
|---|
| 979 | : QLayout( parent, margin, space, name )
|
|---|
| 980 | {
|
|---|
| 981 | init( nRows, nCols );
|
|---|
| 982 | }
|
|---|
| 983 |
|
|---|
| 984 | /*!
|
|---|
| 985 | Constructs a new grid that is placed inside \a parentLayout with
|
|---|
| 986 | \a nRows rows and \a nCols columns. If \a spacing is -1, this
|
|---|
| 987 | QGridLayout inherits its parent's spacing(); otherwise \a spacing
|
|---|
| 988 | is used. The grid layout is called \a name.
|
|---|
| 989 |
|
|---|
| 990 | This grid is placed according to \a parentLayout's default
|
|---|
| 991 | placement rules.
|
|---|
| 992 | */
|
|---|
| 993 | QGridLayout::QGridLayout( QLayout *parentLayout, int nRows, int nCols,
|
|---|
| 994 | int spacing, const char *name )
|
|---|
| 995 | : QLayout( parentLayout, spacing, name )
|
|---|
| 996 | {
|
|---|
| 997 | init( nRows, nCols );
|
|---|
| 998 | }
|
|---|
| 999 |
|
|---|
| 1000 | /*!
|
|---|
| 1001 | Constructs a new grid with \a nRows rows and \a nCols columns. If
|
|---|
| 1002 | \a spacing is -1, this QGridLayout inherits its parent's
|
|---|
| 1003 | spacing(); otherwise \a spacing is used. The grid layout is called
|
|---|
| 1004 | \a name.
|
|---|
| 1005 |
|
|---|
| 1006 | You must insert this grid into another layout. You can insert
|
|---|
| 1007 | widgets and layouts into this layout at any time, but laying out
|
|---|
| 1008 | will not be performed before this is inserted into another layout.
|
|---|
| 1009 | */
|
|---|
| 1010 | QGridLayout::QGridLayout( int nRows, int nCols,
|
|---|
| 1011 | int spacing, const char *name )
|
|---|
| 1012 | : QLayout( spacing, name )
|
|---|
| 1013 | {
|
|---|
| 1014 | init( nRows, nCols );
|
|---|
| 1015 | }
|
|---|
| 1016 |
|
|---|
| 1017 | /*!
|
|---|
| 1018 | Destroys the grid layout. Geometry management is terminated if
|
|---|
| 1019 | this is a top-level grid.
|
|---|
| 1020 |
|
|---|
| 1021 | The layout's widgets aren't destroyed.
|
|---|
| 1022 | */
|
|---|
| 1023 | QGridLayout::~QGridLayout()
|
|---|
| 1024 | {
|
|---|
| 1025 | delete data;
|
|---|
| 1026 | }
|
|---|
| 1027 |
|
|---|
| 1028 | /*!
|
|---|
| 1029 | Returns the number of rows in this grid.
|
|---|
| 1030 | */
|
|---|
| 1031 | int QGridLayout::numRows() const
|
|---|
| 1032 | {
|
|---|
| 1033 | return data->numRows();
|
|---|
| 1034 | }
|
|---|
| 1035 |
|
|---|
| 1036 | /*!
|
|---|
| 1037 | Returns the number of columns in this grid.
|
|---|
| 1038 | */
|
|---|
| 1039 | int QGridLayout::numCols() const
|
|---|
| 1040 | {
|
|---|
| 1041 | return data->numCols();
|
|---|
| 1042 | }
|
|---|
| 1043 |
|
|---|
| 1044 | /*!
|
|---|
| 1045 | Returns the preferred size of this grid.
|
|---|
| 1046 | */
|
|---|
| 1047 | QSize QGridLayout::sizeHint() const
|
|---|
| 1048 | {
|
|---|
| 1049 | return data->sizeHint( spacing() ) + QSize( 2 * margin(), 2 * margin() );
|
|---|
| 1050 | }
|
|---|
| 1051 |
|
|---|
| 1052 | /*!
|
|---|
| 1053 | Returns the minimum size needed by this grid.
|
|---|
| 1054 | */
|
|---|
| 1055 | QSize QGridLayout::minimumSize() const
|
|---|
| 1056 | {
|
|---|
| 1057 | return data->minimumSize( spacing() ) + QSize( 2 * margin(), 2 * margin() );
|
|---|
| 1058 | }
|
|---|
| 1059 |
|
|---|
| 1060 | /*!
|
|---|
| 1061 | Returns the maximum size needed by this grid.
|
|---|
| 1062 | */
|
|---|
| 1063 | QSize QGridLayout::maximumSize() const
|
|---|
| 1064 | {
|
|---|
| 1065 | QSize s = data->maximumSize( spacing() ) +
|
|---|
| 1066 | QSize( 2 * margin(), 2 * margin() );
|
|---|
| 1067 | s = s.boundedTo( QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX) );
|
|---|
| 1068 | if ( alignment() & Qt::AlignHorizontal_Mask )
|
|---|
| 1069 | s.setWidth( QLAYOUTSIZE_MAX );
|
|---|
| 1070 | if ( alignment() & Qt::AlignVertical_Mask )
|
|---|
| 1071 | s.setHeight( QLAYOUTSIZE_MAX );
|
|---|
| 1072 | return s;
|
|---|
| 1073 | }
|
|---|
| 1074 |
|
|---|
| 1075 | /*!
|
|---|
| 1076 | Returns TRUE if this layout's preferred height depends on its
|
|---|
| 1077 | width; otherwise returns FALSE.
|
|---|
| 1078 | */
|
|---|
| 1079 | bool QGridLayout::hasHeightForWidth() const
|
|---|
| 1080 | {
|
|---|
| 1081 | return ((QGridLayout*)this)->data->hasHeightForWidth( spacing() );
|
|---|
| 1082 | }
|
|---|
| 1083 |
|
|---|
| 1084 | /*!
|
|---|
| 1085 | Returns the layout's preferred height when it is \a w pixels wide.
|
|---|
| 1086 | */
|
|---|
| 1087 | int QGridLayout::heightForWidth( int w ) const
|
|---|
| 1088 | {
|
|---|
| 1089 | QGridLayout *that = (QGridLayout*)this;
|
|---|
| 1090 | return that->data->heightForWidth( w, margin(), spacing() );
|
|---|
| 1091 | }
|
|---|
| 1092 |
|
|---|
| 1093 | /*! \internal */
|
|---|
| 1094 | int QGridLayout::minimumHeightForWidth( int w ) const
|
|---|
| 1095 | {
|
|---|
| 1096 | QGridLayout *that = (QGridLayout*)this;
|
|---|
| 1097 | return that->data->minimumHeightForWidth( w, margin(), spacing() );
|
|---|
| 1098 | }
|
|---|
| 1099 |
|
|---|
| 1100 | /*!
|
|---|
| 1101 | Searches for widget \a w in this layout (not including child
|
|---|
| 1102 | layouts). If \a w is found, it sets \c *\a row and \c *\a col to
|
|---|
| 1103 | the row and column and returns TRUE; otherwise returns FALSE.
|
|---|
| 1104 |
|
|---|
| 1105 | Note: if a widget spans multiple rows/columns, the top-left cell
|
|---|
| 1106 | is returned.
|
|---|
| 1107 | */
|
|---|
| 1108 | bool QGridLayout::findWidget( QWidget* w, int *row, int *col )
|
|---|
| 1109 | {
|
|---|
| 1110 | return data->findWidget( w, row, col );
|
|---|
| 1111 | }
|
|---|
| 1112 |
|
|---|
| 1113 | /*!
|
|---|
| 1114 | Resizes managed widgets within the rectangle \a r.
|
|---|
| 1115 | */
|
|---|
| 1116 | void QGridLayout::setGeometry( const QRect &r )
|
|---|
| 1117 | {
|
|---|
| 1118 | if ( data->isDirty() || r != geometry() ) {
|
|---|
| 1119 | QLayout::setGeometry( r );
|
|---|
| 1120 | QRect cr = alignment() ? alignmentRect( r ) : r;
|
|---|
| 1121 | QRect s( cr.x() + margin(), cr.y() + margin(),
|
|---|
| 1122 | cr.width() - 2 * margin(), cr.height() - 2 * margin() );
|
|---|
| 1123 | data->distribute( s, spacing() );
|
|---|
| 1124 | }
|
|---|
| 1125 | }
|
|---|
| 1126 |
|
|---|
| 1127 | /*!
|
|---|
| 1128 | Returns the geometry of the cell with row \a row and column \a col
|
|---|
| 1129 | in the grid. Returns an invalid rectangle if \a row or \a col is
|
|---|
| 1130 | outside the grid.
|
|---|
| 1131 |
|
|---|
| 1132 | \warning in the current version of Qt this function does not
|
|---|
| 1133 | return valid results until setGeometry() has been called, i.e.
|
|---|
| 1134 | after the mainWidget() is visible.
|
|---|
| 1135 | */
|
|---|
| 1136 | QRect QGridLayout::cellGeometry( int row, int col ) const
|
|---|
| 1137 | {
|
|---|
| 1138 | return data->cellGeometry( row, col );
|
|---|
| 1139 | }
|
|---|
| 1140 |
|
|---|
| 1141 | /*!
|
|---|
| 1142 | Expands this grid so that it will have \a nRows rows and \a nCols
|
|---|
| 1143 | columns. Will not shrink the grid. You should not need to call
|
|---|
| 1144 | this function because QGridLayout expands automatically as new
|
|---|
| 1145 | items are inserted.
|
|---|
| 1146 | */
|
|---|
| 1147 | void QGridLayout::expand( int nRows, int nCols )
|
|---|
| 1148 | {
|
|---|
| 1149 | data->expand( nRows, nCols );
|
|---|
| 1150 | }
|
|---|
| 1151 |
|
|---|
| 1152 | /*!
|
|---|
| 1153 | Sets up the grid.
|
|---|
| 1154 | */
|
|---|
| 1155 | void QGridLayout::init( int nRows, int nCols )
|
|---|
| 1156 | {
|
|---|
| 1157 | setSupportsMargin( TRUE );
|
|---|
| 1158 | data = new QGridLayoutData( nRows, nCols );
|
|---|
| 1159 | }
|
|---|
| 1160 |
|
|---|
| 1161 | /*!
|
|---|
| 1162 | \overload
|
|---|
| 1163 |
|
|---|
| 1164 | Adds \a item to the next free position of this layout.
|
|---|
| 1165 | */
|
|---|
| 1166 | void QGridLayout::addItem( QLayoutItem *item )
|
|---|
| 1167 | {
|
|---|
| 1168 | int r, c;
|
|---|
| 1169 | data->getNextPos( r, c );
|
|---|
| 1170 | add( item, r, c );
|
|---|
| 1171 | }
|
|---|
| 1172 |
|
|---|
| 1173 | /*!
|
|---|
| 1174 | Adds \a item at position \a row, \a col. The layout takes
|
|---|
| 1175 | ownership of the \a item.
|
|---|
| 1176 | */
|
|---|
| 1177 | void QGridLayout::addItem( QLayoutItem *item, int row, int col )
|
|---|
| 1178 | {
|
|---|
| 1179 | add( item, row, col );
|
|---|
| 1180 | }
|
|---|
| 1181 |
|
|---|
| 1182 | /*!
|
|---|
| 1183 | Adds \a item at position \a row, \a col. The layout takes
|
|---|
| 1184 | ownership of the \a item.
|
|---|
| 1185 | */
|
|---|
| 1186 | void QGridLayout::add( QLayoutItem *item, int row, int col )
|
|---|
| 1187 | {
|
|---|
| 1188 | QGridBox *box = new QGridBox( item );
|
|---|
| 1189 | data->add( box, row, col );
|
|---|
| 1190 | }
|
|---|
| 1191 |
|
|---|
| 1192 | /*!
|
|---|
| 1193 | Adds the \a item to the cell grid, spanning multiple rows/columns.
|
|---|
| 1194 |
|
|---|
| 1195 | The cell will span from \a fromRow, \a fromCol to \a toRow, \a
|
|---|
| 1196 | toCol. Alignment is specified by \a alignment, which is a bitwise
|
|---|
| 1197 | OR of \l Qt::AlignmentFlags values. The default alignment is 0,
|
|---|
| 1198 | which means that the widget fills the entire cell.
|
|---|
| 1199 | */
|
|---|
| 1200 | void QGridLayout::addMultiCell( QLayoutItem *item, int fromRow, int toRow,
|
|---|
| 1201 | int fromCol, int toCol, int alignment )
|
|---|
| 1202 | {
|
|---|
| 1203 | QGridBox *b = new QGridBox( item );
|
|---|
| 1204 | b->setAlignment( alignment );
|
|---|
| 1205 | data->add( b, fromRow, toRow, fromCol, toCol );
|
|---|
| 1206 | }
|
|---|
| 1207 |
|
|---|
| 1208 | /*
|
|---|
| 1209 | Returns TRUE if the widget \a w can be added to the layout \a l;
|
|---|
| 1210 | otherwise returns FALSE.
|
|---|
| 1211 | */
|
|---|
| 1212 | static bool checkWidget( QLayout *l, QWidget *w )
|
|---|
| 1213 | {
|
|---|
| 1214 | if ( !w ) {
|
|---|
| 1215 | #if defined(QT_CHECK_STATE)
|
|---|
| 1216 | qWarning( "QLayout: Cannot add null widget to %s/%s", l->className(),
|
|---|
| 1217 | l->name() );
|
|---|
| 1218 | #endif
|
|---|
| 1219 | return FALSE;
|
|---|
| 1220 | }
|
|---|
| 1221 | if ( w->parentWidget() != l->mainWidget() && l->mainWidget() ) {
|
|---|
| 1222 | #if defined(QT_CHECK_STATE)
|
|---|
| 1223 | if ( w->parentWidget() )
|
|---|
| 1224 | qWarning( "QLayout: Adding %s/%s (child of %s/%s) to layout for "
|
|---|
| 1225 | "%s/%s", w->className(), w->name(),
|
|---|
| 1226 | w->parentWidget()->className(), w->parentWidget()->name(),
|
|---|
| 1227 | l->mainWidget()->className(), l->mainWidget()->name() );
|
|---|
| 1228 | else
|
|---|
| 1229 | qWarning( "QLayout: Adding %s/%s (top-level widget) to layout for"
|
|---|
| 1230 | " %s/%s", w->className(), w->name(),
|
|---|
| 1231 | l->mainWidget()->className(), l->mainWidget()->name() );
|
|---|
| 1232 | #endif
|
|---|
| 1233 | return FALSE;
|
|---|
| 1234 | }
|
|---|
| 1235 | return TRUE;
|
|---|
| 1236 | }
|
|---|
| 1237 |
|
|---|
| 1238 | /*!
|
|---|
| 1239 | Adds the widget \a w to the cell grid at \a row, \a col. The
|
|---|
| 1240 | top-left position is (0, 0) by default.
|
|---|
| 1241 |
|
|---|
| 1242 | Alignment is specified by \a alignment, which is a bitwise OR of
|
|---|
| 1243 | \l Qt::AlignmentFlags values. The default alignment is 0, which
|
|---|
| 1244 | means that the widget fills the entire cell.
|
|---|
| 1245 |
|
|---|
| 1246 | \list
|
|---|
| 1247 | \i You should not call this if you have enabled the
|
|---|
| 1248 | \link QLayout::setAutoAdd() auto-add facility of the layout\endlink.
|
|---|
| 1249 |
|
|---|
| 1250 | \i From Qt 3.0, the \a alignment parameter is interpreted more
|
|---|
| 1251 | aggressively than in previous versions of Qt. A non-default
|
|---|
| 1252 | alignment now indicates that the widget should not grow to fill
|
|---|
| 1253 | the available space, but should be sized according to sizeHint().
|
|---|
| 1254 | \endlist
|
|---|
| 1255 |
|
|---|
| 1256 | \sa addMultiCellWidget()
|
|---|
| 1257 | */
|
|---|
| 1258 | void QGridLayout::addWidget( QWidget *w, int row, int col, int alignment )
|
|---|
| 1259 | {
|
|---|
| 1260 | if ( !checkWidget( this, w ) )
|
|---|
| 1261 | return;
|
|---|
| 1262 | if ( row < 0 || col < 0 ) {
|
|---|
| 1263 | #if defined(QT_CHECK_STATE)
|
|---|
| 1264 | qWarning( "QGridLayout: Cannot add %s/%s to %s/%s at row %d col %d",
|
|---|
| 1265 | w->className(), w->name(), className(), name(), row, col );
|
|---|
| 1266 | #endif
|
|---|
| 1267 | return;
|
|---|
| 1268 | }
|
|---|
| 1269 | QWidgetItem *b = new QWidgetItem( w );
|
|---|
| 1270 | b->setAlignment( alignment );
|
|---|
| 1271 | add( b, row, col );
|
|---|
| 1272 | }
|
|---|
| 1273 |
|
|---|
| 1274 | /*!
|
|---|
| 1275 | Adds the widget \a w to the cell grid, spanning multiple
|
|---|
| 1276 | rows/columns. The cell will span from \a fromRow, \a fromCol to \a
|
|---|
| 1277 | toRow, \a toCol.
|
|---|
| 1278 |
|
|---|
| 1279 | Alignment is specified by \a alignment, which is a bitwise OR of
|
|---|
| 1280 | \l Qt::AlignmentFlags values. The default alignment is 0, which
|
|---|
| 1281 | means that the widget fills the entire cell.
|
|---|
| 1282 |
|
|---|
| 1283 | A non-zero alignment indicates that the widget should not grow to
|
|---|
| 1284 | fill the available space but should be sized according to
|
|---|
| 1285 | sizeHint().
|
|---|
| 1286 |
|
|---|
| 1287 | \sa addWidget()
|
|---|
| 1288 | */
|
|---|
| 1289 | void QGridLayout::addMultiCellWidget( QWidget *w, int fromRow, int toRow,
|
|---|
| 1290 | int fromCol, int toCol, int alignment )
|
|---|
| 1291 | {
|
|---|
| 1292 | QGridBox *b = new QGridBox( w );
|
|---|
| 1293 | b->setAlignment( alignment );
|
|---|
| 1294 | data->add( b, fromRow, toRow, fromCol, toCol );
|
|---|
| 1295 | }
|
|---|
| 1296 |
|
|---|
| 1297 | /*!
|
|---|
| 1298 | Places the \a layout at position (\a row, \a col) in the grid. The
|
|---|
| 1299 | top-left position is (0, 0).
|
|---|
| 1300 |
|
|---|
| 1301 | \a layout becomes a child of the grid layout.
|
|---|
| 1302 |
|
|---|
| 1303 | \sa addMultiCellLayout()
|
|---|
| 1304 | */
|
|---|
| 1305 | void QGridLayout::addLayout( QLayout *layout, int row, int col )
|
|---|
| 1306 | {
|
|---|
| 1307 | addChildLayout( layout );
|
|---|
| 1308 | add( layout, row, col );
|
|---|
| 1309 | }
|
|---|
| 1310 |
|
|---|
| 1311 | /*!
|
|---|
| 1312 | Adds the layout \a layout to the cell grid, spanning multiple
|
|---|
| 1313 | rows/columns. The cell will span from \a fromRow, \a fromCol to \a
|
|---|
| 1314 | toRow, \a toCol.
|
|---|
| 1315 |
|
|---|
| 1316 | Alignment is specified by \a alignment, which is a bitwise OR of
|
|---|
| 1317 | \l Qt::AlignmentFlags values. The default alignment is 0, which
|
|---|
| 1318 | means that the widget fills the entire cell.
|
|---|
| 1319 |
|
|---|
| 1320 | A non-zero alignment indicates that the layout should not grow to
|
|---|
| 1321 | fill the available space but should be sized according to
|
|---|
| 1322 | sizeHint().
|
|---|
| 1323 |
|
|---|
| 1324 | \a layout becomes a child of the grid layout.
|
|---|
| 1325 |
|
|---|
| 1326 | \sa addLayout()
|
|---|
| 1327 | */
|
|---|
| 1328 | void QGridLayout::addMultiCellLayout( QLayout *layout, int fromRow, int toRow,
|
|---|
| 1329 | int fromCol, int toCol, int alignment )
|
|---|
| 1330 | {
|
|---|
| 1331 | addChildLayout( layout );
|
|---|
| 1332 | QGridBox *b = new QGridBox( layout );
|
|---|
| 1333 | b->setAlignment( alignment );
|
|---|
| 1334 | data->add( b, fromRow, toRow, fromCol, toCol );
|
|---|
| 1335 | }
|
|---|
| 1336 |
|
|---|
| 1337 | /*!
|
|---|
| 1338 | Sets the stretch factor of row \a row to \a stretch. The first row
|
|---|
| 1339 | is number 0.
|
|---|
| 1340 |
|
|---|
| 1341 | The stretch factor is relative to the other rows in this grid.
|
|---|
| 1342 | Rows with a higher stretch factor take more of the available
|
|---|
| 1343 | space.
|
|---|
| 1344 |
|
|---|
| 1345 | The default stretch factor is 0. If the stretch factor is 0 and no
|
|---|
| 1346 | other row in this table can grow at all, the row may still grow.
|
|---|
| 1347 |
|
|---|
| 1348 | \sa rowStretch(), setRowSpacing(), setColStretch()
|
|---|
| 1349 | */
|
|---|
| 1350 | void QGridLayout::setRowStretch( int row, int stretch )
|
|---|
| 1351 | {
|
|---|
| 1352 | data->setRowStretch( row, stretch );
|
|---|
| 1353 | }
|
|---|
| 1354 |
|
|---|
| 1355 | /*!
|
|---|
| 1356 | Returns the stretch factor for row \a row.
|
|---|
| 1357 |
|
|---|
| 1358 | \sa setRowStretch()
|
|---|
| 1359 | */
|
|---|
| 1360 | int QGridLayout::rowStretch( int row ) const
|
|---|
| 1361 | {
|
|---|
| 1362 | return data->rowStretch( row );
|
|---|
| 1363 | }
|
|---|
| 1364 |
|
|---|
| 1365 | /*!
|
|---|
| 1366 | Returns the stretch factor for column \a col.
|
|---|
| 1367 |
|
|---|
| 1368 | \sa setColStretch()
|
|---|
| 1369 | */
|
|---|
| 1370 | int QGridLayout::colStretch( int col ) const
|
|---|
| 1371 | {
|
|---|
| 1372 | return data->colStretch( col );
|
|---|
| 1373 | }
|
|---|
| 1374 |
|
|---|
| 1375 | /*!
|
|---|
| 1376 | Sets the stretch factor of column \a col to \a stretch. The first
|
|---|
| 1377 | column is number 0.
|
|---|
| 1378 |
|
|---|
| 1379 | The stretch factor is relative to the other columns in this grid.
|
|---|
| 1380 | Columns with a higher stretch factor take more of the available
|
|---|
| 1381 | space.
|
|---|
| 1382 |
|
|---|
| 1383 | The default stretch factor is 0. If the stretch factor is 0 and no
|
|---|
| 1384 | other column in this table can grow at all, the column may still
|
|---|
| 1385 | grow.
|
|---|
| 1386 |
|
|---|
| 1387 | \sa colStretch(), addColSpacing(), setRowStretch()
|
|---|
| 1388 | */
|
|---|
| 1389 | void QGridLayout::setColStretch( int col, int stretch )
|
|---|
| 1390 | {
|
|---|
| 1391 | data->setColStretch( col, stretch );
|
|---|
| 1392 | }
|
|---|
| 1393 |
|
|---|
| 1394 | #if QT_VERSION >= 0x040000
|
|---|
| 1395 | #error "Make add{Row,Col}Spacing() inline QT_NO_COMPAT functions defined in terms of set{Row,Col}Spacing()"
|
|---|
| 1396 | #endif
|
|---|
| 1397 |
|
|---|
| 1398 | /*!
|
|---|
| 1399 | \obsolete
|
|---|
| 1400 |
|
|---|
| 1401 | Sets the minimum height of row \a row to \a minsize pixels.
|
|---|
| 1402 |
|
|---|
| 1403 | Use setRowSpacing() instead.
|
|---|
| 1404 | */
|
|---|
| 1405 | void QGridLayout::addRowSpacing( int row, int minsize )
|
|---|
| 1406 | {
|
|---|
| 1407 | QLayoutItem *b = new QSpacerItem( 0, minsize );
|
|---|
| 1408 | add( b, row, 0 );
|
|---|
| 1409 | }
|
|---|
| 1410 |
|
|---|
| 1411 | /*!
|
|---|
| 1412 | \obsolete
|
|---|
| 1413 |
|
|---|
| 1414 | Sets the minimum width of column \a col to \a minsize pixels.
|
|---|
| 1415 |
|
|---|
| 1416 | Use setColSpacing() instead.
|
|---|
| 1417 | */
|
|---|
| 1418 | void QGridLayout::addColSpacing( int col, int minsize )
|
|---|
| 1419 | {
|
|---|
| 1420 | QLayoutItem *b = new QSpacerItem( minsize, 0 );
|
|---|
| 1421 | add( b, 0, col );
|
|---|
| 1422 | }
|
|---|
| 1423 |
|
|---|
| 1424 | /*!
|
|---|
| 1425 | Sets the minimum height of row \a row to \a minSize pixels.
|
|---|
| 1426 |
|
|---|
| 1427 | \sa rowSpacing(), setColSpacing()
|
|---|
| 1428 | */
|
|---|
| 1429 | void QGridLayout::setRowSpacing( int row, int minSize )
|
|---|
| 1430 | {
|
|---|
| 1431 | data->setRowSpacing( row, minSize );
|
|---|
| 1432 | }
|
|---|
| 1433 |
|
|---|
| 1434 | /*!
|
|---|
| 1435 | Returns the row spacing for row \a row.
|
|---|
| 1436 |
|
|---|
| 1437 | \sa setRowSpacing()
|
|---|
| 1438 | */
|
|---|
| 1439 | int QGridLayout::rowSpacing( int row ) const
|
|---|
| 1440 | {
|
|---|
| 1441 | return data->rowSpacing( row );
|
|---|
| 1442 | }
|
|---|
| 1443 |
|
|---|
| 1444 | /*!
|
|---|
| 1445 | Sets the minimum width of column \a col to \a minSize pixels.
|
|---|
| 1446 |
|
|---|
| 1447 | \sa colSpacing(), setRowSpacing()
|
|---|
| 1448 | */
|
|---|
| 1449 | void QGridLayout::setColSpacing( int col, int minSize )
|
|---|
| 1450 | {
|
|---|
| 1451 | data->setColSpacing( col, minSize );
|
|---|
| 1452 | }
|
|---|
| 1453 |
|
|---|
| 1454 | /*!
|
|---|
| 1455 | Returns the column spacing for column \a col.
|
|---|
| 1456 |
|
|---|
| 1457 | \sa setColSpacing()
|
|---|
| 1458 | */
|
|---|
| 1459 | int QGridLayout::colSpacing( int col ) const
|
|---|
| 1460 | {
|
|---|
| 1461 | return data->colSpacing( col );
|
|---|
| 1462 | }
|
|---|
| 1463 |
|
|---|
| 1464 | /*!
|
|---|
| 1465 | Returns whether this layout can make use of more space than
|
|---|
| 1466 | sizeHint(). A value of \c Vertical or \c Horizontal means that it wants
|
|---|
| 1467 | to grow in only one dimension, whereas \c BothDirections means that
|
|---|
| 1468 | it wants to grow in both dimensions.
|
|---|
| 1469 | */
|
|---|
| 1470 | QSizePolicy::ExpandData QGridLayout::expanding() const
|
|---|
| 1471 | {
|
|---|
| 1472 | return data->expanding( spacing() );
|
|---|
| 1473 | }
|
|---|
| 1474 |
|
|---|
| 1475 | /*!
|
|---|
| 1476 | Sets the grid's origin corner, i.e. position (0, 0), to \a c.
|
|---|
| 1477 | */
|
|---|
| 1478 | void QGridLayout::setOrigin( Corner c )
|
|---|
| 1479 | {
|
|---|
| 1480 | data->setReversed( c == BottomLeft || c == BottomRight,
|
|---|
| 1481 | c == TopRight || c == BottomRight );
|
|---|
| 1482 | }
|
|---|
| 1483 |
|
|---|
| 1484 | /*!
|
|---|
| 1485 | Returns the corner that's used for the grid's origin, i.e. for
|
|---|
| 1486 | position (0, 0).
|
|---|
| 1487 | */
|
|---|
| 1488 | QGridLayout::Corner QGridLayout::origin() const
|
|---|
| 1489 | {
|
|---|
| 1490 | if ( data->horReversed() ) {
|
|---|
| 1491 | return data->verReversed() ? BottomRight : TopRight;
|
|---|
| 1492 | } else {
|
|---|
| 1493 | return data->verReversed() ? BottomLeft : TopLeft;
|
|---|
| 1494 | }
|
|---|
| 1495 | }
|
|---|
| 1496 |
|
|---|
| 1497 | /*!
|
|---|
| 1498 | Resets cached information.
|
|---|
| 1499 | */
|
|---|
| 1500 | void QGridLayout::invalidate()
|
|---|
| 1501 | {
|
|---|
| 1502 | QLayout::invalidate();
|
|---|
| 1503 | QLayout::setGeometry( QRect() ); // for binary compatibility (?)
|
|---|
| 1504 | data->setDirty();
|
|---|
| 1505 | }
|
|---|
| 1506 |
|
|---|
| 1507 | /*! \reimp */
|
|---|
| 1508 | QLayoutIterator QGridLayout::iterator()
|
|---|
| 1509 | {
|
|---|
| 1510 | return QLayoutIterator( new QGridLayoutDataIterator(data) );
|
|---|
| 1511 | }
|
|---|
| 1512 |
|
|---|
| 1513 | struct QBoxLayoutItem
|
|---|
| 1514 | {
|
|---|
| 1515 | QBoxLayoutItem( QLayoutItem *it, int stretch_ = 0 )
|
|---|
| 1516 | : item( it ), stretch( stretch_ ), magic( FALSE ) { }
|
|---|
| 1517 | ~QBoxLayoutItem() { delete item; }
|
|---|
| 1518 |
|
|---|
| 1519 | int hfw( int w ) {
|
|---|
| 1520 | if ( item->hasHeightForWidth() ) {
|
|---|
| 1521 | return item->heightForWidth( w );
|
|---|
| 1522 | } else {
|
|---|
| 1523 | return item->sizeHint().height();
|
|---|
| 1524 | }
|
|---|
| 1525 | }
|
|---|
| 1526 | int mhfw( int w ) {
|
|---|
| 1527 | if ( item->hasHeightForWidth() ) {
|
|---|
| 1528 | return item->heightForWidth( w );
|
|---|
| 1529 | } else {
|
|---|
| 1530 | return item->minimumSize().height();
|
|---|
| 1531 | }
|
|---|
| 1532 | }
|
|---|
| 1533 | int hStretch() {
|
|---|
| 1534 | if ( stretch == 0 && item->widget() ) {
|
|---|
| 1535 | return item->widget()->sizePolicy().horStretch();
|
|---|
| 1536 | } else {
|
|---|
| 1537 | return stretch;
|
|---|
| 1538 | }
|
|---|
| 1539 | }
|
|---|
| 1540 | int vStretch() {
|
|---|
| 1541 | if ( stretch == 0 && item->widget() ) {
|
|---|
| 1542 | return item->widget()->sizePolicy().verStretch();
|
|---|
| 1543 | } else {
|
|---|
| 1544 | return stretch;
|
|---|
| 1545 | }
|
|---|
| 1546 | }
|
|---|
| 1547 |
|
|---|
| 1548 | QLayoutItem *item;
|
|---|
| 1549 | int stretch;
|
|---|
| 1550 | bool magic;
|
|---|
| 1551 | };
|
|---|
| 1552 |
|
|---|
| 1553 | class QBoxLayoutData
|
|---|
| 1554 | {
|
|---|
| 1555 | public:
|
|---|
| 1556 | QBoxLayoutData() : geomArray( 0 ), hfwWidth( -1 ), dirty( TRUE )
|
|---|
| 1557 | { list.setAutoDelete( TRUE ); }
|
|---|
| 1558 |
|
|---|
| 1559 | ~QBoxLayoutData() { delete geomArray; }
|
|---|
| 1560 | void setDirty() {
|
|---|
| 1561 | delete geomArray;
|
|---|
| 1562 | geomArray = 0;
|
|---|
| 1563 | hfwWidth = -1;
|
|---|
| 1564 | hfwHeight = -1;
|
|---|
| 1565 | dirty = TRUE;
|
|---|
| 1566 | }
|
|---|
| 1567 |
|
|---|
| 1568 | QPtrList<QBoxLayoutItem> list;
|
|---|
| 1569 | QMemArray<QLayoutStruct> *geomArray;
|
|---|
| 1570 | int hfwWidth;
|
|---|
| 1571 | int hfwHeight;
|
|---|
| 1572 | int hfwMinHeight;
|
|---|
| 1573 | QSize sizeHint;
|
|---|
| 1574 | QSize minSize;
|
|---|
| 1575 | QSize maxSize;
|
|---|
| 1576 | QSizePolicy::ExpandData expanding;
|
|---|
| 1577 | uint hasHfw : 1;
|
|---|
| 1578 | uint dirty : 1;
|
|---|
| 1579 | };
|
|---|
| 1580 |
|
|---|
| 1581 | class QBoxLayoutIterator : public QGLayoutIterator
|
|---|
| 1582 | {
|
|---|
| 1583 | public:
|
|---|
| 1584 | QBoxLayoutIterator( QBoxLayoutData *d ) : data( d ), idx( 0 ) {}
|
|---|
| 1585 | QLayoutItem *current() {
|
|---|
| 1586 | if ( idx >= int(data->list.count()) )
|
|---|
| 1587 | return 0;
|
|---|
| 1588 | return data->list.at(idx)->item;
|
|---|
| 1589 | }
|
|---|
| 1590 | QLayoutItem *next() {
|
|---|
| 1591 | idx++;
|
|---|
| 1592 | return current();
|
|---|
| 1593 | }
|
|---|
| 1594 | QLayoutItem *takeCurrent() {
|
|---|
| 1595 | QLayoutItem *item = 0;
|
|---|
| 1596 |
|
|---|
| 1597 | QBoxLayoutItem *b = data->list.take( idx );
|
|---|
| 1598 | if ( b ) {
|
|---|
| 1599 | item = b->item;
|
|---|
| 1600 | b->item = 0;
|
|---|
| 1601 | delete b;
|
|---|
| 1602 | }
|
|---|
| 1603 | data->setDirty();
|
|---|
| 1604 | return item;
|
|---|
| 1605 | }
|
|---|
| 1606 |
|
|---|
| 1607 | private:
|
|---|
| 1608 | QBoxLayoutData *data;
|
|---|
| 1609 | int idx;
|
|---|
| 1610 | };
|
|---|
| 1611 |
|
|---|
| 1612 | /*!
|
|---|
| 1613 | \class QBoxLayout
|
|---|
| 1614 |
|
|---|
| 1615 | \brief The QBoxLayout class lines up child widgets horizontally or
|
|---|
| 1616 | vertically.
|
|---|
| 1617 |
|
|---|
| 1618 | \ingroup geomanagement
|
|---|
| 1619 | \ingroup appearance
|
|---|
| 1620 |
|
|---|
| 1621 | QBoxLayout takes the space it gets (from its parent layout or from
|
|---|
| 1622 | the mainWidget()), divides it up into a row of boxes, and makes
|
|---|
| 1623 | each managed widget fill one box.
|
|---|
| 1624 |
|
|---|
| 1625 | \img qhbox-m.png Horizontal box with five child widgets
|
|---|
| 1626 |
|
|---|
| 1627 | If the QBoxLayout's orientation is \c Horizontal the boxes are
|
|---|
| 1628 | placed in a row, with suitable sizes. Each widget (or other box)
|
|---|
| 1629 | will get at least its minimum size and at most its maximum size.
|
|---|
| 1630 | Any excess space is shared according to the stretch factors (more
|
|---|
| 1631 | about that below).
|
|---|
| 1632 |
|
|---|
| 1633 | \img qvbox-m.png Vertical box with five child widgets
|
|---|
| 1634 |
|
|---|
| 1635 | If the QBoxLayout's orientation is \c Vertical, the boxes are
|
|---|
| 1636 | placed in a column, again with suitable sizes.
|
|---|
| 1637 |
|
|---|
| 1638 | The easiest way to create a QBoxLayout is to use one of the
|
|---|
| 1639 | convenience classes, e.g. QHBoxLayout (for \c Horizontal boxes) or
|
|---|
| 1640 | QVBoxLayout (for \c Vertical boxes). You can also use the
|
|---|
| 1641 | QBoxLayout constructor directly, specifying its direction as \c
|
|---|
| 1642 | LeftToRight, \c Down, \c RightToLeft or \c Up.
|
|---|
| 1643 |
|
|---|
| 1644 | If the QBoxLayout is not the top-level layout (i.e. it is not
|
|---|
| 1645 | managing all of the widget's area and children), you must add it
|
|---|
| 1646 | to its parent layout before you can do anything with it. The
|
|---|
| 1647 | normal way to add a layout is by calling
|
|---|
| 1648 | parentLayout-\>addLayout().
|
|---|
| 1649 |
|
|---|
| 1650 | Once you have done this, you can add boxes to the QBoxLayout using
|
|---|
| 1651 | one of four functions:
|
|---|
| 1652 |
|
|---|
| 1653 | \list
|
|---|
| 1654 | \i addWidget() to add a widget to the QBoxLayout and set the
|
|---|
| 1655 | widget's stretch factor. (The stretch factor is along the row of
|
|---|
| 1656 | boxes.)
|
|---|
| 1657 |
|
|---|
| 1658 | \i addSpacing() to create an empty box; this is one of the
|
|---|
| 1659 | functions you use to create nice and spacious dialogs. See below
|
|---|
| 1660 | for ways to set margins.
|
|---|
| 1661 |
|
|---|
| 1662 | \i addStretch() to create an empty, stretchable box.
|
|---|
| 1663 |
|
|---|
| 1664 | \i addLayout() to add a box containing another QLayout to the row
|
|---|
| 1665 | and set that layout's stretch factor.
|
|---|
| 1666 | \endlist
|
|---|
| 1667 |
|
|---|
| 1668 | Use insertWidget(), insertSpacing(), insertStretch() or
|
|---|
| 1669 | insertLayout() to insert a box at a specified position in the
|
|---|
| 1670 | layout.
|
|---|
| 1671 |
|
|---|
| 1672 | QBoxLayout also includes two margin widths:
|
|---|
| 1673 |
|
|---|
| 1674 | \list
|
|---|
| 1675 | \i setMargin() sets the width of the outer border. This is the width
|
|---|
| 1676 | of the reserved space along each of the QBoxLayout's four sides.
|
|---|
| 1677 | \i setSpacing() sets the width between neighboring boxes. (You
|
|---|
| 1678 | can use addSpacing() to get more space at a particular spot.)
|
|---|
| 1679 | \endlist
|
|---|
| 1680 |
|
|---|
| 1681 | The margin defaults to 0. The spacing defaults to the same as the
|
|---|
| 1682 | margin width for a top-level layout, or to the same as the parent
|
|---|
| 1683 | layout. Both are parameters to the constructor.
|
|---|
| 1684 |
|
|---|
| 1685 | To remove a widget from a layout, call remove(). Calling
|
|---|
| 1686 | QWidget::hide() on a widget also effectively removes the widget
|
|---|
| 1687 | from the layout until QWidget::show() is called.
|
|---|
| 1688 |
|
|---|
| 1689 | You will almost always want to use QVBoxLayout and QHBoxLayout
|
|---|
| 1690 | rather than QBoxLayout because of their convenient constructors.
|
|---|
| 1691 |
|
|---|
| 1692 | \sa QGrid \link layout.html Layout Overview \endlink
|
|---|
| 1693 | */
|
|---|
| 1694 |
|
|---|
| 1695 | /*!
|
|---|
| 1696 | \enum QBoxLayout::Direction
|
|---|
| 1697 |
|
|---|
| 1698 | This type is used to determine the direction of a box layout.
|
|---|
| 1699 |
|
|---|
| 1700 | \value LeftToRight Horizontal, from left to right
|
|---|
| 1701 | \value RightToLeft Horizontal, from right to left
|
|---|
| 1702 | \value TopToBottom Vertical, from top to bottom
|
|---|
| 1703 | \value Down The same as \c TopToBottom
|
|---|
| 1704 | \value BottomToTop Vertical, from bottom to top
|
|---|
| 1705 | \value Up The same as \c BottomToTop
|
|---|
| 1706 | */
|
|---|
| 1707 |
|
|---|
| 1708 | static inline bool horz( QBoxLayout::Direction dir )
|
|---|
| 1709 | {
|
|---|
| 1710 | return dir == QBoxLayout::RightToLeft || dir == QBoxLayout::LeftToRight;
|
|---|
| 1711 | }
|
|---|
| 1712 |
|
|---|
| 1713 | /*!
|
|---|
| 1714 | Constructs a new QBoxLayout with direction \a d and main widget \a
|
|---|
| 1715 | parent. \a parent may not be 0.
|
|---|
| 1716 |
|
|---|
| 1717 | The \a margin is the number of pixels between the edge of the
|
|---|
| 1718 | widget and its managed children. The \a spacing is the default
|
|---|
| 1719 | number of pixels between neighboring children. If \a spacing is -1
|
|---|
| 1720 | the value of \a margin is used for \a spacing.
|
|---|
| 1721 |
|
|---|
| 1722 | \a name is the internal object name.
|
|---|
| 1723 |
|
|---|
| 1724 | \sa direction()
|
|---|
| 1725 | */
|
|---|
| 1726 | QBoxLayout::QBoxLayout( QWidget *parent, Direction d,
|
|---|
| 1727 | int margin, int spacing, const char *name )
|
|---|
| 1728 | : QLayout( parent, margin, spacing, name )
|
|---|
| 1729 | {
|
|---|
| 1730 | data = new QBoxLayoutData;
|
|---|
| 1731 | dir = d;
|
|---|
| 1732 | setSupportsMargin( TRUE );
|
|---|
| 1733 | }
|
|---|
| 1734 |
|
|---|
| 1735 | /*!
|
|---|
| 1736 | Constructs a new QBoxLayout called \a name, with direction \a d,
|
|---|
| 1737 | and inserts it into \a parentLayout.
|
|---|
| 1738 |
|
|---|
| 1739 | The \a spacing is the default number of pixels between neighboring
|
|---|
| 1740 | children. If \a spacing is -1, the layout will inherit its
|
|---|
| 1741 | parent's spacing().
|
|---|
| 1742 | */
|
|---|
| 1743 | QBoxLayout::QBoxLayout( QLayout *parentLayout, Direction d, int spacing,
|
|---|
| 1744 | const char *name )
|
|---|
| 1745 | : QLayout( parentLayout, spacing, name )
|
|---|
| 1746 | {
|
|---|
| 1747 | data = new QBoxLayoutData;
|
|---|
| 1748 | dir = d;
|
|---|
| 1749 | setSupportsMargin( TRUE );
|
|---|
| 1750 | }
|
|---|
| 1751 |
|
|---|
| 1752 | /*!
|
|---|
| 1753 | Constructs a new QBoxLayout called \a name, with direction \a d.
|
|---|
| 1754 |
|
|---|
| 1755 | If \a spacing is -1, the layout will inherit its parent's
|
|---|
| 1756 | spacing(); otherwise \a spacing is used.
|
|---|
| 1757 |
|
|---|
| 1758 | You must insert this box into another layout.
|
|---|
| 1759 | */
|
|---|
| 1760 | QBoxLayout::QBoxLayout( Direction d, int spacing, const char *name )
|
|---|
| 1761 | : QLayout( spacing, name )
|
|---|
| 1762 | {
|
|---|
| 1763 | data = new QBoxLayoutData;
|
|---|
| 1764 | dir = d;
|
|---|
| 1765 | setSupportsMargin( TRUE );
|
|---|
| 1766 | }
|
|---|
| 1767 |
|
|---|
| 1768 | /*!
|
|---|
| 1769 | Destroys this box layout.
|
|---|
| 1770 |
|
|---|
| 1771 | The layout's widgets aren't destroyed.
|
|---|
| 1772 | */
|
|---|
| 1773 | QBoxLayout::~QBoxLayout()
|
|---|
| 1774 | {
|
|---|
| 1775 | delete data;
|
|---|
| 1776 | }
|
|---|
| 1777 |
|
|---|
| 1778 | /*!
|
|---|
| 1779 | Returns the preferred size of this box layout.
|
|---|
| 1780 | */
|
|---|
| 1781 | QSize QBoxLayout::sizeHint() const
|
|---|
| 1782 | {
|
|---|
| 1783 | if ( data->dirty ) {
|
|---|
| 1784 | QBoxLayout *that = (QBoxLayout*)this;
|
|---|
| 1785 | that->setupGeom();
|
|---|
| 1786 | }
|
|---|
| 1787 | return data->sizeHint + QSize( 2 * margin(), 2 * margin() );
|
|---|
| 1788 | }
|
|---|
| 1789 |
|
|---|
| 1790 | /*!
|
|---|
| 1791 | Returns the minimum size needed by this box layout.
|
|---|
| 1792 | */
|
|---|
| 1793 | QSize QBoxLayout::minimumSize() const
|
|---|
| 1794 | {
|
|---|
| 1795 | if ( data->dirty ) {
|
|---|
| 1796 | QBoxLayout *that = (QBoxLayout*)this;
|
|---|
| 1797 | that->setupGeom();
|
|---|
| 1798 | }
|
|---|
| 1799 | return data->minSize + QSize( 2 * margin(), 2 * margin() );
|
|---|
| 1800 | }
|
|---|
| 1801 |
|
|---|
| 1802 | /*!
|
|---|
| 1803 | Returns the maximum size needed by this box layout.
|
|---|
| 1804 | */
|
|---|
| 1805 | QSize QBoxLayout::maximumSize() const
|
|---|
| 1806 | {
|
|---|
| 1807 | if ( data->dirty ) {
|
|---|
| 1808 | QBoxLayout *that = (QBoxLayout*)this;
|
|---|
| 1809 | that->setupGeom();
|
|---|
| 1810 | }
|
|---|
| 1811 | QSize s = ( data->maxSize + QSize(2 * margin(), 2 * margin()) )
|
|---|
| 1812 | .boundedTo(QSize(QLAYOUTSIZE_MAX, QLAYOUTSIZE_MAX));
|
|---|
| 1813 | if ( alignment() & Qt::AlignHorizontal_Mask )
|
|---|
| 1814 | s.setWidth( QLAYOUTSIZE_MAX );
|
|---|
| 1815 | if ( alignment() & Qt::AlignVertical_Mask )
|
|---|
| 1816 | s.setHeight( QLAYOUTSIZE_MAX );
|
|---|
| 1817 | return s;
|
|---|
| 1818 | }
|
|---|
| 1819 |
|
|---|
| 1820 | /*!
|
|---|
| 1821 | Returns TRUE if this layout's preferred height depends on its width;
|
|---|
| 1822 | otherwise returns FALSE.
|
|---|
| 1823 | */
|
|---|
| 1824 | bool QBoxLayout::hasHeightForWidth() const
|
|---|
| 1825 | {
|
|---|
| 1826 | if ( data->dirty ) {
|
|---|
| 1827 | QBoxLayout *that = (QBoxLayout*)this;
|
|---|
| 1828 | that->setupGeom();
|
|---|
| 1829 | }
|
|---|
| 1830 | return data->hasHfw;
|
|---|
| 1831 | }
|
|---|
| 1832 |
|
|---|
| 1833 | /*!
|
|---|
| 1834 | Returns the layout's preferred height when it is \a w pixels wide.
|
|---|
| 1835 | */
|
|---|
| 1836 | int QBoxLayout::heightForWidth( int w ) const
|
|---|
| 1837 | {
|
|---|
| 1838 | if ( !hasHeightForWidth() )
|
|---|
| 1839 | return -1;
|
|---|
| 1840 | w -= 2 * margin();
|
|---|
| 1841 | if ( w != data->hfwWidth ) {
|
|---|
| 1842 | QBoxLayout *that = (QBoxLayout*)this;
|
|---|
| 1843 | that->calcHfw( w );
|
|---|
| 1844 | }
|
|---|
| 1845 | return data->hfwHeight + 2 * margin();
|
|---|
| 1846 | }
|
|---|
| 1847 |
|
|---|
| 1848 | /*! \internal */
|
|---|
| 1849 | int QBoxLayout::minimumHeightForWidth( int w ) const
|
|---|
| 1850 | {
|
|---|
| 1851 | (void) heightForWidth( w );
|
|---|
| 1852 | return data->hasHfw ? (data->hfwMinHeight + 2 * margin() ) : -1;
|
|---|
| 1853 | }
|
|---|
| 1854 |
|
|---|
| 1855 | /*!
|
|---|
| 1856 | Resets cached information.
|
|---|
| 1857 | */
|
|---|
| 1858 | void QBoxLayout::invalidate()
|
|---|
| 1859 | {
|
|---|
| 1860 | QLayout::invalidate();
|
|---|
| 1861 | data->setDirty();
|
|---|
| 1862 | }
|
|---|
| 1863 |
|
|---|
| 1864 | /*!
|
|---|
| 1865 | \reimp
|
|---|
| 1866 | */
|
|---|
| 1867 | QLayoutIterator QBoxLayout::iterator()
|
|---|
| 1868 | {
|
|---|
| 1869 | return QLayoutIterator( new QBoxLayoutIterator(data) );
|
|---|
| 1870 | }
|
|---|
| 1871 |
|
|---|
| 1872 | /*!
|
|---|
| 1873 | Returns whether this layout can make use of more space than
|
|---|
| 1874 | sizeHint(). A value of \c Vertical or \c Horizontal means that it wants
|
|---|
| 1875 | to grow in only one dimension, whereas \c BothDirections means that
|
|---|
| 1876 | it wants to grow in both dimensions.
|
|---|
| 1877 | */
|
|---|
| 1878 | QSizePolicy::ExpandData QBoxLayout::expanding() const
|
|---|
| 1879 | {
|
|---|
| 1880 | if ( data->dirty ) {
|
|---|
| 1881 | QBoxLayout *that = (QBoxLayout*)this;
|
|---|
| 1882 | that->setupGeom();
|
|---|
| 1883 | }
|
|---|
| 1884 | return data->expanding;
|
|---|
| 1885 | }
|
|---|
| 1886 |
|
|---|
| 1887 | /*!
|
|---|
| 1888 | Resizes managed widgets within the rectangle \a r.
|
|---|
| 1889 | */
|
|---|
| 1890 | void QBoxLayout::setGeometry( const QRect &r )
|
|---|
| 1891 | {
|
|---|
| 1892 | if ( !data->geomArray || r != geometry() ) {
|
|---|
| 1893 | QLayout::setGeometry( r );
|
|---|
| 1894 | if ( !data->geomArray )
|
|---|
| 1895 | setupGeom();
|
|---|
| 1896 | QRect cr = alignment() ? alignmentRect( r ) : r;
|
|---|
| 1897 | QRect s( cr.x() + margin(), cr.y() + margin(),
|
|---|
| 1898 | cr.width() - 2 * margin(), cr.height() - 2 * margin() );
|
|---|
| 1899 |
|
|---|
| 1900 | QMemArray<QLayoutStruct> a = *data->geomArray;
|
|---|
| 1901 | int pos = horz( dir ) ? s.x() : s.y();
|
|---|
| 1902 | int space = horz( dir ) ? s.width() : s.height();
|
|---|
| 1903 | int n = a.count();
|
|---|
| 1904 | if ( data->hasHfw && !horz(dir) ) {
|
|---|
| 1905 | for ( int i = 0; i < n; i++ ) {
|
|---|
| 1906 | QBoxLayoutItem *box = data->list.at( i );
|
|---|
| 1907 | if ( box->item->hasHeightForWidth() )
|
|---|
| 1908 | a[i].sizeHint = a[i].minimumSize =
|
|---|
| 1909 | box->item->heightForWidth( s.width() );
|
|---|
| 1910 | }
|
|---|
| 1911 | }
|
|---|
| 1912 |
|
|---|
| 1913 | Direction visualDir = dir;
|
|---|
| 1914 | if ( QApplication::reverseLayout() ) {
|
|---|
| 1915 | if ( dir == LeftToRight )
|
|---|
| 1916 | visualDir = RightToLeft;
|
|---|
| 1917 | else if ( dir == RightToLeft )
|
|---|
| 1918 | visualDir = LeftToRight;
|
|---|
| 1919 | }
|
|---|
| 1920 |
|
|---|
| 1921 | qGeomCalc( a, 0, n, pos, space, spacing() );
|
|---|
| 1922 | for ( int i = 0; i < n; i++ ) {
|
|---|
| 1923 | QBoxLayoutItem *box = data->list.at( i );
|
|---|
| 1924 |
|
|---|
| 1925 | switch ( visualDir ) {
|
|---|
| 1926 | case LeftToRight:
|
|---|
| 1927 | box->item->setGeometry( QRect(a[i].pos, s.y(),
|
|---|
| 1928 | a[i].size, s.height()) );
|
|---|
| 1929 | break;
|
|---|
| 1930 | case RightToLeft:
|
|---|
| 1931 | box->item->setGeometry( QRect(s.left() + s.right()
|
|---|
| 1932 | - a[i].pos - a[i].size + 1, s.y(),
|
|---|
| 1933 | a[i].size, s.height()) );
|
|---|
| 1934 | break;
|
|---|
| 1935 | case TopToBottom:
|
|---|
| 1936 | box->item->setGeometry( QRect(s.x(), a[i].pos,
|
|---|
| 1937 | s.width(), a[i].size) );
|
|---|
| 1938 | break;
|
|---|
| 1939 | case BottomToTop:
|
|---|
| 1940 | box->item->setGeometry( QRect(s.x(), s.top() + s.bottom()
|
|---|
| 1941 | - a[i].pos - a[i].size + 1,
|
|---|
| 1942 | s.width(), a[i].size) );
|
|---|
| 1943 | }
|
|---|
| 1944 | }
|
|---|
| 1945 | }
|
|---|
| 1946 | }
|
|---|
| 1947 |
|
|---|
| 1948 | /*!
|
|---|
| 1949 | Adds \a item to the end of this box layout.
|
|---|
| 1950 | */
|
|---|
| 1951 | void QBoxLayout::addItem( QLayoutItem *item )
|
|---|
| 1952 | {
|
|---|
| 1953 | QBoxLayoutItem *it = new QBoxLayoutItem( item );
|
|---|
| 1954 | data->list.append( it );
|
|---|
| 1955 | invalidate();
|
|---|
| 1956 | }
|
|---|
| 1957 |
|
|---|
| 1958 | /*!
|
|---|
| 1959 | Inserts \a item into this box layout at position \a index. If \a
|
|---|
| 1960 | index is negative, the item is added at the end.
|
|---|
| 1961 |
|
|---|
| 1962 | \warning Does not call QLayout::insertChildLayout() if \a item is
|
|---|
| 1963 | a QLayout.
|
|---|
| 1964 |
|
|---|
| 1965 | \sa addItem(), findWidget()
|
|---|
| 1966 | */
|
|---|
| 1967 | void QBoxLayout::insertItem( int index, QLayoutItem *item )
|
|---|
| 1968 | {
|
|---|
| 1969 | if ( index < 0 ) // append
|
|---|
| 1970 | index = data->list.count();
|
|---|
| 1971 |
|
|---|
| 1972 | QBoxLayoutItem *it = new QBoxLayoutItem( item );
|
|---|
| 1973 | data->list.insert( index, it );
|
|---|
| 1974 | invalidate();
|
|---|
| 1975 | }
|
|---|
| 1976 |
|
|---|
| 1977 | /*!
|
|---|
| 1978 | Inserts a non-stretchable space at position \a index, with size \a
|
|---|
| 1979 | size. If \a index is negative the space is added at the end.
|
|---|
| 1980 |
|
|---|
| 1981 | The box layout has default margin and spacing. This function adds
|
|---|
| 1982 | additional space.
|
|---|
| 1983 |
|
|---|
| 1984 | \sa insertStretch()
|
|---|
| 1985 | */
|
|---|
| 1986 | void QBoxLayout::insertSpacing( int index, int size )
|
|---|
| 1987 | {
|
|---|
| 1988 | if ( index < 0 ) // append
|
|---|
| 1989 | index = data->list.count();
|
|---|
| 1990 |
|
|---|
| 1991 | // hack in QGridLayoutData: spacers do not get insideSpacing
|
|---|
| 1992 | QLayoutItem *b;
|
|---|
| 1993 | if ( horz( dir ) )
|
|---|
| 1994 | b = new QSpacerItem( size, 0, QSizePolicy::Fixed,
|
|---|
| 1995 | QSizePolicy::Minimum );
|
|---|
| 1996 | else
|
|---|
| 1997 | b = new QSpacerItem( 0, size, QSizePolicy::Minimum,
|
|---|
| 1998 | QSizePolicy::Fixed );
|
|---|
| 1999 |
|
|---|
| 2000 | QBoxLayoutItem *it = new QBoxLayoutItem( b );
|
|---|
| 2001 | it->magic = TRUE;
|
|---|
| 2002 | data->list.insert( index, it );
|
|---|
| 2003 | invalidate();
|
|---|
| 2004 | }
|
|---|
| 2005 |
|
|---|
| 2006 | /*!
|
|---|
| 2007 | Inserts a stretchable space at position \a index, with zero
|
|---|
| 2008 | minimum size and stretch factor \a stretch. If \a index is
|
|---|
| 2009 | negative the space is added at the end.
|
|---|
| 2010 |
|
|---|
| 2011 | \sa insertSpacing()
|
|---|
| 2012 | */
|
|---|
| 2013 | void QBoxLayout::insertStretch( int index, int stretch )
|
|---|
| 2014 | {
|
|---|
| 2015 | if ( index < 0 ) // append
|
|---|
| 2016 | index = data->list.count();
|
|---|
| 2017 |
|
|---|
| 2018 | // hack in QGridLayoutData: spacers do not get insideSpacing
|
|---|
| 2019 | QLayoutItem *b;
|
|---|
| 2020 | if ( horz( dir ) )
|
|---|
| 2021 | b = new QSpacerItem( 0, 0, QSizePolicy::Expanding,
|
|---|
| 2022 | QSizePolicy::Minimum );
|
|---|
| 2023 | else
|
|---|
| 2024 | b = new QSpacerItem( 0, 0, QSizePolicy::Minimum,
|
|---|
| 2025 | QSizePolicy::Expanding );
|
|---|
| 2026 |
|
|---|
| 2027 | QBoxLayoutItem *it = new QBoxLayoutItem( b, stretch );
|
|---|
| 2028 | it->magic = TRUE;
|
|---|
| 2029 | data->list.insert( index, it );
|
|---|
| 2030 | invalidate();
|
|---|
| 2031 | }
|
|---|
| 2032 |
|
|---|
| 2033 | /*!
|
|---|
| 2034 | Inserts \a layout at position \a index, with stretch factor \a
|
|---|
| 2035 | stretch. If \a index is negative, the layout is added at the end.
|
|---|
| 2036 |
|
|---|
| 2037 | \a layout becomes a child of the box layout.
|
|---|
| 2038 |
|
|---|
| 2039 | \sa setAutoAdd(), insertWidget(), insertSpacing()
|
|---|
| 2040 | */
|
|---|
| 2041 | void QBoxLayout::insertLayout( int index, QLayout *layout, int stretch )
|
|---|
| 2042 | {
|
|---|
| 2043 | if ( index < 0 ) // append
|
|---|
| 2044 | index = data->list.count();
|
|---|
| 2045 |
|
|---|
| 2046 | addChildLayout( layout );
|
|---|
| 2047 | QBoxLayoutItem *it = new QBoxLayoutItem( layout, stretch );
|
|---|
| 2048 | data->list.insert( index, it );
|
|---|
| 2049 | invalidate();
|
|---|
| 2050 | }
|
|---|
| 2051 |
|
|---|
| 2052 | /*!
|
|---|
| 2053 | Inserts \a widget at position \a index, with stretch factor \a
|
|---|
| 2054 | stretch and alignment \a alignment. If \a index is negative, the
|
|---|
| 2055 | widget is added at the end.
|
|---|
| 2056 |
|
|---|
| 2057 | The stretch factor applies only in the \link direction() direction
|
|---|
| 2058 | \endlink of the QBoxLayout, and is relative to the other boxes and
|
|---|
| 2059 | widgets in this QBoxLayout. Widgets and boxes with higher stretch
|
|---|
| 2060 | factors grow more.
|
|---|
| 2061 |
|
|---|
| 2062 | If the stretch factor is 0 and nothing else in the QBoxLayout has
|
|---|
| 2063 | a stretch factor greater than zero, the space is distributed
|
|---|
| 2064 | according to the QWidget:sizePolicy() of each widget that's
|
|---|
| 2065 | involved.
|
|---|
| 2066 |
|
|---|
| 2067 | Alignment is specified by \a alignment, which is a bitwise OR of
|
|---|
| 2068 | \l Qt::AlignmentFlags values. The default alignment is 0, which
|
|---|
| 2069 | means that the widget fills the entire cell.
|
|---|
| 2070 |
|
|---|
| 2071 | From Qt 3.0, the \a alignment parameter is interpreted more
|
|---|
| 2072 | aggressively than in previous versions of Qt. A non-default
|
|---|
| 2073 | alignment now indicates that the widget should not grow to fill
|
|---|
| 2074 | the available space, but should be sized according to sizeHint().
|
|---|
| 2075 |
|
|---|
| 2076 | \sa setAutoAdd(), insertLayout(), insertSpacing()
|
|---|
| 2077 | */
|
|---|
| 2078 | void QBoxLayout::insertWidget( int index, QWidget *widget, int stretch,
|
|---|
| 2079 | int alignment )
|
|---|
| 2080 | {
|
|---|
| 2081 | if ( !checkWidget(this, widget) )
|
|---|
| 2082 | return;
|
|---|
| 2083 |
|
|---|
| 2084 | if ( index < 0 ) // append
|
|---|
| 2085 | index = data->list.count();
|
|---|
| 2086 |
|
|---|
| 2087 | QWidgetItem *b = new QWidgetItem( widget );
|
|---|
| 2088 | b->setAlignment( alignment );
|
|---|
| 2089 | QBoxLayoutItem *it = new QBoxLayoutItem( b, stretch );
|
|---|
| 2090 | data->list.insert( index, it );
|
|---|
| 2091 | invalidate();
|
|---|
| 2092 | }
|
|---|
| 2093 |
|
|---|
| 2094 | /*!
|
|---|
| 2095 | Adds a non-stretchable space with size \a size to the end of this
|
|---|
| 2096 | box layout. QBoxLayout provides default margin and spacing. This
|
|---|
| 2097 | function adds additional space.
|
|---|
| 2098 |
|
|---|
| 2099 | \sa insertSpacing(), addStretch()
|
|---|
| 2100 | */
|
|---|
| 2101 | void QBoxLayout::addSpacing( int size )
|
|---|
| 2102 | {
|
|---|
| 2103 | insertSpacing( -1, size );
|
|---|
| 2104 | }
|
|---|
| 2105 |
|
|---|
| 2106 | /*!
|
|---|
| 2107 | Adds a stretchable space with zero minimum size and stretch factor
|
|---|
| 2108 | \a stretch to the end of this box layout.
|
|---|
| 2109 |
|
|---|
| 2110 | \sa addSpacing()
|
|---|
| 2111 | */
|
|---|
| 2112 | void QBoxLayout::addStretch( int stretch )
|
|---|
| 2113 | {
|
|---|
| 2114 | insertStretch( -1, stretch );
|
|---|
| 2115 | }
|
|---|
| 2116 |
|
|---|
| 2117 | /*!
|
|---|
| 2118 | Adds \a widget to the end of this box layout, with a stretch
|
|---|
| 2119 | factor of \a stretch and alignment \a alignment.
|
|---|
| 2120 |
|
|---|
| 2121 | The stretch factor applies only in the \link direction() direction
|
|---|
| 2122 | \endlink of the QBoxLayout, and is relative to the other boxes and
|
|---|
| 2123 | widgets in this QBoxLayout. Widgets and boxes with higher stretch
|
|---|
| 2124 | factors grow more.
|
|---|
| 2125 |
|
|---|
| 2126 | If the stretch factor is 0 and nothing else in the QBoxLayout has
|
|---|
| 2127 | a stretch factor greater than zero, the space is distributed
|
|---|
| 2128 | according to the QWidget:sizePolicy() of each widget that's
|
|---|
| 2129 | involved.
|
|---|
| 2130 |
|
|---|
| 2131 | Alignment is specified by \a alignment which is a bitwise OR of \l
|
|---|
| 2132 | Qt::AlignmentFlags values. The default alignment is 0, which means
|
|---|
| 2133 | that the widget fills the entire cell.
|
|---|
| 2134 |
|
|---|
| 2135 | From Qt 3.0, the \a alignment parameter is interpreted more
|
|---|
| 2136 | aggressively than in previous versions of Qt. A non-default
|
|---|
| 2137 | alignment now indicates that the widget should not grow to fill
|
|---|
| 2138 | the available space, but should be sized according to sizeHint().
|
|---|
| 2139 |
|
|---|
| 2140 | \sa insertWidget(), setAutoAdd(), addLayout(), addSpacing()
|
|---|
| 2141 | */
|
|---|
| 2142 | void QBoxLayout::addWidget( QWidget *widget, int stretch,
|
|---|
| 2143 | int alignment )
|
|---|
| 2144 | {
|
|---|
| 2145 | insertWidget( -1, widget, stretch, alignment );
|
|---|
| 2146 | }
|
|---|
| 2147 |
|
|---|
| 2148 | /*!
|
|---|
| 2149 | Adds \a layout to the end of the box, with serial stretch factor
|
|---|
| 2150 | \a stretch.
|
|---|
| 2151 |
|
|---|
| 2152 | \sa insertLayout(), setAutoAdd(), addWidget(), addSpacing()
|
|---|
| 2153 | */
|
|---|
| 2154 | void QBoxLayout::addLayout( QLayout *layout, int stretch )
|
|---|
| 2155 | {
|
|---|
| 2156 | insertLayout( -1, layout, stretch );
|
|---|
| 2157 | }
|
|---|
| 2158 |
|
|---|
| 2159 | /*!
|
|---|
| 2160 | Limits the perpendicular dimension of the box (e.g. height if the
|
|---|
| 2161 | box is LeftToRight) to a minimum of \a size. Other constraints may
|
|---|
| 2162 | increase the limit.
|
|---|
| 2163 | */
|
|---|
| 2164 | void QBoxLayout::addStrut( int size )
|
|---|
| 2165 | {
|
|---|
| 2166 | QLayoutItem *b;
|
|---|
| 2167 | if ( horz( dir ) )
|
|---|
| 2168 | b = new QSpacerItem( 0, size, QSizePolicy::Fixed,
|
|---|
| 2169 | QSizePolicy::Minimum );
|
|---|
| 2170 | else
|
|---|
| 2171 | b = new QSpacerItem( size, 0, QSizePolicy::Minimum,
|
|---|
| 2172 | QSizePolicy::Fixed );
|
|---|
| 2173 |
|
|---|
| 2174 | QBoxLayoutItem *it = new QBoxLayoutItem( b );
|
|---|
| 2175 | it->magic = TRUE;
|
|---|
| 2176 | data->list.append( it );
|
|---|
| 2177 | invalidate();
|
|---|
| 2178 | }
|
|---|
| 2179 |
|
|---|
| 2180 | /*!
|
|---|
| 2181 | Searches for widget \a w in this layout (not including child
|
|---|
| 2182 | layouts).
|
|---|
| 2183 |
|
|---|
| 2184 | Returns the index of \a w, or -1 if \a w is not found.
|
|---|
| 2185 | */
|
|---|
| 2186 | int QBoxLayout::findWidget( QWidget* w )
|
|---|
| 2187 | {
|
|---|
| 2188 | const int n = data->list.count();
|
|---|
| 2189 | for ( int i = 0; i < n; i++ ) {
|
|---|
| 2190 | if ( data->list.at(i)->item->widget() == w )
|
|---|
| 2191 | return i;
|
|---|
| 2192 | }
|
|---|
| 2193 | return -1;
|
|---|
| 2194 | }
|
|---|
| 2195 |
|
|---|
| 2196 | /*!
|
|---|
| 2197 | Sets the stretch factor for widget \a w to \a stretch and returns
|
|---|
| 2198 | TRUE if \a w is found in this layout (not including child
|
|---|
| 2199 | layouts); otherwise returns FALSE.
|
|---|
| 2200 | */
|
|---|
| 2201 | bool QBoxLayout::setStretchFactor( QWidget *w, int stretch )
|
|---|
| 2202 | {
|
|---|
| 2203 | QPtrListIterator<QBoxLayoutItem> it( data->list );
|
|---|
| 2204 | QBoxLayoutItem *box;
|
|---|
| 2205 | while ( (box=it.current()) != 0 ) {
|
|---|
| 2206 | ++it;
|
|---|
| 2207 | if ( box->item->widget() == w ) {
|
|---|
| 2208 | box->stretch = stretch;
|
|---|
| 2209 | invalidate();
|
|---|
| 2210 | return TRUE;
|
|---|
| 2211 | }
|
|---|
| 2212 | }
|
|---|
| 2213 | return FALSE;
|
|---|
| 2214 | }
|
|---|
| 2215 |
|
|---|
| 2216 | /*!
|
|---|
| 2217 | \overload
|
|---|
| 2218 |
|
|---|
| 2219 | Sets the stretch factor for the layout \a l to \a stretch and
|
|---|
| 2220 | returns TRUE if \a l is found in this layout (not including child
|
|---|
| 2221 | layouts); otherwise returns FALSE.
|
|---|
| 2222 | */
|
|---|
| 2223 | bool QBoxLayout::setStretchFactor( QLayout *l, int stretch )
|
|---|
| 2224 | {
|
|---|
| 2225 | QPtrListIterator<QBoxLayoutItem> it( data->list );
|
|---|
| 2226 | QBoxLayoutItem *box;
|
|---|
| 2227 | while ( (box=it.current()) != 0 ) {
|
|---|
| 2228 | ++it;
|
|---|
| 2229 | if ( box->item->layout() == l ) {
|
|---|
| 2230 | box->stretch = stretch;
|
|---|
| 2231 | invalidate();
|
|---|
| 2232 | return TRUE;
|
|---|
| 2233 | }
|
|---|
| 2234 | }
|
|---|
| 2235 | return FALSE;
|
|---|
| 2236 | }
|
|---|
| 2237 |
|
|---|
| 2238 | /*!
|
|---|
| 2239 | Sets the direction of this layout to \a direction.
|
|---|
| 2240 | */
|
|---|
| 2241 | void QBoxLayout::setDirection( Direction direction )
|
|---|
| 2242 | {
|
|---|
| 2243 | if ( dir == direction )
|
|---|
| 2244 | return;
|
|---|
| 2245 | if ( horz(dir) != horz(direction) ) {
|
|---|
| 2246 | //swap around the spacers (the "magic" bits)
|
|---|
| 2247 | //#### a bit yucky, knows too much.
|
|---|
| 2248 | //#### probably best to add access functions to spacerItem
|
|---|
| 2249 | //#### or even a QSpacerItem::flip()
|
|---|
| 2250 | QPtrListIterator<QBoxLayoutItem> it( data->list );
|
|---|
| 2251 | QBoxLayoutItem *box;
|
|---|
| 2252 | while ( (box=it.current()) != 0 ) {
|
|---|
| 2253 | ++it;
|
|---|
| 2254 | if ( box->magic ) {
|
|---|
| 2255 | QSpacerItem *sp = box->item->spacerItem();
|
|---|
| 2256 | if ( sp ) {
|
|---|
| 2257 | if ( sp->expanding() == QSizePolicy::NoDirection ) {
|
|---|
| 2258 | //spacing or strut
|
|---|
| 2259 | QSize s = sp->sizeHint();
|
|---|
| 2260 | sp->changeSize( s.height(), s.width(),
|
|---|
| 2261 | horz(direction) ? QSizePolicy::Fixed:QSizePolicy::Minimum,
|
|---|
| 2262 | horz(direction) ? QSizePolicy::Minimum:QSizePolicy::Fixed );
|
|---|
| 2263 |
|
|---|
| 2264 | } else {
|
|---|
| 2265 | //stretch
|
|---|
| 2266 | if ( horz(direction) )
|
|---|
| 2267 | sp->changeSize( 0, 0, QSizePolicy::Expanding,
|
|---|
| 2268 | QSizePolicy::Minimum );
|
|---|
| 2269 | else
|
|---|
| 2270 | sp->changeSize( 0, 0, QSizePolicy::Minimum,
|
|---|
| 2271 | QSizePolicy::Expanding );
|
|---|
| 2272 | }
|
|---|
| 2273 | }
|
|---|
| 2274 | }
|
|---|
| 2275 | }
|
|---|
| 2276 | }
|
|---|
| 2277 | dir = direction;
|
|---|
| 2278 | invalidate();
|
|---|
| 2279 | if ( mainWidget() ) {
|
|---|
| 2280 | QEvent *lh = new QEvent( QEvent::LayoutHint );
|
|---|
| 2281 | QApplication::postEvent( mainWidget(), lh );
|
|---|
| 2282 | }
|
|---|
| 2283 |
|
|---|
| 2284 | }
|
|---|
| 2285 |
|
|---|
| 2286 | /*
|
|---|
| 2287 | Initializes the data structure needed by qGeomCalc and
|
|---|
| 2288 | recalculates max/min and size hint.
|
|---|
| 2289 | */
|
|---|
| 2290 | void QBoxLayout::setupGeom()
|
|---|
| 2291 | {
|
|---|
| 2292 | if ( !data->dirty )
|
|---|
| 2293 | return;
|
|---|
| 2294 |
|
|---|
| 2295 | int maxw = horz( dir ) ? 0 : QLAYOUTSIZE_MAX;
|
|---|
| 2296 | int maxh = horz( dir ) ? QLAYOUTSIZE_MAX : 0;
|
|---|
| 2297 | int minw = 0;
|
|---|
| 2298 | int minh = 0;
|
|---|
| 2299 | int hintw = 0;
|
|---|
| 2300 | int hinth = 0;
|
|---|
| 2301 |
|
|---|
| 2302 | bool horexp = FALSE;
|
|---|
| 2303 | bool verexp = FALSE;
|
|---|
| 2304 |
|
|---|
| 2305 | data->hasHfw = FALSE;
|
|---|
| 2306 |
|
|---|
| 2307 | delete data->geomArray;
|
|---|
| 2308 | int n = data->list.count();
|
|---|
| 2309 | data->geomArray = new QMemArray<QLayoutStruct>( n );
|
|---|
| 2310 | QMemArray<QLayoutStruct>& a = *data->geomArray;
|
|---|
| 2311 |
|
|---|
| 2312 | bool first = TRUE;
|
|---|
| 2313 | for ( int i = 0; i < n; i++ ) {
|
|---|
| 2314 | QBoxLayoutItem *box = data->list.at( i );
|
|---|
| 2315 | QSize max = box->item->maximumSize();
|
|---|
| 2316 | QSize min = box->item->minimumSize();
|
|---|
| 2317 | QSize hint = box->item->sizeHint();
|
|---|
| 2318 | QSizePolicy::ExpandData exp = box->item->expanding();
|
|---|
| 2319 | bool empty = box->item->isEmpty();
|
|---|
| 2320 | // space before non-empties, except the first:
|
|---|
| 2321 | int space = ( empty || first ) ? 0 : spacing();
|
|---|
| 2322 | bool ignore = empty && box->item->widget(); // ignore hidden widgets
|
|---|
| 2323 |
|
|---|
| 2324 | if ( horz(dir) ) {
|
|---|
| 2325 | bool expand = exp & QSizePolicy::Horizontally || box->stretch > 0;
|
|---|
| 2326 | horexp = horexp || expand;
|
|---|
| 2327 | maxw += max.width() + space;
|
|---|
| 2328 | minw += min.width() + space;
|
|---|
| 2329 | hintw += hint.width() + space;
|
|---|
| 2330 | if ( !ignore )
|
|---|
| 2331 | qMaxExpCalc( maxh, verexp,
|
|---|
| 2332 | max.height(), exp & QSizePolicy::Vertically );
|
|---|
| 2333 | minh = QMAX( minh, min.height() );
|
|---|
| 2334 | hinth = QMAX( hinth, hint.height() );
|
|---|
| 2335 |
|
|---|
| 2336 | a[i].sizeHint = hint.width();
|
|---|
| 2337 | a[i].maximumSize = max.width();
|
|---|
| 2338 | a[i].minimumSize = min.width();
|
|---|
| 2339 | a[i].expansive = expand;
|
|---|
| 2340 | a[i].stretch = box->stretch ? box->stretch : box->hStretch();
|
|---|
| 2341 | } else {
|
|---|
| 2342 | bool expand = ( exp & QSizePolicy::Vertically || box->stretch > 0 );
|
|---|
| 2343 | verexp = verexp || expand;
|
|---|
| 2344 | maxh += max.height() + space;
|
|---|
| 2345 | minh += min.height() + space;
|
|---|
| 2346 | hinth += hint.height() + space;
|
|---|
| 2347 | if ( !ignore )
|
|---|
| 2348 | qMaxExpCalc( maxw, horexp,
|
|---|
| 2349 | max.width(), exp & QSizePolicy::Horizontally );
|
|---|
| 2350 | minw = QMAX( minw, min.width() );
|
|---|
| 2351 | hintw = QMAX( hintw, hint.width() );
|
|---|
| 2352 |
|
|---|
| 2353 | a[i].sizeHint = hint.height();
|
|---|
| 2354 | a[i].maximumSize = max.height();
|
|---|
| 2355 | a[i].minimumSize = min.height();
|
|---|
| 2356 | a[i].expansive = expand;
|
|---|
| 2357 | a[i].stretch = box->stretch ? box->stretch : box->vStretch();
|
|---|
| 2358 | }
|
|---|
| 2359 |
|
|---|
| 2360 | a[i].empty = empty;
|
|---|
| 2361 | data->hasHfw = data->hasHfw || box->item->hasHeightForWidth();
|
|---|
| 2362 | first = first && empty;
|
|---|
| 2363 | }
|
|---|
| 2364 |
|
|---|
| 2365 | data->expanding = (QSizePolicy::ExpandData)
|
|---|
| 2366 | ( (horexp ? QSizePolicy::Horizontally : 0)
|
|---|
| 2367 | | (verexp ? QSizePolicy::Vertically : 0) );
|
|---|
| 2368 |
|
|---|
| 2369 | data->minSize = QSize( minw, minh );
|
|---|
| 2370 | data->maxSize = QSize( maxw, maxh ).expandedTo( data->minSize );
|
|---|
| 2371 | data->sizeHint = QSize( hintw, hinth )
|
|---|
| 2372 | .expandedTo( data->minSize )
|
|---|
| 2373 | .boundedTo( data->maxSize );
|
|---|
| 2374 |
|
|---|
| 2375 | data->dirty = FALSE;
|
|---|
| 2376 | }
|
|---|
| 2377 |
|
|---|
| 2378 | /*
|
|---|
| 2379 | Calculates and stores the preferred height given the width \a w.
|
|---|
| 2380 | */
|
|---|
| 2381 | void QBoxLayout::calcHfw( int w )
|
|---|
| 2382 | {
|
|---|
| 2383 | int h = 0;
|
|---|
| 2384 | int mh = 0;
|
|---|
| 2385 |
|
|---|
| 2386 | if ( horz(dir) ) {
|
|---|
| 2387 | QMemArray<QLayoutStruct> &a = *data->geomArray;
|
|---|
| 2388 | int n = a.count();
|
|---|
| 2389 | qGeomCalc( a, 0, n, 0, w, spacing() );
|
|---|
| 2390 | for ( int i = 0; i < n; i++ ) {
|
|---|
| 2391 | QBoxLayoutItem *box = data->list.at(i);
|
|---|
| 2392 | h = QMAX( h, box->hfw(a[i].size) );
|
|---|
| 2393 | mh = QMAX( mh, box->mhfw(a[i].size) );
|
|---|
| 2394 | }
|
|---|
| 2395 | } else {
|
|---|
| 2396 | QPtrListIterator<QBoxLayoutItem> it( data->list );
|
|---|
| 2397 | QBoxLayoutItem *box;
|
|---|
| 2398 | bool first = TRUE;
|
|---|
| 2399 | while ( (box = it.current()) != 0 ) {
|
|---|
| 2400 | ++it;
|
|---|
| 2401 | bool empty = box->item->isEmpty();
|
|---|
| 2402 | h += box->hfw( w );
|
|---|
| 2403 | mh += box->mhfw( w );
|
|---|
| 2404 | if ( !first && !empty ) {
|
|---|
| 2405 | h += spacing();
|
|---|
| 2406 | mh += spacing();
|
|---|
| 2407 | }
|
|---|
| 2408 | first = first && empty;
|
|---|
| 2409 | }
|
|---|
| 2410 | }
|
|---|
| 2411 | data->hfwWidth = w;
|
|---|
| 2412 | data->hfwHeight = h;
|
|---|
| 2413 | data->hfwMinHeight = mh;
|
|---|
| 2414 | }
|
|---|
| 2415 |
|
|---|
| 2416 | /*!
|
|---|
| 2417 | \fn QBoxLayout::Direction QBoxLayout::direction() const
|
|---|
| 2418 |
|
|---|
| 2419 | Returns the direction of the box. addWidget() and addSpacing()
|
|---|
| 2420 | work in this direction; the stretch stretches in this direction.
|
|---|
| 2421 |
|
|---|
| 2422 | \sa QBoxLayout::Direction addWidget() addSpacing()
|
|---|
| 2423 | */
|
|---|
| 2424 |
|
|---|
| 2425 | /*!
|
|---|
| 2426 | \class QHBoxLayout
|
|---|
| 2427 | \brief The QHBoxLayout class lines up widgets horizontally.
|
|---|
| 2428 |
|
|---|
| 2429 | \ingroup geomanagement
|
|---|
| 2430 | \ingroup appearance
|
|---|
| 2431 | \mainclass
|
|---|
| 2432 |
|
|---|
| 2433 | This class is used to construct horizontal box layout objects. See
|
|---|
| 2434 | \l QBoxLayout for more details.
|
|---|
| 2435 |
|
|---|
| 2436 | The simplest use of the class is like this:
|
|---|
| 2437 | \code
|
|---|
| 2438 | QBoxLayout * l = new QHBoxLayout( widget );
|
|---|
| 2439 | l->setAutoAdd( TRUE );
|
|---|
| 2440 | new QSomeWidget( widget );
|
|---|
| 2441 | new QSomeOtherWidget( widget );
|
|---|
| 2442 | new QAnotherWidget( widget );
|
|---|
| 2443 | \endcode
|
|---|
| 2444 |
|
|---|
| 2445 | or like this:
|
|---|
| 2446 | \code
|
|---|
| 2447 | QBoxLayout * l = new QHBoxLayout( widget );
|
|---|
| 2448 | l->addWidget( existingChildOfWidget );
|
|---|
| 2449 | l->addWidget( anotherChildOfWidget );
|
|---|
| 2450 | \endcode
|
|---|
| 2451 |
|
|---|
| 2452 | \img qhboxlayout.png QHBox
|
|---|
| 2453 |
|
|---|
| 2454 | \sa QVBoxLayout QGridLayout
|
|---|
| 2455 | \link layout.html the Layout overview \endlink
|
|---|
| 2456 | */
|
|---|
| 2457 |
|
|---|
| 2458 | /*!
|
|---|
| 2459 | Constructs a new top-level horizontal box called \a name, with
|
|---|
| 2460 | parent \a parent.
|
|---|
| 2461 |
|
|---|
| 2462 | The \a margin is the number of pixels between the edge of the
|
|---|
| 2463 | widget and its managed children. The \a spacing is the default
|
|---|
| 2464 | number of pixels between neighboring children. If \a spacing is -1
|
|---|
| 2465 | the value of \a margin is used for \a spacing.
|
|---|
| 2466 | */
|
|---|
| 2467 | QHBoxLayout::QHBoxLayout( QWidget *parent, int margin,
|
|---|
| 2468 | int spacing, const char *name )
|
|---|
| 2469 | : QBoxLayout( parent, LeftToRight, margin, spacing, name )
|
|---|
| 2470 | {
|
|---|
| 2471 | }
|
|---|
| 2472 |
|
|---|
| 2473 | /*!
|
|---|
| 2474 | Constructs a new horizontal box called name \a name and adds it to
|
|---|
| 2475 | \a parentLayout.
|
|---|
| 2476 |
|
|---|
| 2477 | The \a spacing is the default number of pixels between neighboring
|
|---|
| 2478 | children. If \a spacing is -1, this QHBoxLayout will inherit its
|
|---|
| 2479 | parent's spacing().
|
|---|
| 2480 | */
|
|---|
| 2481 | QHBoxLayout::QHBoxLayout( QLayout *parentLayout, int spacing,
|
|---|
| 2482 | const char *name )
|
|---|
| 2483 | : QBoxLayout( parentLayout, LeftToRight, spacing, name )
|
|---|
| 2484 | {
|
|---|
| 2485 | }
|
|---|
| 2486 |
|
|---|
| 2487 | /*!
|
|---|
| 2488 | Constructs a new horizontal box called name \a name. You must add
|
|---|
| 2489 | it to another layout.
|
|---|
| 2490 |
|
|---|
| 2491 | The \a spacing is the default number of pixels between neighboring
|
|---|
| 2492 | children. If \a spacing is -1, this QHBoxLayout will inherit its
|
|---|
| 2493 | parent's spacing().
|
|---|
| 2494 | */
|
|---|
| 2495 | QHBoxLayout::QHBoxLayout( int spacing, const char *name )
|
|---|
| 2496 | : QBoxLayout( LeftToRight, spacing, name )
|
|---|
| 2497 | {
|
|---|
| 2498 | }
|
|---|
| 2499 |
|
|---|
| 2500 | /*!
|
|---|
| 2501 | Destroys this box layout.
|
|---|
| 2502 |
|
|---|
| 2503 | The layout's widgets aren't destroyed.
|
|---|
| 2504 | */
|
|---|
| 2505 | QHBoxLayout::~QHBoxLayout()
|
|---|
| 2506 | {
|
|---|
| 2507 | }
|
|---|
| 2508 |
|
|---|
| 2509 | /*!
|
|---|
| 2510 | \class QVBoxLayout
|
|---|
| 2511 |
|
|---|
| 2512 | \brief The QVBoxLayout class lines up widgets vertically.
|
|---|
| 2513 |
|
|---|
| 2514 | \ingroup geomanagement
|
|---|
| 2515 | \ingroup appearance
|
|---|
| 2516 | \mainclass
|
|---|
| 2517 |
|
|---|
| 2518 | This class is used to construct vertical box layout objects. See
|
|---|
| 2519 | QBoxLayout for more details.
|
|---|
| 2520 |
|
|---|
| 2521 | The simplest use of the class is like this:
|
|---|
| 2522 | \code
|
|---|
| 2523 | QBoxLayout * l = new QVBoxLayout( widget );
|
|---|
| 2524 | l->addWidget( aWidget );
|
|---|
| 2525 | l->addWidget( anotherWidget );
|
|---|
| 2526 | \endcode
|
|---|
| 2527 |
|
|---|
| 2528 | \img qvboxlayout.png QVBox
|
|---|
| 2529 |
|
|---|
| 2530 | \sa QHBoxLayout QGridLayout \link layout.html the Layout overview \endlink
|
|---|
| 2531 | */
|
|---|
| 2532 |
|
|---|
| 2533 | /*!
|
|---|
| 2534 | Constructs a new top-level vertical box called \a name, with
|
|---|
| 2535 | parent \a parent.
|
|---|
| 2536 |
|
|---|
| 2537 | The \a margin is the number of pixels between the edge of the
|
|---|
| 2538 | widget and its managed children. The \a spacing is the default
|
|---|
| 2539 | number of pixels between neighboring children. If \a spacing is -1
|
|---|
| 2540 | the value of \a margin is used for \a spacing.
|
|---|
| 2541 | */
|
|---|
| 2542 | QVBoxLayout::QVBoxLayout( QWidget *parent, int margin, int spacing,
|
|---|
| 2543 | const char *name )
|
|---|
| 2544 | : QBoxLayout( parent, TopToBottom, margin, spacing, name )
|
|---|
| 2545 | {
|
|---|
| 2546 |
|
|---|
| 2547 | }
|
|---|
| 2548 |
|
|---|
| 2549 | /*!
|
|---|
| 2550 | Constructs a new vertical box called name \a name and adds it to
|
|---|
| 2551 | \a parentLayout.
|
|---|
| 2552 |
|
|---|
| 2553 | The \a spacing is the default number of pixels between neighboring
|
|---|
| 2554 | children. If \a spacing is -1, this QVBoxLayout will inherit its
|
|---|
| 2555 | parent's spacing().
|
|---|
| 2556 | */
|
|---|
| 2557 | QVBoxLayout::QVBoxLayout( QLayout *parentLayout, int spacing,
|
|---|
| 2558 | const char *name )
|
|---|
| 2559 | : QBoxLayout( parentLayout, TopToBottom, spacing, name )
|
|---|
| 2560 | {
|
|---|
| 2561 | }
|
|---|
| 2562 |
|
|---|
| 2563 | /*!
|
|---|
| 2564 | Constructs a new vertical box called name \a name. You must add
|
|---|
| 2565 | it to another layout.
|
|---|
| 2566 |
|
|---|
| 2567 | The \a spacing is the default number of pixels between neighboring
|
|---|
| 2568 | children. If \a spacing is -1, this QVBoxLayout will inherit its
|
|---|
| 2569 | parent's spacing().
|
|---|
| 2570 | */
|
|---|
| 2571 | QVBoxLayout::QVBoxLayout( int spacing, const char *name )
|
|---|
| 2572 | : QBoxLayout( TopToBottom, spacing, name )
|
|---|
| 2573 | {
|
|---|
| 2574 | }
|
|---|
| 2575 |
|
|---|
| 2576 | /*!
|
|---|
| 2577 | Destroys this box layout.
|
|---|
| 2578 |
|
|---|
| 2579 | The layout's widgets aren't destroyed.
|
|---|
| 2580 | */
|
|---|
| 2581 | QVBoxLayout::~QVBoxLayout()
|
|---|
| 2582 | {
|
|---|
| 2583 | }
|
|---|
| 2584 |
|
|---|
| 2585 | QBoxLayout *QBoxLayout::createTmpCopy()
|
|---|
| 2586 | {
|
|---|
| 2587 | QBoxLayout *bl = new QBoxLayout( direction() );
|
|---|
| 2588 | delete bl->data;
|
|---|
| 2589 | bl->data = data;
|
|---|
| 2590 | return bl;
|
|---|
| 2591 | }
|
|---|
| 2592 |
|
|---|
| 2593 | #endif // QT_NO_LAYOUT
|
|---|