Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmlpropertycache_p.h
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
4#ifndef QQMLPROPERTYCACHE_P_H
5#define QQMLPROPERTYCACHE_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <private/qlinkedstringhash_p.h>
19#include <private/qqmlenumdata_p.h>
20#include <private/qqmlenumvalue_p.h>
21#include <private/qqmlpropertydata_p.h>
22#include <private/qqmlrefcount_p.h>
23
24#include <QtCore/qvarlengtharray.h>
25#include <QtCore/qvector.h>
26#include <QtCore/qversionnumber.h>
27
28#include <limits>
29
31
33class QJSEngine;
35class QQmlContextData;
39
41{
42public:
44
46 : d(quintptr(staticMetaObject))
47 {
48 Q_ASSERT((d.loadRelaxed() & Shared) == 0);
49 }
50
52 {
53 const auto dd = d.loadAcquire();
54 if (dd & Shared)
55 reinterpret_cast<SharedHolder *>(dd ^ Shared)->release();
56 }
57
58private:
59 friend class QQmlPropertyCache;
61 : d(other.d.loadRelaxed())
62 {
63 // other has to survive until this ctor is done. So d cannot disappear before.
64 const auto od = other.d.loadRelaxed();
65 if (od & Shared)
66 reinterpret_cast<SharedHolder *>(od ^ Shared)->addref();
67 }
68
71 QQmlMetaObjectPointer &operator=(const QQmlMetaObjectPointer &other) = delete;
72
73public:
74 void setSharedOnce(QMetaObject *shared) const
75 {
76 SharedHolder *holder = new SharedHolder(shared);
77 if (!d.testAndSetRelease(0, quintptr(holder) | Shared))
78 holder->release();
79 }
80
81 const QMetaObject *metaObject() const
82 {
83 const auto dd = d.loadAcquire();
84 if (dd & Shared)
85 return reinterpret_cast<SharedHolder *>(dd ^ Shared)->metaObject;
86 return reinterpret_cast<const QMetaObject *>(dd);
87 }
88
89 bool isShared() const
90 {
91 // This works because static metaobjects need to be set in the ctor and once a shared
92 // metaobject has been set, it cannot be removed anymore.
93 const auto dd = d.loadRelaxed();
94 return !dd || (dd & Shared);
95 }
96
97 bool isNull() const
98 {
99 return d.loadRelaxed() == 0;
100 }
101
102private:
103 enum Tag {
104 Static = 0,
105 Shared = 1
106 };
107
108 struct SharedHolder final : public QQmlRefCounted<SharedHolder>
109 {
110 Q_DISABLE_COPY_MOVE(SharedHolder)
111 SharedHolder(QMetaObject *shared) : metaObject(shared) {}
112 ~SharedHolder() { free(metaObject); }
113 QMetaObject *metaObject;
114 };
115
116 mutable QBasicAtomicInteger<quintptr> d = 0;
117};
118
119class Q_QML_EXPORT QQmlPropertyCache final
120 : public QQmlRefCounted<QQmlPropertyCache>
121{
122public:
123 using Ptr = QQmlRefPointer<QQmlPropertyCache>;
124
125 struct ConstPtr : public QQmlRefPointer<const QQmlPropertyCache>
126 {
128
129 ConstPtr(const Ptr &ptr) : ConstPtr(ptr.data(), AddRef) {}
130 ConstPtr(Ptr &&ptr) : ConstPtr(ptr.take(), Adopt) {}
132 ConstPtr &operator=(Ptr &&ptr) { return operator=(ConstPtr(std::move(ptr))); }
133 };
134
135 static Ptr createStandalone(
136 const QMetaObject *, QTypeRevision metaObjectRevision = QTypeRevision::zero());
137
138 QQmlPropertyCache() = default;
140
141 void update(const QMetaObject *);
142 void invalidate(const QMetaObject *);
143
145
146 QQmlPropertyCache::Ptr copyAndAppend(
147 const QMetaObject *, QTypeRevision typeVersion,
151
152 QQmlPropertyCache::Ptr copyAndReserve(
153 int propertyCount, int methodCount, int signalCount, int enumCount) const;
154 void appendProperty(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
155 QMetaType propType, QTypeRevision revision, int notifyIndex);
156 void appendSignal(const QString &, QQmlPropertyData::Flags, int coreIndex,
157 const QMetaType *types = nullptr,
158 const QList<QByteArray> &names = QList<QByteArray>());
159 void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
160 QMetaType returnType, const QList<QByteArray> &names,
161 const QVector<QMetaType> &parameterTypes);
162 void appendEnum(const QString &, const QVector<QQmlEnumValue> &);
163
164 const QMetaObject *metaObject() const;
165 const QMetaObject *createMetaObject() const;
166 const QMetaObject *firstCppMetaObject() const;
167
168 template<typename K>
169 const QQmlPropertyData *property(const K &key, QObject *object,
170 const QQmlRefPointer<QQmlContextData> &context) const
171 {
172 return findProperty(stringCache.find(key), object, context);
173 }
174
175 const QQmlPropertyData *property(int) const;
176 const QQmlPropertyData *maybeUnresolvedProperty(int) const;
177 const QQmlPropertyData *method(int) const;
178 const QQmlPropertyData *signal(int index) const;
179 QQmlEnumData *qmlEnum(int) const;
180 int methodIndexToSignalIndex(int) const;
181
182 QString defaultPropertyName() const;
183 const QQmlPropertyData *defaultProperty() const;
184
185 // Return a reference here so that we don't have to addref/release all the time
186 inline const QQmlPropertyCache::ConstPtr &parent() const;
187
188 // is used by the Qml Designer
190
191 inline const QQmlPropertyData *overrideData(const QQmlPropertyData *) const;
192 inline bool isAllowedInRevision(const QQmlPropertyData *) const;
193
194 static const QQmlPropertyData *property(
195 QObject *, QStringView, const QQmlRefPointer<QQmlContextData> &,
197 static const QQmlPropertyData *property(QObject *, const QLatin1String &, const QQmlRefPointer<QQmlContextData> &,
199 static const QQmlPropertyData *property(QObject *, const QV4::String *, const QQmlRefPointer<QQmlContextData> &,
201
202 //see QMetaObjectPrivate::originalClone
203 int originalClone(int index) const;
204 static int originalClone(const QObject *, int index);
205
206 QList<QByteArray> signalParameterNames(int index) const;
207 static QString signalParameterStringForJS(QV4::ExecutionEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString = nullptr);
208
209 const char *className() const;
210
211 inline int propertyCount() const;
212 inline int propertyOffset() const;
213 inline int methodCount() const;
214 inline int methodOffset() const;
215 inline int signalCount() const;
216 inline int signalOffset() const;
217 inline int qmlEnumCount() const;
218
219 void toMetaObjectBuilder(QMetaObjectBuilder &) const;
220
221 inline bool callJSFactoryMethod(QObject *object, void **args) const;
222
223 static bool determineMetaObjectSizes(const QMetaObject &mo, int *fieldCount, int *stringCount);
224 static bool addToHash(QCryptographicHash &hash, const QMetaObject &mo);
225
226 QByteArray checksum(QHash<quintptr, QByteArray> *checksums, bool *ok) const;
227
228 QTypeRevision allowedRevision(int index) const { return allowedRevisionCache[index]; }
229 void setAllowedRevision(int index, QTypeRevision allowed) { allowedRevisionCache[index] = allowed; }
230
231private:
232 friend class QQmlEnginePrivate;
233 friend class QQmlCompiler;
234 template <typename T> friend class QQmlPropertyCacheCreator;
235 template <typename T> friend class QQmlPropertyCacheAliasCreator;
236 template <typename T> friend class QQmlComponentAndAliasResolver;
237 friend class QQmlMetaObject;
238
240
242
243 void append(const QMetaObject *, QTypeRevision typeVersion,
247
248 QQmlPropertyCacheMethodArguments *createArgumentsObject(int count, const QList<QByteArray> &names);
249
250 typedef QVector<QQmlPropertyData> IndexCache;
251 typedef QLinkedStringMultiHash<QPair<int, QQmlPropertyData *> > StringCache;
252 typedef QVector<QTypeRevision> AllowedRevisionCache;
253
254 const QQmlPropertyData *findProperty(StringCache::ConstIterator it, QObject *,
255 const QQmlRefPointer<QQmlContextData> &) const;
256 const QQmlPropertyData *findProperty(StringCache::ConstIterator it, const QQmlVMEMetaObject *,
257 const QQmlRefPointer<QQmlContextData> &) const;
258
259 template<typename K>
260 QQmlPropertyData *findNamedProperty(const K &key) const
261 {
262 StringCache::mapped_type *it = stringCache.value(key);
263 return it ? it->second : 0;
264 }
265
266 template<typename K>
267 void setNamedProperty(const K &key, int index, QQmlPropertyData *data)
268 {
269 stringCache.insert(key, qMakePair(index, data));
270 }
271
272private:
273 enum OverrideResult { NoOverride, InvalidOverride, ValidOverride };
274
275 template<typename String>
276 OverrideResult handleOverride(const String &name, QQmlPropertyData *data, QQmlPropertyData *old)
277 {
278 if (!old)
279 return NoOverride;
280
281 if (data->markAsOverrideOf(old))
282 return ValidOverride;
283
284 qWarning("Final member %s is overridden in class %s. The override won't be used.",
286 return InvalidOverride;
287 }
288
289 template<typename String>
290 OverrideResult handleOverride(const String &name, QQmlPropertyData *data)
291 {
292 return handleOverride(name, data, findNamedProperty(name));
293 }
294
295 int propertyIndexCacheStart = 0; // placed here to avoid gap between QQmlRefCount and _parent
297
298 IndexCache propertyIndexCache;
299 IndexCache methodIndexCache;
300 IndexCache signalHandlerIndexCache;
301 StringCache stringCache;
302 AllowedRevisionCache allowedRevisionCache;
303 QVector<QQmlEnumData> enumCache;
304
305 QQmlMetaObjectPointer _metaObject;
306 QByteArray _dynamicClassName;
307 QByteArray _dynamicStringData;
308 QByteArray _listPropertyAssignBehavior;
309 QString _defaultPropertyName;
310 QQmlPropertyCacheMethodArguments *argumentsCache = nullptr;
311 int methodIndexCacheStart = 0;
312 int signalHandlerIndexCacheStart = 0;
313 int _jsFactoryMethodIndex = -1;
314};
315
316// Returns this property cache's metaObject. May be null if it hasn't been created yet.
318{
319 return _metaObject.metaObject();
320}
321
322// Returns the first C++ type's QMetaObject - that is, the first QMetaObject not created by
323// QML
325{
326 const QQmlPropertyCache *p = this;
327 while (p->_metaObject.isShared())
328 p = p->parent().data();
329 return p->_metaObject.metaObject();
330}
331
333{
334 if (index < 0 || index >= propertyCount())
335 return nullptr;
336
337 if (index < propertyIndexCacheStart)
338 return _parent->property(index);
339
340 return &propertyIndexCache.at(index - propertyIndexCacheStart);
341}
342
344{
345 if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.size()))
346 return nullptr;
347
348 if (index < methodIndexCacheStart)
349 return _parent->method(index);
350
351 return const_cast<const QQmlPropertyData *>(&methodIndexCache.at(index - methodIndexCacheStart));
352}
353
359{
360 if (index < 0 || index >= (signalHandlerIndexCacheStart + signalHandlerIndexCache.size()))
361 return nullptr;
362
363 if (index < signalHandlerIndexCacheStart)
364 return _parent->signal(index);
365
366 const QQmlPropertyData *rv = const_cast<const QQmlPropertyData *>(&methodIndexCache.at(index - signalHandlerIndexCacheStart));
367 Q_ASSERT(rv->isSignal() || rv->coreIndex() == -1);
368 return rv;
369}
370
372{
373 if (index < 0 || index >= enumCache.size())
374 return nullptr;
375
376 return const_cast<QQmlEnumData *>(&enumCache.at(index));
377}
378
380{
381 if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.size()))
382 return index;
383
384 if (index < methodIndexCacheStart)
385 return _parent->methodIndexToSignalIndex(index);
386
387 return index - methodIndexCacheStart + signalHandlerIndexCacheStart;
388}
389
390// Returns the name of the default property for this cache
392{
393 return _defaultPropertyName;
394}
395
397{
398 return _parent;
399}
400
401const QQmlPropertyData *
403{
404 if (!data->hasOverride())
405 return nullptr;
406
407 if (data->overrideIndexIsProperty())
408 return property(data->overrideIndex());
409 else
410 return method(data->overrideIndex());
411}
412
414{
415 const QTypeRevision requested = data->revision();
416 const int offset = data->metaObjectOffset();
417 if (offset == -1 && requested == QTypeRevision::zero())
418 return true;
419
420 Q_ASSERT(offset >= 0);
421 Q_ASSERT(offset < allowedRevisionCache.size());
422 const QTypeRevision allowed = allowedRevisionCache[offset];
423
424 if (requested.hasMajorVersion()) {
425 if (requested.majorVersion() > allowed.majorVersion())
426 return false;
427 if (requested.majorVersion() < allowed.majorVersion())
428 return true;
429 }
430
431 return !requested.hasMinorVersion() || requested.minorVersion() <= allowed.minorVersion();
432}
433
435{
436 return propertyIndexCacheStart + int(propertyIndexCache.size());
437}
438
440{
441 return propertyIndexCacheStart;
442}
443
445{
446 return methodIndexCacheStart + int(methodIndexCache.size());
447}
448
450{
451 return methodIndexCacheStart;
452}
453
455{
456 return signalHandlerIndexCacheStart + int(signalHandlerIndexCache.size());
457}
458
460{
461 return signalHandlerIndexCacheStart;
462}
463
465{
466 return int(enumCache.size());
467}
468
470{
471 if (_jsFactoryMethodIndex != -1) {
472 if (const QMetaObject *mo = _metaObject.metaObject()) {
473 mo->d.static_metacall(object, QMetaObject::InvokeMetaMethod,
474 _jsFactoryMethodIndex, args);
475 return true;
476 }
477 return false;
478 }
479 if (_parent)
480 return _parent->callJSFactoryMethod(object, args);
481 return false;
482}
483
485
486#endif // QQMLPROPERTYCACHE_P_H
T loadAcquire() const noexcept
T loadRelaxed() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
The QJSEngine class provides an environment for evaluating JavaScript code.
Definition qjsengine.h:26
\inmodule QtCore
Definition qmetatype.h:341
\inmodule QtCore
Definition qobject.h:103
const QMetaObject * metaObject() const
Q_NODISCARD_CTOR QQmlMetaObjectPointer(const QMetaObject *staticMetaObject)
void setSharedOnce(QMetaObject *shared) const
Q_NODISCARD_CTOR QQmlMetaObjectPointer()=default
const QQmlPropertyData * method(int) const
const QQmlPropertyData * signal(int index) const
QQmlPropertyCache()=default
QTypeRevision allowedRevision(int index) const
const QQmlPropertyData * property(const K &key, QObject *object, const QQmlRefPointer< QQmlContextData > &context) const
QQmlEnumData * qmlEnum(int) const
const QQmlPropertyData * overrideData(const QQmlPropertyData *) const
bool callJSFactoryMethod(QObject *object, void **args) const
const QMetaObject * metaObject() const
bool isAllowedInRevision(const QQmlPropertyData *) const
const QQmlPropertyCache::ConstPtr & parent() const
const QMetaObject * firstCppMetaObject() const
void setAllowedRevision(int index, QTypeRevision allowed)
QString defaultPropertyName() const
int methodIndexToSignalIndex(int) const
void release() const
T * data() const
iterator insert(const T &value)
Definition qset.h:155
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
constexpr bool hasMinorVersion() const
Returns true if the minor version is known, otherwise false.
static constexpr QTypeRevision zero()
Produces a QTypeRevision with major and minor version {0}.
constexpr bool hasMajorVersion() const
Returns true if the major version is known, otherwise false.
constexpr quint8 minorVersion() const
Returns the minor version encoded in the revision.
constexpr quint8 majorVersion() const
Returns the major version encoded in the revision.
QHash< int, QWidget * > hash
[35multi]
list append(new Employee("Blackpool", "Stephen"))
QSet< QString >::iterator it
set reserve(20000)
auto signal
auto mo
[7]
Combined button and popup list for selecting options.
static void * context
static jboolean copy(JNIEnv *, jobject)
#define Q_NODISCARD_CTOR
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
static quint32 checksum(const QByteArray &table)
quint32 Tag
#define qWarning
Definition qlogging.h:166
static ControlElement< T > * ptr(QWidget *widget)
static int methodIndexToSignalIndex(const QMetaObject **base, int signal_index)
Definition qobject.cpp:3528
GLuint64 key
GLuint index
[2]
GLsizei GLenum GLenum * types
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLbitfield flags
GLenum GLuint GLintptr offset
GLuint name
GLuint GLuint * names
GLfloat GLfloat p
[1]
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition qpair.h:19
const QMetaObject * firstCppMetaObject(QQuickAttachedPropertyPropagator *propagator)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1531
size_t quintptr
Definition qtypes.h:167
const char property[13]
Definition qwizard.cpp:101
const char className[16]
[1]
Definition qwizard.cpp:100
obj metaObject() -> className()
sem release()
QSharedPointer< T > other(t)
[5]
file setParent(multiPart)
QJSValueList args
QJSEngine engine
[0]
\inmodule QtCore
ConstPtr & operator=(const Ptr &ptr)
ConstPtr & operator=(Ptr &&ptr)