source: trunk/src/gui/graphicsview/qgraphicsgridlayout.cpp@ 1147

Last change on this file since 1147 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 19.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*!
43 \class QGraphicsGridLayout
44 \brief The QGraphicsGridLayout class provides a grid layout for managing
45 widgets in Graphics View.
46 \since 4.4
47
48 \ingroup graphicsview-api
49
50 The most common way to use QGraphicsGridLayout is to construct an object
51 on the heap with no parent, add widgets and layouts by calling addItem(),
52 and finally assign the layout to a widget by calling
53 QGraphicsWidget::setLayout(). QGraphicsGridLayout automatically computes
54 the dimensions of the grid as you add items.
55
56 \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsgridlayout.cpp 0
57
58 The layout takes ownership of the items. In some cases when the layout
59 item also inherits from QGraphicsItem (such as QGraphicsWidget) there will be a
60 ambiguity in ownership because the layout item belongs to two ownership hierarchies.
61 See the documentation of QGraphicsLayoutItem::setOwnedByLayout() how to handle
62 this.
63 You can access each item in the layout by calling count() and itemAt(). Calling
64 removeAt() will remove an item from the layout, without
65 destroying it.
66
67 \section1 Size Hints and Size Policies in QGraphicsGridLayout
68
69 QGraphicsGridLayout respects each item's size hints and size policies,
70 and when a cell in the grid has more space than the items can fill, each item
71 is arranged according to the layout's alignment for that item. You can set
72 an alignment for each item by calling setAlignment(), and check the
73 alignment for any item by calling alignment(). You can also set the alignment
74 for an entire row or column by calling setRowAlignment() and setColumnAlignment()
75 respectively. By default, items are aligned to the top left.
76
77
78 \sa QGraphicsLinearLayout, QGraphicsWidget
79*/
80
81#include "qglobal.h"
82
83#ifndef QT_NO_GRAPHICSVIEW
84
85#include "qapplication.h"
86#include "qwidget.h"
87#include "qgraphicslayout_p.h"
88#include "qgraphicslayoutitem.h"
89#include "qgraphicsgridlayout.h"
90#include "qgraphicswidget.h"
91#include "qgridlayoutengine_p.h"
92#include <QtCore/qdebug.h>
93
94QT_BEGIN_NAMESPACE
95
96class QGraphicsGridLayoutPrivate : public QGraphicsLayoutPrivate
97{
98public:
99 QGraphicsGridLayoutPrivate() { }
100 QLayoutStyleInfo styleInfo() const;
101
102 QGridLayoutEngine engine;
103#ifdef QT_DEBUG
104 void dump(int indent) const;
105#endif
106};
107
108Q_GLOBAL_STATIC(QWidget, globalStyleInfoWidget);
109
110QLayoutStyleInfo QGraphicsGridLayoutPrivate::styleInfo() const
111{
112 QGraphicsItem *item = parentItem();
113 QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style();
114 return QLayoutStyleInfo(style, globalStyleInfoWidget());
115}
116
117/*!
118 Constructs a QGraphicsGridLayout instance. \a parent is passed to
119 QGraphicsLayout's constructor.
120*/
121QGraphicsGridLayout::QGraphicsGridLayout(QGraphicsLayoutItem *parent)
122 : QGraphicsLayout(*new QGraphicsGridLayoutPrivate(), parent)
123{
124}
125
126/*!
127 Destroys the QGraphicsGridLayout object.
128*/
129QGraphicsGridLayout::~QGraphicsGridLayout()
130{
131 for (int i = count() - 1; i >= 0; --i) {
132 QGraphicsLayoutItem *item = itemAt(i);
133 // The following lines can be removed, but this removes the item
134 // from the layout more efficiently than the implementation of
135 // ~QGraphicsLayoutItem.
136 removeAt(i);
137 if (item) {
138 item->setParentLayoutItem(0);
139 if (item->ownedByLayout())
140 delete item;
141 }
142 }
143}
144
145/*!
146 Adds \a item to the grid on \a row and \a column. You can specify a
147 \a rowSpan and \a columnSpan and an optional \a alignment.
148*/
149void QGraphicsGridLayout::addItem(QGraphicsLayoutItem *item, int row, int column,
150 int rowSpan, int columnSpan, Qt::Alignment alignment)
151{
152 Q_D(QGraphicsGridLayout);
153 if (row < 0 || column < 0) {
154 qWarning("QGraphicsGridLayout::addItem: invalid row/column: %d",
155 row < 0 ? row : column);
156 return;
157 }
158 if (columnSpan < 1 || rowSpan < 1) {
159 qWarning("QGraphicsGridLayout::addItem: invalid row span/column span: %d",
160 rowSpan < 1 ? rowSpan : columnSpan);
161 return;
162 }
163 if (!item) {
164 qWarning("QGraphicsGridLayout::addItem: cannot add null item");
165 return;
166 }
167 if (item == this) {
168 qWarning("QGraphicsGridLayout::addItem: cannot insert itself");
169 return;
170 }
171
172 d->addChildLayoutItem(item);
173
174 new QGridLayoutItem(&d->engine, item, row, column, rowSpan, columnSpan, alignment);
175 invalidate();
176}
177
178/*!
179 \fn QGraphicsGridLayout::addItem(QGraphicsLayoutItem *item, int row, int column, Qt::Alignment alignment = 0)
180
181 Adds \a item to the grid on \a row and \a column. You can specify
182 an optional \a alignment for \a item.
183*/
184
185/*!
186 Sets the default horizontal spacing for the grid layout to \a spacing.
187*/
188void QGraphicsGridLayout::setHorizontalSpacing(qreal spacing)
189{
190 Q_D(QGraphicsGridLayout);
191 d->engine.setSpacing(spacing, Qt::Horizontal);
192 invalidate();
193}
194
195/*!
196 Returns the default horizontal spacing for the grid layout.
197*/
198qreal QGraphicsGridLayout::horizontalSpacing() const
199{
200 Q_D(const QGraphicsGridLayout);
201 return d->engine.spacing(d->styleInfo(), Qt::Horizontal);
202}
203
204/*!
205 Sets the default vertical spacing for the grid layout to \a spacing.
206*/
207void QGraphicsGridLayout::setVerticalSpacing(qreal spacing)
208{
209 Q_D(QGraphicsGridLayout);
210 d->engine.setSpacing(spacing, Qt::Vertical);
211 invalidate();
212}
213
214/*!
215 Returns the default vertical spacing for the grid layout.
216*/
217qreal QGraphicsGridLayout::verticalSpacing() const
218{
219 Q_D(const QGraphicsGridLayout);
220 return d->engine.spacing(d->styleInfo(), Qt::Vertical);
221}
222
223/*!
224 Sets the grid layout's default spacing, both vertical and
225 horizontal, to \a spacing.
226
227 \sa rowSpacing(), columnSpacing()
228*/
229void QGraphicsGridLayout::setSpacing(qreal spacing)
230{
231 Q_D(QGraphicsGridLayout);
232 d->engine.setSpacing(spacing, Qt::Horizontal | Qt::Vertical);
233 invalidate();
234}
235
236/*!
237 Sets the spacing for \a row to \a spacing.
238*/
239void QGraphicsGridLayout::setRowSpacing(int row, qreal spacing)
240{
241 Q_D(QGraphicsGridLayout);
242 d->engine.setRowSpacing(row, spacing, Qt::Vertical);
243 invalidate();
244}
245
246/*!
247 Returns the row spacing for \a row.
248*/
249qreal QGraphicsGridLayout::rowSpacing(int row) const
250{
251 Q_D(const QGraphicsGridLayout);
252 return d->engine.rowSpacing(row, Qt::Vertical);
253}
254
255/*!
256 Sets the spacing for \a column to \a spacing.
257*/
258void QGraphicsGridLayout::setColumnSpacing(int column, qreal spacing)
259{
260 Q_D(QGraphicsGridLayout);
261 d->engine.setRowSpacing(column, spacing, Qt::Horizontal);
262 invalidate();
263}
264
265/*!
266 Returns the column spacing for \a column.
267*/
268qreal QGraphicsGridLayout::columnSpacing(int column) const
269{
270 Q_D(const QGraphicsGridLayout);
271 return d->engine.rowSpacing(column, Qt::Horizontal);
272}
273
274/*!
275 Sets the stretch factor for \a row to \a stretch.
276*/
277void QGraphicsGridLayout::setRowStretchFactor(int row, int stretch)
278{
279 Q_D(QGraphicsGridLayout);
280 d->engine.setRowStretchFactor(row, stretch, Qt::Vertical);
281 invalidate();
282}
283
284/*!
285 Returns the stretch factor for \a row.
286*/
287int QGraphicsGridLayout::rowStretchFactor(int row) const
288{
289 Q_D(const QGraphicsGridLayout);
290 return d->engine.rowStretchFactor(row, Qt::Vertical);
291}
292
293/*!
294 Sets the stretch factor for \a column to \a stretch.
295*/
296void QGraphicsGridLayout::setColumnStretchFactor(int column, int stretch)
297{
298 Q_D(QGraphicsGridLayout);
299 d->engine.setRowStretchFactor(column, stretch, Qt::Horizontal);
300 invalidate();
301}
302
303/*!
304 Returns the stretch factor for \a column.
305*/
306int QGraphicsGridLayout::columnStretchFactor(int column) const
307{
308 Q_D(const QGraphicsGridLayout);
309 return d->engine.rowStretchFactor(column, Qt::Horizontal);
310}
311
312/*!
313 Sets the minimum height for row, \a row, to \a height.
314*/
315void QGraphicsGridLayout::setRowMinimumHeight(int row, qreal height)
316{
317 Q_D(QGraphicsGridLayout);
318 d->engine.setRowSizeHint(Qt::MinimumSize, row, height, Qt::Vertical);
319 invalidate();
320}
321
322/*!
323 Returns the minimum height for row, \a row.
324*/
325qreal QGraphicsGridLayout::rowMinimumHeight(int row) const
326{
327 Q_D(const QGraphicsGridLayout);
328 return d->engine.rowSizeHint(Qt::MinimumSize, row, Qt::Vertical);
329}
330
331/*!
332 Sets the preferred height for row, \a row, to \a height.
333*/
334void QGraphicsGridLayout::setRowPreferredHeight(int row, qreal height)
335{
336 Q_D(QGraphicsGridLayout);
337 d->engine.setRowSizeHint(Qt::PreferredSize, row, height, Qt::Vertical);
338 invalidate();
339}
340
341/*!
342 Returns the preferred height for row, \a row.
343*/
344qreal QGraphicsGridLayout::rowPreferredHeight(int row) const
345{
346 Q_D(const QGraphicsGridLayout);
347 return d->engine.rowSizeHint(Qt::PreferredSize, row, Qt::Vertical);
348}
349
350/*!
351 Sets the maximum height for row, \a row, to \a height.
352*/
353void QGraphicsGridLayout::setRowMaximumHeight(int row, qreal height)
354{
355 Q_D(QGraphicsGridLayout);
356 d->engine.setRowSizeHint(Qt::MaximumSize, row, height, Qt::Vertical);
357 invalidate();
358}
359
360/*!
361 Returns the maximum height for row, \a row.
362*/
363qreal QGraphicsGridLayout::rowMaximumHeight(int row) const
364{
365 Q_D(const QGraphicsGridLayout);
366 return d->engine.rowSizeHint(Qt::MaximumSize, row, Qt::Vertical);
367}
368
369/*!
370 Sets the fixed height for row, \a row, to \a height.
371*/
372void QGraphicsGridLayout::setRowFixedHeight(int row, qreal height)
373{
374 Q_D(QGraphicsGridLayout);
375 d->engine.setRowSizeHint(Qt::MinimumSize, row, height, Qt::Vertical);
376 d->engine.setRowSizeHint(Qt::MaximumSize, row, height, Qt::Vertical);
377 invalidate();
378}
379
380/*!
381 Sets the minimum width for \a column to \a width.
382*/
383void QGraphicsGridLayout::setColumnMinimumWidth(int column, qreal width)
384{
385 Q_D(QGraphicsGridLayout);
386 d->engine.setRowSizeHint(Qt::MinimumSize, column, width, Qt::Horizontal);
387 invalidate();
388}
389
390/*!
391 Returns the minimum width for \a column.
392*/
393qreal QGraphicsGridLayout::columnMinimumWidth(int column) const
394{
395 Q_D(const QGraphicsGridLayout);
396 return d->engine.rowSizeHint(Qt::MinimumSize, column, Qt::Horizontal);
397}
398
399/*!
400 Sets the preferred width for \a column to \a width.
401*/
402void QGraphicsGridLayout::setColumnPreferredWidth(int column, qreal width)
403{
404 Q_D(QGraphicsGridLayout);
405 d->engine.setRowSizeHint(Qt::PreferredSize, column, width, Qt::Horizontal);
406 invalidate();
407}
408
409/*!
410 Returns the preferred width for \a column.
411*/
412qreal QGraphicsGridLayout::columnPreferredWidth(int column) const
413{
414 Q_D(const QGraphicsGridLayout);
415 return d->engine.rowSizeHint(Qt::PreferredSize, column, Qt::Horizontal);
416}
417
418/*!
419 Sets the maximum width of \a column to \a width.
420*/
421void QGraphicsGridLayout::setColumnMaximumWidth(int column, qreal width)
422{
423 Q_D(QGraphicsGridLayout);
424 d->engine.setRowSizeHint(Qt::MaximumSize, column, width, Qt::Horizontal);
425 invalidate();
426}
427
428/*!
429 Returns the maximum width for \a column.
430*/
431qreal QGraphicsGridLayout::columnMaximumWidth(int column) const
432{
433 Q_D(const QGraphicsGridLayout);
434 return d->engine.rowSizeHint(Qt::MaximumSize, column, Qt::Horizontal);
435}
436
437/*!
438 Sets the fixed width of \a column to \a width.
439*/
440void QGraphicsGridLayout::setColumnFixedWidth(int column, qreal width)
441{
442 Q_D(QGraphicsGridLayout);
443 d->engine.setRowSizeHint(Qt::MinimumSize, column, width, Qt::Horizontal);
444 d->engine.setRowSizeHint(Qt::MaximumSize, column, width, Qt::Horizontal);
445 invalidate();
446}
447
448/*!
449 Sets the alignment of \a row to \a alignment.
450*/
451void QGraphicsGridLayout::setRowAlignment(int row, Qt::Alignment alignment)
452{
453 Q_D(QGraphicsGridLayout);
454 d->engine.setRowAlignment(row, alignment, Qt::Vertical);
455 invalidate();
456}
457
458/*!
459 Returns the alignment of \a row.
460*/
461Qt::Alignment QGraphicsGridLayout::rowAlignment(int row) const
462{
463 Q_D(const QGraphicsGridLayout);
464 return d->engine.rowAlignment(row, Qt::Vertical);
465}
466
467/*!
468 Sets the alignment for \a column to \a alignment.
469*/
470void QGraphicsGridLayout::setColumnAlignment(int column, Qt::Alignment alignment)
471{
472 Q_D(QGraphicsGridLayout);
473 d->engine.setRowAlignment(column, alignment, Qt::Horizontal);
474 invalidate();
475}
476
477/*!
478 Returns the alignment for \a column.
479*/
480Qt::Alignment QGraphicsGridLayout::columnAlignment(int column) const
481{
482 Q_D(const QGraphicsGridLayout);
483 return d->engine.rowAlignment(column, Qt::Horizontal);
484}
485
486/*!
487 Sets the alignment for \a item to \a alignment.
488*/
489void QGraphicsGridLayout::setAlignment(QGraphicsLayoutItem *item, Qt::Alignment alignment)
490{
491 Q_D(QGraphicsGridLayout);
492 d->engine.setAlignment(item, alignment);
493 invalidate();
494}
495
496/*!
497 Returns the alignment for \a item.
498*/
499Qt::Alignment QGraphicsGridLayout::alignment(QGraphicsLayoutItem *item) const
500{
501 Q_D(const QGraphicsGridLayout);
502 return d->engine.alignment(item);
503}
504
505/*!
506 Returns the number of rows in the grid layout. This is always one more
507 than the index of the last row that is occupied by a layout item (empty
508 rows are counted except for those at the end).
509*/
510int QGraphicsGridLayout::rowCount() const
511{
512 Q_D(const QGraphicsGridLayout);
513 return d->engine.effectiveLastRow(Qt::Vertical) + 1;
514}
515
516/*!
517 Returns the number of columns in the grid layout. This is always one more
518 than the index of the last column that is occupied by a layout item (empty
519 columns are counted except for those at the end).
520*/
521int QGraphicsGridLayout::columnCount() const
522{
523 Q_D(const QGraphicsGridLayout);
524 return d->engine.effectiveLastRow(Qt::Horizontal) + 1;
525}
526
527/*!
528 Returns a pointer to the layout item at (\a row, \a column).
529*/
530QGraphicsLayoutItem *QGraphicsGridLayout::itemAt(int row, int column) const
531{
532 Q_D(const QGraphicsGridLayout);
533 if (row < 0 || row >= rowCount() || column < 0 || column >= columnCount()) {
534 qWarning("QGraphicsGridLayout::itemAt: invalid row, column %d, %d", row, column);
535 return 0;
536 }
537 if (QGridLayoutItem *item = d->engine.itemAt(row, column))
538 return item->layoutItem();
539 return 0;
540}
541
542/*!
543 Returns the number of layout items in this grid layout.
544*/
545int QGraphicsGridLayout::count() const
546{
547 Q_D(const QGraphicsGridLayout);
548 return d->engine.itemCount();
549}
550
551/*!
552 Returns the layout item at \a index, or 0 if there is no layout item at
553 this index.
554*/
555QGraphicsLayoutItem *QGraphicsGridLayout::itemAt(int index) const
556{
557 Q_D(const QGraphicsGridLayout);
558 if (index < 0 || index >= d->engine.itemCount()) {
559 qWarning("QGraphicsGridLayout::itemAt: invalid index %d", index);
560 return 0;
561 }
562 QGraphicsLayoutItem *item = 0;
563 if (QGridLayoutItem *gridItem = d->engine.itemAt(index))
564 item = gridItem->layoutItem();
565 return item;
566}
567
568/*!
569 Removes the layout item at \a index without destroying it. Ownership of
570 the item is transferred to the caller.
571
572 \sa addItem()
573*/
574void QGraphicsGridLayout::removeAt(int index)
575{
576 Q_D(QGraphicsGridLayout);
577 if (index < 0 || index >= d->engine.itemCount()) {
578 qWarning("QGraphicsGridLayout::removeAt: invalid index %d", index);
579 return;
580 }
581 if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) {
582 if (QGraphicsLayoutItem *layoutItem = gridItem->layoutItem())
583 layoutItem->setParentLayoutItem(0);
584 d->engine.removeItem(gridItem);
585
586 // recalculate rowInfo.count if we remove an item that is on the right/bottommost row
587 for (int j = 0; j < NOrientations; ++j) {
588 // 0: Hor, 1: Ver
589 const Qt::Orientation orient = (j == 0 ? Qt::Horizontal : Qt::Vertical);
590 const int oldCount = d->engine.rowCount(orient);
591 if (gridItem->lastRow(orient) == oldCount - 1) {
592 const int newCount = d->engine.effectiveLastRow(orient) + 1;
593 d->engine.removeRows(newCount, oldCount - newCount, orient);
594 }
595 }
596
597 delete gridItem;
598 invalidate();
599 }
600}
601
602/*!
603 \reimp
604*/
605void QGraphicsGridLayout::invalidate()
606{
607 Q_D(QGraphicsGridLayout);
608 d->engine.invalidate();
609 QGraphicsLayout::invalidate();
610}
611
612#ifdef QT_DEBUG
613void QGraphicsGridLayoutPrivate::dump(int indent) const
614{
615 if (qt_graphicsLayoutDebug()) {
616 engine.dump(indent + 1);
617 }
618}
619#endif
620
621/*!
622 Sets the bounding geometry of the grid layout to \a rect.
623*/
624void QGraphicsGridLayout::setGeometry(const QRectF &rect)
625{
626 Q_D(QGraphicsGridLayout);
627 QGraphicsLayout::setGeometry(rect);
628 QRectF effectiveRect = geometry();
629 qreal left, top, right, bottom;
630 getContentsMargins(&left, &top, &right, &bottom);
631 Qt::LayoutDirection visualDir = d->visualDirection();
632 d->engine.setVisualDirection(visualDir);
633 if (visualDir == Qt::RightToLeft)
634 qSwap(left, right);
635 effectiveRect.adjust(+left, +top, -right, -bottom);
636 d->engine.setGeometries(d->styleInfo(), effectiveRect);
637#ifdef QT_DEBUG
638 if (qt_graphicsLayoutDebug()) {
639 static int counter = 0;
640 qDebug("==== BEGIN DUMP OF QGraphicsGridLayout (%d)====", counter++);
641 d->dump(1);
642 qDebug("==== END DUMP OF QGraphicsGridLayout ====");
643 }
644#endif
645}
646
647/*!
648 \reimp
649*/
650QSizeF QGraphicsGridLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
651{
652 Q_D(const QGraphicsGridLayout);
653 qreal left, top, right, bottom;
654 getContentsMargins(&left, &top, &right, &bottom);
655 const QSizeF extraMargins(left + right, top + bottom);
656 return d->engine.sizeHint(d->styleInfo(), which , constraint - extraMargins) + extraMargins;
657}
658
659
660#if 0
661// ### kill? (implement and kill?)
662QRect QGraphicsGridLayout::cellRect(int row, int column, int rowSpan, int columnSpan) const
663{
664 Q_D(const QGraphicsGridLayout);
665 return QRect();
666// return d->engine.cellRect(parentLayoutable(), contentsGeometry(), row, column, rowSpan, columnSpan);
667}
668
669QSizePolicy::ControlTypes QGraphicsGridLayout::controlTypes(LayoutSide side) const
670{
671 Q_D(const QGraphicsGridLayout);
672 return d->engine.controlTypes(side);
673}
674#endif
675
676QT_END_NAMESPACE
677
678#endif //QT_NO_GRAPHICSVIEW
Note: See TracBrowser for help on using the repository browser.