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
qqmlpropertydata_p.h
Go to the documentation of this file.
1// Copyright (C) 2019 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 QQMLPROPERTYDATA_P_H
5#define QQMLPROPERTYDATA_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/qobject_p.h>
19#include <QtCore/qglobal.h>
20#include <QtCore/qversionnumber.h>
21
23
26{
27public:
34 Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
35
37
38 struct Flags {
39 friend class QQmlPropertyData;
40 enum Type {
41 OtherType = 0,
42 FunctionType = 1, // Is an invokable
43 QObjectDerivedType = 2, // Property type is a QObject* derived type
44 EnumType = 3, // Property type is an enum
45 QListType = 4, // Property type is a QML list
46 VarPropertyType = 5, // Property type is a "var" property of VMEMO
47 QVariantType = 6, // Property is a QVariant
48 // One spot left for an extra type in the 3 bits used to store this.
49 };
50
51 private:
52 // The _otherBits (which "pad" the Flags struct to align it nicely) are used
53 // to store the relative property index. It will only get used when said index fits. See
54 // trySetStaticMetaCallFunction for details.
55 // (Note: this padding is done here, because certain compilers have surprising behavior
56 // when an enum is declared in-between two bit fields.)
57 enum { BitsLeftInFlags = 16 };
58 unsigned otherBits : BitsLeftInFlags; // align to 32 bits
59
60 // Members of the form aORb can only be a when type is not FunctionType, and only be
61 // b when type equals FunctionType. For that reason, the semantic meaning of the bit is
62 // overloaded, and the accessor functions are used to get the correct value
63 //
64 // Moreover, isSignalHandler, isOverridableSignal and isCloned make only sense
65 // for functions, too (and could at a later point be reused for flags that only make sense
66 // for non-functions)
67 //
68 // Lastly, isDirect and isOverridden apply to both functions and non-functions
69 unsigned isConst : 1; // Property: has CONST flag/Method: is const
70 unsigned isVMEFunction : 1; // Function was added by QML
71 unsigned isWritableORhasArguments : 1; // Has WRITE function OR Function takes arguments
72 unsigned isResettableORisSignal : 1; // Has RESET function OR Function is a signal
73 unsigned isAliasORisVMESignal : 1; // Is a QML alias to another property OR Signal was added by QML
74 unsigned isFinalORisV4Function : 1; // Has FINAL flag OR Function takes QQmlV4FunctionPtr args
75 unsigned isSignalHandler : 1; // Function is a signal handler
76
77 // TODO: Remove this once we can. Signals should not be overridable.
78 unsigned isOverridableSignal : 1; // Function is an overridable signal
79
80 unsigned isRequiredORisCloned : 1; // Has REQUIRED flag OR The function was marked as cloned
81 unsigned isConstructorORisBindable : 1; // The function was marked is a constructor OR property is backed by QProperty<T>
82 unsigned isOverridden : 1; // Is overridden by a extension property
83 unsigned hasMetaObject : 1;
84 unsigned type : 3; // stores an entry of Types
85
86 // Internal QQmlPropertyCache flags
87 unsigned overrideIndexIsProperty : 1;
88
89 public:
90 inline Flags();
91 inline bool operator==(const Flags &other) const;
92 inline void copyPropertyTypeFlags(Flags from);
93
94 void setIsConstant(bool b) {
95 isConst = b;
96 }
97
98 void setIsWritable(bool b) {
99 Q_ASSERT(type != FunctionType);
100 isWritableORhasArguments = b;
101 }
102
103 void setIsResettable(bool b) {
104 Q_ASSERT(type != FunctionType);
105 isResettableORisSignal = b;
106 }
107
108 void setIsAlias(bool b) {
109 Q_ASSERT(type != FunctionType);
110 isAliasORisVMESignal = b;
111 }
112
113 void setIsFinal(bool b) {
114 Q_ASSERT(type != FunctionType);
115 isFinalORisV4Function = b;
116 }
117
118 void setIsOverridden(bool b) {
119 isOverridden = b;
120 }
121
122 void setIsBindable(bool b) {
123 Q_ASSERT(type != FunctionType);
124 isConstructorORisBindable = b;
125 }
126
127 void setIsRequired(bool b) {
128 Q_ASSERT(type != FunctionType);
129 isRequiredORisCloned = b;
130 }
131
132 void setIsVMEFunction(bool b) {
133 Q_ASSERT(type == FunctionType);
135 }
136 void setHasArguments(bool b) {
137 Q_ASSERT(type == FunctionType);
138 isWritableORhasArguments = b;
139 }
140 void setIsSignal(bool b) {
141 Q_ASSERT(type == FunctionType);
142 isResettableORisSignal = b;
143 }
144 void setIsVMESignal(bool b) {
145 Q_ASSERT(type == FunctionType);
146 isAliasORisVMESignal = b;
147 }
148
149 void setIsV4Function(bool b) {
150 Q_ASSERT(type == FunctionType);
151 isFinalORisV4Function = b;
152 }
153
155 Q_ASSERT(type == FunctionType);
157 }
158
159 // TODO: Remove this once we can. Signals should not be overridable.
161 Q_ASSERT(type == FunctionType);
162 Q_ASSERT(isResettableORisSignal);
164 }
165
166 void setIsCloned(bool b) {
167 Q_ASSERT(type == FunctionType);
168 isRequiredORisCloned = b;
169 }
170
171 void setIsConstructor(bool b) {
172 Q_ASSERT(type == FunctionType);
173 isConstructorORisBindable = b;
174 }
175
176 void setHasMetaObject(bool b) {
178 }
179
180 void setType(Type newType) {
181 type = newType;
182 }
183 };
184
185
186 inline bool operator==(const QQmlPropertyData &) const;
187
188 Flags flags() const { return m_flags; }
190 {
191 unsigned otherBits = m_flags.otherBits;
192 m_flags = f;
193 m_flags.otherBits = otherBits;
194 }
195
196 bool isValid() const { return coreIndex() != -1; }
197
198 bool isConstant() const { return m_flags.isConst; }
199 bool isWritable() const { return !isFunction() && m_flags.isWritableORhasArguments; }
200 void setWritable(bool onoff) { Q_ASSERT(!isFunction()); m_flags.isWritableORhasArguments = onoff; }
201 bool isResettable() const { return !isFunction() && m_flags.isResettableORisSignal; }
202 bool isAlias() const { return !isFunction() && m_flags.isAliasORisVMESignal; }
203 bool isFinal() const { return !isFunction() && m_flags.isFinalORisV4Function; }
204 bool isOverridden() const { return m_flags.isOverridden; }
205 bool isRequired() const { return !isFunction() && m_flags.isRequiredORisCloned; }
206 bool hasStaticMetaCallFunction() const { return staticMetaCallFunction() != nullptr; }
207 bool isFunction() const { return m_flags.type == Flags::FunctionType; }
208 bool isQObject() const { return m_flags.type == Flags::QObjectDerivedType; }
209 bool isEnum() const { return m_flags.type == Flags::EnumType; }
210 bool isQList() const { return m_flags.type == Flags::QListType; }
211 bool isVarProperty() const { return m_flags.type == Flags::VarPropertyType; }
212 bool isQVariant() const { return m_flags.type == Flags::QVariantType; }
213 bool isVMEFunction() const { return isFunction() && m_flags.isVMEFunction; }
214 bool hasArguments() const { return isFunction() && m_flags.isWritableORhasArguments; }
215 bool isSignal() const { return isFunction() && m_flags.isResettableORisSignal; }
216 bool isVMESignal() const { return isFunction() && m_flags.isAliasORisVMESignal; }
217 bool isV4Function() const { return isFunction() && m_flags.isFinalORisV4Function; }
218 bool isSignalHandler() const { return m_flags.isSignalHandler; }
219 bool hasMetaObject() const { return m_flags.hasMetaObject; }
220
221 // TODO: Remove this once we can. Signals should not be overridable.
222 bool isOverridableSignal() const { return m_flags.isOverridableSignal; }
223
224 bool isCloned() const { return isFunction() && m_flags.isRequiredORisCloned; }
225 bool isConstructor() const { return isFunction() && m_flags.isConstructorORisBindable; }
226 bool isBindable() const { return !isFunction() && m_flags.isConstructorORisBindable; }
227
228 bool hasOverride() const { return overrideIndex() >= 0; }
229 bool hasRevision() const { return revision() != QTypeRevision::zero(); }
230
231 QMetaType propType() const { return m_propType; }
233 {
234 m_propType = pt;
235 }
236
237 int notifyIndex() const { return m_notifyIndex; }
238 void setNotifyIndex(int idx)
239 {
240 Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
241 Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
242 m_notifyIndex = qint16(idx);
243 }
244
245 bool overrideIndexIsProperty() const { return m_flags.overrideIndexIsProperty; }
246 void setOverrideIndexIsProperty(bool onoff) { m_flags.overrideIndexIsProperty = onoff; }
247
248 int overrideIndex() const { return m_overrideIndex; }
249 void setOverrideIndex(int idx)
250 {
251 Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
252 Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
253 m_overrideIndex = qint16(idx);
254 }
255
256 int coreIndex() const { return m_coreIndex; }
257 void setCoreIndex(int idx)
258 {
259 Q_ASSERT(idx >= std::numeric_limits<qint16>::min());
260 Q_ASSERT(idx <= std::numeric_limits<qint16>::max());
261 m_coreIndex = qint16(idx);
262 }
263
264 QTypeRevision revision() const { return m_revision; }
266
267 /* If a property is a C++ type, then we store the minor
268 * version of this type.
269 * This is required to resolve property or signal revisions
270 * if this property is used as a grouped property.
271 *
272 * Test.qml
273 * property TextEdit someTextEdit: TextEdit {}
274 *
275 * Test {
276 * someTextEdit.preeditText: "test" //revision 7
277 * someTextEdit.onEditingFinished: console.log("test") //revision 6
278 * }
279 *
280 * To determine if these properties with revisions are available we need
281 * the minor version of TextEdit as imported in Test.qml.
282 *
283 */
284
285 QTypeRevision typeVersion() const { return m_typeVersion; }
287
298
299 const QMetaObject *metaObject() const
300 {
302 return m_metaObject;
303 }
304
306 {
308 m_flags.setHasMetaObject(true);
310 }
311
313 {
316 return m_metaObject->method(m_coreIndex);
317 }
318
319 int metaObjectOffset() const { return m_metaObjectOffset; }
321 {
322 Q_ASSERT(off >= std::numeric_limits<qint16>::min());
323 Q_ASSERT(off <= std::numeric_limits<qint16>::max());
324 m_metaObjectOffset = qint16(off);
325 }
326
329 {
331 if (relativePropertyIndex < (1 << Flags::BitsLeftInFlags) - 1) {
332 m_flags.otherBits = relativePropertyIndex;
334 }
335 }
336 quint16 relativePropertyIndex() const { Q_ASSERT(hasStaticMetaCallFunction()); return m_flags.otherBits; }
337
338 static Flags flagsForProperty(const QMetaProperty &);
339 void load(const QMetaProperty &);
340 void load(const QMetaMethod &);
341 QString name(QObject *) const;
342 QString name(const QMetaObject *) const;
343
344 bool markAsOverrideOf(QQmlPropertyData *predecessor);
345
346 inline void readProperty(QObject *target, void *property) const
347 {
348 void *args[] = { property, nullptr };
350 }
351
352 // This is the same as QMetaObject::metacall(), but inlined here to avoid a function call.
353 // And we ignore the return value.
354 template<QMetaObject::Call call>
355 void doMetacall(QObject *object, int idx, void **argv) const
356 {
357 if (QDynamicMetaObjectData *dynamicMetaObject = QObjectPrivate::get(object)->metaObject)
358 dynamicMetaObject->metaCall(object, call, idx, argv);
359 else
360 object->qt_metacall(call, idx, argv);
361 }
362
364 {
367 else
368 doMetacall<QMetaObject::ReadProperty>(target, coreIndex(), args);
369 }
370
371 bool writeProperty(QObject *target, void *value, WriteFlags flags) const
372 {
373 int status = -1;
374 void *argv[] = { value, nullptr, &status, &flags };
377 else
378 doMetacall<QMetaObject::WriteProperty>(target, coreIndex(), argv);
379 return true;
380 }
381
382 bool resetProperty(QObject *target, WriteFlags flags) const
383 {
386 else
387 doMetacall<QMetaObject::ResetProperty>(target, coreIndex(), nullptr);
388 return true;
389 }
390
392 {
393 Flags f;
394 f.setType(Flags::FunctionType);
395 f.setIsSignal(true);
396 f.setIsVMESignal(true);
397 return f;
398 }
399
401 {
402 Flags f;
403 f.setType(Flags::FunctionType);
404 f.setIsVMEFunction(true);
405 return f;
406 }
407
408private:
409 friend class QQmlPropertyCache;
410
411 Flags m_flags;
412 qint16 m_coreIndex = -1;
413
414 // The notify index is in the range returned by QObjectPrivate::signalIndex().
415 // This is different from QMetaMethod::methodIndex().
416 qint16 m_notifyIndex = -1;
417 qint16 m_overrideIndex = -1;
418
419 qint16 m_metaObjectOffset = -1;
420
421 QTypeRevision m_revision = QTypeRevision::zero();
422 QTypeRevision m_typeVersion = QTypeRevision::zero();
423
424 QMetaType m_propType = {};
425
426 union {
430 };
431};
432
433#if QT_POINTER_SIZE == 4
434 Q_STATIC_ASSERT(sizeof(QQmlPropertyData) == 24);
435#else // QT_POINTER_SIZE == 8
437#endif
438
439static_assert(std::is_trivially_copyable<QQmlPropertyData>::value);
440
442{
443 return flags() == other.flags() &&
444 propType() == other.propType() &&
445 coreIndex() == other.coreIndex() &&
446 notifyIndex() == other.notifyIndex() &&
447 revision() == other.revision();
448}
449
451 : otherBits(0)
452 , isConst(false)
453 , isVMEFunction(false)
454 , isWritableORhasArguments(false)
455 , isResettableORisSignal(false)
456 , isAliasORisVMESignal(false)
457 , isFinalORisV4Function(false)
458 , isSignalHandler(false)
459 , isOverridableSignal(false)
460 , isRequiredORisCloned(false)
461 , isConstructorORisBindable(false)
462 , isOverridden(false)
463 , hasMetaObject(false)
464 , type(OtherType)
465 , overrideIndexIsProperty(false)
466{
467}
468
470{
471 return isConst == other.isConst &&
472 isVMEFunction == other.isVMEFunction &&
473 isWritableORhasArguments == other.isWritableORhasArguments &&
474 isResettableORisSignal == other.isResettableORisSignal &&
475 isAliasORisVMESignal == other.isAliasORisVMESignal &&
476 isFinalORisV4Function == other.isFinalORisV4Function &&
477 isOverridden == other.isOverridden &&
478 isSignalHandler == other.isSignalHandler &&
479 isRequiredORisCloned == other.isRequiredORisCloned &&
480 hasMetaObject == other.hasMetaObject &&
481 type == other.type &&
482 isConstructorORisBindable == other.isConstructorORisBindable &&
483 overrideIndexIsProperty == other.overrideIndexIsProperty;
484}
485
487{
488 switch (from.type) {
489 case QObjectDerivedType:
490 case EnumType:
491 case QListType:
492 case QVariantType:
493 type = from.type;
494 }
495}
496
497Q_DECLARE_OPERATORS_FOR_FLAGS(QQmlPropertyData::WriteFlags)
498
500
501#endif // QQMLPROPERTYDATA_P_H
\inmodule QtCore
Definition qmetaobject.h:19
\inmodule QtCore
\inmodule QtCore
Definition qmetatype.h:341
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:150
\inmodule QtCore
Definition qobject.h:103
bool overrideIndexIsProperty() const
void readProperty(QObject *target, void *property) const
bool isResettable() const
bool isConstructor() const
bool isOverridden() const
int metaObjectOffset() const
bool isVarProperty() const
void readPropertyWithArgs(QObject *target, void *args[]) const
QMetaMethod metaMethod() const
QTypeRevision typeVersion() const
void setRevision(QTypeRevision revision)
bool writeProperty(QObject *target, void *value, WriteFlags flags) const
QTypeRevision revision() const
bool isVMEFunction() const
void setNotifyIndex(int idx)
StaticMetaCallFunction m_staticMetaCallFunction
StaticMetaCallFunction staticMetaCallFunction() const
bool operator==(const QQmlPropertyData &) const
void setMetaObjectOffset(int off)
void setMetaObject(const QMetaObject *metaObject)
bool hasArguments() const
QMetaType propType() const
bool isV4Function() const
void doMetacall(QObject *object, int idx, void **argv) const
void setOverrideIndexIsProperty(bool onoff)
void setCoreIndex(int idx)
void setArguments(QQmlPropertyCacheMethodArguments *args)
QObjectPrivate::StaticMetaCallFunction StaticMetaCallFunction
void setPropType(QMetaType pt)
bool hasMetaObject() const
const QMetaObject * m_metaObject
bool markAsOverrideOf(QQmlPropertyData *predecessor)
void setOverrideIndex(int idx)
QQmlPropertyCacheMethodArguments * arguments() const
QQmlPropertyCacheMethodArguments * m_arguments
static Flags defaultSlotFlags()
void setWritable(bool onoff)
bool hasStaticMetaCallFunction() const
void trySetStaticMetaCallFunction(StaticMetaCallFunction f, unsigned relativePropertyIndex)
static Flags defaultSignalFlags()
static Flags flagsForProperty(const QMetaProperty &)
void load(const QMetaProperty &)
bool resetProperty(QObject *target, WriteFlags flags) const
bool isSignalHandler() const
bool isOverridableSignal() const
void setTypeVersion(QTypeRevision typeVersion)
const QMetaObject * metaObject() const
quint16 relativePropertyIndex() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
static constexpr QTypeRevision zero()
Produces a QTypeRevision with major and minor version {0}.
Combined button and popup list for selecting options.
#define Q_STATIC_ASSERT(Condition)
Definition qassert.h:108
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_DECLARE_FLAGS(Flags, Enum)
Definition qflags.h:174
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
Definition qflags.h:194
Flags
GLboolean GLboolean GLboolean b
GLfloat GLfloat f
GLenum type
GLenum target
GLbitfield flags
GLuint name
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
short qint16
Definition qtypes.h:47
unsigned short quint16
Definition qtypes.h:48
const char property[13]
Definition qwizard.cpp:101
QSharedPointer< T > other(t)
[5]
QJSValueList args
\inmodule QtCore
QMetaMethod method(int index) const
Returns the meta-data for the method with the given index.
void copyPropertyTypeFlags(Flags from)
bool operator==(const Flags &other) const
Definition moc.h:23