Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquicklayoutitemproxy.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 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
4#include "qquicklayout_p.h"
5
79Q_LOGGING_CATEGORY(lcLayouts, "qt.quick.layouts")
80
81
84{
85
86}
87
89{
91
92 if (!d->target)
93 return;
94
95 QQuickLayoutItemProxyAttachedData * attachedData = d->target->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>();
96 // De-register this proxy from the proxies controlling the target
97 if (attachedData) {
98 if (attachedData->getControllingProxy() == this) {
99 attachedData->releaseControl(this);
100 d->target->setParentItem(nullptr);
101 }
102 attachedData->releaseProxy(this);
103 }
104 // The target item still has a QObject parent that takes care of its destrctuion.
105 // No need to invoke destruction of the target tiem from here.
106}
107
112void QQuickLayoutItemProxy::geometryChange(const QRectF &newGeom, const QRectF &oldGeom)
113{
114 QQuickItem::geometryChange(newGeom, oldGeom);
115 if (!isVisible())
116 return;
117
118 const QSizeF sz = newGeom.size();
119 QPointF pos(0., 0.);
120
121 if (QQuickItem *t = effectiveTarget()) {
122 if (QQuickLayoutItemProxyAttachedData * attachedData = target()->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>()) {
123 if (attachedData->getControllingProxy() != this)
124 return;
125 }
126
127 // Should normally not be the case, except the user resets the parent
128 // This is a failsave for this case and positions the item correctly
129 if (t->parentItem() != this)
130 pos = t->parentItem()->mapFromGlobal(mapToGlobal(0, 0));
131
132 if (t->size() == sz && t->position() == pos && newGeom == oldGeom)
133 return;
134
135 t->setSize(sz);
136 t->setPosition(pos);
137 }
138}
139
145{
147 {
149 }
151}
152
153// Implementation of the slots to react to changes of the Layout attached properties.
154// If the target Layout propertie change, we change the proxy Layout properties accordingly
155// If the proxy Layout properties have been changed externally, we want to remove this binding.
156// The member variables m_expectProxy##Property##Change help us keep track about who invokes
157// the change of the parameter. If it is invoked by the target we expect a proxy property
158// change and will not remove the connection.
159#define propertyForwarding(property, Property) \
160 void QQuickLayoutItemProxy::target##Property##Changed() { \
161 Q_D(QQuickLayoutItemProxy); \
162 QQuickLayoutAttached *attTarget = attachedLayoutObject(target(), false); \
163 QQuickLayoutAttached *attProxy = attachedLayoutObject(this, false); \
164 if (!attTarget) return; \
165 if (attProxy->property() == attTarget->property()) \
166 return; \
167 d->m_expectProxy##Property##Change = true; \
168 attProxy->set##Property(attTarget->property()); \
169 } \
170 void QQuickLayoutItemProxy::proxy##Property##Changed() { \
171 Q_D(QQuickLayoutItemProxy); \
172 if (d->m_expectProxy##Property##Change) { \
173 d->m_expectProxy##Property##Change = false; \
174 return; \
175 } \
176 QQuickLayoutAttached *attTarget = attachedLayoutObject(target(), false); \
177 if (!attTarget) return; \
178 disconnect(attTarget, &QQuickLayoutAttached::property##Changed, this, &QQuickLayoutItemProxy::target##Property##Changed); \
179 }
180
181propertyForwarding(minimumWidth, MinimumWidth)
182propertyForwarding(minimumHeight, MinimumHeight)
183propertyForwarding(preferredWidth, PreferredWidth)
184propertyForwarding(preferredHeight, PreferredHeight)
185propertyForwarding(maximumWidth, MaximumWidth)
186propertyForwarding(maximumHeight, MaximumHeight)
187propertyForwarding(fillWidth, FillWidth)
188propertyForwarding(fillHeight, FillHeight)
190propertyForwarding(horizontalStretchFactor, HorizontalStretchFactor)
191propertyForwarding(verticalStretchFactor, VerticalStretchFactor)
192propertyForwarding(margins, Margins)
193propertyForwarding(leftMargin, LeftMargin)
194propertyForwarding(topMargin, TopMargin)
195propertyForwarding(rightMargin, RightMargin)
196propertyForwarding(bottomMargin, BottomMargin)
197
198#undef propertyForwarding
199
212{
213 Q_D(const QQuickLayoutItemProxy);
214 return d->target;
215}
216
226{
228
229 if (newTarget == d->target)
230 return;
231
232 d->target = newTarget;
233
234 if (newTarget) {
235
237 if (newTarget->property("QQuickLayoutItemProxyAttachedData").isValid()) {
238 attachedData = newTarget->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>();
239 } else {
240 attachedData = new QQuickLayoutItemProxyAttachedData(newTarget);
241 QVariant v;
242 v.setValue(attachedData);
243 newTarget->setProperty("QQuickLayoutItemProxyAttachedData", v);
244 }
245 attachedData->registerProxy(this);
246
247 // If there is no other controlling proxy, we will hide the target
248 if (!attachedData->proxyHasControl())
249 newTarget->setVisible(false);
250 // We are calling maybeTakeControl at the end to eventually take
251 // responsibility of showing the target.
252
253 if (QQuickLayoutAttached *attTarget = attachedLayoutObject(newTarget)) {
254 QQuickLayoutAttached *attProxy = attachedLayoutObject(this, true);
255
256 disconnect(attTarget, nullptr, attProxy, nullptr);
257
258 // bind item-specific layout properties:
259
260#define connectPropertyForwarding(property, Property) \
261 if (!attProxy->is##Property##Set()) { \
262 connect(attTarget, &QQuickLayoutAttached::property##Changed, this, &QQuickLayoutItemProxy::target##Property##Changed); \
263 connect(attProxy, &QQuickLayoutAttached::property##Changed, this, &QQuickLayoutItemProxy::proxy##Property##Changed); \
264 target##Property##Changed(); \
265 }
266 connectPropertyForwarding(minimumWidth, MinimumWidth)
267 connectPropertyForwarding(minimumHeight, MinimumHeight)
268 connectPropertyForwarding(preferredWidth, PreferredWidth)
269 connectPropertyForwarding(preferredHeight, PreferredHeight)
270 connectPropertyForwarding(maximumWidth, MaximumWidth)
271 connectPropertyForwarding(maximumHeight, MaximumHeight)
272 connectPropertyForwarding(fillWidth, FillWidth)
273 connectPropertyForwarding(fillHeight, FillHeight)
275 connectPropertyForwarding(horizontalStretchFactor, HorizontalStretchFactor)
276 connectPropertyForwarding(verticalStretchFactor, VerticalStretchFactor)
277 connectPropertyForwarding(margins, Margins)
278 connectPropertyForwarding(leftMargin, LeftMargin)
279 connectPropertyForwarding(topMargin, TopMargin)
280 connectPropertyForwarding(rightMargin, RightMargin)
281 connectPropertyForwarding(bottomMargin, BottomMargin)
282#undef connectPropertyForwarding
283
284 // proxy.implicitWidth: target.implicitWidth
285 auto fnBindImplW = [newTarget, this](){ this->setImplicitWidth(newTarget->implicitWidth()); };
286 fnBindImplW();
287 connect(newTarget, &QQuickItem::implicitWidthChanged, fnBindImplW);
288
289 // proxy.implicitHeight: target.implicitHeight
290 auto fnBindImplH = [newTarget, this](){ this->setImplicitHeight(newTarget->implicitHeight()); };
291 fnBindImplH();
292 connect(newTarget, &QQuickItem::implicitHeightChanged, fnBindImplH);
293 }
294 }
295
296 if (isVisible())
298
299 emit targetChanged();
300}
301
307{
308 if (target() == nullptr)
309 return nullptr;
310
311 QQuickLayoutItemProxyAttachedData * attachedData = target()->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>();
312 return (attachedData->getControllingProxy() == this) ? target() : nullptr;
313}
314
322{
323 setTarget(nullptr);
324}
325
336{
338 if (!d->target)
339 return;
340
341 QQuickLayoutItemProxyAttachedData * attachedData = d->target->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>();
342 if (isVisible() && attachedData->getControllingProxy() != this) {
343 if (attachedData->takeControl(this)) {
344 d->target->setVisible(true);
345 d->target->setParentItem(this);
346 updatePos();
347 }
348 }
349 if (!isVisible() && attachedData->getControllingProxy() == this){
350 if (d->target->parentItem() == this) {
351 d->target->setParentItem(nullptr);
352 } else
353 qCDebug(lcLayouts) << "Parent was changed to" << d->target->parentItem() << "while an ItemProxy had control";
354 d->target->setVisible(false);
355 attachedData->releaseControl(this);
356 }
357}
358
364{
365 if (!isVisible())
366 return;
367 if (target()) {
368 if (QQuickLayoutItemProxyAttachedData * attachedData = target()->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>()) {
369 if (attachedData->getControllingProxy() == this)
371 }
372 }
373}
374
377 m_expectProxyMinimumWidthChange(false),
378 m_expectProxyMinimumHeightChange(false),
379 m_expectProxyPreferredWidthChange(false),
380 m_expectProxyPreferredHeightChange(false),
381 m_expectProxyMaximumWidthChange(false),
382 m_expectProxyMaximumHeightChange(false),
383 m_expectProxyFillWidthChange(false),
384 m_expectProxyFillHeightChange(false),
385 m_expectProxyAlignmentChange(false),
386 m_expectProxyHorizontalStretchFactorChange(false),
387 m_expectProxyVerticalStretchFactorChange(false),
388 m_expectProxyMarginsChange(false),
389 m_expectProxyLeftMarginChange(false),
390 m_expectProxyTopMarginChange(false),
391 m_expectProxyRightMarginChange(false),
392 m_expectProxyBottomMarginChange(false)
393{
394
395}
396
407 : QObject(parent), controllingProxy(nullptr)
408{
409
410}
411
413{
414 // If this is destroyed, so is the target. Clear the target from the
415 // proxies so they do not try to access a destroyed object
416 for (auto &proxy: std::as_const(proxies))
417 proxy->clearTarget();
418}
419
428{
429 if (proxies.contains(proxy))
430 return;
431
432 proxies.append(proxy);
434}
435
441{
442 if (proxy == controllingProxy)
444
445 proxies.removeAll(proxy);
446
447 if (proxies.isEmpty())
448 deleteLater();
449
451}
452
463{
464 if (controllingProxy || !proxies.contains(proxy))
465 return false;
466
467 qCDebug(lcLayouts) << proxy
468 << "takes control of"
469 << parent();
470
474 return true;
475}
476
484{
485 if (controllingProxy != proxy)
486 return;
487
488 qCDebug(lcLayouts) << proxy
489 << "no longer controls"
490 << parent();
491
492 controllingProxy = nullptr;
495
496 for (auto &otherProxy: std::as_const(proxies)) {
497 if (proxy != otherProxy)
498 otherProxy->maybeTakeControl();
499 }
500}
501
508{
509 return controllingProxy;
510}
511
517{
518 return proxies;
519}
520
526{
527 return controllingProxy != nullptr;
528}
Definition qlist.h:74
\inmodule QtCore
Definition qobject.h:90
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:311
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
QVariant property(const char *name) const
Returns the value of the object's name property.
Definition qobject.cpp:4187
bool setProperty(const char *name, const QVariant &value)
Sets the value of the object's name property to value.
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
\inmodule QtCore\reentrant
Definition qpoint.h:214
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
qreal implicitWidth
Definition qquickitem.h:113
void implicitWidthChanged()
void implicitHeightChanged()
bool isVisible() const
virtual QRectF boundingRect() const
Returns the extents of the item in its own coordinate system: a rectangle from {0,...
void setVisible(bool)
virtual void itemChange(ItemChange, const ItemChangeData &)
Called when change occurs for this item.
qreal implicitHeight
Definition qquickitem.h:114
void setImplicitHeight(qreal)
ItemChange
Used in conjunction with QQuickItem::itemChange() to notify the item about certain types of changes.
Definition qquickitem.h:143
@ ItemVisibleHasChanged
Definition qquickitem.h:147
void setImplicitWidth(qreal)
Provides attached properties for items that are managed by one or more LayoutItemProxy.
void registerProxy(QQuickLayoutItemProxy *proxy)
QQuickLayoutItemProxyAttachedData::registerProxy registers a proxy that manages the item this data is...
void releaseControl(QQuickLayoutItemProxy *proxy)
QQuickLayoutItemProxyAttachedData::releaseControl is called by LayoutItemProxies when they try no lon...
QList< QQuickLayoutItemProxy * > proxies
bool takeControl(QQuickLayoutItemProxy *proxy)
QQuickLayoutItemProxyAttachedData::takeControl is called by LayoutItemProxies when they try to take c...
void releaseProxy(QQuickLayoutItemProxy *proxy)
QQuickLayoutItemProxyAttachedData::releaseProxy removes a proxy from a list of known proxies that man...
const QList< QQuickLayoutItemProxy * > & getProxies() const
QQuickLayoutItemProxyAttachedData::getProxies.
QQuickLayoutItemProxy * getControllingProxy() const
QQuickLayoutItemProxyAttachedData::getControllingProxy.
void clearTarget()
QQuickLayoutItemProxy::clearTarget sets the target to null.
void setTarget(QQuickItem *newTarget)
QQuickLayoutItemProxy::setTarget sets the target.
void geometryChange(const QRectF &newGeom, const QRectF &oldGeom) override
QQuickLayoutItemProxy::geometryChange Reimplementation of QQuickItem::geometryChange to update the ta...
void itemChange(ItemChange c, const ItemChangeData &d) override
QQuickLayoutItemProxy::itemChange is a reimplementation of QQuickItem::itemChange to react to changes...
void maybeTakeControl()
QQuickLayoutItemProxy::maybeTakeControl checks and takes over control of the item.
void updatePos()
QQuickLayoutItemProxy::updatePos sets the geometry of the target to the geometry of the proxy.
Q_INVOKABLE QQuickItem * effectiveTarget() const
QQuickLayoutItemProxy::effectiveTarget.
\inmodule QtCore\reentrant
Definition qrect.h:483
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:721
\inmodule QtCore
Definition qsize.h:207
\inmodule QtCore
Definition qvariant.h:64
T value() const &
Definition qvariant.h:511
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
uint alignment
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLsizei const GLfloat * v
[13]
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
QQuickLayoutAttached * attachedLayoutObject(QQuickItem *item, bool create=true)
#define connectPropertyForwarding(property, Property)
#define propertyForwarding(property, Property)
#define emit
const char property[13]
Definition qwizard.cpp:101
QObject::connect nullptr
myObject disconnect()
[26]
QNetworkProxy proxy
[0]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent
\inmodule QtQuick
Definition qquickitem.h:158