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
qqmlproxymetaobject.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
7
9
10QQmlProxyMetaObject::QQmlProxyMetaObject(QObject *obj, const QList<ProxyData> *mList)
11 : metaObjects(mList), proxies(nullptr), parent(nullptr), object(obj)
12{
13 metaObject = metaObjects->constFirst().metaObject;
14
15 QObjectPrivate *op = QObjectPrivate::get(obj);
16 if (op->metaObject)
17 parent = op->metaObject;
18
19 op->metaObject = this;
20}
21
22QQmlProxyMetaObject::~QQmlProxyMetaObject()
23{
24 // If the parent still exists, we're being deleted while the object is still alive.
25 // In that case, restore the parent.
26 if (QDynamicMetaObjectData *dynamicParent = std::exchange(parent, nullptr))
27 QObjectPrivate::get(object)->metaObject = dynamicParent;
28
29 if (proxies)
30 delete [] proxies;
31 proxies = nullptr;
32}
33
34QObject *QQmlProxyMetaObject::getProxy(int index)
35{
36 if (!proxies) {
37 proxies = new QObject *[metaObjects->size()];
38 ::memset(proxies, 0, sizeof(QObject *) * metaObjects->size());
39 }
40
41 if (!proxies[index]) {
42 const ProxyData &data = metaObjects->at(index);
43 if (!data.createFunc)
44 return nullptr;
45
46 QObject *proxy = data.createFunc(object);
47 const QMetaObject *metaObject = proxy->metaObject();
48 proxies[index] = proxy;
49
50 int localOffset = data.metaObject->methodOffset();
51 int methodOffset = metaObject->methodOffset();
52 int methods = metaObject->methodCount() - methodOffset;
53
54 // ### - Can this be done more optimally?
55 for (int jj = 0; jj < methods; ++jj) {
56 QMetaMethod method =
57 metaObject->method(jj + methodOffset);
58 if (method.methodType() == QMetaMethod::Signal)
59 QQmlPropertyPrivate::connect(proxy, methodOffset + jj, object, localOffset + jj);
60 }
61 }
62
63 return proxies[index];
64}
65
66int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void **a)
67{
68 Q_ASSERT(object == o);
69
70 switch (c) {
71 case QMetaObject::ReadProperty:
72 case QMetaObject::WriteProperty: {
73 if (id < metaObjects->constLast().propertyOffset)
74 break;
75
76 for (int ii = 0; ii < metaObjects->size(); ++ii) {
77 const int globalPropertyOffset = metaObjects->at(ii).propertyOffset;
78 if (id < globalPropertyOffset)
79 continue;
80
81 QObject *proxy = getProxy(ii);
82 Q_ASSERT(proxy);
83 const int localProxyOffset = proxy->metaObject()->propertyOffset();
84 const int localProxyId = id - globalPropertyOffset + localProxyOffset;
85 return proxy->qt_metacall(c, localProxyId, a);
86 }
87 break;
88 }
89 case QMetaObject::InvokeMetaMethod: {
90 if (id < metaObjects->constLast().methodOffset)
91 break;
92
93 QMetaMethod m = object->metaObject()->method(id);
94 if (m.methodType() == QMetaMethod::Signal) {
95 QMetaObject::activate(object, id, a);
96 return -1;
97 }
98
99 for (int ii = 0; ii < metaObjects->size(); ++ii) {
100 const int globalMethodOffset = metaObjects->at(ii).methodOffset;
101 if (id < globalMethodOffset)
102 continue;
103
104 QObject *proxy = getProxy(ii);
105 Q_ASSERT(proxy);
106 const int localMethodOffset = proxy->metaObject()->methodOffset();
107 const int localMethodId = id - globalMethodOffset + localMethodOffset;
108 return proxy->qt_metacall(c, localMethodId, a);
109 }
110
111 break;
112 }
113 case QMetaObject::CustomCall: {
114 if ((id & ~MaxExtensionCount) != ExtensionObjectId)
115 break;
116 int index = id & MaxExtensionCount;
117 if (qsizetype(index) >= metaObjects->size())
118 break;
119 a[0] = getProxy(index);
120 return id;
121 }
122 default:
123 break;
124 }
125
126 if (parent)
127 return parent->metaCall(o, c, id, a);
128 else
129 return object->qt_metacall(c, id, a);
130}
131
132void QQmlProxyMetaObject::objectDestroyed(QObject *object)
133{
134 // The object is being deleted. parent will likely delete itself on objectDestroyed().
135 // We don't want to keep a dangling pointer, so null it. Also, we're in
136 // ~QObjectPrivate(). Don't mess with object anymore here.
137 if (QDynamicMetaObjectData *dynamicParent = std::exchange(parent, nullptr))
138 dynamicParent->objectDestroyed(object);
139 QDynamicMetaObjectData::objectDestroyed(object);
140}
141
142QT_END_NAMESPACE
Combined button and popup list for selecting options.