1 // This is the implementation of the QPyQuickItem classes.
2 //
3 // Copyright (c) 2021 Riverbank Computing Limited <info@riverbankcomputing.com>
4 //
5 // This file is part of PyQt5.
6 //
7 // This file may be used under the terms of the GNU General Public License
8 // version 3.0 as published by the Free Software Foundation and appearing in
9 // the file LICENSE included in the packaging of this file.  Please review the
10 // following information to ensure the GNU General Public License version 3.0
11 // requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 //
13 // If you do not wish to use this file under the terms of the GPL version 3.0
14 // then you may purchase a commercial license.  For more information contact
15 // info@riverbankcomputing.com.
16 //
17 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
18 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 
20 
21 #include <Python.h>
22 
23 #include <QQmlListProperty>
24 
25 #include "qpyquickitem.h"
26 
27 #include "sipAPIQtQuick.h"
28 
29 
30 // The maximum number of Python QQuickItem types.
31 const int NrOfQuickItemTypes = 60;
32 
33 // The list of registered Python types.
34 static QList<PyTypeObject *> pyqt_types;
35 
36 // The registration data for the canned types.
37 static QQmlPrivate::RegisterType canned_types[NrOfQuickItemTypes];
38 
39 
40 // Pick the correct meta-object, either the one from the super-class or the
41 // static meta-object.
qpyquick_pick_metaobject(const QMetaObject * super_mo,const QMetaObject * static_mo)42 const QMetaObject *qpyquick_pick_metaobject(const QMetaObject *super_mo,
43         const QMetaObject *static_mo)
44 {
45     // If a Python type has been sub-classed in QML then we need to use the
46     // QtQuick supplied meta-object.  In this case it's super-class meta-object
47     // will be the meta-object of the Python type.  Otherwise we need to use
48     // the static meta-object (which is a copy of the meta-object of the Python
49     // type).  We use the class names held by the meta-objects to determine the
50     // correct meta-object to return.
51 
52     return (qstrcmp(super_mo->superClass()->className(), static_mo->className()) == 0) ? super_mo : static_mo;
53 }
54 
55 
56 #define QPYQUICKITEM_INIT(n) \
57     case n##U: \
58         QPyQuickItem##n::staticMetaObject = *mo; \
59         rt->typeId = qRegisterNormalizedMetaType<QPyQuickItem##n *>(ptr_name); \
60         rt->listId = qRegisterNormalizedMetaType<QQmlListProperty<QPyQuickItem##n> >(list_name); \
61         rt->objectSize = sizeof(QPyQuickItem##n); \
62         rt->create = QQmlPrivate::createInto<QPyQuickItem##n>; \
63         rt->metaObject = mo; \
64         rt->attachedPropertiesFunction = QQmlPrivate::attachedPropertiesFunc<QPyQuickItem##n>(); \
65         rt->attachedPropertiesMetaObject = QQmlPrivate::attachedPropertiesMetaObject<QPyQuickItem##n>(); \
66         rt->parserStatusCast = QQmlPrivate::StaticCastSelector<QPyQuickItem##n,QQmlParserStatus>::cast(); \
67         rt->valueSourceCast = QQmlPrivate::StaticCastSelector<QPyQuickItem##n,QQmlPropertyValueSource>::cast(); \
68         rt->valueInterceptorCast = QQmlPrivate::StaticCastSelector<QPyQuickItem##n,QQmlPropertyValueInterceptor>::cast(); \
69         break
70 
71 
72 // The ctor.
QPyQuickItem(QQuickItem * parent)73 QPyQuickItem::QPyQuickItem(QQuickItem *parent) : sipQQuickItem(parent)
74 {
75 }
76 
77 
78 // Add a new Python type and return its number.
addType(PyTypeObject * type,const QMetaObject * mo,const QByteArray & ptr_name,const QByteArray & list_name)79 QQmlPrivate::RegisterType *QPyQuickItem::addType(PyTypeObject *type,
80         const QMetaObject *mo, const QByteArray &ptr_name,
81         const QByteArray &list_name)
82 {
83     int type_nr = pyqt_types.size();
84 
85     // Check we have a spare canned type.
86     if (type_nr >= NrOfQuickItemTypes)
87     {
88         PyErr_Format(PyExc_TypeError,
89                 "a maximum of %d QQuickItem types may be registered with QML",
90                 NrOfQuickItemTypes);
91         return 0;
92     }
93 
94     pyqt_types.append(type);
95 
96     QQmlPrivate::RegisterType *rt = &canned_types[type_nr];
97 
98     // Initialise those members that depend on the C++ type.
99     switch (type_nr)
100     {
101         QPYQUICKITEM_INIT(0);
102         QPYQUICKITEM_INIT(1);
103         QPYQUICKITEM_INIT(2);
104         QPYQUICKITEM_INIT(3);
105         QPYQUICKITEM_INIT(4);
106         QPYQUICKITEM_INIT(5);
107         QPYQUICKITEM_INIT(6);
108         QPYQUICKITEM_INIT(7);
109         QPYQUICKITEM_INIT(8);
110         QPYQUICKITEM_INIT(9);
111         QPYQUICKITEM_INIT(10);
112         QPYQUICKITEM_INIT(11);
113         QPYQUICKITEM_INIT(12);
114         QPYQUICKITEM_INIT(13);
115         QPYQUICKITEM_INIT(14);
116         QPYQUICKITEM_INIT(15);
117         QPYQUICKITEM_INIT(16);
118         QPYQUICKITEM_INIT(17);
119         QPYQUICKITEM_INIT(18);
120         QPYQUICKITEM_INIT(19);
121         QPYQUICKITEM_INIT(20);
122         QPYQUICKITEM_INIT(21);
123         QPYQUICKITEM_INIT(22);
124         QPYQUICKITEM_INIT(23);
125         QPYQUICKITEM_INIT(24);
126         QPYQUICKITEM_INIT(25);
127         QPYQUICKITEM_INIT(26);
128         QPYQUICKITEM_INIT(27);
129         QPYQUICKITEM_INIT(28);
130         QPYQUICKITEM_INIT(29);
131         QPYQUICKITEM_INIT(30);
132         QPYQUICKITEM_INIT(31);
133         QPYQUICKITEM_INIT(32);
134         QPYQUICKITEM_INIT(33);
135         QPYQUICKITEM_INIT(34);
136         QPYQUICKITEM_INIT(35);
137         QPYQUICKITEM_INIT(36);
138         QPYQUICKITEM_INIT(37);
139         QPYQUICKITEM_INIT(38);
140         QPYQUICKITEM_INIT(39);
141         QPYQUICKITEM_INIT(40);
142         QPYQUICKITEM_INIT(41);
143         QPYQUICKITEM_INIT(42);
144         QPYQUICKITEM_INIT(43);
145         QPYQUICKITEM_INIT(44);
146         QPYQUICKITEM_INIT(45);
147         QPYQUICKITEM_INIT(46);
148         QPYQUICKITEM_INIT(47);
149         QPYQUICKITEM_INIT(48);
150         QPYQUICKITEM_INIT(49);
151         QPYQUICKITEM_INIT(50);
152         QPYQUICKITEM_INIT(51);
153         QPYQUICKITEM_INIT(52);
154         QPYQUICKITEM_INIT(53);
155         QPYQUICKITEM_INIT(54);
156         QPYQUICKITEM_INIT(55);
157         QPYQUICKITEM_INIT(56);
158         QPYQUICKITEM_INIT(57);
159         QPYQUICKITEM_INIT(58);
160         QPYQUICKITEM_INIT(59);
161     }
162 
163     return rt;
164 }
165 
166 
167 // Create the Python instance.
createPyObject(QQuickItem * parent)168 void QPyQuickItem::createPyObject(QQuickItem *parent)
169 {
170     SIP_BLOCK_THREADS
171 
172     // Assume C++ owns everything.
173     PyObject *obj = sipConvertFromNewPyType(this, pyqt_types.at(typeNr()),
174             NULL, &sipPySelf, "D", parent, sipType_QQuickItem, NULL);
175 
176     if (!obj)
177         pyqt5_qtquick_err_print();
178 
179     SIP_UNBLOCK_THREADS
180 }
181 
182 
183 // The canned type implementations.
184 #define QPYQUICKITEM_IMPL(n) \
185 QPyQuickItem##n::QPyQuickItem##n(QQuickItem *parent) : QPyQuickItem(parent) \
186 { \
187     createPyObject(parent); \
188 } \
189 const QMetaObject *QPyQuickItem##n::metaObject() const \
190 { \
191     return qpyquick_pick_metaobject(QPyQuickItem::metaObject(), &staticMetaObject); \
192 } \
193 QMetaObject QPyQuickItem##n::staticMetaObject
194 
195 
196 QPYQUICKITEM_IMPL(0);
197 QPYQUICKITEM_IMPL(1);
198 QPYQUICKITEM_IMPL(2);
199 QPYQUICKITEM_IMPL(3);
200 QPYQUICKITEM_IMPL(4);
201 QPYQUICKITEM_IMPL(5);
202 QPYQUICKITEM_IMPL(6);
203 QPYQUICKITEM_IMPL(7);
204 QPYQUICKITEM_IMPL(8);
205 QPYQUICKITEM_IMPL(9);
206 QPYQUICKITEM_IMPL(10);
207 QPYQUICKITEM_IMPL(11);
208 QPYQUICKITEM_IMPL(12);
209 QPYQUICKITEM_IMPL(13);
210 QPYQUICKITEM_IMPL(14);
211 QPYQUICKITEM_IMPL(15);
212 QPYQUICKITEM_IMPL(16);
213 QPYQUICKITEM_IMPL(17);
214 QPYQUICKITEM_IMPL(18);
215 QPYQUICKITEM_IMPL(19);
216 QPYQUICKITEM_IMPL(20);
217 QPYQUICKITEM_IMPL(21);
218 QPYQUICKITEM_IMPL(22);
219 QPYQUICKITEM_IMPL(23);
220 QPYQUICKITEM_IMPL(24);
221 QPYQUICKITEM_IMPL(25);
222 QPYQUICKITEM_IMPL(26);
223 QPYQUICKITEM_IMPL(27);
224 QPYQUICKITEM_IMPL(28);
225 QPYQUICKITEM_IMPL(29);
226 QPYQUICKITEM_IMPL(30);
227 QPYQUICKITEM_IMPL(31);
228 QPYQUICKITEM_IMPL(32);
229 QPYQUICKITEM_IMPL(33);
230 QPYQUICKITEM_IMPL(34);
231 QPYQUICKITEM_IMPL(35);
232 QPYQUICKITEM_IMPL(36);
233 QPYQUICKITEM_IMPL(37);
234 QPYQUICKITEM_IMPL(38);
235 QPYQUICKITEM_IMPL(39);
236 QPYQUICKITEM_IMPL(40);
237 QPYQUICKITEM_IMPL(41);
238 QPYQUICKITEM_IMPL(42);
239 QPYQUICKITEM_IMPL(43);
240 QPYQUICKITEM_IMPL(44);
241 QPYQUICKITEM_IMPL(45);
242 QPYQUICKITEM_IMPL(46);
243 QPYQUICKITEM_IMPL(47);
244 QPYQUICKITEM_IMPL(48);
245 QPYQUICKITEM_IMPL(49);
246 QPYQUICKITEM_IMPL(50);
247 QPYQUICKITEM_IMPL(51);
248 QPYQUICKITEM_IMPL(52);
249 QPYQUICKITEM_IMPL(53);
250 QPYQUICKITEM_IMPL(54);
251 QPYQUICKITEM_IMPL(55);
252 QPYQUICKITEM_IMPL(56);
253 QPYQUICKITEM_IMPL(57);
254 QPYQUICKITEM_IMPL(58);
255 QPYQUICKITEM_IMPL(59);
256