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 |
3 | #include "qquicklayoutitemproxy_p.h" |
4 | #include "qquicklayout_p.h" |
5 | |
6 | /*! |
7 | \qmltype LayoutItemProxy |
8 | \nativetype QQuickLayoutItemProxy |
9 | \inherits Item |
10 | \inqmlmodule QtQuick.Layouts |
11 | \ingroup layouts |
12 | \since QtQuick.Layouts 6.6 |
13 | \brief The LayoutItemProxy class provides a placeholder for \l{QQuickItem}s |
14 | in layouts. |
15 | |
16 | Some responsive layouts require different layout hierarchies for different |
17 | screen sizes, but the layout hierarchy is the same as the QML structure and |
18 | can therefore not be changed at runtime. LayoutItemProxy overcomes this |
19 | limitation by representing a \l{target} item within the layout. The |
20 | \l{target} item itself can be defined anywhere in the QML hierarchy. This |
21 | allows declaration of multiple layouts with the same content items. The |
22 | layouts can be shown and hidden to switch between them. |
23 | |
24 | The LayoutItemProxy will try to take control of the \l{target} item if it |
25 | is \l [QML] {Item::}{visible}. Taking control will position and resize the |
26 | \l{target} item to match the position and size of the LayoutItemProxy. |
27 | Further, the LayoutItemProxy will set itself as the parent of the |
28 | \l{target} (to ensure event delivery and useful drawing order) and set the |
29 | visibility to \c true. Multiple LayoutItemProxies can \l{target} the same |
30 | item, but only one LayoutItemProxy can control an item at a time. Therefore |
31 | only one of the proxies targeting the same item should be visible at a |
32 | time. If multiple proxies target the same item but \e visible is set to |
33 | false for each proxy, the item will also be invisible. |
34 | |
35 | All \l{Layout} attached properties of the \l {target}, as well as the |
36 | \l{QQuickItem::implicitWidth} and \l{QQuickItem::implicitHeight} of the |
37 | \l{target} are forwarded by the LayoutItemProxy. The LayoutItemProxy will |
38 | mimic the \l{target} as closely as possible in terms of \l{Layout} |
39 | properties and size. \l{Layout} attached properties can also be set |
40 | explicitly on the LayoutItemProxy which will stop the forwarding of the |
41 | \l {target} properties. |
42 | |
43 | \section1 Example Usage |
44 | |
45 | This is a minimalistic example, changing between two layouts using proxies |
46 | to use the same items in both layouts. The items that populate the layouts |
47 | can be defined at an arbitrary point in the QML structure. |
48 | |
49 | \snippet layouts/simpleProxy.qml item definition |
50 | |
51 | Then we can define the Layouts with LayoutItemProxys |
52 | |
53 | \snippet layouts/simpleProxy.qml layout definition |
54 | |
55 | We can switch now between the layouts, depending on a criterion of our |
56 | choice by toggling the visibility of the layouts on and off. |
57 | |
58 | \snippet layouts/simpleProxy.qml layout choice |
59 | |
60 | The two resulting layouts look like this: |
61 | |
62 | \div {class="float-right"} |
63 | \inlineimage simpleProxy.png |
64 | \enddiv |
65 | |
66 | The LayoutItemProxy can also be used without layouts, e.g. by anchoring it |
67 | to different items. A mix of real \l {Item}{Items} and proxy items is |
68 | equally possible, as well as nested structures of layouts and items. |
69 | |
70 | \warning The LayoutItemProxy will set the parent of its target to itself. |
71 | Keep this in mind when referring to the parent of the target item. |
72 | |
73 | \sa Item, GridLayout, RowLayout, ColumnLayout |
74 | */ |
75 | |
76 | Q_LOGGING_CATEGORY(lcLayouts, "qt.quick.layouts" ) |
77 | |
78 | |
79 | QQuickLayoutItemProxy::QQuickLayoutItemProxy(QQuickItem *parent) |
80 | : QQuickItem(*new QQuickLayoutItemProxyPrivate, parent) |
81 | { |
82 | |
83 | } |
84 | |
85 | QQuickLayoutItemProxy::~QQuickLayoutItemProxy() |
86 | { |
87 | Q_D(QQuickLayoutItemProxy); |
88 | |
89 | if (!d->target) |
90 | return; |
91 | |
92 | QQuickLayoutItemProxyAttachedData * attachedData = d->target->property(name: "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(proxy: this); |
97 | d->target->setParentItem(nullptr); |
98 | } |
99 | attachedData->releaseProxy(proxy: 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 | |
105 | /*! \internal |
106 | \brief QQuickLayoutItemProxy::geometryChange Reimplementation of |
107 | QQuickItem::geometryChange to update the target geometry too. |
108 | */ |
109 | void QQuickLayoutItemProxy::geometryChange(const QRectF &newGeom, const QRectF &oldGeom) |
110 | { |
111 | QQuickItem::geometryChange(newGeometry: newGeom, oldGeometry: 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(name: "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(point: mapToGlobal(x: 0, y: 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 | |
137 | /*! \internal |
138 | \brief QQuickLayoutItemProxy::itemChange is a reimplementation of |
139 | QQuickItem::itemChange to react to changes in visibility. |
140 | */ |
141 | void QQuickLayoutItemProxy::itemChange(ItemChange c, const ItemChangeData &d) |
142 | { |
143 | if (c == QQuickItem::ItemVisibleHasChanged) |
144 | { |
145 | maybeTakeControl(); |
146 | } |
147 | QQuickItem::itemChange(c, d); |
148 | } |
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 | |
178 | propertyForwarding(minimumWidth, MinimumWidth) |
179 | propertyForwarding(minimumHeight, MinimumHeight) |
180 | propertyForwarding(preferredWidth, PreferredWidth) |
181 | propertyForwarding(preferredHeight, PreferredHeight) |
182 | propertyForwarding(maximumWidth, MaximumWidth) |
183 | propertyForwarding(maximumHeight, MaximumHeight) |
184 | propertyForwarding(fillWidth, FillWidth) |
185 | propertyForwarding(fillHeight, FillHeight) |
186 | propertyForwarding(alignment, Alignment) |
187 | propertyForwarding(horizontalStretchFactor, HorizontalStretchFactor) |
188 | propertyForwarding(verticalStretchFactor, VerticalStretchFactor) |
189 | propertyForwarding(margins, Margins) |
190 | propertyForwarding(leftMargin, LeftMargin) |
191 | propertyForwarding(topMargin, TopMargin) |
192 | propertyForwarding(rightMargin, RightMargin) |
193 | propertyForwarding(bottomMargin, BottomMargin) |
194 | |
195 | #undef propertyForwarding |
196 | |
197 | /*! |
198 | \qmlproperty Item LayoutItemProxy::target |
199 | |
200 | This property holds the \l Item that the proxy should represent in a |
201 | \l {Layout} hierarchy. |
202 | */ |
203 | |
204 | /*! \internal |
205 | \brief QQuickLayoutItemProxy::target |
206 | \return The target item of the proxy |
207 | */ |
208 | QQuickItem *QQuickLayoutItemProxy::target() const |
209 | { |
210 | Q_D(const QQuickLayoutItemProxy); |
211 | return d->target; |
212 | } |
213 | |
214 | /*! \internal |
215 | \brief QQuickLayoutItemProxy::setTarget sets the target |
216 | \param newTarget The item that the proxy stands in place for. |
217 | |
218 | All layout properties of the target are connected to the layout properties |
219 | of the LayoutItemProxy. It the LayoutItemProxy is visible, it will try to |
220 | take control of the target. |
221 | */ |
222 | void QQuickLayoutItemProxy::setTarget(QQuickItem *newTarget) |
223 | { |
224 | Q_D(QQuickLayoutItemProxy); |
225 | |
226 | if (newTarget == d->target) |
227 | return; |
228 | |
229 | if (d->target && d->target->property(name: "QQuickLayoutItemProxyAttachedData" ).isValid()) { |
230 | QQuickLayoutItemProxyAttachedData *attachedData = d->target->property(name: "QQuickLayoutItemProxyAttachedData" ).value<QQuickLayoutItemProxyAttachedData*>(); |
231 | attachedData->releaseProxy(proxy: this); |
232 | } |
233 | d->target = newTarget; |
234 | |
235 | if (newTarget) { |
236 | |
237 | QQuickLayoutItemProxyAttachedData *attachedData; |
238 | if (newTarget->property(name: "QQuickLayoutItemProxyAttachedData" ).isValid()) { |
239 | attachedData = newTarget->property(name: "QQuickLayoutItemProxyAttachedData" ).value<QQuickLayoutItemProxyAttachedData*>(); |
240 | } else { |
241 | attachedData = new QQuickLayoutItemProxyAttachedData(newTarget); |
242 | QVariant v; |
243 | v.setValue(attachedData); |
244 | newTarget->setProperty(name: "QQuickLayoutItemProxyAttachedData" , value: v); |
245 | } |
246 | attachedData->registerProxy(proxy: this); |
247 | |
248 | // If there is no other controlling proxy, we will hide the target |
249 | if (!attachedData->proxyHasControl()) |
250 | newTarget->setVisible(false); |
251 | // We are calling maybeTakeControl at the end to eventually take |
252 | // responsibility of showing the target. |
253 | |
254 | if (QQuickLayoutAttached *attTarget = attachedLayoutObject(item: newTarget)) { |
255 | QQuickLayoutAttached *attProxy = attachedLayoutObject(item: this, create: true); |
256 | |
257 | disconnect(sender: attTarget, signal: nullptr, receiver: attProxy, member: nullptr); |
258 | |
259 | // bind item-specific layout properties: |
260 | |
261 | #define connectPropertyForwarding(property, Property) \ |
262 | if (!attProxy->is##Property##Set()) { \ |
263 | connect(attTarget, &QQuickLayoutAttached::property##Changed, this, &QQuickLayoutItemProxy::target##Property##Changed); \ |
264 | connect(attProxy, &QQuickLayoutAttached::property##Changed, this, &QQuickLayoutItemProxy::proxy##Property##Changed); \ |
265 | target##Property##Changed(); \ |
266 | } |
267 | connectPropertyForwarding(minimumWidth, MinimumWidth) |
268 | connectPropertyForwarding(minimumHeight, MinimumHeight) |
269 | connectPropertyForwarding(preferredWidth, PreferredWidth) |
270 | connectPropertyForwarding(preferredHeight, PreferredHeight) |
271 | connectPropertyForwarding(maximumWidth, MaximumWidth) |
272 | connectPropertyForwarding(maximumHeight, MaximumHeight) |
273 | connectPropertyForwarding(fillWidth, FillWidth) |
274 | connectPropertyForwarding(fillHeight, FillHeight) |
275 | connectPropertyForwarding(alignment, Alignment) |
276 | connectPropertyForwarding(horizontalStretchFactor, HorizontalStretchFactor) |
277 | connectPropertyForwarding(verticalStretchFactor, VerticalStretchFactor) |
278 | connectPropertyForwarding(margins, Margins) |
279 | connectPropertyForwarding(leftMargin, LeftMargin) |
280 | connectPropertyForwarding(topMargin, TopMargin) |
281 | connectPropertyForwarding(rightMargin, RightMargin) |
282 | connectPropertyForwarding(bottomMargin, BottomMargin) |
283 | #undef connectPropertyForwarding |
284 | |
285 | // proxy.implicitWidth: target.implicitWidth |
286 | auto fnBindImplW = [newTarget, this](){ this->setImplicitWidth(newTarget->implicitWidth()); }; |
287 | fnBindImplW(); |
288 | connect(sender: newTarget, signal: &QQuickItem::implicitWidthChanged, slot&: fnBindImplW); |
289 | |
290 | // proxy.implicitHeight: target.implicitHeight |
291 | auto fnBindImplH = [newTarget, this](){ this->setImplicitHeight(newTarget->implicitHeight()); }; |
292 | fnBindImplH(); |
293 | connect(sender: newTarget, signal: &QQuickItem::implicitHeightChanged, slot&: fnBindImplH); |
294 | } |
295 | } |
296 | |
297 | if (isVisible()) |
298 | maybeTakeControl(); |
299 | |
300 | emit targetChanged(); |
301 | } |
302 | |
303 | /*! \internal |
304 | \brief QQuickLayoutItemProxy::effectiveTarget |
305 | \return The target item of the proxy if it is in control, \c null otherwise. |
306 | */ |
307 | QQuickItem *QQuickLayoutItemProxy::effectiveTarget() const |
308 | { |
309 | if (target() == nullptr) |
310 | return nullptr; |
311 | |
312 | QQuickLayoutItemProxyAttachedData * attachedData = target()->property(name: "QQuickLayoutItemProxyAttachedData" ).value<QQuickLayoutItemProxyAttachedData*>(); |
313 | return (attachedData->getControllingProxy() == this) ? target() : nullptr; |
314 | } |
315 | |
316 | /*! \internal |
317 | \brief QQuickLayoutItemProxy::clearTarget sets the target to null. |
318 | |
319 | This function is called if the target is destroyed to make sure we do not |
320 | try to access a non-existing object. |
321 | */ |
322 | void QQuickLayoutItemProxy::clearTarget() |
323 | { |
324 | setTarget(nullptr); |
325 | } |
326 | |
327 | /*! \internal |
328 | \brief QQuickLayoutItemProxy::maybeTakeControl checks and takes over control |
329 | of the item. |
330 | |
331 | If the proxy is visible it will try to take control over the target and set |
332 | its visibility to true. If the proxy is hidden it will also hide the target |
333 | and another LayoutItemProxy has to set the visibility to \c true or the |
334 | target will stay invisible. |
335 | */ |
336 | void QQuickLayoutItemProxy::maybeTakeControl() |
337 | { |
338 | Q_D(QQuickLayoutItemProxy); |
339 | if (!d->target) |
340 | return; |
341 | |
342 | QQuickLayoutItemProxyAttachedData * attachedData = d->target->property(name: "QQuickLayoutItemProxyAttachedData" ).value<QQuickLayoutItemProxyAttachedData*>(); |
343 | if (isVisible() && attachedData->getControllingProxy() != this) { |
344 | if (attachedData->takeControl(proxy: this)) { |
345 | d->target->setVisible(true); |
346 | d->target->setParentItem(this); |
347 | updatePos(); |
348 | } |
349 | } |
350 | if (!isVisible() && attachedData->getControllingProxy() == this){ |
351 | if (d->target->parentItem() == this) { |
352 | d->target->setParentItem(nullptr); |
353 | } else |
354 | qCDebug(lcLayouts) << "Parent was changed to" << d->target->parentItem() << "while an ItemProxy had control" ; |
355 | d->target->setVisible(false); |
356 | attachedData->releaseControl(proxy: this); |
357 | } |
358 | } |
359 | |
360 | /*! \internal |
361 | \brief QQuickLayoutItemProxy::updatePos sets the geometry of the target to |
362 | the geometry of the proxy |
363 | */ |
364 | void QQuickLayoutItemProxy::updatePos() |
365 | { |
366 | if (!isVisible()) |
367 | return; |
368 | if (target()) { |
369 | if (QQuickLayoutItemProxyAttachedData * attachedData = target()->property(name: "QQuickLayoutItemProxyAttachedData" ).value<QQuickLayoutItemProxyAttachedData*>()) { |
370 | if (attachedData->getControllingProxy() == this) |
371 | geometryChange(newGeom: boundingRect(), oldGeom: boundingRect()); |
372 | } |
373 | } |
374 | } |
375 | |
376 | QQuickLayoutItemProxyPrivate::QQuickLayoutItemProxyPrivate() |
377 | : QQuickItemPrivate(), |
378 | m_expectProxyMinimumWidthChange(false), |
379 | m_expectProxyMinimumHeightChange(false), |
380 | m_expectProxyPreferredWidthChange(false), |
381 | m_expectProxyPreferredHeightChange(false), |
382 | m_expectProxyMaximumWidthChange(false), |
383 | m_expectProxyMaximumHeightChange(false), |
384 | m_expectProxyFillWidthChange(false), |
385 | m_expectProxyFillHeightChange(false), |
386 | m_expectProxyAlignmentChange(false), |
387 | m_expectProxyHorizontalStretchFactorChange(false), |
388 | m_expectProxyVerticalStretchFactorChange(false), |
389 | m_expectProxyMarginsChange(false), |
390 | m_expectProxyLeftMarginChange(false), |
391 | m_expectProxyTopMarginChange(false), |
392 | m_expectProxyRightMarginChange(false), |
393 | m_expectProxyBottomMarginChange(false) |
394 | { |
395 | |
396 | } |
397 | |
398 | /*! \internal |
399 | \class QQuickLayoutItemProxyAttachedData |
400 | \brief Provides attached properties for items that are managed by one or |
401 | more LayoutItemProxy. |
402 | |
403 | It stores all proxies that target the item, and will emit signals when the |
404 | proxies or the controlling proxy changes. Proxies can listen to the signal |
405 | and pick up control if they wish to. |
406 | */ |
407 | QQuickLayoutItemProxyAttachedData::QQuickLayoutItemProxyAttachedData(QObject *parent) |
408 | : QObject(parent), controllingProxy(nullptr) |
409 | { |
410 | |
411 | } |
412 | |
413 | QQuickLayoutItemProxyAttachedData::~QQuickLayoutItemProxyAttachedData() |
414 | { |
415 | if (QObject *par = parent()) |
416 | par->setProperty(name: "QQuickLayoutItemProxyAttachedData" , value: QVariant()); |
417 | |
418 | // If this is destroyed, so is the target. Clear the target from the |
419 | // proxies so they do not try to access a destroyed object |
420 | for (auto &proxy: std::as_const(t&: proxies)) |
421 | proxy->clearTarget(); |
422 | } |
423 | |
424 | /*! \internal |
425 | \brief QQuickLayoutItemProxyAttachedData::registerProxy registers a proxy |
426 | that manages the item this data is attached to. |
427 | |
428 | This is required to easily notify proxies when the target is destroyed or |
429 | when it is free to take over control. |
430 | */ |
431 | void QQuickLayoutItemProxyAttachedData::registerProxy(QQuickLayoutItemProxy *proxy) |
432 | { |
433 | if (proxies.contains(t: proxy)) |
434 | return; |
435 | |
436 | proxies.append(t: proxy); |
437 | emit proxiesChanged(); |
438 | } |
439 | |
440 | /*! \internal |
441 | \brief QQuickLayoutItemProxyAttachedData::releaseProxy removes a proxy from |
442 | a list of known proxies that manage the item this data is attached to. |
443 | */ |
444 | void QQuickLayoutItemProxyAttachedData::releaseProxy(QQuickLayoutItemProxy *proxy) |
445 | { |
446 | if (proxy == controllingProxy) |
447 | releaseControl(proxy); |
448 | |
449 | proxies.removeAll(t: proxy); |
450 | |
451 | if (proxies.isEmpty()) |
452 | deleteLater(); |
453 | |
454 | emit proxiesChanged(); |
455 | } |
456 | |
457 | /*! \internal |
458 | \brief QQuickLayoutItemProxyAttachedData::takeControl is called by |
459 | LayoutItemProxies when they try to take control over the item this data is |
460 | attached to. |
461 | \return \c true if no other proxy controls the item and if control is |
462 | granted to the proxy, \c false otherwise. |
463 | |
464 | \param proxy The proxy that tries to take control. |
465 | */ |
466 | bool QQuickLayoutItemProxyAttachedData::takeControl(QQuickLayoutItemProxy *proxy) |
467 | { |
468 | if (controllingProxy || !proxies.contains(t: proxy)) |
469 | return false; |
470 | |
471 | qCDebug(lcLayouts) << proxy |
472 | << "takes control of" |
473 | << parent(); |
474 | |
475 | controllingProxy = proxy; |
476 | emit controlTaken(); |
477 | emit controllingProxyChanged(); |
478 | return true; |
479 | } |
480 | |
481 | /*! \internal |
482 | \brief QQuickLayoutItemProxyAttachedData::releaseControl is called by |
483 | LayoutItemProxies when they try no longer control the item |
484 | |
485 | \param proxy The proxy that gives up control. |
486 | */ |
487 | void QQuickLayoutItemProxyAttachedData::releaseControl(QQuickLayoutItemProxy *proxy) |
488 | { |
489 | if (controllingProxy != proxy) |
490 | return; |
491 | |
492 | qCDebug(lcLayouts) << proxy |
493 | << "no longer controls" |
494 | << parent(); |
495 | |
496 | controllingProxy = nullptr; |
497 | emit controlReleased(); |
498 | emit controllingProxyChanged(); |
499 | |
500 | for (auto &otherProxy: std::as_const(t&: proxies)) { |
501 | if (proxy != otherProxy) |
502 | otherProxy->maybeTakeControl(); |
503 | } |
504 | } |
505 | |
506 | /*! \internal |
507 | \brief QQuickLayoutItemProxyAttachedData::getControllingProxy |
508 | \return the proxy that currently controls the item this data is attached to. |
509 | Returns \c null if no proxy controls the item. |
510 | */ |
511 | QQuickLayoutItemProxy *QQuickLayoutItemProxyAttachedData::getControllingProxy() const |
512 | { |
513 | return controllingProxy; |
514 | } |
515 | |
516 | /*! \internal |
517 | \brief QQuickLayoutItemProxyAttachedData::getProxies |
518 | \return a list of all proxies that target the item this data is attached to. |
519 | */ |
520 | QQmlListProperty<QQuickLayoutItemProxy> QQuickLayoutItemProxyAttachedData::getProxies() |
521 | { |
522 | using Type = QQuickLayoutItemProxy; |
523 | using Property = QQmlListProperty<Type>; |
524 | |
525 | return Property( |
526 | this, &proxies, |
527 | [](Property *p) { return static_cast<QList<Type *> *>(p->data)->size(); }, |
528 | [](Property *p, qsizetype i) { return static_cast<QList<Type *> *>(p->data)->at(i); } |
529 | ); |
530 | } |
531 | |
532 | /*! \internal |
533 | \brief QQuickLayoutItemProxyAttachedData::proxyHasControl |
534 | \return \c true if a proxy is controlling the item, \c false otherwise. |
535 | */ |
536 | bool QQuickLayoutItemProxyAttachedData::proxyHasControl() const |
537 | { |
538 | return controllingProxy != nullptr; |
539 | } |
540 | |