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
qquickdesignercustomobjectdata.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// Qt-Security score:significant reason:default
4
7
9
10#include <QGlobalStatic>
11#include <QQmlContext>
12#include <QQmlEngine>
13
14#include <private/qqmlanybinding_p.h>
15
17
18using namespace Qt::StringLiterals;
19
22
27
28QQuickDesignerCustomObjectData::QQuickDesignerCustomObjectData(QObject *object)
29 : m_object(object)
30{
31 if (object) {
32 populateResetHashes();
33 s_designerObjectToDataHash()->insert(object, this);
34
36 functor.data = this;
37 QObject::connect(object, &QObject::destroyed, functor);
38 }
39}
40
42{
44}
45
47{
48 return s_designerObjectToDataHash()->value(object);
49}
50
51QVariant QQuickDesignerCustomObjectData::getResetValue(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
52{
54
55 if (data)
56 return data->getResetValue(propertyName);
57
58 return QVariant();
59}
60
61void QQuickDesignerCustomObjectData::doResetProperty(QObject *object, QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName)
62{
64
65 if (data)
66 data->doResetProperty(context, propertyName);
67}
68
69bool QQuickDesignerCustomObjectData::hasValidResetBinding(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
70{
72
73 if (data)
74 return data->hasValidResetBinding(propertyName);
75
76 return false;
77}
78
79bool QQuickDesignerCustomObjectData::hasBindingForProperty(QObject *object,
80 QQmlContext *context,
81 const QQuickDesignerSupport::PropertyName &propertyName,
82 bool *hasChanged)
83{
85
86 if (data)
87 return data->hasBindingForProperty(context, propertyName, hasChanged);
88
89 return false;
90}
91
92void QQuickDesignerCustomObjectData::setPropertyBinding(QObject *object,
93 QQmlContext *context,
94 const QQuickDesignerSupport::PropertyName &propertyName,
95 const QString &expression)
96{
98
99 if (data)
100 data->setPropertyBinding(context, propertyName, expression);
101}
102
103void QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(QObject *object,
104 QQmlContext *context,
105 const QQuickDesignerSupport::PropertyName &propertyName)
106{
108
109 if (data)
110 data->keepBindingFromGettingDeleted(context, propertyName);
111}
112
113void QQuickDesignerCustomObjectData::populateResetHashes()
114{
115 const QQuickDesignerSupport::PropertyNameList propertyNameList =
116 QQuickDesignerSupportProperties::propertyNameListForWritableProperties(object());
117
118 const QMetaObject *mo = object()->metaObject();
119 QByteArrayList deferredPropertyNames;
120 const int namesIndex = mo->indexOfClassInfo("DeferredPropertyNames");
121 if (namesIndex != -1) {
122 QMetaClassInfo classInfo = mo->classInfo(namesIndex);
123 deferredPropertyNames = QByteArray(classInfo.value()).split(',');
124 }
125
126 for (const QQuickDesignerSupport::PropertyName &propertyName : propertyNameList) {
127
128 if (deferredPropertyNames.contains(propertyName))
129 continue;
130
131 QQmlProperty property(object(), QString::fromUtf8(propertyName), QQmlEngine::contextForObject(object()));
132
133 auto binding = QQmlAnyBinding::ofProperty(property);
134
135 if (binding) {
136 m_resetBindingHash.insert(propertyName, binding);
137 } else if (property.isWritable()) {
138 m_resetValueHash.insert(propertyName, property.read());
139 }
140 }
141}
142
143QObject *QQuickDesignerCustomObjectData::object() const
144{
145 return m_object;
146}
147
148QVariant QQuickDesignerCustomObjectData::getResetValue(const QQuickDesignerSupport::PropertyName &propertyName) const
149{
150 return m_resetValueHash.value(propertyName);
151}
152
153void QQuickDesignerCustomObjectData::doResetProperty(QQmlContext *context, const QQuickDesignerSupport::PropertyName &propertyName)
154{
155 QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
156
157 if (!property.isValid())
158 return;
159
160 // remove existing binding
161 QQmlAnyBinding::takeFrom(property);
162
163
164 if (hasValidResetBinding(propertyName)) {
165 QQmlAnyBinding binding = getResetBinding(propertyName);
166 binding.installOn(property);
167
168 if (binding.isAbstractPropertyBinding()) {
169 // for new style properties, we will evaluate during setBinding anyway
170 static_cast<QQmlBinding *>(binding.asAbstractBinding())->update();
171 }
172
173 } else if (property.isResettable()) {
174 property.reset();
175 } else if (property.propertyTypeCategory() == QQmlProperty::List) {
176 QQmlListReference list = qvariant_cast<QQmlListReference>(property.read());
177
178 if (!QQuickDesignerSupportProperties::hasFullImplementedListInterface(list)) {
179 qWarning() << "Property list interface not fully implemented for Class " << property.property().typeName() << " in property " << property.name() << "!";
180 return;
181 }
182
183 list.clear();
184 } else if (property.isWritable()) {
185 if (property.read() == getResetValue(propertyName))
186 return;
187
188 property.write(getResetValue(propertyName));
189 }
190}
191
192bool QQuickDesignerCustomObjectData::hasValidResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const
193{
194 return m_resetBindingHash.contains(propertyName) && m_resetBindingHash.value(propertyName);
195}
196
197QQmlAnyBinding QQuickDesignerCustomObjectData::getResetBinding(const QQuickDesignerSupport::PropertyName &propertyName) const
198{
199 return m_resetBindingHash.value(propertyName);
200}
201
202bool QQuickDesignerCustomObjectData::hasBindingForProperty(QQmlContext *context,
203 const QQuickDesignerSupport::PropertyName &propertyName,
204 bool *hasChanged) const
205{
206 if (QQuickDesignerSupportProperties::isPropertyBlackListed(propertyName))
207 return false;
208
209 QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
210
211 bool hasBinding = QQmlAnyBinding::ofProperty(property);
212
213 if (hasChanged) {
214 *hasChanged = hasBinding != m_hasBindingHash.value(propertyName, false);
215 if (*hasChanged)
216 m_hasBindingHash.insert(propertyName, hasBinding);
217 }
218
219 return hasBinding;
220}
221
222void QQuickDesignerCustomObjectData::setPropertyBinding(QQmlContext *context,
223 const QQuickDesignerSupport::PropertyName &propertyName,
224 const QString &expression)
225{
226 QQmlProperty property(object(), QString::fromUtf8(propertyName), context);
227
228 if (!property.isValid())
229 return;
230
231 if (property.isProperty()) {
232 QString url = u"@designer"_s;
233 int lineNumber = 0;
234 QQmlAnyBinding binding = QQmlAnyBinding::createFromCodeString(property,
235 expression, object(), QQmlContextData::get(context), url, lineNumber);
236
237 binding.installOn(property);
238 if (binding.isAbstractPropertyBinding()) {
239 // for new style properties, we will evaluate during setBinding anyway
240 static_cast<QQmlBinding *>(binding.asAbstractBinding())->update();
241 }
242
243 if (binding.hasError()) {
244 if (property.property().userType() == QMetaType::QString)
245 property.write(QVariant(QLatin1Char('#') + expression + QLatin1Char('#')));
246 }
247
248 } else {
249 qWarning() << Q_FUNC_INFO << ": Cannot set binding for property" << propertyName << ": property is unknown for type";
250 }
251}
252
253void QQuickDesignerCustomObjectData::keepBindingFromGettingDeleted(QQmlContext *context,
254 const QQuickDesignerSupport::PropertyName &propertyName)
255{
256 //Refcounting is taking care
257 Q_UNUSED(context);
258 Q_UNUSED(propertyName);
259}
260
261void QQuickDesignerCustomObjectData::handleDestroyed()
262{
263 s_designerObjectToDataHash()->remove(m_object);
264 delete this;
265}
266
267QT_END_NAMESPACE
static QQuickDesignerCustomObjectData * get(QObject *object)
Combined button and popup list for selecting options.
Q_GLOBAL_STATIC(QReadWriteLock, g_updateMutex)
QHash< QObject *, QQuickDesignerCustomObjectData * > CustomObjectDataHash
QQuickDesignerCustomObjectData * data