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_p.h"
7#include "qgraphicslayout.h"
8#include "qgraphicswidget.h"
9#include "qapplication.h"
10
11QT_BEGIN_NAMESPACE
12
13/*!
14 \internal
15
16 \a mw is the new parent. all items in the layout will be a child of \a mw.
17 */
18void QGraphicsLayoutPrivate::reparentChildItems(QGraphicsItem *newParent)
19{
20 Q_Q(QGraphicsLayout);
21 int n = q->count();
22 //bool mwVisible = mw && mw->isVisible();
23 for (int i = 0; i < n; ++i) {
24 QGraphicsLayoutItem *layoutChild = q->itemAt(i);
25 if (!layoutChild) {
26 // Skip stretch items
27 continue;
28 }
29 if (layoutChild->isLayout()) {
30 QGraphicsLayout *l = static_cast<QGraphicsLayout*>(layoutChild);
31 l->d_func()->reparentChildItems(newParent);
32 } else if (QGraphicsItem *itemChild = layoutChild->graphicsItem()){
33 QGraphicsItem *childParent = itemChild->parentItem();
34#ifdef QT_DEBUG
35 if (childParent && childParent != newParent && itemChild->isWidget() && qt_graphicsLayoutDebug()) {
36 QGraphicsWidget *w = static_cast<QGraphicsWidget*>(layoutChild);
37 qWarning(msg: "QGraphicsLayout::addChildLayout: widget %s \"%s\" in wrong parent; moved to correct parent",
38 w->metaObject()->className(), w->objectName().toLocal8Bit().constData());
39 }
40#endif
41 if (childParent != newParent)
42 itemChild->setParentItem(newParent);
43 }
44 }
45}
46
47void QGraphicsLayoutPrivate::getMargin(qreal *result, qreal userMargin, QStyle::PixelMetric pm) const
48{
49 if (!result)
50 return;
51 Q_Q(const QGraphicsLayout);
52
53 QGraphicsLayoutItem *parent = q->parentLayoutItem();
54 if (userMargin >= 0.0) {
55 *result = userMargin;
56 } else if (!parent) {
57 *result = 0.0;
58 } else if (parent->isLayout()) { // sublayouts have 0 margin by default
59 *result = 0.0;
60 } else {
61 *result = 0.0;
62 if (QGraphicsItem *layoutParentItem = parentItem()) {
63 if (layoutParentItem->isWidget())
64 *result = (qreal)static_cast<QGraphicsWidget*>(layoutParentItem)->style()->pixelMetric(metric: pm, option: nullptr);
65 }
66 }
67}
68
69Qt::LayoutDirection QGraphicsLayoutPrivate::visualDirection() const
70{
71 if (QGraphicsItem *maybeWidget = parentItem()) {
72 if (maybeWidget->isWidget())
73 return static_cast<QGraphicsWidget*>(maybeWidget)->layoutDirection();
74 }
75 return QGuiApplication::layoutDirection();
76}
77
78static bool removeLayoutItemFromLayout(QGraphicsLayout *lay, QGraphicsLayoutItem *layoutItem)
79{
80 if (!lay)
81 return false;
82
83 for (int i = lay->count() - 1; i >= 0; --i) {
84 QGraphicsLayoutItem *child = lay->itemAt(i);
85 if (child && child->isLayout()) {
86 if (removeLayoutItemFromLayout(lay: static_cast<QGraphicsLayout*>(child), layoutItem))
87 return true;
88 } else if (child == layoutItem) {
89 lay->removeAt(index: i);
90 return true;
91 }
92 }
93 return false;
94}
95
96/*!
97 \internal
98
99 This function is called from subclasses to add a layout item \a layoutItem
100 to a layout.
101
102 It takes care of automatically reparenting graphics items, if needed.
103
104 If \a layoutItem is a is already in a layout, it will remove it from that layout.
105
106*/
107void QGraphicsLayoutPrivate::addChildLayoutItem(QGraphicsLayoutItem *layoutItem)
108{
109 Q_Q(QGraphicsLayout);
110 if (QGraphicsLayoutItem *maybeLayout = layoutItem->parentLayoutItem()) {
111 if (maybeLayout->isLayout())
112 removeLayoutItemFromLayout(lay: static_cast<QGraphicsLayout*>(maybeLayout), layoutItem);
113 }
114 layoutItem->setParentLayoutItem(q);
115 if (layoutItem->isLayout()) {
116 if (QGraphicsItem *parItem = parentItem()) {
117 static_cast<QGraphicsLayout*>(layoutItem)->d_func()->reparentChildItems(newParent: parItem);
118 }
119 } else {
120 if (QGraphicsItem *item = layoutItem->graphicsItem()) {
121 QGraphicsItem *newParent = parentItem();
122 QGraphicsItem *oldParent = item->parentItem();
123 if (oldParent == newParent || !newParent)
124 return;
125
126#ifdef QT_DEBUG
127 if (oldParent && item->isWidget()) {
128 QGraphicsWidget *w = static_cast<QGraphicsWidget*>(item);
129 qWarning(msg: "QGraphicsLayout::addChildLayoutItem: %s \"%s\" in wrong parent; moved to correct parent",
130 w->metaObject()->className(), w->objectName().toLocal8Bit().constData());
131 }
132#endif
133
134 item->setParentItem(newParent);
135 }
136 }
137}
138
139void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item)
140{
141 if (item->isLayout()) {
142 QGraphicsLayout *layout = static_cast<QGraphicsLayout *>(item);
143 if (layout->d_func()->activated) {
144 if (QGraphicsLayout::instantInvalidatePropagation()) {
145 return;
146 } else {
147 layout->invalidate(); // ### LOOKS SUSPICIOUSLY WRONG!!???
148 }
149 }
150
151 for (int i = layout->count() - 1; i >= 0; --i) {
152 QGraphicsLayoutItem *childItem = layout->itemAt(i);
153 if (childItem)
154 activateRecursive(item: childItem);
155 }
156 layout->d_func()->activated = true;
157 }
158}
159
160QT_END_NAMESPACE
161

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