Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
76Q_LOGGING_CATEGORY(lcLayouts, "qt.quick.layouts")
77
78
84
86{
88
89 if (!d->target)
90 return;
91
92 QQuickLayoutItemProxyAttachedData * attachedData = d->target->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>();
93 // De-register this proxy from the proxies controlling the target
94 if (attachedData) {
95 if (attachedData->getControllingProxy() == this) {
96 attachedData->releaseControl(this);
97 d->target->setParentItem(nullptr);
98 }
99 attachedData->releaseProxy(this);
100 }
101 // The target item still has a QObject parent that takes care of its destrctuion.
102 // No need to invoke destruction of the target tiem from here.
103}
104
109void QQuickLayoutItemProxy::geometryChange(const QRectF &newGeom, const QRectF &oldGeom)
110{
111 QQuickItem::geometryChange(newGeom, oldGeom);
112 if (!isVisible())
113 return;
114
115 const QSizeF sz = newGeom.size();
116 QPointF pos(0., 0.);
117
118 if (QQuickItem *t = effectiveTarget()) {
119 if (QQuickLayoutItemProxyAttachedData * attachedData = target()->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>()) {
120 if (attachedData->getControllingProxy() != this)
121 return;
122 }
123
124 // Should normally not be the case, except the user resets the parent
125 // This is a failsave for this case and positions the item correctly
126 if (t->parentItem() != this)
127 pos = t->parentItem()->mapFromGlobal(mapToGlobal(0, 0));
128
129 if (t->size() == sz && t->position() == pos && newGeom == oldGeom)
130 return;
131
132 t->setSize(sz);
133 t->setPosition(pos);
134 }
135}
136
149
150// Implementation of the slots to react to changes of the Layout attached properties.
151// If the target Layout propertie change, we change the proxy Layout properties accordingly
152// If the proxy Layout properties have been changed externally, we want to remove this binding.
153// The member variables m_expectProxy##Property##Change help us keep track about who invokes
154// the change of the parameter. If it is invoked by the target we expect a proxy property
155// change and will not remove the connection.
156#define propertyForwarding(property, Property) \
157 void QQuickLayoutItemProxy::target##Property##Changed() { \
158 Q_D(QQuickLayoutItemProxy); \
159 QQuickLayoutAttached *attTarget = attachedLayoutObject(target(), false); \
160 QQuickLayoutAttached *attProxy = attachedLayoutObject(this, false); \
161 if (!attTarget) return; \
162 if (attProxy->property() == attTarget->property()) \
163 return; \
164 d->m_expectProxy##Property##Change = true; \
165 attProxy->set##Property(attTarget->property()); \
166 } \
167 void QQuickLayoutItemProxy::proxy##Property##Changed() { \
168 Q_D(QQuickLayoutItemProxy); \
169 if (d->m_expectProxy##Property##Change) { \
170 d->m_expectProxy##Property##Change = false; \
171 return; \
172 } \
173 QQuickLayoutAttached *attTarget = attachedLayoutObject(target(), false); \
174 if (!attTarget) return; \
175 disconnect(attTarget, &QQuickLayoutAttached::property##Changed, this, &QQuickLayoutItemProxy::target##Property##Changed); \
176 }
177
178propertyForwarding(minimumWidth, MinimumWidth)
179propertyForwarding(minimumHeight, MinimumHeight)
180propertyForwarding(preferredWidth, PreferredWidth)
181propertyForwarding(preferredHeight, PreferredHeight)
182propertyForwarding(maximumWidth, MaximumWidth)
183propertyForwarding(maximumHeight, MaximumHeight)
184propertyForwarding(fillWidth, FillWidth)
185propertyForwarding(fillHeight, FillHeight)
187propertyForwarding(horizontalStretchFactor, HorizontalStretchFactor)
188propertyForwarding(verticalStretchFactor, VerticalStretchFactor)
189propertyForwarding(margins, Margins)
190propertyForwarding(leftMargin, LeftMargin)
191propertyForwarding(topMargin, TopMargin)
192propertyForwarding(rightMargin, RightMargin)
193propertyForwarding(bottomMargin, BottomMargin)
194
195#undef propertyForwarding
196
209{
210 Q_D(const QQuickLayoutItemProxy);
211 return d->target;
212}
213
223{
225
226 if (newTarget == d->target)
227 return;
228
229 d->target = newTarget;
230
231 if (newTarget) {
232
234 if (newTarget->property("QQuickLayoutItemProxyAttachedData").isValid()) {
235 attachedData = newTarget->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>();
236 } else {
237 attachedData = new QQuickLayoutItemProxyAttachedData(newTarget);
238 QVariant v;
239 v.setValue(attachedData);
240 newTarget->setProperty("QQuickLayoutItemProxyAttachedData", v);
241 }
242 attachedData->registerProxy(this);
243
244 // If there is no other controlling proxy, we will hide the target
245 if (!attachedData->proxyHasControl())
246 newTarget->setVisible(false);
247 // We are calling maybeTakeControl at the end to eventually take
248 // responsibility of showing the target.
249
250 if (QQuickLayoutAttached *attTarget = attachedLayoutObject(newTarget)) {
251 QQuickLayoutAttached *attProxy = attachedLayoutObject(this, true);
252
253 disconnect(attTarget, nullptr, attProxy, nullptr);
254
255 // bind item-specific layout properties:
256
257#define connectPropertyForwarding(property, Property) \
258 if (!attProxy->is##Property##Set()) { \
259 connect(attTarget, &QQuickLayoutAttached::property##Changed, this, &QQuickLayoutItemProxy::target##Property##Changed); \
260 connect(attProxy, &QQuickLayoutAttached::property##Changed, this, &QQuickLayoutItemProxy::proxy##Property##Changed); \
261 target##Property##Changed(); \
262 }
263 connectPropertyForwarding(minimumWidth, MinimumWidth)
264 connectPropertyForwarding(minimumHeight, MinimumHeight)
265 connectPropertyForwarding(preferredWidth, PreferredWidth)
266 connectPropertyForwarding(preferredHeight, PreferredHeight)
267 connectPropertyForwarding(maximumWidth, MaximumWidth)
268 connectPropertyForwarding(maximumHeight, MaximumHeight)
269 connectPropertyForwarding(fillWidth, FillWidth)
270 connectPropertyForwarding(fillHeight, FillHeight)
272 connectPropertyForwarding(horizontalStretchFactor, HorizontalStretchFactor)
273 connectPropertyForwarding(verticalStretchFactor, VerticalStretchFactor)
274 connectPropertyForwarding(margins, Margins)
275 connectPropertyForwarding(leftMargin, LeftMargin)
276 connectPropertyForwarding(topMargin, TopMargin)
277 connectPropertyForwarding(rightMargin, RightMargin)
278 connectPropertyForwarding(bottomMargin, BottomMargin)
279#undef connectPropertyForwarding
280
281 // proxy.implicitWidth: target.implicitWidth
282 auto fnBindImplW = [newTarget, this](){ this->setImplicitWidth(newTarget->implicitWidth()); };
283 fnBindImplW();
284 connect(newTarget, &QQuickItem::implicitWidthChanged, fnBindImplW);
285
286 // proxy.implicitHeight: target.implicitHeight
287 auto fnBindImplH = [newTarget, this](){ this->setImplicitHeight(newTarget->implicitHeight()); };
288 fnBindImplH();
289 connect(newTarget, &QQuickItem::implicitHeightChanged, fnBindImplH);
290 }
291 }
292
293 if (isVisible())
295
296 emit targetChanged();
297}
298
304{
305 if (target() == nullptr)
306 return nullptr;
307
308 QQuickLayoutItemProxyAttachedData * attachedData = target()->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>();
309 return (attachedData->getControllingProxy() == this) ? target() : nullptr;
310}
311
319{
320 setTarget(nullptr);
321}
322
333{
335 if (!d->target)
336 return;
337
338 QQuickLayoutItemProxyAttachedData * attachedData = d->target->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>();
339 if (isVisible() && attachedData->getControllingProxy() != this) {
340 if (attachedData->takeControl(this)) {
341 d->target->setVisible(true);
342 d->target->setParentItem(this);
343 updatePos();
344 }
345 }
346 if (!isVisible() && attachedData->getControllingProxy() == this){
347 if (d->target->parentItem() == this) {
348 d->target->setParentItem(nullptr);
349 } else
350 qCDebug(lcLayouts) << "Parent was changed to" << d->target->parentItem() << "while an ItemProxy had control";
351 d->target->setVisible(false);
352 attachedData->releaseControl(this);
353 }
354}
355
361{
362 if (!isVisible())
363 return;
364 if (target()) {
365 if (QQuickLayoutItemProxyAttachedData * attachedData = target()->property("QQuickLayoutItemProxyAttachedData").value<QQuickLayoutItemProxyAttachedData*>()) {
366 if (attachedData->getControllingProxy() == this)
368 }
369 }
370}
371
374 m_expectProxyMinimumWidthChange(false),
375 m_expectProxyMinimumHeightChange(false),
376 m_expectProxyPreferredWidthChange(false),
377 m_expectProxyPreferredHeightChange(false),
378 m_expectProxyMaximumWidthChange(false),
379 m_expectProxyMaximumHeightChange(false),
380 m_expectProxyFillWidthChange(false),
381 m_expectProxyFillHeightChange(false),
382 m_expectProxyAlignmentChange(false),
383 m_expectProxyHorizontalStretchFactorChange(false),
384 m_expectProxyVerticalStretchFactorChange(false),
385 m_expectProxyMarginsChange(false),
386 m_expectProxyLeftMarginChange(false),
387 m_expectProxyTopMarginChange(false),
388 m_expectProxyRightMarginChange(false),
389 m_expectProxyBottomMarginChange(false)
390{
391
392}
393
408
410{
411 // If this is destroyed, so is the target. Clear the target from the
412 // proxies so they do not try to access a destroyed object
413 for (auto &proxy: std::as_const(proxies))
414 proxy->clearTarget();
415}
416
425{
426 if (proxies.contains(proxy))
427 return;
428
429 proxies.append(proxy);
431}
432
449
460{
461 if (controllingProxy || !proxies.contains(proxy))
462 return false;
463
464 qCDebug(lcLayouts) << proxy
465 << "takes control of"
466 << parent();
467
471 return true;
472}
473
481{
482 if (controllingProxy != proxy)
483 return;
484
485 qCDebug(lcLayouts) << proxy
486 << "no longer controls"
487 << parent();
488
489 controllingProxy = nullptr;
492
493 for (auto &otherProxy: std::as_const(proxies)) {
494 if (proxy != otherProxy)
495 otherProxy->maybeTakeControl();
496 }
497}
498
508
513QQmlListProperty<QQuickLayoutItemProxy> QQuickLayoutItemProxyAttachedData::getProxies()
514{
516 using Property = QQmlListProperty<Type>;
517
518 return Property(
519 this, &proxies,
520 [](Property *p) { return static_cast<QList<Type *> *>(p->data)->size(); },
521 [](Property *p, qsizetype i) { return static_cast<QList<Type *> *>(p->data)->at(i); }
522 );
523}
524
530{
531 return controllingProxy != nullptr;
532}
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
QVariant property(const char *name) const
Returns the value of the object's name property.
Definition qobject.cpp:4323
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:2435
\inmodule QtCore\reentrant
Definition qpoint.h:217
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
qreal implicitWidth
Definition qquickitem.h:114
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:115
void setImplicitHeight(qreal)
ItemChange
Used in conjunction with QQuickItem::itemChange() to notify the item about certain types of changes.
Definition qquickitem.h:144
@ ItemVisibleHasChanged
Definition qquickitem.h:148
void setImplicitWidth(qreal)
Provides attached properties for items that are managed by one or more LayoutItemProxy.
QQmlListProperty< QQuickLayoutItemProxy > getProxies()
QQuickLayoutItemProxyAttachedData::getProxies.
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...
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...
QQmlListProperty< QQuickLayoutItemProxy > proxies
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:484
\inmodule QtCore
Definition qsize.h:208
\inmodule QtCore
Definition qvariant.h:65
T value() const &
Definition qvariant.h:516
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
void setValue(T &&avalue)
Definition qvariant.h:493
uint alignment
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLsizei const GLfloat * v
[13]
GLenum GLuint GLintptr GLsizeiptr size
[1]
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLfloat GLfloat p
[1]
QQuickLayoutAttached * attachedLayoutObject(QQuickItem *item, bool create=true)
#define connectPropertyForwarding(property, Property)
#define propertyForwarding(property, Property)
#define emit
ptrdiff_t qsizetype
Definition qtypes.h:165
const char property[13]
Definition qwizard.cpp:101
QObject::connect nullptr
myObject disconnect()
[26]
QAction * at
QNetworkProxy proxy
[0]
Definition moc.h:23
\inmodule QtQuick
Definition qquickitem.h:159