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
qqmldesignermetaobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 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
5
6#include <QSharedPointer>
7#include <QMetaProperty>
8#include <QtCore/private/qnumeric_p.h>
9#include <QDebug>
10
11#include <private/qqmlengine_p.h>
12
14
16static void (*notifyPropertyChangeCallBack)(QObject*, const QQuickDesignerSupport::PropertyName &propertyName) = nullptr;
17
19 inline std::pair<QVariant, bool> &getDataRef(int idx) {
20 while (m_data.size() <= idx)
21 m_data << std::pair<QVariant, bool>(QVariant(), false);
22 return m_data[idx];
23 }
24
25 inline QVariant &getData(int idx) {
26 std::pair<QVariant, bool> &prop = getDataRef(idx);
27 if (!prop.second) {
28 prop.first = QVariant();
29 prop.second = true;
30 }
31 return prop.first;
32 }
33
34 inline bool hasData(int idx) const {
35 if (idx >= m_data.size())
36 return false;
37 return m_data[idx].second;
38 }
39
40 inline int count() { return m_data.size(); }
41
43};
44
45QQmlDesignerMetaObject* QQmlDesignerMetaObject::getNodeInstanceMetaObject(QObject *object, QQmlEngine *engine)
46{
47 //Avoid setting up multiple MetaObjects on the same QObject
48 QObjectPrivate *op = QObjectPrivate::get(object);
49 QDynamicMetaObjectData *parent = op->metaObject;
50 if (nodeInstanceMetaObjectList.contains(parent))
51 return static_cast<QQmlDesignerMetaObject *>(parent);
52
53 // we just create one and the ownership goes automatically to the object in nodeinstance see init method
54
55 QQmlData *ddata = QQmlData::get(object, false);
56
57 QQmlDesignerMetaObject *mo = new QQmlDesignerMetaObject(object, engine);
58 ddata->hasVMEMetaObject = false;
59 ddata->hasInterceptorMetaObject = false;
60
61 return mo;
62}
63
64void QQmlDesignerMetaObject::init(QObject *object)
65{
66 //Assign this to object
67 QObjectPrivate *op = QObjectPrivate::get(object);
68 op->metaObject = this;
69 nodeInstanceMetaObjectList.insert(this, true);
70}
71
72QQmlPropertyCache::Ptr QQmlDesignerMetaObject::cache() const
73{
74 return type()->cache();
75}
76
77QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine)
78 : QQmlOpenMetaObject(object),
79 m_context(engine->contextForObject(object)),
80 m_data(new MetaPropertyData)
81{
82 init(object);
83 setCached(true);
84}
85
90
92{
93 int id = type()->createProperty(name.toUtf8());
94 setValue(id, QVariant());
95 Q_ASSERT(id >= 0);
96
97 //Updating cache
98 cache()->invalidate(this);
99
100 QQmlProperty property(myObject(), name, m_context);
101 Q_ASSERT(property.isValid());
102}
103
104int QQmlDesignerMetaObject::createProperty(const char *name, const char *passAlong)
105{
106 int ret = QQmlOpenMetaObject::createProperty(name, passAlong);
107 if (ret != -1) {
108 // compare createNewDynamicProperty
109 cache()->invalidate(this);
110 }
111 return ret;
112}
113
114void QQmlDesignerMetaObject::setValue(int id, const QVariant &value)
115{
116 std::pair<QVariant, bool> &prop = m_data->getDataRef(id);
117 prop.first = propertyWriteValue(id, value);
118 prop.second = true;
119 QMetaObject::activate(myObject(), id + type()->signalOffset(), nullptr);
120}
121
123{
124 return value;
125}
126
131
133{
134 return cache()->propertyOffset();
135}
136
137int QQmlDesignerMetaObject::openMetaCall(QObject *o, QMetaObject::Call call, int id, void **a)
138{
139 if ((call == QMetaObject::ReadProperty || call == QMetaObject::WriteProperty)
140 && id >= type()->propertyOffset()) {
141 int propId = id - type()->propertyOffset();
142 if (call == QMetaObject::ReadProperty) {
143 //propertyRead(propId);
144 *reinterpret_cast<QVariant *>(a[0]) = m_data->getData(propId);
145 } else if (call == QMetaObject::WriteProperty) {
146 if (propId <= m_data->count() || m_data->m_data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
147 //propertyWrite(propId);
148 std::pair<QVariant, bool> &prop = m_data->getDataRef(propId);
149 prop.first = propertyWriteValue(propId, *reinterpret_cast<QVariant *>(a[0]));
150 prop.second = true;
151 //propertyWritten(propId);
152 activate(myObject(), type()->signalOffset() + propId, nullptr);
153 }
154 }
155 return -1;
156 } else {
157 QDynamicMetaObjectData *dynamicParent = dynamicMetaObjectParent();
158 if (dynamicParent)
159 return dynamicParent->metaCall(o, call, id, a);
160 else
161 return myObject()->qt_metacall(call, id, a);
162 }
163}
164
165int QQmlDesignerMetaObject::metaCall(QObject *o, QMetaObject::Call call, int id, void **a)
166{
167 Q_ASSERT(myObject() == o);
168
169 int metaCallReturnValue = -1;
170
171 const QMetaProperty propertyById = property(id);
172
173 if (call == QMetaObject::WriteProperty
174 && propertyById.userType() == QMetaType::QVariant
175 && reinterpret_cast<QVariant *>(a[0])->userType() == QMetaType::Double
176 && qt_is_nan(reinterpret_cast<QVariant *>(a[0])->toDouble())) {
177 return -1;
178 }
179
180 if (call == QMetaObject::WriteProperty
181 && propertyById.userType() == QMetaType::Double
182 && qt_is_nan(*reinterpret_cast<double*>(a[0]))) {
183 return -1;
184 }
185
186 if (call == QMetaObject::WriteProperty
187 && propertyById.userType() == QMetaType::Float
188 && qt_is_nan(*reinterpret_cast<float*>(a[0]))) {
189 return -1;
190 }
191
192 QVariant oldValue;
193
194 if (call == QMetaObject::WriteProperty && !propertyById.hasNotifySignal())
195 {
196 oldValue = propertyById.read(myObject());
197 }
198
199 QDynamicMetaObjectData *dynamicParent = dynamicMetaObjectParent();
200 const QMetaObject *staticParent = dynamicParent
201 ? dynamicParent->toDynamicMetaObject(object())
202 : nullptr;
203 if (staticParent && id < staticParent->propertyOffset())
204 metaCallReturnValue = dynamicParent->metaCall(o, call, id, a);
205 else
206 openMetaCall(o, call, id, a);
207
208
209 if (call == QMetaObject::WriteProperty
210 && !propertyById.hasNotifySignal()
211 && oldValue != propertyById.read(myObject()))
213
214 return metaCallReturnValue;
215}
216
218{
219 const QMetaProperty propertyById = property(id);
220
221 if (id < propertyOffset()) {
224 } else {
225 if (notifyPropertyChangeCallBack)
226 notifyPropertyChangeCallBack(myObject(), name(id - propertyOffset()));
227 }
228}
229
231{
232 return type()->propertyCount();
233}
234
236{
237 return type()->propertyName(idx);
238}
239
240void QQmlDesignerMetaObject::registerNotifyPropertyChangeCallBack(void (*callback)(QObject *, const QQuickDesignerSupport::PropertyName &))
241{
243}
244
245QT_END_NAMESPACE
int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) override
void createNewDynamicProperty(const QString &name)
QDynamicMetaObjectData * dynamicMetaObjectParent() const
static void registerNotifyPropertyChangeCallBack(void(*callback)(QObject *, const QQuickDesignerSupport::PropertyName &propertyName))
void setValue(int id, const QVariant &value)
QVariant propertyWriteValue(int, const QVariant &) override
int createProperty(const char *name, const char *passAlong) override
int openMetaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a)
static QT_BEGIN_NAMESPACE QHash< QDynamicMetaObjectData *, bool > nodeInstanceMetaObjectList
static void(* notifyPropertyChangeCallBack)(QObject *, const QQuickDesignerSupport::PropertyName &propertyName)
std::pair< QVariant, bool > & getDataRef(int idx)
bool hasData(int idx) const
QVector< std::pair< QVariant, bool > > m_data
QVariant & getData(int idx)