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