Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlpropertytopropertybinding_p.h
Go to the documentation of this file.
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// Qt-Security score:significant
4
5#ifndef QQMLPROPERTYTOPROPERTYBINDINDING_P_H
6#define QQMLPROPERTYTOPROPERTYBINDINDING_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qqmlabstractbinding_p.h>
20#include <private/qqmlengine_p.h>
21#include <private/qqmlnotifier_p.h>
22#include <private/qqmlvaluetype_p.h>
23#include <private/qv4jscall_p.h>
24
25#include <QtCore/qproperty.h>
26
27QT_BEGIN_NAMESPACE
28
29// Different forms of property-to-property binding
30// unbindable -> unbindable: QQmlAbstractBinding + QQmlNotifierEndpoint
31// unbindable -> bindable: QPropertyBindingPrivate + QQmlNotifierEndpoint
32// bindable -> unbindable: QQmlAbstractBinding + QPropertyObserver
33// bindable -> bindable: QPropertyBindingPrivate only
34
35class QQmlPropertyToPropertyBinding
36{
37public:
38 static Q_QML_EXPORT QQmlAnyBinding create(
39 QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target);
40
41private:
42 friend class QQmlPropertyToUnbindablePropertyBinding;
43 friend class QQmlUnbindableToUnbindablePropertyBinding;
44 friend class QQmlBindableToUnbindablePropertyBinding;
45 friend class QQmlPropertyToBindablePropertyBinding;
46 friend class QQmlUnbindableToBindablePropertyBinding;
47 friend class QQmlBindableToBindablePropertyBinding;
48
49 QQmlPropertyToPropertyBinding(QQmlEngine *engine, const QQmlProperty &source);
50
51 template<typename Capture>
52 QVariant readSourceValue(Capture &&capture) const
53 {
54 const QMetaObject *sourceMetaObject = sourceObject->metaObject();
55 const QMetaProperty property
56 = sourceMetaObject->property(sourcePropertyIndex.coreIndex());
57 if (!property.isConstant())
58 capture(sourceMetaObject, property);
59
60 QVariant value;
61
62 const int valueTypeIndex = sourcePropertyIndex.valueTypeIndex();
63 if (valueTypeIndex == -1) {
64 value = property.read(sourceObject);
65 } else {
66 QQmlGadgetPtrWrapper *wrapper
67 = QQmlEnginePrivate::get(engine)->valueTypeInstance(property.metaType());
68 wrapper->read(sourceObject, sourcePropertyIndex.coreIndex());
69 value = wrapper->readOnGadget(wrapper->property(valueTypeIndex));
70 }
71
72 return value;
73 }
74
75 void doConnectNotify(QQmlNotifierEndpoint *endpoint, const QMetaProperty &property)
76 {
77 const int notifyIndex = QMetaObjectPrivate::signalIndex(property.notifySignal());
78
79 // We cannot capture non-bindable properties without signals
80 if (notifyIndex == -1)
81 return;
82
83 if (endpoint->isConnected(sourceObject, notifyIndex))
84 endpoint->cancelNotify();
85 else
86 endpoint->connect(sourceObject, notifyIndex, engine, true);
87 }
88
89 QQmlEngine *engine = nullptr;
90 QObject *sourceObject = nullptr;
91 QQmlPropertyIndex sourcePropertyIndex;
92};
93
95{
96public:
97 Kind kind() const final;
98 void setEnabled(bool e, QQmlPropertyData::WriteFlags flags) final;
99 void update(QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding);
100
101protected:
103 QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target);
104
105 virtual void captureProperty(
106 const QMetaObject *sourceMetaObject, const QMetaProperty &sourceProperty) = 0;
107
108 QQmlPropertyToPropertyBinding m_binding;
109};
110
113{
114public:
116 QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target);
117protected:
118 void captureProperty(
119 const QMetaObject *sourceMetaObject, const QMetaProperty &sourceProperty) final;
120};
121
124{
125public:
127 QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target);
128
129 static void update(QPropertyObserver *observer, QUntypedPropertyData *);
130
131protected:
132 void captureProperty(
133 const QMetaObject *sourceMetaObject, const QMetaProperty &sourceProperty) final;
134private:
135 bool m_isObserving = false;
136};
137
139{
140public:
142 QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target,
143 const QtPrivate::BindingFunctionVTable *vtable);
144
145 template<typename Concrete>
146 static bool update(QMetaType metaType, QUntypedPropertyData *dataPtr, void *f)
147 {
148 Concrete *self = reinterpret_cast<Concrete *>(
149 // Address of QPropertyBindingPrivate subobject
150 static_cast<std::byte *>(f) - QPropertyBindingPrivate::getSizeEnsuringAlignment());
151
152 const QVariant value = self->m_binding.readSourceValue(
153 [self](const QMetaObject *metaObject, const QMetaProperty &property) {
154 self->captureProperty(metaObject, property);
155 });
156
157 QV4::coerce(
158 self->m_binding.engine->handle(), value.metaType(), value.constData(),
159 metaType, dataPtr);
160 return true;
161 }
162
163protected:
164 QQmlPropertyToPropertyBinding m_binding;
165};
166
169{
170public:
172 QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target);
173
174 void update();
175
176 void captureProperty(const QMetaObject *, const QMetaProperty &property)
177 {
178 m_binding.doConnectNotify(this, property);
179 }
180};
181
183{
184public:
186 QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target);
187
188 void captureProperty(const QMetaObject *, const QMetaProperty &) {}
189};
190
191void QQmlUnbindableToUnbindableGuard_callback(QQmlNotifierEndpoint *e, void **);
192void QQmlUnbindableToBindableGuard_callback(QQmlNotifierEndpoint *e, void **);
193
194QT_END_NAMESPACE
195
196#endif
QQmlBindableToBindablePropertyBinding(QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target)
void captureProperty(const QMetaObject *, const QMetaProperty &)
void captureProperty(const QMetaObject *sourceMetaObject, const QMetaProperty &sourceProperty) final
QQmlBindableToUnbindablePropertyBinding(QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target)
static void update(QPropertyObserver *observer, QUntypedPropertyData *)
QQmlPropertyToBindablePropertyBinding(QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target, const QtPrivate::BindingFunctionVTable *vtable)
static bool update(QMetaType metaType, QUntypedPropertyData *dataPtr, void *f)
void setEnabled(bool e, QQmlPropertyData::WriteFlags flags) final
QQmlPropertyToUnbindablePropertyBinding(QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target)
virtual void captureProperty(const QMetaObject *sourceMetaObject, const QMetaProperty &sourceProperty)=0
void update(QQmlPropertyData::WriteFlags flags=QQmlPropertyData::DontRemoveBinding)
void captureProperty(const QMetaObject *, const QMetaProperty &property)
QQmlUnbindableToBindablePropertyBinding(QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target)
QQmlUnbindableToUnbindablePropertyBinding(QQmlEngine *engine, const QQmlProperty &source, const QQmlProperty &target)
void captureProperty(const QMetaObject *sourceMetaObject, const QMetaProperty &sourceProperty) final
Combined button and popup list for selecting options.
constexpr BindingFunctionVTable bindingFunctionVTableForQQmlPropertyToBindablePropertyBinding
void QQmlUnbindableToBindableGuard_callback(QQmlNotifierEndpoint *e, void **)
void QQmlUnbindableToUnbindableGuard_callback(QQmlNotifierEndpoint *e, void **)