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
4#include "qglobal.h"
5
6#include "qgraphicslayout.h"
7#include "qgraphicsscene.h"
8#include "qgraphicslayoutitem.h"
9#include "qgraphicslayoutitem_p.h"
10#include "qwidget.h"
11#include "qgraphicswidget.h"
12#include "qgraphicsitem_p.h"
13
14#include <QtDebug>
15
16QT_BEGIN_NAMESPACE
17
18/*
19 COMBINE_SIZE() is identical to combineSize(), except that it
20 doesn't evaluate 'size' unless necessary.
21*/
22#define COMBINE_SIZE(result, size) \
23 do { \
24 if ((result).width() < 0 || (result).height() < 0) \
25 combineSize((result), (size)); \
26 } while (false)
27
28static void combineSize(QSizeF &result, const QSizeF &size)
29{
30 if (result.width() < 0)
31 result.setWidth(size.width());
32 if (result.height() < 0)
33 result.setHeight(size.height());
34}
35
36static void boundSize(QSizeF &result, const QSizeF &size)
37{
38 if (size.width() >= 0 && size.width() < result.width())
39 result.setWidth(size.width());
40 if (size.height() >= 0 && size.height() < result.height())
41 result.setHeight(size.height());
42}
43
44static void expandSize(QSizeF &result, const QSizeF &size)
45{
46 if (size.width() >= 0 && size.width() > result.width())
47 result.setWidth(size.width());
48 if (size.height() >= 0 && size.height() > result.height())
49 result.setHeight(size.height());
50}
51
52static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qreal &descent)
53{
54 if (minimum >= 0 && maximum >= 0 && minimum > maximum)
55 minimum = maximum;
56
57 if (preferred >= 0) {
58 if (minimum >= 0 && preferred < minimum) {
59 preferred = minimum;
60 } else if (maximum >= 0 && preferred > maximum) {
61 preferred = maximum;
62 }
63 }
64
65 if (minimum >= 0 && descent > minimum)
66 descent = minimum;
67}
68
69/*!
70 \internal
71*/
72QGraphicsLayoutItemPrivate::QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *par, bool layout)
73 : parent(par), userSizeHints(nullptr), isLayout(layout), ownedByLayout(false), graphicsItem(nullptr)
74{
75}
76
77/*!
78 \internal
79*/
80QGraphicsLayoutItemPrivate::~QGraphicsLayoutItemPrivate()
81{
82 // Remove any lazily allocated data
83 delete[] userSizeHints;
84}
85
86/*!
87 \internal
88*/
89void QGraphicsLayoutItemPrivate::init()
90{
91 sizeHintCacheDirty = true;
92 sizeHintWithConstraintCacheDirty = true;
93}
94
95/*!
96 \internal
97*/
98QSizeF *QGraphicsLayoutItemPrivate::effectiveSizeHints(const QSizeF &constraint) const
99{
100 Q_Q(const QGraphicsLayoutItem);
101 QSizeF *sizeHintCache;
102 const bool hasConstraint = constraint.width() >= 0 || constraint.height() >= 0;
103 if (hasConstraint) {
104 if (!sizeHintWithConstraintCacheDirty && constraint == cachedConstraint)
105 return cachedSizeHintsWithConstraints;
106 sizeHintCache = cachedSizeHintsWithConstraints;
107 } else {
108 if (!sizeHintCacheDirty)
109 return cachedSizeHints;
110 sizeHintCache = cachedSizeHints;
111 }
112
113 for (int i = 0; i < Qt::NSizeHints; ++i) {
114 sizeHintCache[i] = constraint;
115 if (userSizeHints)
116 combineSize(result&: sizeHintCache[i], size: userSizeHints[i]);
117 }
118
119 QSizeF &minS = sizeHintCache[Qt::MinimumSize];
120 QSizeF &prefS = sizeHintCache[Qt::PreferredSize];
121 QSizeF &maxS = sizeHintCache[Qt::MaximumSize];
122 QSizeF &descentS = sizeHintCache[Qt::MinimumDescent];
123
124 normalizeHints(minimum&: minS.rwidth(), preferred&: prefS.rwidth(), maximum&: maxS.rwidth(), descent&: descentS.rwidth());
125 normalizeHints(minimum&: minS.rheight(), preferred&: prefS.rheight(), maximum&: maxS.rheight(), descent&: descentS.rheight());
126
127 // if the minimum, preferred and maximum sizes contradict each other
128 // (e.g. the minimum is larger than the maximum) we give priority to
129 // the maximum size, then the minimum size and finally the preferred size
130 COMBINE_SIZE(maxS, q->sizeHint(Qt::MaximumSize, maxS));
131 combineSize(result&: maxS, size: QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
132 expandSize(result&: maxS, size: prefS);
133 expandSize(result&: maxS, size: minS);
134 boundSize(result&: maxS, size: QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
135
136 COMBINE_SIZE(minS, q->sizeHint(Qt::MinimumSize, minS));
137 expandSize(result&: minS, size: QSizeF(0, 0));
138 boundSize(result&: minS, size: prefS);
139 boundSize(result&: minS, size: maxS);
140
141 COMBINE_SIZE(prefS, q->sizeHint(Qt::PreferredSize, prefS));
142 expandSize(result&: prefS, size: minS);
143 boundSize(result&: prefS, size: maxS);
144
145 // Not supported yet
146 // COMBINE_SIZE(descentS, q->sizeHint(Qt::MinimumDescent, constraint));
147
148 if (hasConstraint) {
149 cachedConstraint = constraint;
150 sizeHintWithConstraintCacheDirty = false;
151 } else {
152 sizeHintCacheDirty = false;
153 }
154 return sizeHintCache;
155}
156
157
158/*!
159 \internal
160
161 Returns the parent item of this layout, or \nullptr if this layout is
162 not installed on any widget.
163
164 If this is the item that the layout is installed on, it will return "itself".
165
166 If the layout is a sub-layout, this function returns the parent
167 widget of the parent layout.
168
169 Note that it will traverse up the layout item hierarchy instead of just calling
170 QGraphicsItem::parentItem(). This is on purpose.
171
172 \sa parent()
173*/
174QGraphicsItem *QGraphicsLayoutItemPrivate::parentItem() const
175{
176 Q_Q(const QGraphicsLayoutItem);
177
178 const QGraphicsLayoutItem *parent = q;
179 while (parent && parent->isLayout()) {
180 parent = parent->parentLayoutItem();
181 }
182 return parent ? parent->graphicsItem() : nullptr;
183}
184
185/*!
186 \internal
187
188 Ensures that userSizeHints is allocated.
189 This function must be called before any dereferencing.
190*/
191void QGraphicsLayoutItemPrivate::ensureUserSizeHints()
192{
193 if (!userSizeHints)
194 userSizeHints = new QSizeF[Qt::NSizeHints];
195}
196
197/*!
198 \internal
199
200 Sets the user size hint \a which to \a size. Use an invalid size to unset the size hint.
201 */
202void QGraphicsLayoutItemPrivate::setSize(Qt::SizeHint which, const QSizeF &size)
203{
204 Q_Q(QGraphicsLayoutItem);
205
206 if (userSizeHints) {
207 if (size == userSizeHints[which])
208 return;
209 } else if (size.width() < 0 && size.height() < 0) {
210 return;
211 }
212
213 ensureUserSizeHints();
214 userSizeHints[which] = size;
215 q->updateGeometry();
216}
217
218/*!
219 \internal
220
221 Sets the width of the user size hint \a which to \a width.
222 */
223void QGraphicsLayoutItemPrivate::setSizeComponent(
224 Qt::SizeHint which, SizeComponent component, qreal value)
225{
226 Q_Q(QGraphicsLayoutItem);
227 ensureUserSizeHints();
228 qreal &userValue = (component == Width)
229 ? userSizeHints[which].rwidth()
230 : userSizeHints[which].rheight();
231 if (value == userValue)
232 return;
233 userValue = value;
234 q->updateGeometry();
235}
236
237
238bool QGraphicsLayoutItemPrivate::hasHeightForWidth() const
239{
240 Q_Q(const QGraphicsLayoutItem);
241 if (isLayout) {
242 const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q);
243 for (int i = l->count() - 1; i >= 0; --i) {
244 if (QGraphicsLayoutItemPrivate::get(q: l->itemAt(i))->hasHeightForWidth())
245 return true;
246 }
247 } else if (QGraphicsItem *item = q->graphicsItem()) {
248 if (item->isWidget()) {
249 QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
250 if (w->layout()) {
251 return QGraphicsLayoutItemPrivate::get(q: w->layout())->hasHeightForWidth();
252 }
253 }
254 }
255 return q->sizePolicy().hasHeightForWidth();
256}
257
258bool QGraphicsLayoutItemPrivate::hasWidthForHeight() const
259{
260 Q_Q(const QGraphicsLayoutItem);
261 if (isLayout) {
262 const QGraphicsLayout *l = static_cast<const QGraphicsLayout *>(q);
263 for (int i = l->count() - 1; i >= 0; --i) {
264 if (QGraphicsLayoutItemPrivate::get(q: l->itemAt(i))->hasWidthForHeight())
265 return true;
266 }
267 } else if (QGraphicsItem *item = q->graphicsItem()) {
268 if (item->isWidget()) {
269 QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
270 if (w->layout()) {
271 return QGraphicsLayoutItemPrivate::get(q: w->layout())->hasWidthForHeight();
272 }
273 }
274 }
275 return q->sizePolicy().hasWidthForHeight();
276}
277
278/*!
279 \class QGraphicsLayoutItem
280 \brief The QGraphicsLayoutItem class can be inherited to allow your custom
281 items to be managed by layouts.
282 \since 4.4
283 \ingroup graphicsview-api
284 \inmodule QtWidgets
285
286 QGraphicsLayoutItem is an abstract class that defines a set of virtual
287 functions describing sizes, size policies, and size hints for any object
288 arranged by QGraphicsLayout. The API contains functions relevant
289 for both the item itself and for the user of the item as most of
290 QGraphicsLayoutItem's functions are also part of the subclass' public API.
291
292 In most cases, existing layout-aware classes such as QGraphicsWidget and
293 QGraphicsLayout already provide the functionality you require. However,
294 subclassing these classes will enable you to create both graphical
295 elements that work well with layouts (QGraphicsWidget) or custom layouts
296 (QGraphicsLayout).
297
298 \section1 Subclassing QGraphicsLayoutItem
299
300 If you create a subclass of QGraphicsLayoutItem and reimplement its
301 virtual functions, you will enable the layout to resize and position your
302 item along with other QGraphicsLayoutItems including QGraphicsWidget
303 and QGraphicsLayout.
304
305 You can start by reimplementing important functions: the protected
306 sizeHint() function, as well as the public setGeometry()
307 function. If you want your items to be aware of immediate geometry
308 changes, you can also reimplement updateGeometry().
309
310 The geometry, size hint, and size policy affect the item's size and
311 position. Calling setGeometry() will always resize and reposition the item
312 immediately. Normally, this function is called by QGraphicsLayout after
313 the layout has been activated, but it can also be called by the item's user
314 at any time.
315
316 The sizeHint() function returns the item' minimum, preferred and maximum
317 size hints. You can override these properties by calling setMinimumSize(),
318 setPreferredSize() or setMaximumSize(). You can also use functions such as
319 setMinimumWidth() or setMaximumHeight() to set only the width or height
320 component if desired.
321
322 The effectiveSizeHint() function, on the other hand, returns a size hint
323 for any given Qt::SizeHint, and guarantees that the returned size is bound
324 to the minimum and maximum sizes and size hints. You can set the item's
325 vertical and horizontal size policy by calling setSizePolicy(). The
326 sizePolicy property is used by the layout system to describe how this item
327 prefers to grow or shrink.
328
329 \section1 Nesting QGraphicsLayoutItems
330
331 QGraphicsLayoutItems can be nested within other QGraphicsLayoutItems,
332 similar to layouts that can contain sublayouts. This is done either by
333 passing a QGraphicsLayoutItem pointer to QGraphicsLayoutItem's
334 protected constructor, or by calling setParentLayoutItem(). The
335 parentLayoutItem() function returns a pointer to the item's layoutItem
336 parent. If the item's parent is \nullptr or if the parent does not inherit
337 from QGraphicsItem, the parentLayoutItem() function then returns \nullptr.
338 isLayout() returns \c true if the QGraphicsLayoutItem subclass is itself a
339 layout, or false otherwise.
340
341 Qt uses QGraphicsLayoutItem to provide layout functionality in the
342 \l{Graphics View Framework}, but in the future its use may spread
343 throughout Qt itself.
344
345 \sa QGraphicsWidget, QGraphicsLayout, QGraphicsLinearLayout,
346 QGraphicsGridLayout
347*/
348
349/*!
350 Constructs the QGraphicsLayoutItem object. \a parent becomes the object's
351 parent. If \a isLayout is true the item is a layout, otherwise
352 \a isLayout is false.
353*/
354QGraphicsLayoutItem::QGraphicsLayoutItem(QGraphicsLayoutItem *parent, bool isLayout)
355 : d_ptr(new QGraphicsLayoutItemPrivate(parent, isLayout))
356{
357 Q_D(QGraphicsLayoutItem);
358 d->init();
359 d->sizePolicy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
360 d->q_ptr = this;
361}
362
363/*!
364 \internal
365*/
366QGraphicsLayoutItem::QGraphicsLayoutItem(QGraphicsLayoutItemPrivate &dd)
367 : d_ptr(&dd)
368{
369 Q_D(QGraphicsLayoutItem);
370 d->init();
371 d->q_ptr = this;
372}
373
374/*!
375 Destroys the QGraphicsLayoutItem object.
376*/
377QGraphicsLayoutItem::~QGraphicsLayoutItem()
378{
379 QGraphicsLayoutItem *parentLI = parentLayoutItem();
380 if (parentLI && parentLI->isLayout()) {
381 QGraphicsLayout *lay = static_cast<QGraphicsLayout*>(parentLI);
382 // this is not optimal
383 for (int i = lay->count() - 1; i >= 0; --i) {
384 if (lay->itemAt(i) == this) {
385 lay->removeAt(index: i);
386 break;
387 }
388 }
389 }
390}
391
392/*!
393 \fn virtual QSizeF QGraphicsLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const = 0;
394
395 This pure virtual function returns the size hint for \a which of the
396 QGraphicsLayoutItem, using the width or height of \a constraint to
397 constrain the output.
398
399 Reimplement this function in a subclass of QGraphicsLayoutItem to
400 provide the necessary size hints for your items.
401
402 \sa effectiveSizeHint()
403*/
404
405/*!
406 Sets the size policy to \a policy. The size policy describes how the item
407 should grow horizontally and vertically when arranged in a layout.
408
409 QGraphicsLayoutItem's default size policy is (QSizePolicy::Fixed,
410 QSizePolicy::Fixed, QSizePolicy::DefaultType), but it is common for
411 subclasses to change the default. For example, QGraphicsWidget defaults
412 to (QSizePolicy::Preferred, QSizePolicy::Preferred,
413 QSizePolicy::DefaultType).
414
415 \sa sizePolicy(), QWidget::sizePolicy()
416*/
417void QGraphicsLayoutItem::setSizePolicy(const QSizePolicy &policy)
418{
419 Q_D(QGraphicsLayoutItem);
420 if (d->sizePolicy == policy)
421 return;
422 d->sizePolicy = policy;
423 updateGeometry();
424}
425
426/*!
427 \overload
428
429 This function is equivalent to calling
430 setSizePolicy(QSizePolicy(\a hPolicy, \a vPolicy, \a controlType)).
431
432 \sa sizePolicy(), QWidget::sizePolicy()
433*/
434void QGraphicsLayoutItem::setSizePolicy(QSizePolicy::Policy hPolicy,
435 QSizePolicy::Policy vPolicy,
436 QSizePolicy::ControlType controlType)
437{
438 setSizePolicy(QSizePolicy(hPolicy, vPolicy, controlType));
439}
440
441/*!
442 Returns the current size policy.
443
444 \sa setSizePolicy(), QWidget::sizePolicy()
445*/
446QSizePolicy QGraphicsLayoutItem::sizePolicy() const
447{
448 Q_D(const QGraphicsLayoutItem);
449 return d->sizePolicy;
450}
451
452/*!
453 Sets the minimum size to \a size. This property overrides sizeHint() for
454 Qt::MinimumSize and ensures that effectiveSizeHint() will never return
455 a size smaller than \a size. In order to unset the minimum size, use an
456 invalid size.
457
458 \sa minimumSize(), maximumSize(), preferredSize(), Qt::MinimumSize,
459 sizeHint(), setMinimumWidth(), setMinimumHeight()
460*/
461void QGraphicsLayoutItem::setMinimumSize(const QSizeF &size)
462{
463 d_ptr->setSize(which: Qt::MinimumSize, size);
464}
465
466/*!
467 \fn QGraphicsLayoutItem::setMinimumSize(qreal w, qreal h)
468
469 This convenience function is equivalent to calling
470 setMinimumSize(QSizeF(\a w, \a h)).
471
472 \sa minimumSize(), setMaximumSize(), setPreferredSize(), sizeHint()
473*/
474
475/*!
476 Returns the minimum size.
477
478 \sa setMinimumSize(), preferredSize(), maximumSize(), Qt::MinimumSize,
479 sizeHint()
480*/
481QSizeF QGraphicsLayoutItem::minimumSize() const
482{
483 return effectiveSizeHint(which: Qt::MinimumSize);
484}
485
486/*!
487 Sets the minimum width to \a width.
488
489 \sa minimumWidth(), setMinimumSize(), minimumSize()
490*/
491void QGraphicsLayoutItem::setMinimumWidth(qreal width)
492{
493 d_ptr->setSizeComponent(which: Qt::MinimumSize, component: d_ptr->Width, value: width);
494}
495
496/*!
497 Sets the minimum height to \a height.
498
499 \sa minimumHeight(), setMinimumSize(), minimumSize()
500*/
501void QGraphicsLayoutItem::setMinimumHeight(qreal height)
502{
503 d_ptr->setSizeComponent(which: Qt::MinimumSize, component: d_ptr->Height, value: height);
504}
505
506
507/*!
508 Sets the preferred size to \a size. This property overrides sizeHint() for
509 Qt::PreferredSize and provides the default value for effectiveSizeHint().
510 In order to unset the preferred size, use an invalid size.
511
512 \sa preferredSize(), minimumSize(), maximumSize(), Qt::PreferredSize,
513 sizeHint()
514*/
515void QGraphicsLayoutItem::setPreferredSize(const QSizeF &size)
516{
517 d_ptr->setSize(which: Qt::PreferredSize, size);
518}
519
520/*!
521 \fn QGraphicsLayoutItem::setPreferredSize(qreal w, qreal h)
522
523 This convenience function is equivalent to calling
524 setPreferredSize(QSizeF(\a w, \a h)).
525
526 \sa preferredSize(), setMaximumSize(), setMinimumSize(), sizeHint()
527*/
528
529/*!
530 Returns the preferred size.
531
532 \sa setPreferredSize(), minimumSize(), maximumSize(), Qt::PreferredSize,
533 sizeHint()
534*/
535QSizeF QGraphicsLayoutItem::preferredSize() const
536{
537 return effectiveSizeHint(which: Qt::PreferredSize);
538}
539
540/*!
541 Sets the preferred height to \a height.
542
543 \sa preferredWidth(), setPreferredSize(), preferredSize()
544*/
545void QGraphicsLayoutItem::setPreferredHeight(qreal height)
546{
547 d_ptr->setSizeComponent(which: Qt::PreferredSize, component: d_ptr->Height, value: height);
548}
549
550/*!
551 Sets the preferred width to \a width.
552
553 \sa preferredHeight(), setPreferredSize(), preferredSize()
554*/
555void QGraphicsLayoutItem::setPreferredWidth(qreal width)
556{
557 d_ptr->setSizeComponent(which: Qt::PreferredSize, component: d_ptr->Width, value: width);
558}
559
560/*!
561 Sets the maximum size to \a size. This property overrides sizeHint() for
562 Qt::MaximumSize and ensures that effectiveSizeHint() will never return a
563 size larger than \a size. In order to unset the maximum size, use an
564 invalid size.
565
566 \sa maximumSize(), minimumSize(), preferredSize(), Qt::MaximumSize,
567 sizeHint()
568*/
569void QGraphicsLayoutItem::setMaximumSize(const QSizeF &size)
570{
571 d_ptr->setSize(which: Qt::MaximumSize, size);
572}
573
574/*!
575 \fn QGraphicsLayoutItem::setMaximumSize(qreal w, qreal h)
576
577 This convenience function is equivalent to calling
578 setMaximumSize(QSizeF(\a w, \a h)).
579
580 \sa maximumSize(), setMinimumSize(), setPreferredSize(), sizeHint()
581*/
582
583/*!
584 Returns the maximum size.
585
586 \sa setMaximumSize(), minimumSize(), preferredSize(), Qt::MaximumSize,
587 sizeHint()
588*/
589QSizeF QGraphicsLayoutItem::maximumSize() const
590{
591 return effectiveSizeHint(which: Qt::MaximumSize);
592}
593
594/*!
595 Sets the maximum width to \a width.
596
597 \sa maximumWidth(), setMaximumSize(), maximumSize()
598*/
599void QGraphicsLayoutItem::setMaximumWidth(qreal width)
600{
601 d_ptr->setSizeComponent(which: Qt::MaximumSize, component: d_ptr->Width, value: width);
602}
603
604/*!
605 Sets the maximum height to \a height.
606
607 \sa maximumHeight(), setMaximumSize(), maximumSize()
608*/
609void QGraphicsLayoutItem::setMaximumHeight(qreal height)
610{
611 d_ptr->setSizeComponent(which: Qt::MaximumSize, component: d_ptr->Height, value: height);
612}
613
614/*!
615 \fn qreal QGraphicsLayoutItem::minimumWidth() const
616
617 Returns the minimum width.
618
619 \sa setMinimumWidth(), setMinimumSize(), minimumSize()
620*/
621
622/*!
623 \fn qreal QGraphicsLayoutItem::minimumHeight() const
624
625 Returns the minimum height.
626
627 \sa setMinimumHeight(), setMinimumSize(), minimumSize()
628*/
629
630/*!
631 \fn qreal QGraphicsLayoutItem::preferredWidth() const
632
633 Returns the preferred width.
634
635 \sa setPreferredWidth(), setPreferredSize(), preferredSize()
636*/
637
638/*!
639 \fn qreal QGraphicsLayoutItem::preferredHeight() const
640
641 Returns the preferred height.
642
643 \sa setPreferredHeight(), setPreferredSize(), preferredSize()
644*/
645
646/*!
647 \fn qreal QGraphicsLayoutItem::maximumWidth() const
648
649 Returns the maximum width.
650
651 \sa setMaximumWidth(), setMaximumSize(), maximumSize()
652*/
653
654/*!
655 \fn qreal QGraphicsLayoutItem::maximumHeight() const
656
657 Returns the maximum height.
658
659 \sa setMaximumHeight(), setMaximumSize(), maximumSize()
660*/
661
662/*!
663 \fn virtual void QGraphicsLayoutItem::setGeometry(const QRectF &rect)
664
665 This virtual function sets the geometry of the QGraphicsLayoutItem to
666 \a rect, which is in parent coordinates (e.g., the top-left corner of \a rect
667 is equivalent to the item's position in parent coordinates).
668
669 You must reimplement this function in a subclass of QGraphicsLayoutItem to
670 receive geometry updates. The layout will call this function when it does a
671 rearrangement.
672
673 If \a rect is outside of the bounds of minimumSize and maximumSize, it
674 will be adjusted to its closest size so that it is within the legal
675 bounds.
676
677 \sa geometry()
678*/
679void QGraphicsLayoutItem::setGeometry(const QRectF &rect)
680{
681 Q_D(QGraphicsLayoutItem);
682 QSizeF effectiveSize = rect.size().expandedTo(otherSize: effectiveSizeHint(which: Qt::MinimumSize))
683 .boundedTo(otherSize: effectiveSizeHint(which: Qt::MaximumSize));
684 d->geom = QRectF(rect.topLeft(), effectiveSize);
685}
686
687/*!
688 \fn QRectF QGraphicsLayoutItem::geometry() const
689
690 Returns the item's geometry (e.g., position and size) as a
691 QRectF. This function is equivalent to QRectF(pos(), size()).
692
693 \sa setGeometry()
694*/
695QRectF QGraphicsLayoutItem::geometry() const
696{
697 Q_D(const QGraphicsLayoutItem);
698 return d->geom;
699}
700
701/*!
702 This virtual function provides the \a left, \a top, \a right and \a bottom
703 contents margins for this QGraphicsLayoutItem. The default implementation
704 assumes all contents margins are 0. The parameters point to values stored
705 in qreals. If any of the pointers is \nullptr, that value will not be updated.
706
707 \sa QGraphicsWidget::setContentsMargins()
708*/
709void QGraphicsLayoutItem::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
710{
711 if (left)
712 *left = 0;
713 if (top)
714 *top = 0;
715 if (right)
716 *right = 0;
717 if (bottom)
718 *bottom = 0;
719}
720
721/*!
722 Returns the contents rect in local coordinates.
723
724 The contents rect defines the subrectangle used by an associated layout
725 when arranging subitems. This function is a convenience function that
726 adjusts the item's geometry() by its contents margins. Note that
727 getContentsMargins() is a virtual function that you can reimplement to
728 return the item's contents margins.
729
730 \sa getContentsMargins(), geometry()
731*/
732QRectF QGraphicsLayoutItem::contentsRect() const
733{
734 qreal left, top, right, bottom;
735 getContentsMargins(left: &left, top: &top, right: &right, bottom: &bottom);
736 return QRectF(QPointF(), geometry().size()).adjusted(xp1: +left, yp1: +top, xp2: -right, yp2: -bottom);
737}
738
739/*!
740 Returns the effective size hint for this QGraphicsLayoutItem.
741
742 \a which is the size hint in question.
743 \a constraint is an optional argument that defines a special constrain
744 when calculating the effective size hint. By default, \a constraint is
745 QSizeF(-1, -1), which means there is no constraint to the size hint.
746
747 If you want to specify the widget's size hint for a given width or height,
748 you can provide the fixed dimension in \a constraint. This is useful for
749 widgets that can grow only either vertically or horizontally, and need to
750 set either their width or their height to a special value.
751
752 For example, a text paragraph item fit into a column width of 200 may
753 grow vertically. You can pass QSizeF(200, -1) as a constraint to get a
754 suitable minimum, preferred and maximum height).
755
756 You can adjust the effective size hint by reimplementing sizeHint()
757 in a QGraphicsLayoutItem subclass, or by calling one of the following
758 functions: setMinimumSize(), setPreferredSize, or setMaximumSize()
759 (or a combination of both).
760
761 This function caches each of the size hints and guarantees that
762 sizeHint() will be called only once for each value of \a which - unless
763 \a constraint is not specified and updateGeometry() has been called.
764
765 \sa sizeHint()
766*/
767QSizeF QGraphicsLayoutItem::effectiveSizeHint(Qt::SizeHint which, const QSizeF &constraint) const
768{
769 Q_D(const QGraphicsLayoutItem);
770
771 if (!d->userSizeHints && constraint.isValid())
772 return constraint;
773
774 // ### should respect size policy???
775 return d_ptr->effectiveSizeHints(constraint)[which];
776}
777
778/*!
779 This virtual function discards any cached size hint information. You
780 should always call this function if you change the return value of the
781 sizeHint() function. Subclasses must always call the base implementation
782 when reimplementing this function.
783
784 \sa effectiveSizeHint()
785*/
786void QGraphicsLayoutItem::updateGeometry()
787{
788 Q_D(QGraphicsLayoutItem);
789 d->sizeHintCacheDirty = true;
790 d->sizeHintWithConstraintCacheDirty = true;
791}
792
793/*!
794 \since 6.0
795
796 Returns \c true if this item is empty, i.e whether it has no content and
797 should not occupy any space.
798
799 The default implementation returns \c true true if the item has been hidden,
800 unless its \l{sizePolicy()}{size policy} has retainSizeWhenHidden set to \c true
801
802 \sa sizePolicy()
803*/
804bool QGraphicsLayoutItem::isEmpty() const
805{
806 bool isHidden = false;
807 if (QGraphicsItem *item = graphicsItem())
808 isHidden = QGraphicsItemPrivate::get(item)->explicitlyHidden;
809
810 return isHidden && !sizePolicy().retainSizeWhenHidden();
811}
812
813/*!
814 Returns the parent of this QGraphicsLayoutItem, or \nullptr if there is
815 no parent, or if the parent does not inherit from QGraphicsLayoutItem
816 (QGraphicsLayoutItem is often used through multiple inheritance with
817 QObject-derived classes).
818
819 \sa setParentLayoutItem()
820*/
821QGraphicsLayoutItem *QGraphicsLayoutItem::parentLayoutItem() const
822{
823 return d_func()->parent;
824}
825
826/*!
827 Sets the parent of this QGraphicsLayoutItem to \a parent.
828
829 \sa parentLayoutItem()
830*/
831void QGraphicsLayoutItem::setParentLayoutItem(QGraphicsLayoutItem *parent)
832{
833 d_func()->parent = parent;
834}
835
836/*!
837 Returns \c true if this QGraphicsLayoutItem is a layout (e.g., is inherited
838 by an object that arranges other QGraphicsLayoutItem objects); otherwise
839 returns \c false.
840
841 \sa QGraphicsLayout
842*/
843bool QGraphicsLayoutItem::isLayout() const
844{
845 return d_func()->isLayout;
846}
847
848/*!
849 \since 4.6
850
851 Returns whether a layout should delete this item in its destructor.
852 If its true, then the layout will delete it. If its false, then it is
853 assumed that another object has the ownership of it, and the layout won't
854 delete this item.
855
856 If the item inherits both QGraphicsItem and QGraphicsLayoutItem (such
857 as QGraphicsWidget does) the item is really part of two ownership
858 hierarchies. This property informs what the layout should do with its
859 child items when it is destructed. In the case of QGraphicsWidget, it
860 is preferred that when the layout is deleted it won't delete its children
861 (since they are also part of the graphics item hierarchy).
862
863 By default this value is initialized to false in QGraphicsLayoutItem,
864 but it is overridden by QGraphicsLayout to return true. This is because
865 QGraphicsLayout is not normally part of the QGraphicsItem hierarchy, so the
866 parent layout should delete it.
867 Subclasses might override this default behaviour by calling
868 setOwnedByLayout(true).
869
870 \sa setOwnedByLayout()
871*/
872bool QGraphicsLayoutItem::ownedByLayout() const
873{
874 return d_func()->ownedByLayout;
875}
876/*!
877 \since 4.6
878
879 Sets whether a layout should delete this item in its destructor or not.
880 \a ownership must be true to in order for the layout to delete it.
881 \sa ownedByLayout()
882*/
883void QGraphicsLayoutItem::setOwnedByLayout(bool ownership)
884{
885 d_func()->ownedByLayout = ownership;
886}
887
888/*!
889 * Returns the QGraphicsItem that this layout item represents.
890 * For QGraphicsWidget it will return itself. For custom items it can return an
891 * aggregated value.
892 *
893 * \sa setGraphicsItem()
894 */
895QGraphicsItem *QGraphicsLayoutItem::graphicsItem() const
896{
897 return d_func()->graphicsItem;
898}
899
900/*!
901 * If the QGraphicsLayoutItem represents a QGraphicsItem, and it wants to take
902 * advantage of the automatic reparenting capabilities of QGraphicsLayout it
903 * should set this value.
904 * Note that if you delete \a item and not delete the layout item, you are
905 * responsible of calling setGraphicsItem(\nullptr) in order to avoid having a
906 * dangling pointer.
907 *
908 * \sa graphicsItem()
909 */
910void QGraphicsLayoutItem::setGraphicsItem(QGraphicsItem *item)
911{
912 d_func()->graphicsItem = item;
913}
914
915QT_END_NAMESPACE
916

source code of qtbase/src/widgets/graphicsview/qgraphicslayoutitem.cpp