1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qqmlproxymetaobject_p.h"
41#include "qqmlproperty_p.h"
42
43QT_BEGIN_NAMESPACE
44
45QQmlProxyMetaObject::QQmlProxyMetaObject(QObject *obj, QList<ProxyData> *mList)
46: metaObjects(mList), proxies(nullptr), parent(nullptr), object(obj)
47{
48 *static_cast<QMetaObject *>(this) = *metaObjects->constFirst().metaObject;
49
50 QObjectPrivate *op = QObjectPrivate::get(obj);
51 if (op->metaObject)
52 parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject);
53
54 op->metaObject = this;
55}
56
57QQmlProxyMetaObject::~QQmlProxyMetaObject()
58{
59 if (parent)
60 delete parent;
61 parent = nullptr;
62
63 if (proxies)
64 delete [] proxies;
65 proxies = nullptr;
66}
67
68int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void **a)
69{
70 Q_ASSERT(object == o);
71
72 if ((c == QMetaObject::ReadProperty ||
73 c == QMetaObject::WriteProperty) &&
74 id >= metaObjects->constLast().propertyOffset) {
75
76 for (int ii = 0; ii < metaObjects->count(); ++ii) {
77 const ProxyData &data = metaObjects->at(ii);
78 if (id >= data.propertyOffset) {
79 if (!proxies) {
80 proxies = new QObject*[metaObjects->count()];
81 ::memset(proxies, 0,
82 sizeof(QObject *) * metaObjects->count());
83 }
84
85 if (!proxies[ii]) {
86 QObject *proxy = data.createFunc(object);
87 const QMetaObject *metaObject = proxy->metaObject();
88 proxies[ii] = proxy;
89
90 int localOffset = data.metaObject->methodOffset();
91 int methodOffset = metaObject->methodOffset();
92 int methods = metaObject->methodCount() - methodOffset;
93
94 // ### - Can this be done more optimally?
95 for (int jj = 0; jj < methods; ++jj) {
96 QMetaMethod method =
97 metaObject->method(jj + methodOffset);
98 if (method.methodType() == QMetaMethod::Signal)
99 QQmlPropertyPrivate::connect(proxy, methodOffset + jj, object, localOffset + jj);
100 }
101 }
102
103 int proxyOffset = proxies[ii]->metaObject()->propertyOffset();
104 int proxyId = id - data.propertyOffset + proxyOffset;
105
106 return proxies[ii]->qt_metacall(c, proxyId, a);
107 }
108 }
109 } else if (c == QMetaObject::InvokeMetaMethod &&
110 id >= metaObjects->constLast().methodOffset) {
111 QMetaMethod m = object->metaObject()->method(id);
112 if (m.methodType() == QMetaMethod::Signal) {
113 QMetaObject::activate(object, id, a);
114 return -1;
115 }
116 }
117
118 if (parent)
119 return parent->metaCall(o, c, id, a);
120 else
121 return object->qt_metacall(c, id, a);
122}
123
124QT_END_NAMESPACE
125