1 | // Copyright (C) 2022 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 "qquickattachedpropertypropagator.h" |
5 | |
6 | #include <QtCore/qpointer.h> |
7 | #include <QtQuick/qquickwindow.h> |
8 | #include <QtQuick/private/qquickitem_p.h> |
9 | #include <QtQuick/private/qquickitemchangelistener_p.h> |
10 | #include <QtQuickTemplates2/private/qquickpopup_p.h> |
11 | #include <QtQuickTemplates2/private/qquickpopupitem_p_p.h> |
12 | #include <QtQuickTemplates2/private/qquickpopupwindow_p_p.h> |
13 | |
14 | QT_BEGIN_NAMESPACE |
15 | |
16 | Q_LOGGING_CATEGORY(lcAttached, "qt.quick.controls.attachedpropertypropagator" ) |
17 | |
18 | /*! |
19 | \class QQuickAttachedPropertyPropagator |
20 | \brief The QQuickAttachedPropertyPropagator class provides a way to |
21 | propagate attached properties. |
22 | \inmodule QtQuickControls2 |
23 | \since 6.5 |
24 | |
25 | In QML, it is possible to |
26 | \l {Attached Properties and Attached Signal Handlers}{attach properties and |
27 | signal handlers} to objects. \l {Providing Attached Properties} goes into more |
28 | detail about how to expose your own C++ attached types. |
29 | |
30 | QQuickAttachedPropertyPropagator provides an API to propagate attached |
31 | properties from a parent object to its children, similar to |
32 | \l {Control::}{font} and \l {Item::}{palette} propagation. It supports |
33 | propagation through \l {Item}{items}, \l {Popup}{popups}, and |
34 | \l {Window}{windows}. |
35 | |
36 | If propagation of properties is not important, consider using a |
37 | \l {QML_SINGLETON}{C++} or |
38 | \l {Contents of a Module Definition qmldir File}{QML} singleton instead, |
39 | as it is better suited for that use case, and is more efficient in that |
40 | it only requires one QObject. |
41 | |
42 | To implement a custom attached property: |
43 | |
44 | \list 1 |
45 | \li Derive a class that exposes the attached property from |
46 | QQuickAttachedPropertyPropagator. |
47 | |
48 | For example, to implement an attached \c {MyStyle.theme} property, |
49 | declare the \c {MyStyle} class: |
50 | |
51 | \quotefromfile ../../examples/quickcontrols/attachedstyleproperties/MyStyle/mystyle.h |
52 | \skipto class |
53 | \printto { |
54 | |
55 | \li Call \l initialize() in the constructor of your class: |
56 | |
57 | \quotefromfile ../../examples/quickcontrols/attachedstyleproperties/MyStyle/mystyle.cpp |
58 | \skipto MyStyle::MyStyle |
59 | \printuntil } |
60 | |
61 | \li Define set/inherit/propagate/reset functions for the attached property |
62 | as needed. For example, to define a \c theme attached property: |
63 | |
64 | \quotefromfile ../../examples/quickcontrols/attachedstyleproperties/MyStyle/mystyle.cpp |
65 | \skipto theme() |
66 | \printto MyStyle::themeChange() |
67 | |
68 | \li Reimplement \l attachedParentChange() to handle property inheritance: |
69 | |
70 | \quotefromfile ../../examples/quickcontrols/attachedstyleproperties/MyStyle/mystyle.cpp |
71 | \skipto attachedParentChange |
72 | \printuntil /^\}/ |
73 | |
74 | \li Implement a static \c qmlAttachedProperties function and declare the |
75 | type as an attached QML type with \l QML_ELEMENT and \l QML_ATTACHED, |
76 | as detailed in \l {Providing Attached Properties}: |
77 | |
78 | \quotefromfile ../../examples/quickcontrols/attachedstyleproperties/MyStyle/mystyle.cpp |
79 | \skipto qmlAttachedProperties |
80 | \printuntil } |
81 | |
82 | \endlist |
83 | |
84 | The complete implementation is available in |
85 | \l {Qt Quick Controls - Attached Style Properties Example}. |
86 | |
87 | \sa {Styling Qt Quick Controls} |
88 | */ |
89 | |
90 | static QQuickAttachedPropertyPropagator *attachedObject(const QMetaObject *type, QObject *object, bool create = false) |
91 | { |
92 | if (!object) |
93 | return nullptr; |
94 | auto func = qmlAttachedPropertiesFunction(object, type); |
95 | return qobject_cast<QQuickAttachedPropertyPropagator *>(object: qmlAttachedPropertiesObject(object, func, create)); |
96 | } |
97 | |
98 | /*! |
99 | \internal |
100 | |
101 | Tries to find a QQuickAttachedPropertyPropagator whose type is \a ourAttachedType |
102 | and is attached to an ancestor of \a objectWeAreAttachedTo. |
103 | |
104 | QQuickAttachedPropertyPropagator needs to know who its parent attached object is in |
105 | order to inherit attached property values from it. This is called when an |
106 | instance of QQuickAttachedPropertyPropagator is created, and whenever |
107 | \c {objectWeAreAttachedTo}'s parent changes, for example. |
108 | */ |
109 | static QQuickAttachedPropertyPropagator *findAttachedParent(const QMetaObject *ourAttachedType, QObject *objectWeAreAttachedTo) |
110 | { |
111 | qCDebug(lcAttached).noquote() << "findAttachedParent called with" << ourAttachedType->className() << objectWeAreAttachedTo; |
112 | /* |
113 | In the Material ComboBox.qml, we have code like this: |
114 | |
115 | popup: T.Popup { |
116 | // ... |
117 | Material.theme: control.Material.theme |
118 | // ... |
119 | |
120 | background: Rectangle { |
121 | //... |
122 | color: parent.Material.dialogColor |
123 | |
124 | The Material attached object has to be accessed this way due to |
125 | deferred execution limitations (see 3e87695fb4b1a5d503c744046e6d9f43a2ae18a6). |
126 | However, since parent here refers to QQuickPopupItem and not the popup, |
127 | the color will actually come from the window. If a dark theme was set on |
128 | the ComboBox, it will not be respected in the background if we don't have |
129 | the check below. |
130 | */ |
131 | auto = qobject_cast<QQuickPopupItem *>(object: objectWeAreAttachedTo); |
132 | if (popupItem) { |
133 | qCDebug(lcAttached).noquote() << "- attachee belongs to popup item" << popupItem << "- checking if it has an attached object" ; |
134 | auto = QQuickPopupItemPrivate::get(popupItem); |
135 | QQuickAttachedPropertyPropagator * = attachedObject(type: ourAttachedType, object: popupItemPrivate->popup); |
136 | if (popupAttached) { |
137 | qCDebug(lcAttached).noquote() << "- popup item has attached object" << popupAttached << "- returning" ; |
138 | return popupAttached; |
139 | } else { |
140 | qCDebug(lcAttached).noquote() << "- popup item does not have attached object" ; |
141 | } |
142 | } else { |
143 | qCDebug(lcAttached).noquote() << "- attachee does not belong to a popup" ; |
144 | } |
145 | |
146 | QQuickItem *item = qobject_cast<QQuickItem *>(o: objectWeAreAttachedTo); |
147 | if (item) { |
148 | qCDebug(lcAttached).noquote() << "- attachee is an item; checking its parent items and popups" ; |
149 | // lookup parent items and popups |
150 | QQuickItem *parent = item->parentItem(); |
151 | while (parent) { |
152 | qCDebug(lcAttached).noquote() << " - checking parent item" << parent; |
153 | QQuickAttachedPropertyPropagator *attached = attachedObject(type: ourAttachedType, object: parent); |
154 | if (attached) { |
155 | qCDebug(lcAttached).noquote() << " - parent item has attached object" << attached << "- returning" ; |
156 | return attached; |
157 | } |
158 | |
159 | QQuickPopup * = qobject_cast<QQuickPopup *>(object: parent->parent()); |
160 | if (popup) { |
161 | qCDebug(lcAttached).noquote() << " - parent popup has attached object" << attached << "- returning" ; |
162 | return attachedObject(type: ourAttachedType, object: popup); |
163 | } |
164 | |
165 | parent = parent->parentItem(); |
166 | } |
167 | |
168 | // fallback to item's window |
169 | qCDebug(lcAttached).noquote() << "- checking parent window" << item->window(); |
170 | QQuickAttachedPropertyPropagator *attached = attachedObject(type: ourAttachedType, object: item->window()); |
171 | if (attached) { |
172 | qCDebug(lcAttached).noquote() << "- parent window has attached object" << attached << "- returning" ; |
173 | return attached; |
174 | } |
175 | } else { |
176 | // lookup popup's window |
177 | QQuickPopup * = qobject_cast<QQuickPopup *>(object: objectWeAreAttachedTo); |
178 | if (popup) { |
179 | qCDebug(lcAttached).noquote() << "- attachee is a popup; checking its window" ; |
180 | auto* = popup->popupItem()->window(); |
181 | auto *object = attachedObject(type: ourAttachedType, object: popupWindow); |
182 | // Check if the attached object exists for the popup window. If it |
183 | // doesn't, use transient parent attached object |
184 | if (!object && qobject_cast<QQuickPopupWindow *>(object: popupWindow)) |
185 | return attachedObject(type: ourAttachedType, object: popupWindow->transientParent()); |
186 | return object; |
187 | } |
188 | } |
189 | |
190 | // lookup parent window |
191 | QQuickWindow *window = qobject_cast<QQuickWindow *>(object: objectWeAreAttachedTo); |
192 | if (window) { |
193 | // It doesn't seem like a parent window can be anything but transient in Qt Quick. |
194 | QQuickWindow *parentWindow = qobject_cast<QQuickWindow *>(object: window->transientParent()); |
195 | qCDebug(lcAttached).noquote() << "- attachee is a window; checking its parent window" << parentWindow; |
196 | if (parentWindow) { |
197 | QQuickAttachedPropertyPropagator *attached = attachedObject(type: ourAttachedType, object: parentWindow); |
198 | if (attached) { |
199 | qCDebug(lcAttached).noquote() << "- parent window has attached object" << attached << "- returning" ; |
200 | return attached; |
201 | } |
202 | } |
203 | } |
204 | |
205 | // fallback to engine (global) |
206 | if (objectWeAreAttachedTo) { |
207 | QQmlEngine *engine = qmlEngine(objectWeAreAttachedTo); |
208 | qCDebug(lcAttached).noquote() << "- falling back to engine" << engine; |
209 | if (engine) { |
210 | QByteArray name = QByteArray("_q_" ) + ourAttachedType->className(); |
211 | QQuickAttachedPropertyPropagator *attached = engine->property(name).value<QQuickAttachedPropertyPropagator *>(); |
212 | if (!attached) { |
213 | attached = attachedObject(type: ourAttachedType, object: engine, create: true); |
214 | engine->setProperty(name, value: QVariant::fromValue(value: attached)); |
215 | } |
216 | return attached; |
217 | } |
218 | } |
219 | |
220 | return nullptr; |
221 | } |
222 | |
223 | static QList<QQuickAttachedPropertyPropagator *> findAttachedChildren(const QMetaObject *type, QObject *object) |
224 | { |
225 | QList<QQuickAttachedPropertyPropagator *> children; |
226 | |
227 | QQuickItem *item = qobject_cast<QQuickItem *>(o: object); |
228 | if (!item) { |
229 | QQuickWindow *window = qobject_cast<QQuickWindow *>(object); |
230 | if (window) |
231 | item = window->contentItem(); |
232 | } |
233 | |
234 | if (!item) |
235 | return children; |
236 | |
237 | // At this point, "item" could either be an item that the attached object is |
238 | // attached to directly, or the contentItem of a window that the attached object |
239 | // is attached to. |
240 | |
241 | // Look for attached properties on items. |
242 | const auto childItems = item->childItems(); |
243 | for (QQuickItem *child : childItems) { |
244 | QQuickAttachedPropertyPropagator *attached = attachedObject(type, object: child); |
245 | if (attached) |
246 | children += attached; |
247 | else |
248 | children += findAttachedChildren(type, object: child); |
249 | } |
250 | |
251 | // Look for attached properties on windows. Windows declared in QML |
252 | // as children of a Window are QObject-parented to the contentItem (see |
253 | // QQuickWindowPrivate::data_append()). Windows declared as children |
254 | // of items are QObject-parented to those items. |
255 | const auto &windowChildren = item->children(); |
256 | for (QObject *child : windowChildren) { |
257 | QQuickWindow *childWindow = qobject_cast<QQuickWindow *>(object: child); |
258 | if (childWindow) { |
259 | QQuickAttachedPropertyPropagator *attached = attachedObject(type, object: childWindow); |
260 | if (attached) |
261 | children += attached; |
262 | } |
263 | } |
264 | |
265 | return children; |
266 | } |
267 | |
268 | static QQuickItem *findAttachedItem(QObject *parent) |
269 | { |
270 | QQuickItem *item = qobject_cast<QQuickItem *>(o: parent); |
271 | if (!item) { |
272 | QQuickPopup * = qobject_cast<QQuickPopup *>(object: parent); |
273 | if (popup) |
274 | item = popup->popupItem(); |
275 | } |
276 | return item; |
277 | } |
278 | |
279 | class QQuickAttachedPropertyPropagatorPrivate : public QObjectPrivate, public QQuickItemChangeListener |
280 | { |
281 | public: |
282 | Q_DECLARE_PUBLIC(QQuickAttachedPropertyPropagator) |
283 | |
284 | static QQuickAttachedPropertyPropagatorPrivate *get(QQuickAttachedPropertyPropagator *attachedObject) |
285 | { |
286 | return attachedObject->d_func(); |
287 | } |
288 | |
289 | void attachTo(QObject *object); |
290 | void detachFrom(QObject *object); |
291 | void setAttachedParent(QQuickAttachedPropertyPropagator *parent); |
292 | |
293 | void itemWindowChanged(QQuickWindow *window); |
294 | void transientParentWindowChanged(QWindow *newTransientParent); |
295 | void itemParentChanged(QQuickItem *item, QQuickItem *parent) override; |
296 | |
297 | QList<QQuickAttachedPropertyPropagator *> attachedChildren; |
298 | QPointer<QQuickAttachedPropertyPropagator> attachedParent; |
299 | }; |
300 | |
301 | void QQuickAttachedPropertyPropagatorPrivate::attachTo(QObject *object) |
302 | { |
303 | if (QQuickItem *item = findAttachedItem(parent: object)) { |
304 | connect(sender: item, signal: &QQuickItem::windowChanged, receiverPrivate: this, slot: &QQuickAttachedPropertyPropagatorPrivate::itemWindowChanged); |
305 | QQuickItemPrivate::get(item)->addItemChangeListener(listener: this, types: QQuickItemPrivate::Parent); |
306 | } else if (auto *window = qobject_cast<QQuickWindow *>(object)) { |
307 | QObjectPrivate::connect(sender: window, signal: &QWindow::transientParentChanged, receiverPrivate: this, |
308 | slot: &QQuickAttachedPropertyPropagatorPrivate::transientParentWindowChanged); |
309 | } |
310 | } |
311 | |
312 | void QQuickAttachedPropertyPropagatorPrivate::detachFrom(QObject *object) |
313 | { |
314 | if (QQuickItem *item = findAttachedItem(parent: object)) { |
315 | disconnect(sender: item, signal: &QQuickItem::windowChanged, receiverPrivate: this, slot: &QQuickAttachedPropertyPropagatorPrivate::itemWindowChanged); |
316 | QQuickItemPrivate::get(item)->removeItemChangeListener(this, types: QQuickItemPrivate::Parent); |
317 | } else if (auto *window = qobject_cast<QQuickWindow *>(object)) { |
318 | QObjectPrivate::disconnect(sender: window, signal: &QWindow::transientParentChanged, |
319 | receiverPrivate: this, slot: &QQuickAttachedPropertyPropagatorPrivate::transientParentWindowChanged); |
320 | } |
321 | } |
322 | |
323 | /*! |
324 | \internal |
325 | |
326 | This function sets the attached parent of this attached object. |
327 | |
328 | Currently it is called when: |
329 | \list |
330 | \li The target item's parent changes. |
331 | \li The target item's window changes. |
332 | \li The attached object is constructed, to set the attached parent |
333 | and the attached parent of the attached object children. |
334 | \li The attached object is destructed. |
335 | \endlist |
336 | |
337 | \quotefromfile ../../examples/quickcontrols/attachedstyleproperties/MyStyle/mystyle.cpp |
338 | \skipto MyStyle::resetTheme |
339 | \printuntil } |
340 | */ |
341 | void QQuickAttachedPropertyPropagatorPrivate::setAttachedParent(QQuickAttachedPropertyPropagator *parent) |
342 | { |
343 | Q_Q(QQuickAttachedPropertyPropagator); |
344 | if (attachedParent == parent) |
345 | return; |
346 | |
347 | QQuickAttachedPropertyPropagator *oldParent = attachedParent; |
348 | qCDebug(lcAttached).noquote() << "setAttachedParent called on" << q << "with parent" << parent; |
349 | if (attachedParent) { |
350 | qCDebug(lcAttached).noquote() << "- removing ourselves as an attached child of" << attachedParent; |
351 | QQuickAttachedPropertyPropagatorPrivate::get(attachedObject: attachedParent)->attachedChildren.removeOne(t: q); |
352 | } |
353 | attachedParent = parent; |
354 | if (parent) { |
355 | qCDebug(lcAttached).noquote() << "- adding ourselves as an attached child of" << parent; |
356 | QQuickAttachedPropertyPropagatorPrivate::get(attachedObject: parent)->attachedChildren.append(t: q); |
357 | } |
358 | q->attachedParentChange(newParent: parent, oldParent); |
359 | } |
360 | |
361 | /* |
362 | If there's e.g. code like this: |
363 | |
364 | Behavior on Material.elevation {} |
365 | |
366 | The meta type will be something like QQuickMaterialStyle_QML_125, |
367 | whereas QQmlMetaType::attachedPropertiesFunc only has attached |
368 | property data for QQuickMaterialStyle (i.e. attached property types |
369 | created from C++). We work around this by finding the first C++ |
370 | meta object, which works even for attached types created in QML. |
371 | */ |
372 | const QMetaObject *firstCppMetaObject(QQuickAttachedPropertyPropagator *propagator) |
373 | { |
374 | return QQmlData::ensurePropertyCache(object: propagator)->firstCppMetaObject(); |
375 | } |
376 | |
377 | void QQuickAttachedPropertyPropagatorPrivate::itemWindowChanged(QQuickWindow *window) |
378 | { |
379 | Q_Q(QQuickAttachedPropertyPropagator); |
380 | QQuickAttachedPropertyPropagator *attachedParent = nullptr; |
381 | qCDebug(lcAttached).noquote() << "window of" << q << "changed to" << window; |
382 | |
383 | attachedParent = findAttachedParent(ourAttachedType: firstCppMetaObject(propagator: q), objectWeAreAttachedTo: q->parent()); |
384 | if (!attachedParent) |
385 | attachedParent = attachedObject(type: firstCppMetaObject(propagator: q), object: window); |
386 | setAttachedParent(attachedParent); |
387 | } |
388 | |
389 | void QQuickAttachedPropertyPropagatorPrivate::transientParentWindowChanged(QWindow *newTransientParent) |
390 | { |
391 | Q_Q(QQuickAttachedPropertyPropagator); |
392 | QQuickAttachedPropertyPropagator *attachedParent = nullptr; |
393 | qCDebug(lcAttached).noquote() << "transient parent window of" << q << "changed to" << newTransientParent; |
394 | attachedParent = findAttachedParent(ourAttachedType: firstCppMetaObject(propagator: q), objectWeAreAttachedTo: q->parent()); |
395 | if (!attachedParent) |
396 | attachedParent = attachedObject(type: firstCppMetaObject(propagator: q), object: newTransientParent); |
397 | setAttachedParent(attachedParent); |
398 | } |
399 | |
400 | void QQuickAttachedPropertyPropagatorPrivate::itemParentChanged(QQuickItem *item, QQuickItem *parent) |
401 | { |
402 | Q_Q(QQuickAttachedPropertyPropagator); |
403 | Q_UNUSED(item); |
404 | Q_UNUSED(parent); |
405 | setAttachedParent(findAttachedParent(ourAttachedType: firstCppMetaObject(propagator: q), objectWeAreAttachedTo: q->parent())); |
406 | } |
407 | |
408 | /*! |
409 | Constructs a QQuickAttachedPropertyPropagator with the given \a parent. |
410 | |
411 | The \c parent will be used to find this object's |
412 | \l {attachedParent()}{attached parent}. |
413 | |
414 | Derived classes should call \l initialize() in their constructor. |
415 | */ |
416 | QQuickAttachedPropertyPropagator::QQuickAttachedPropertyPropagator(QObject *parent) |
417 | : QObject(*(new QQuickAttachedPropertyPropagatorPrivate), parent) |
418 | { |
419 | Q_D(QQuickAttachedPropertyPropagator); |
420 | d->attachTo(object: parent); |
421 | } |
422 | |
423 | /*! |
424 | Destroys the QQuickAttachedPropertyPropagator. |
425 | */ |
426 | QQuickAttachedPropertyPropagator::~QQuickAttachedPropertyPropagator() |
427 | { |
428 | Q_D(QQuickAttachedPropertyPropagator); |
429 | d->detachFrom(object: parent()); |
430 | d->setAttachedParent(nullptr); |
431 | } |
432 | |
433 | /*! |
434 | This function returns the attached children of this attached object. |
435 | |
436 | The attached children are used when propagating property values: |
437 | |
438 | \quotefromfile ../../examples/quickcontrols/attachedstyleproperties/MyStyle/mystyle.cpp |
439 | \skipto MyStyle::propagateTheme |
440 | \printuntil } |
441 | \printuntil } |
442 | */ |
443 | QList<QQuickAttachedPropertyPropagator *> QQuickAttachedPropertyPropagator::attachedChildren() const |
444 | { |
445 | Q_D(const QQuickAttachedPropertyPropagator); |
446 | return d->attachedChildren; |
447 | } |
448 | |
449 | /*! |
450 | This function returns the attached parent of this attached object. |
451 | |
452 | The attached parent is used when inheriting property values: |
453 | |
454 | \quotefromfile ../../examples/quickcontrols/attachedstyleproperties/MyStyle/mystyle.cpp |
455 | \skipto MyStyle::resetTheme |
456 | \printuntil } |
457 | */ |
458 | QQuickAttachedPropertyPropagator *QQuickAttachedPropertyPropagator::attachedParent() const |
459 | { |
460 | Q_D(const QQuickAttachedPropertyPropagator); |
461 | return d->attachedParent; |
462 | } |
463 | |
464 | /*! |
465 | Finds and sets the attached parent for this attached object, and then does |
466 | the same for its children. This must be called upon construction of the |
467 | attached object in order for propagation to work. |
468 | |
469 | It can be useful to read global/default values before calling this |
470 | function. For example, before calling \c initialize(), the |
471 | \l {Imagine Style}{Imagine} style checks a static "globalsInitialized" flag |
472 | to see if it should read default values from \l QSettings. The values from |
473 | that file form the basis for any attached property values that have not |
474 | been explicitly set. |
475 | |
476 | \quotefromfile ../../examples/quickcontrols/attachedstyleproperties/MyStyle/mystyle.cpp |
477 | \skipto MyStyle::MyStyle |
478 | \printuntil } |
479 | */ |
480 | void QQuickAttachedPropertyPropagator::initialize() |
481 | { |
482 | Q_D(QQuickAttachedPropertyPropagator); |
483 | qCDebug(lcAttached) << "initialize called for" << parent() << "- looking for attached parent..." ; |
484 | QQuickAttachedPropertyPropagator *attachedParent = findAttachedParent(ourAttachedType: metaObject(), objectWeAreAttachedTo: parent()); |
485 | if (attachedParent) |
486 | d->setAttachedParent(attachedParent); |
487 | |
488 | const QList<QQuickAttachedPropertyPropagator *> attachedChildren = findAttachedChildren(type: metaObject(), object: parent()); |
489 | qCDebug(lcAttached) << "- found" << attachedChildren.size() << "attached children:" ; |
490 | for (QQuickAttachedPropertyPropagator *child : attachedChildren) { |
491 | qCDebug(lcAttached) << " -" << child->parent(); |
492 | QQuickAttachedPropertyPropagatorPrivate::get(attachedObject: child)->setAttachedParent(this); |
493 | } |
494 | |
495 | qCDebug(lcAttached) << "... finished initializing" ; |
496 | } |
497 | |
498 | /*! |
499 | This function is called whenever the attached parent of this |
500 | QQuickAttachedPropertyPropagator changes from \a oldParent to \a newParent. |
501 | |
502 | Subclasses should reimplement this function to inherit attached properties |
503 | from \c newParent. |
504 | |
505 | \quotefromfile ../../examples/quickcontrols/attachedstyleproperties/MyStyle/mystyle.cpp |
506 | \skipto attachedParentChange |
507 | \printuntil } |
508 | \printuntil } |
509 | */ |
510 | void QQuickAttachedPropertyPropagator::attachedParentChange(QQuickAttachedPropertyPropagator *newParent, QQuickAttachedPropertyPropagator *oldParent) |
511 | { |
512 | Q_UNUSED(newParent); |
513 | Q_UNUSED(oldParent); |
514 | } |
515 | |
516 | #ifndef QT_NO_DEBUG_STREAM |
517 | QDebug operator<<(QDebug debug, const QQuickAttachedPropertyPropagator *propagator) |
518 | { |
519 | QDebugStateSaver saver(debug); |
520 | debug.nospace().noquote(); |
521 | if (!propagator) { |
522 | debug << "QQuickAttachedPropertyPropagator(nullptr)" ; |
523 | return debug; |
524 | } |
525 | |
526 | // Cast to QObject to avoid recursion. |
527 | debug << static_cast<const QObject *>(propagator) << " (which is attached to " << propagator->parent() << ')'; |
528 | return debug; |
529 | } |
530 | #endif |
531 | |
532 | QT_END_NAMESPACE |
533 | |
534 | #include "moc_qquickattachedpropertypropagator.cpp" |
535 | |