Qwt User's Guide 6.3.0

Loading...
Searching...
No Matches
qwt_dyngrid_layout.cpp
1/******************************************************************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_dyngrid_layout.h"
11
12#include <qvector.h>
13#include <qlist.h>
14
15 class QwtDynGridLayout::PrivateData
16{
17 public:
18 PrivateData()
19 : isDirty( true )
20 {
21 }
22
23 void updateLayoutCache();
24
25 mutable QList< QLayoutItem* > itemList;
26
27 uint maxColumns;
28 uint numRows;
29 uint numColumns;
30
31 Qt::Orientations expanding;
32
33 bool isDirty;
34 QVector< QSize > itemSizeHints;
35};
36
37 void QwtDynGridLayout::PrivateData::updateLayoutCache()
38{
39 itemSizeHints.resize( itemList.count() );
40
41 int index = 0;
42
43 for ( QList< QLayoutItem* >::const_iterator it = itemList.constBegin();
44 it != itemList.constEnd(); ++it, index++ )
45 {
46 itemSizeHints[ index ] = ( *it )->sizeHint();
47 }
48
49 isDirty = false;
50}
51
58 QwtDynGridLayout::QwtDynGridLayout( QWidget* parent, int margin, int spacing )
59 : QLayout( parent )
60{
61 init();
62
63 setSpacing( spacing );
64 setContentsMargins( margin, margin, margin, margin );
65}
66
71 QwtDynGridLayout::QwtDynGridLayout( int spacing )
72{
73 init();
74 setSpacing( spacing );
75}
76
80 void QwtDynGridLayout::init()
81{
82 m_data = new QwtDynGridLayout::PrivateData;
83 m_data->maxColumns = m_data->numRows = m_data->numColumns = 0;
84}
85
87
88 QwtDynGridLayout::~QwtDynGridLayout()
89{
90 qDeleteAll( m_data->itemList );
91 delete m_data;
92}
93
95 void QwtDynGridLayout::invalidate()
96{
97 m_data->isDirty = true;
98 QLayout::invalidate();
99}
100
106 void QwtDynGridLayout::setMaxColumns( uint maxColumns )
107{
108 m_data->maxColumns = maxColumns;
109}
110
119uint QwtDynGridLayout::maxColumns() const
120{
121 return m_data->maxColumns;
122}
123
128 void QwtDynGridLayout::addItem( QLayoutItem* item )
129{
130 m_data->itemList.append( item );
131 invalidate();
132}
133
137 bool QwtDynGridLayout::isEmpty() const
138{
139 return m_data->itemList.isEmpty();
140}
141
145uint QwtDynGridLayout::itemCount() const
146{
147 return m_data->itemList.count();
148}
149
157QLayoutItem* QwtDynGridLayout::itemAt( int index ) const
158{
159 if ( index < 0 || index >= m_data->itemList.count() )
160 return NULL;
161
162 return m_data->itemList.at( index );
163}
164
172QLayoutItem* QwtDynGridLayout::takeAt( int index )
173{
174 if ( index < 0 || index >= m_data->itemList.count() )
175 return NULL;
176
177 m_data->isDirty = true;
178 return m_data->itemList.takeAt( index );
179}
180
182 int QwtDynGridLayout::count() const
183{
184 return m_data->itemList.count();
185}
186
196 void QwtDynGridLayout::setExpandingDirections( Qt::Orientations expanding )
197{
198 m_data->expanding = expanding;
199}
200
211Qt::Orientations QwtDynGridLayout::expandingDirections() const
212{
213 return m_data->expanding;
214}
215
222 void QwtDynGridLayout::setGeometry( const QRect& rect )
223{
224 QLayout::setGeometry( rect );
225
226 if ( isEmpty() )
227 return;
228
229 m_data->numColumns = columnsForWidth( rect.width() );
230 m_data->numRows = itemCount() / m_data->numColumns;
231 if ( itemCount() % m_data->numColumns )
232 m_data->numRows++;
233
234 const QList< QRect > itemGeometries = layoutItems( rect, m_data->numColumns );
235
236 int index = 0;
237 for ( QList< QLayoutItem* >::const_iterator it = m_data->itemList.constBegin();
238 it != m_data->itemList.constEnd(); ++it )
239 {
240 ( *it )->setGeometry( itemGeometries[index] );
241 index++;
242 }
243}
244
256uint QwtDynGridLayout::columnsForWidth( int width ) const
257{
258 if ( isEmpty() )
259 return 0;
260
261 uint maxColumns = itemCount();
262 if ( m_data->maxColumns > 0 )
263 maxColumns = qMin( m_data->maxColumns, maxColumns );
264
265 if ( maxRowWidth( maxColumns ) <= width )
266 return maxColumns;
267
268 for ( uint numColumns = 2; numColumns <= maxColumns; numColumns++ )
269 {
270 const int rowWidth = maxRowWidth( numColumns );
271 if ( rowWidth > width )
272 return numColumns - 1;
273 }
274
275 return 1; // At least 1 column
276}
277
285 int QwtDynGridLayout::maxRowWidth( int numColumns ) const
286{
287 int col;
288
289 QVector< int > colWidth( numColumns );
290 for ( col = 0; col < numColumns; col++ )
291 colWidth[col] = 0;
292
293 if ( m_data->isDirty )
294 m_data->updateLayoutCache();
295
296 for ( int index = 0;
297 index < m_data->itemSizeHints.count(); index++ )
298 {
299 col = index % numColumns;
300 colWidth[col] = qMax( colWidth[col],
301 m_data->itemSizeHints[index].width() );
302 }
303
304 const QMargins m = contentsMargins();
305
306 int rowWidth = m.left() + m.right() + ( numColumns - 1 ) * spacing();
307 for ( col = 0; col < numColumns; col++ )
308 rowWidth += colWidth[col];
309
310 return rowWidth;
311}
312
316 int QwtDynGridLayout::maxItemWidth() const
317{
318 if ( isEmpty() )
319 return 0;
320
321 if ( m_data->isDirty )
322 m_data->updateLayoutCache();
323
324 int w = 0;
325 for ( int i = 0; i < m_data->itemSizeHints.count(); i++ )
326 {
327 const int itemW = m_data->itemSizeHints[i].width();
328 if ( itemW > w )
329 w = itemW;
330 }
331
332 return w;
333}
334
344 QList< QRect > QwtDynGridLayout::layoutItems( const QRect& rect,
345 uint numColumns ) const
346{
347 QList< QRect > itemGeometries;
348 if ( numColumns == 0 || isEmpty() )
349 return itemGeometries;
350
351 uint numRows = itemCount() / numColumns;
352 if ( numColumns % itemCount() )
353 numRows++;
354
355 if ( numRows == 0 )
356 return itemGeometries;
357
358 QVector< int > rowHeight( numRows );
359 QVector< int > colWidth( numColumns );
360
361 layoutGrid( numColumns, rowHeight, colWidth );
362
363 bool expandH, expandV;
364 expandH = expandingDirections() & Qt::Horizontal;
365 expandV = expandingDirections() & Qt::Vertical;
366
367 if ( expandH || expandV )
368 stretchGrid( rect, numColumns, rowHeight, colWidth );
369
370 const int maxColumns = m_data->maxColumns;
371 m_data->maxColumns = numColumns;
372 const QRect alignedRect = alignmentRect( rect );
373 m_data->maxColumns = maxColumns;
374
375 const int xOffset = expandH ? 0 : alignedRect.x();
376 const int yOffset = expandV ? 0 : alignedRect.y();
377
378 QVector< int > colX( numColumns );
379 QVector< int > rowY( numRows );
380
381 const int xySpace = spacing();
382
383 const QMargins m = contentsMargins();
384
385 rowY[0] = yOffset + m.top();
386 for ( uint r = 1; r < numRows; r++ )
387 rowY[r] = rowY[r - 1] + rowHeight[r - 1] + xySpace;
388
389 colX[0] = xOffset + m.left();
390 for ( uint c = 1; c < numColumns; c++ )
391 colX[c] = colX[c - 1] + colWidth[c - 1] + xySpace;
392
393 const int itemCount = m_data->itemList.size();
394 itemGeometries.reserve( itemCount );
395
396 for ( int i = 0; i < itemCount; i++ )
397 {
398 const int row = i / numColumns;
399 const int col = i % numColumns;
400
401 const QRect itemGeometry( colX[col], rowY[row],
402 colWidth[col], rowHeight[row] );
403 itemGeometries.append( itemGeometry );
404 }
405
406 return itemGeometries;
407}
408
409
419 void QwtDynGridLayout::layoutGrid( uint numColumns,
420 QVector< int >& rowHeight, QVector< int >& colWidth ) const
421{
422 if ( numColumns <= 0 )
423 return;
424
425 if ( m_data->isDirty )
426 m_data->updateLayoutCache();
427
428 for ( int index = 0; index < m_data->itemSizeHints.count(); index++ )
429 {
430 const int row = index / numColumns;
431 const int col = index % numColumns;
432
433 const QSize& size = m_data->itemSizeHints[index];
434
435 rowHeight[row] = ( col == 0 )
436 ? size.height() : qMax( rowHeight[row], size.height() );
437 colWidth[col] = ( row == 0 )
438 ? size.width() : qMax( colWidth[col], size.width() );
439 }
440}
441
446 bool QwtDynGridLayout::hasHeightForWidth() const
447{
448 return true;
449}
450
455 int QwtDynGridLayout::heightForWidth( int width ) const
456{
457 if ( isEmpty() )
458 return 0;
459
460 const uint numColumns = columnsForWidth( width );
461 uint numRows = itemCount() / numColumns;
462 if ( itemCount() % numColumns )
463 numRows++;
464
465 QVector< int > rowHeight( numRows );
466 QVector< int > colWidth( numColumns );
467
468 layoutGrid( numColumns, rowHeight, colWidth );
469
470 const QMargins m = contentsMargins();
471
472 int h = m.top() + m.bottom() + ( numRows - 1 ) * spacing();
473 for ( uint row = 0; row < numRows; row++ )
474 h += rowHeight[row];
475
476 return h;
477}
478
491 void QwtDynGridLayout::stretchGrid( const QRect& rect,
492 uint numColumns, QVector< int >& rowHeight, QVector< int >& colWidth ) const
493{
494 if ( numColumns == 0 || isEmpty() )
495 return;
496
497 bool expandH, expandV;
498 expandH = expandingDirections() & Qt::Horizontal;
499 expandV = expandingDirections() & Qt::Vertical;
500
501 const QMargins m = contentsMargins();
502
503 if ( expandH )
504 {
505 int xDelta = rect.width() - m.left() - m.right() - ( numColumns - 1 ) * spacing();
506 for ( uint col = 0; col < numColumns; col++ )
507 xDelta -= colWidth[col];
508
509 if ( xDelta > 0 )
510 {
511 for ( uint col = 0; col < numColumns; col++ )
512 {
513 const int space = xDelta / ( numColumns - col );
514 colWidth[col] += space;
515 xDelta -= space;
516 }
517 }
518 }
519
520 if ( expandV )
521 {
522 uint numRows = itemCount() / numColumns;
523 if ( itemCount() % numColumns )
524 numRows++;
525
526 int yDelta = rect.height() - m.top() - m.bottom() - ( numRows - 1 ) * spacing();
527 for ( uint row = 0; row < numRows; row++ )
528 yDelta -= rowHeight[row];
529
530 if ( yDelta > 0 )
531 {
532 for ( uint row = 0; row < numRows; row++ )
533 {
534 const int space = yDelta / ( numRows - row );
535 rowHeight[row] += space;
536 yDelta -= space;
537 }
538 }
539 }
540}
541
550QSize QwtDynGridLayout::sizeHint() const
551{
552 if ( isEmpty() )
553 return QSize();
554
555 uint numColumns = itemCount();
556 if ( m_data->maxColumns > 0 )
557 numColumns = qMin( m_data->maxColumns, numColumns );
558
559 uint numRows = itemCount() / numColumns;
560 if ( itemCount() % numColumns )
561 numRows++;
562
563 QVector< int > rowHeight( numRows );
564 QVector< int > colWidth( numColumns );
565
566 layoutGrid( numColumns, rowHeight, colWidth );
567
568 const QMargins m = contentsMargins();
569
570 int h = m.top() + m.bottom() + ( numRows - 1 ) * spacing();
571 for ( uint row = 0; row < numRows; row++ )
572 h += rowHeight[row];
573
574 int w = m.left() + m.right() + ( numColumns - 1 ) * spacing();
575 for ( uint col = 0; col < numColumns; col++ )
576 w += colWidth[col];
577
578 return QSize( w, h );
579}
580
586uint QwtDynGridLayout::numRows() const
587{
588 return m_data->numRows;
589}
590
596uint QwtDynGridLayout::numColumns() const
597{
598 return m_data->numColumns;
599}
600
601#include "moc_qwt_dyngrid_layout.cpp"
QList
Definition qwt_abstract_legend.h:17
QVector< QSize >
QwtDynGridLayout::layoutGrid
void layoutGrid(uint numColumns, QVector< int > &rowHeight, QVector< int > &colWidth) const
Definition qwt_dyngrid_layout.cpp:419
QwtDynGridLayout::heightForWidth
virtual int heightForWidth(int) const override
Definition qwt_dyngrid_layout.cpp:455
QwtDynGridLayout::itemAt
virtual QLayoutItem * itemAt(int index) const override
Definition qwt_dyngrid_layout.cpp:157
QwtDynGridLayout::columnsForWidth
virtual uint columnsForWidth(int width) const
Calculate the number of columns for a given width.
Definition qwt_dyngrid_layout.cpp:256
QwtDynGridLayout::isEmpty
virtual bool isEmpty() const override
Definition qwt_dyngrid_layout.cpp:137
QwtDynGridLayout::takeAt
virtual QLayoutItem * takeAt(int index) override
Definition qwt_dyngrid_layout.cpp:172
QwtDynGridLayout::maxItemWidth
virtual int maxItemWidth() const
Definition qwt_dyngrid_layout.cpp:316
QwtDynGridLayout::setExpandingDirections
void setExpandingDirections(Qt::Orientations)
Definition qwt_dyngrid_layout.cpp:196
QwtDynGridLayout::sizeHint
virtual QSize sizeHint() const override
Definition qwt_dyngrid_layout.cpp:550
QwtDynGridLayout::expandingDirections
virtual Qt::Orientations expandingDirections() const override
Returns whether this layout can make use of more space than sizeHint().
Definition qwt_dyngrid_layout.cpp:211
QwtDynGridLayout::maxColumns
uint maxColumns() const
Return the upper limit for the number of columns.
Definition qwt_dyngrid_layout.cpp:119
QwtDynGridLayout::stretchGrid
void stretchGrid(const QRect &rect, uint numColumns, QVector< int > &rowHeight, QVector< int > &colWidth) const
Definition qwt_dyngrid_layout.cpp:491
QwtDynGridLayout::numColumns
uint numColumns() const
Definition qwt_dyngrid_layout.cpp:596
QwtDynGridLayout::setMaxColumns
void setMaxColumns(uint maxColumns)
Definition qwt_dyngrid_layout.cpp:106
QwtDynGridLayout::numRows
uint numRows() const
Definition qwt_dyngrid_layout.cpp:586
QwtDynGridLayout::addItem
virtual void addItem(QLayoutItem *) override
Add an item to the next free position.
Definition qwt_dyngrid_layout.cpp:128
QwtDynGridLayout::layoutItems
QList< QRect > layoutItems(const QRect &, uint numColumns) const
Definition qwt_dyngrid_layout.cpp:344
QwtDynGridLayout::setGeometry
virtual void setGeometry(const QRect &) override
Definition qwt_dyngrid_layout.cpp:222
QwtDynGridLayout::~QwtDynGridLayout
virtual ~QwtDynGridLayout()
Destructor.
Definition qwt_dyngrid_layout.cpp:88
QwtDynGridLayout::itemCount
uint itemCount() const
Definition qwt_dyngrid_layout.cpp:145
QwtDynGridLayout::QwtDynGridLayout
QwtDynGridLayout(QWidget *, int margin=0, int spacing=-1)
Definition qwt_dyngrid_layout.cpp:58
QwtDynGridLayout::hasHeightForWidth
virtual bool hasHeightForWidth() const override
Definition qwt_dyngrid_layout.cpp:446
QwtDynGridLayout::count
virtual int count() const override
Definition qwt_dyngrid_layout.cpp:182
QwtDynGridLayout::invalidate
virtual void invalidate() override
Invalidate all internal caches.
Definition qwt_dyngrid_layout.cpp:95