Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qqmlopenmetaobject.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
4
5
#
include
"qqmlopenmetaobject_p.h"
6
#
include
<
private
/
qqmlpropertycache_p
.
h
>
7
#
include
<
private
/
qqmldata_p
.
h
>
8
#
include
<
private
/
qqmlmetatype_p
.
h
>
9
10
#
include
<
private
/
qmetaobjectbuilder_p
.
h
>
11
#
include
<
qdebug
.
h
>
12
#
include
<
QtCore
/
qpointer
.
h
>
13
#
include
<
QtCore
/
qset
.
h
>
14
15
QT_BEGIN_NAMESPACE
16
17
18
class
QQmlOpenMetaObjectTypePrivate
19
{
20
public
:
21
QQmlOpenMetaObjectTypePrivate
() :
mem
(
nullptr
) {}
22
23
void
init
(
const
QMetaObject *metaObj);
24
25
int
propertyOffset
;
26
int
signalOffset
;
27
QHash
<
QByteArray
,
int
>
names
;
28
QMetaObjectBuilder
mob
;
29
QMetaObject
*
mem
;
30
31
// TODO: We need to make sure that this does not escape into other threads.
32
// In particular, all its non-const uses are probably wrong. You should
33
// only set the open metaobject to "cached" once it's not going to be
34
// modified anymore.
35
QQmlPropertyCache
::
Ptr
cache
;
36
37
QSet
<
QQmlOpenMetaObject
*>
referers
;
38
};
39
40
QQmlOpenMetaObjectType::QQmlOpenMetaObjectType(
const
QMetaObject *base)
41
: d(
new
QQmlOpenMetaObjectTypePrivate)
42
{
43
d->init(base);
44
}
45
46
QQmlOpenMetaObjectType::~QQmlOpenMetaObjectType()
47
{
48
if
(d->mem)
49
free(d->mem);
50
delete
d;
51
}
52
53
int
QQmlOpenMetaObjectType::propertyOffset()
const
54
{
55
return
d->propertyOffset;
56
}
57
58
int
QQmlOpenMetaObjectType::signalOffset()
const
59
{
60
return
d->signalOffset;
61
}
62
63
int
QQmlOpenMetaObjectType::propertyCount()
const
64
{
65
return
d->names.size();
66
}
67
68
QByteArray QQmlOpenMetaObjectType::propertyName(
int
idx)
const
69
{
70
Q_ASSERT(idx >= 0 && idx < d->names.size());
71
72
return
d->mob.property(idx).name();
73
}
74
75
QQmlPropertyCache::Ptr QQmlOpenMetaObjectType::cache()
const
76
{
77
return
d->cache;
78
}
79
80
void
QQmlOpenMetaObjectType::createProperties(
const
QList<QByteArray> &names)
81
{
82
for
(
int
i = 0; i < names.size(); ++i) {
83
const
QByteArray &name = names.at(i);
84
const
int
id = d->mob.propertyCount();
85
d->mob.addSignal(
"__"
+ QByteArray::number(id) +
"()"
);
86
QMetaPropertyBuilder build = d->mob.addProperty(name,
"QVariant"
, id);
87
propertyCreated(id, build);
88
d->names.insert(name, id);
89
}
90
free(d->mem);
91
d->mem = d->mob.toMetaObject();
92
QSet<QQmlOpenMetaObject*>::iterator it = d->referers.begin();
93
while
(it != d->referers.end()) {
94
QQmlOpenMetaObject *omo = *it;
95
*
static_cast
<QMetaObject *>(omo) = *d->mem;
96
if
(d->cache)
97
d->cache->update(omo);
98
++it;
99
}
100
}
101
102
int
QQmlOpenMetaObjectType::createProperty(
const
QByteArray &name)
103
{
104
const
int
signalIdx = d->mob.addSignal(
105
"__"
+ QByteArray::number(d->mob.propertyCount()) +
"()"
).index();
106
QMetaPropertyBuilder build = d->mob.addProperty(name,
"QVariant"
, signalIdx);
107
propertyCreated(build.index(), build);
108
free(d->mem);
109
d->mem = d->mob.toMetaObject();
110
d->names.insert(name, build.index());
111
QSet<QQmlOpenMetaObject*>::iterator it = d->referers.begin();
112
while
(it != d->referers.end()) {
113
QQmlOpenMetaObject *omo = *it;
114
*
static_cast
<QMetaObject *>(omo) = *d->mem;
115
if
(d->cache)
116
d->cache->update(omo);
117
++it;
118
}
119
120
return
d->propertyOffset + build.index();
121
}
122
123
void
QQmlOpenMetaObjectType::propertyCreated(
int
id, QMetaPropertyBuilder &builder)
124
{
125
if
(d->referers.size())
126
(*d->referers.begin())->propertyCreated(id, builder);
127
}
128
129
void
QQmlOpenMetaObjectTypePrivate
::
init
(
const
QMetaObject *metaObj)
130
{
131
if
(!mem) {
132
mob.setSuperClass(metaObj);
133
mob.setClassName(metaObj->className());
134
mob.setFlags(MetaObjectFlag::DynamicMetaObject);
135
136
mem = mob.toMetaObject();
137
138
propertyOffset
= mem->propertyOffset();
139
signalOffset
= mem->methodOffset();
140
}
141
}
142
143
//----------------------------------------------------------------------------
144
145
class
QQmlOpenMetaObjectPrivate
146
{
147
public
:
148
QQmlOpenMetaObjectPrivate
(QQmlOpenMetaObject *_q, QObject *obj)
149
:
q
(
_q
),
object
(
obj
) {}
150
151
struct
Property
{
152
private
:
153
QVariant m_value;
154
QPointer<QObject> qobjectTracker;
155
public
:
156
bool
valueSet
=
false
;
157
158
QVariant
value
()
const
{
159
if
(m_value.metaType().flags() & QMetaType::PointerToQObject
160
&& qobjectTracker.isNull())
161
return
QVariant::fromValue<QObject*>(
nullptr
);
162
return
m_value;
163
}
164
QVariant
&
valueRef
() {
return
m_value; }
165
void
setValue
(
const
QVariant &v) {
166
m_value = v;
167
valueSet
=
true
;
168
if
(v.metaType().flags() & QMetaType::PointerToQObject)
169
qobjectTracker = m_value.value<QObject*>();
170
}
171
};
172
173
inline
void
setPropertyValue
(
int
idx,
const
QVariant &value) {
174
if
(data.size() <= idx)
175
data.resize(idx + 1);
176
data[idx].setValue(value);
177
}
178
179
inline
Property
&
propertyRef
(
int
idx) {
180
if
(data.size() <= idx)
181
data.resize(idx + 1);
182
Property
&prop = data[idx];
183
if
(!prop
.
valueSet
)
184
prop.setValue(q->initialValue(idx));
185
return
prop;
186
}
187
188
inline
QVariant
propertyValue
(
int
idx) {
189
auto
&prop =
propertyRef
(
idx
)
;
190
return
prop.value();
191
}
192
193
inline
QVariant
&
propertyValueRef
(
int
idx) {
194
auto
&prop =
propertyRef
(
idx
)
;
195
return
prop.valueRef();
196
}
197
198
inline
bool
hasProperty
(
int
idx)
const
{
199
if
(idx >= data.size())
200
return
false
;
201
return
data[idx].valueSet;
202
}
203
204
void
dropStalePropertyCache
() {
205
// Do not drop the property cache if we've created it ourselves.
206
// In that case we've also updated it to reflect any changes.
207
if
(
cacheProperties
)
208
return
;
209
if
(QQmlData *ddata = QQmlData::get(object,
/*create*/
false
))
210
ddata->propertyCache.reset();
211
}
212
213
QQmlOpenMetaObject
*
q
;
214
QDynamicMetaObjectData
*
parent
=
nullptr
;
215
QList
<
Property
>
data
;
216
QObject
*
object
;
217
QQmlRefPointer
<
QQmlOpenMetaObjectType
>
type
;
218
QList
<
QByteArray
> *
deferredPropertyNames
=
nullptr
;
219
bool
autoCreate
=
true
;
220
bool
cacheProperties
=
false
;
221
};
222
223
QQmlOpenMetaObject::QQmlOpenMetaObject(QObject *obj,
const
QMetaObject *base)
224
: d(
new
QQmlOpenMetaObjectPrivate(
this
, obj))
225
{
226
d->type.adopt(
new
QQmlOpenMetaObjectType(base ? base : obj->metaObject()));
227
d->type->d->referers.insert(
this
);
228
229
QObjectPrivate *op = QObjectPrivate::get(obj);
230
d->parent = op->metaObject;
231
*
static_cast
<QMetaObject *>(
this
) = *d->type->d->mem;
232
op->metaObject =
this
;
233
}
234
235
QQmlOpenMetaObject::QQmlOpenMetaObject(
236
QObject *obj,
const
QQmlRefPointer<QQmlOpenMetaObjectType> &type)
237
: d(
new
QQmlOpenMetaObjectPrivate(
this
, obj))
238
{
239
d->type = type;
240
d->type->d->referers.insert(
this
);
241
242
QObjectPrivate *op = QObjectPrivate::get(obj);
243
d->parent = op->metaObject;
244
*
static_cast
<QMetaObject *>(
this
) = *d->type->d->mem;
245
op->metaObject =
this
;
246
}
247
248
QQmlOpenMetaObject::~QQmlOpenMetaObject()
249
{
250
if
(d->parent)
251
delete
d->parent;
252
d->type->d->referers.remove(
this
);
253
delete
d;
254
}
255
256
QQmlOpenMetaObjectType *QQmlOpenMetaObject::type()
const
257
{
258
return
d->type.data();
259
}
260
261
void
QQmlOpenMetaObject::emitPropertyNotification(
const
QByteArray &propertyName)
262
{
263
QHash<QByteArray,
int
>::ConstIterator iter = d->type->d->names.constFind(propertyName);
264
if
(iter == d->type->d->names.constEnd())
265
return
;
266
activate(d->object, *iter + d->type->d->signalOffset,
nullptr
);
267
}
268
269
void
QQmlOpenMetaObject::unparent()
270
{
271
d->parent =
nullptr
;
272
}
273
274
int
QQmlOpenMetaObject::metaCall(QObject *o, QMetaObject::Call c,
int
id,
void
**a)
275
{
276
Q_ASSERT(d->object == o);
277
278
if
(( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty)
279
&& id >= d->type->d->propertyOffset) {
280
int
propId = id - d->type->d->propertyOffset;
281
if
(c == QMetaObject::ReadProperty) {
282
propertyRead(propId);
283
*
reinterpret_cast
<QVariant *>(a[0]) = d->propertyValue(propId);
284
}
else
if
(c == QMetaObject::WriteProperty) {
285
if
(propId >= d->data.size() || d->data.at(propId).value() != *
reinterpret_cast
<QVariant *>(a[0])) {
286
propertyWrite(propId);
287
d->setPropertyValue(propId, propertyWriteValue(propId, *
reinterpret_cast
<QVariant *>(a[0])));
288
propertyWritten(propId);
289
activate(o, d->type->d->signalOffset + propId,
nullptr
);
290
}
291
}
292
return
-1;
293
}
else
{
294
if
(d->parent)
295
return
d->parent->metaCall(o, c, id, a);
296
else
297
return
o->qt_metacall(c, id, a);
298
}
299
}
300
301
QDynamicMetaObjectData *QQmlOpenMetaObject::parent()
const
302
{
303
return
d->parent;
304
}
305
306
bool
QQmlOpenMetaObject::checkedSetValue(
int
index,
const
QVariant &value,
bool
force)
307
{
308
if
(!force && d->propertyValue(index) == value)
309
return
false
;
310
311
d->setPropertyValue(index, value);
312
activate(d->object, index + d->type->d->signalOffset,
nullptr
);
313
return
true
;
314
}
315
316
QVariant QQmlOpenMetaObject::value(
int
id)
const
317
{
318
return
d->propertyValue(id);
319
}
320
321
void
QQmlOpenMetaObject::setValue(
int
id,
const
QVariant &value)
322
{
323
d->setPropertyValue(id, propertyWriteValue(id, value));
324
activate(d->object, id + d->type->d->signalOffset,
nullptr
);
325
}
326
327
QVariant QQmlOpenMetaObject::value(
const
QByteArray &name)
const
328
{
329
QHash<QByteArray,
int
>::ConstIterator iter = d->type->d->names.constFind(name);
330
if
(iter == d->type->d->names.cend())
331
return
QVariant();
332
333
return
d->propertyValue(*iter);
334
}
335
336
QVariant &QQmlOpenMetaObject::valueRef(
const
QByteArray &name)
337
{
338
QHash<QByteArray,
int
>::ConstIterator iter = d->type->d->names.constFind(name);
339
Q_ASSERT(iter != d->type->d->names.cend());
340
341
return
d->propertyValueRef(*iter);
342
}
343
344
bool
QQmlOpenMetaObject::setValue(
const
QByteArray &name,
const
QVariant &val,
bool
force)
345
{
346
QHash<QByteArray,
int
>::ConstIterator iter = d->type->d->names.constFind(name);
347
348
int
id = -1;
349
if
(iter == d->type->d->names.cend()) {
350
id = createProperty(name.constData(),
""
) - d->type->d->propertyOffset;
351
}
else
{
352
id = *iter;
353
}
354
355
if
(id >= 0)
356
return
checkedSetValue(id, val, force);
357
358
return
false
;
359
}
360
361
void
QQmlOpenMetaObject::setValues(
const
QHash<QByteArray, QVariant> &values,
bool
force)
362
{
363
QList<QByteArray> missingProperties;
364
d->deferredPropertyNames = &missingProperties;
365
const
auto
&names = d->type->d->names;
366
367
for
(
auto
valueIt = values.begin(), end = values.end(); valueIt != end; ++valueIt) {
368
const
auto
nameIt = names.constFind(valueIt.key());
369
if
(nameIt == names.constEnd()) {
370
const
int
id = createProperty(valueIt.key(),
""
) - d->type->d->propertyOffset;
371
372
// If id >= 0 some override of createProperty() created it. Then set it.
373
// Else it either ends up in missingProperties and we create it later
374
// or it cannot be created.
375
376
if
(id >= 0)
377
checkedSetValue(id, valueIt.value(), force);
378
}
else
{
379
checkedSetValue(*nameIt, valueIt.value(), force);
380
}
381
}
382
383
d->deferredPropertyNames =
nullptr
;
384
if
(missingProperties.isEmpty())
385
return
;
386
387
d->type->createProperties(missingProperties);
388
d->dropStalePropertyCache();
389
390
for
(
const
QByteArray &name : std::as_const(missingProperties))
391
checkedSetValue(names[name], values[name], force);
392
}
393
394
// returns true if this value has been initialized by a call to either value() or setValue()
395
bool
QQmlOpenMetaObject::hasValue(
int
id)
const
396
{
397
return
d->hasProperty(id);
398
}
399
400
void
QQmlOpenMetaObject::setCached(
bool
c)
401
{
402
if
(c == d->cacheProperties)
403
return
;
404
405
d->cacheProperties = c;
406
407
QQmlData *qmldata = QQmlData::get(d->object,
true
);
408
if
(d->cacheProperties) {
409
// As the propertyCache is not saved in QQmlMetaType (due to it being dynamic)
410
// we cannot leak it to other places before we're done with it. Yes, it's still
411
// terrible.
412
if
(!d->type->d->cache)
413
d->type->d->cache = QQmlPropertyCache::createStandalone(
this
);
414
qmldata->propertyCache = d->type->d->cache;
415
}
else
{
416
d->type->d->cache.reset();
417
qmldata->propertyCache.reset();
418
}
419
}
420
421
bool
QQmlOpenMetaObject::autoCreatesProperties()
const
422
{
423
return
d->autoCreate;
424
}
425
426
void
QQmlOpenMetaObject::setAutoCreatesProperties(
bool
autoCreate)
427
{
428
d->autoCreate = autoCreate;
429
}
430
431
432
int
QQmlOpenMetaObject::createProperty(
const
char
*name,
const
char
*)
433
{
434
if
(d->autoCreate) {
435
if
(d->deferredPropertyNames) {
436
// Defer the creation of new properties. See setValues(QHash<QByteArray, QVariant>)
437
d->deferredPropertyNames->append(name);
438
return
-1;
439
}
440
441
const
int
result = d->type->createProperty(name);
442
d->dropStalePropertyCache();
443
return
result;
444
}
else
445
return
-1;
446
}
447
448
void
QQmlOpenMetaObject::propertyRead(
int
)
449
{
450
}
451
452
void
QQmlOpenMetaObject::propertyWrite(
int
)
453
{
454
}
455
456
QVariant QQmlOpenMetaObject::propertyWriteValue(
int
,
const
QVariant &value)
457
{
458
return
value;
459
}
460
461
void
QQmlOpenMetaObject::propertyWritten(
int
)
462
{
463
}
464
465
void
QQmlOpenMetaObject::propertyCreated(
int
, QMetaPropertyBuilder &)
466
{
467
}
468
469
QVariant QQmlOpenMetaObject::initialValue(
int
)
470
{
471
return
QVariant();
472
}
473
474
int
QQmlOpenMetaObject::count()
const
475
{
476
return
d->type->d->names.size();
477
}
478
479
QByteArray QQmlOpenMetaObject::name(
int
idx)
const
480
{
481
Q_ASSERT(idx >= 0 && idx < d->type->d->names.size());
482
483
return
d->type->d->mob.property(idx).name();
484
}
485
486
QObject *QQmlOpenMetaObject::object()
const
487
{
488
return
d->object;
489
}
490
491
QT_END_NAMESPACE
QQmlOpenMetaObjectPrivate
Definition
qqmlopenmetaobject.cpp:146
QQmlOpenMetaObjectPrivate::deferredPropertyNames
QList< QByteArray > * deferredPropertyNames
Definition
qqmlopenmetaobject.cpp:218
QQmlOpenMetaObjectPrivate::autoCreate
bool autoCreate
Definition
qqmlopenmetaobject.cpp:219
QQmlOpenMetaObjectPrivate::hasProperty
bool hasProperty(int idx) const
Definition
qqmlopenmetaobject.cpp:198
QQmlOpenMetaObjectPrivate::object
QObject * object
Definition
qqmlopenmetaobject.cpp:216
QQmlOpenMetaObjectPrivate::cacheProperties
bool cacheProperties
Definition
qqmlopenmetaobject.cpp:220
QQmlOpenMetaObjectPrivate::setPropertyValue
void setPropertyValue(int idx, const QVariant &value)
Definition
qqmlopenmetaobject.cpp:173
QQmlOpenMetaObjectPrivate::data
QList< Property > data
Definition
qqmlopenmetaobject.cpp:215
QQmlOpenMetaObjectPrivate::type
QQmlRefPointer< QQmlOpenMetaObjectType > type
Definition
qqmlopenmetaobject.cpp:217
QQmlOpenMetaObjectPrivate::QQmlOpenMetaObjectPrivate
QQmlOpenMetaObjectPrivate(QQmlOpenMetaObject *_q, QObject *obj)
Definition
qqmlopenmetaobject.cpp:148
QQmlOpenMetaObjectPrivate::propertyValueRef
QVariant & propertyValueRef(int idx)
Definition
qqmlopenmetaobject.cpp:193
QQmlOpenMetaObjectPrivate::parent
QDynamicMetaObjectData * parent
Definition
qqmlopenmetaobject.cpp:214
QQmlOpenMetaObjectPrivate::propertyRef
Property & propertyRef(int idx)
Definition
qqmlopenmetaobject.cpp:179
QQmlOpenMetaObjectPrivate::q
QQmlOpenMetaObject * q
Definition
qqmlopenmetaobject.cpp:213
QQmlOpenMetaObjectPrivate::propertyValue
QVariant propertyValue(int idx)
Definition
qqmlopenmetaobject.cpp:188
QQmlOpenMetaObjectPrivate::dropStalePropertyCache
void dropStalePropertyCache()
Definition
qqmlopenmetaobject.cpp:204
QQmlOpenMetaObjectTypePrivate
Definition
qqmlopenmetaobject.cpp:19
QQmlOpenMetaObjectTypePrivate::init
void init(const QMetaObject *metaObj)
Definition
qqmlopenmetaobject.cpp:129
QQmlOpenMetaObjectTypePrivate::propertyOffset
int propertyOffset
Definition
qqmlopenmetaobject.cpp:25
QQmlOpenMetaObjectTypePrivate::names
QHash< QByteArray, int > names
Definition
qqmlopenmetaobject.cpp:27
QQmlOpenMetaObjectTypePrivate::mem
QMetaObject * mem
Definition
qqmlopenmetaobject.cpp:29
QQmlOpenMetaObjectTypePrivate::cache
QQmlPropertyCache::Ptr cache
Definition
qqmlopenmetaobject.cpp:35
QQmlOpenMetaObjectTypePrivate::QQmlOpenMetaObjectTypePrivate
QQmlOpenMetaObjectTypePrivate()
Definition
qqmlopenmetaobject.cpp:21
QQmlOpenMetaObjectTypePrivate::referers
QSet< QQmlOpenMetaObject * > referers
Definition
qqmlopenmetaobject.cpp:37
QQmlOpenMetaObjectTypePrivate::signalOffset
int signalOffset
Definition
qqmlopenmetaobject.cpp:26
QQmlOpenMetaObjectTypePrivate::mob
QMetaObjectBuilder mob
Definition
qqmlopenmetaobject.cpp:28
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QQmlOpenMetaObjectPrivate::Property
Definition
qqmlopenmetaobject.cpp:151
QQmlOpenMetaObjectPrivate::Property::setValue
void setValue(const QVariant &v)
Definition
qqmlopenmetaobject.cpp:165
QQmlOpenMetaObjectPrivate::Property::valueSet
bool valueSet
Definition
qqmlopenmetaobject.cpp:156
QQmlOpenMetaObjectPrivate::Property::value
QVariant value() const
Definition
qqmlopenmetaobject.cpp:158
QQmlOpenMetaObjectPrivate::Property::valueRef
QVariant & valueRef()
Definition
qqmlopenmetaobject.cpp:164
qtdeclarative
src
qml
qml
qqmlopenmetaobject.cpp
Generated on
for Qt by
1.18.0