##// END OF EJS Templates
enabled signals to be emitted by simply calling them...
florianlink -
r69:5f2efada2db6
parent child
Show More
@@ -1,841 +1,843
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtClassInfo.h"
42 #include "PythonQtClassInfo.h"
43 #include "PythonQtMethodInfo.h"
43 #include "PythonQtMethodInfo.h"
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include <QMetaMethod>
45 #include <QMetaMethod>
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaEnum>
47 #include <QMetaEnum>
48
48
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
50
50
51 PythonQtClassInfo::PythonQtClassInfo() {
51 PythonQtClassInfo::PythonQtClassInfo() {
52 _meta = NULL;
52 _meta = NULL;
53 _constructors = NULL;
53 _constructors = NULL;
54 _destructor = NULL;
54 _destructor = NULL;
55 _decoratorProvider = NULL;
55 _decoratorProvider = NULL;
56 _decoratorProviderCB = NULL;
56 _decoratorProviderCB = NULL;
57 _pythonQtClassWrapper = NULL;
57 _pythonQtClassWrapper = NULL;
58 _shellSetInstanceWrapperCB = NULL;
58 _shellSetInstanceWrapperCB = NULL;
59 _metaTypeId = -1;
59 _metaTypeId = -1;
60 _isQObject = false;
60 _isQObject = false;
61 _enumsCreated = false;
61 _enumsCreated = false;
62 }
62 }
63
63
64 PythonQtClassInfo::~PythonQtClassInfo()
64 PythonQtClassInfo::~PythonQtClassInfo()
65 {
65 {
66 clearCachedMembers();
66 clearCachedMembers();
67
67
68 if (_constructors) {
68 if (_constructors) {
69 _constructors->deleteOverloadsAndThis();
69 _constructors->deleteOverloadsAndThis();
70 }
70 }
71 if (_destructor) {
71 if (_destructor) {
72 _destructor->deleteOverloadsAndThis();
72 _destructor->deleteOverloadsAndThis();
73 }
73 }
74 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
74 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 info->deleteOverloadsAndThis();
75 info->deleteOverloadsAndThis();
76 }
76 }
77 }
77 }
78
78
79 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
79 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 {
80 {
81 // _wrappedClassName is already set earlier in the class setup
81 // _wrappedClassName is already set earlier in the class setup
82 _isQObject = true;
82 _isQObject = true;
83 _meta = meta;
83 _meta = meta;
84 }
84 }
85
85
86 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
86 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 {
87 {
88 _isQObject = false;
88 _isQObject = false;
89 _wrappedClassName = classname;
89 _wrappedClassName = classname;
90 _metaTypeId = QMetaType::type(classname);
90 _metaTypeId = QMetaType::type(classname);
91 }
91 }
92
92
93 void PythonQtClassInfo::clearCachedMembers()
93 void PythonQtClassInfo::clearCachedMembers()
94 {
94 {
95 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
95 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 while (i.hasNext()) {
96 while (i.hasNext()) {
97 PythonQtMemberInfo member = i.next().value();
97 PythonQtMemberInfo member = i.next().value();
98 if (member._type== PythonQtMemberInfo::Slot) {
98 if (member._type== PythonQtMemberInfo::Slot) {
99 PythonQtSlotInfo* info = member._slot;
99 PythonQtSlotInfo* info = member._slot;
100 while (info) {
100 while (info) {
101 PythonQtSlotInfo* next = info->nextInfo();
101 PythonQtSlotInfo* next = info->nextInfo();
102 delete info;
102 delete info;
103 info = next;
103 info = next;
104 }
104 }
105 }
105 }
106 }
106 }
107 }
107 }
108
108
109 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
109 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 {
110 {
111 const char* sigEnd = sigStart;
111 const char* sigEnd = sigStart;
112 char c;
112 char c;
113 do {
113 do {
114 c = *sigEnd++;
114 c = *sigEnd++;
115 } while (c!=someChar && c!=0);
115 } while (c!=someChar && c!=0);
116 return sigEnd-sigStart-1;
116 return sigEnd-sigStart-1;
117 }
117 }
118
118
119 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
119 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 {
120 {
121 bool found = false;
121 bool found = false;
122 bool nameMapped = false;
122 bool nameMapped = false;
123 const char* attributeName = memberName;
123 const char* attributeName = memberName;
124 // look for properties
124 // look for properties
125 int i = _meta->indexOfProperty(attributeName);
125 int i = _meta->indexOfProperty(attributeName);
126 if (i==-1) {
126 if (i==-1) {
127 // try to map name to objectName
127 // try to map name to objectName
128 if (qstrcmp(attributeName, "name")==0) {
128 if (qstrcmp(attributeName, "name")==0) {
129 attributeName = "objectName";
129 attributeName = "objectName";
130 nameMapped = true;
130 nameMapped = true;
131 i = _meta->indexOfProperty(attributeName);
131 i = _meta->indexOfProperty(attributeName);
132 }
132 }
133 }
133 }
134 if (i!=-1) {
134 if (i!=-1) {
135 PythonQtMemberInfo newInfo(_meta->property(i));
135 PythonQtMemberInfo newInfo(_meta->property(i));
136 _cachedMembers.insert(attributeName, newInfo);
136 _cachedMembers.insert(attributeName, newInfo);
137 if (nameMapped) {
137 if (nameMapped) {
138 _cachedMembers.insert(memberName, newInfo);
138 _cachedMembers.insert(memberName, newInfo);
139 }
139 }
140 #ifdef PYTHONQT_DEBUG
140 #ifdef PYTHONQT_DEBUG
141 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
141 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
142 #endif
142 #endif
143 found = true;
143 found = true;
144 }
144 }
145 return found;
145 return found;
146 }
146 }
147
147
148 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
148 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
149 {
149 {
150 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
150 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
151 foreach(const ParentClassInfo& info, _parentClasses) {
151 foreach(const ParentClassInfo& info, _parentClasses) {
152 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
152 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
153 }
153 }
154 return inputInfo;
154 return inputInfo;
155 }
155 }
156
156
157 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
157 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
158 QObject* decoratorProvider = decorator();
158 QObject* decoratorProvider = decorator();
159 int memberNameLen = strlen(memberName);
159 int memberNameLen = strlen(memberName);
160 if (decoratorProvider) {
160 if (decoratorProvider) {
161 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
161 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
162 const QMetaObject* meta = decoratorProvider->metaObject();
162 const QMetaObject* meta = decoratorProvider->metaObject();
163 int numMethods = meta->methodCount();
163 int numMethods = meta->methodCount();
164 int startFrom = QObject::staticMetaObject.methodCount();
164 int startFrom = QObject::staticMetaObject.methodCount();
165 for (int i = startFrom; i < numMethods; i++) {
165 for (int i = startFrom; i < numMethods; i++) {
166 QMetaMethod m = meta->method(i);
166 QMetaMethod m = meta->method(i);
167 if ((m.methodType() == QMetaMethod::Method ||
167 if ((m.methodType() == QMetaMethod::Method ||
168 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
168 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
169
169
170 const char* sigStart = m.signature();
170 const char* sigStart = m.signature();
171 bool isClassDeco = false;
171 bool isClassDeco = false;
172 if (qstrncmp(sigStart, "static_", 7)==0) {
172 if (qstrncmp(sigStart, "static_", 7)==0) {
173 // skip the static_classname_ part of the string
173 // skip the static_classname_ part of the string
174 sigStart += 7 + 1 + strlen(className());
174 sigStart += 7 + 1 + strlen(className());
175 isClassDeco = true;
175 isClassDeco = true;
176 } else if (qstrncmp(sigStart, "new_", 4)==0) {
176 } else if (qstrncmp(sigStart, "new_", 4)==0) {
177 isClassDeco = true;
177 isClassDeco = true;
178 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
178 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
179 isClassDeco = true;
179 isClassDeco = true;
180 }
180 }
181 // find the first '('
181 // find the first '('
182 int offset = findCharOffset(sigStart, '(');
182 int offset = findCharOffset(sigStart, '(');
183
183
184 // XXX no checking is currently done if the slots have correct first argument or not...
184 // XXX no checking is currently done if the slots have correct first argument or not...
185
185
186 // check if same length and same name
186 // check if same length and same name
187 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
187 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
188 found = true;
188 found = true;
189 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
189 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
190 info->setUpcastingOffset(upcastingOffset);
190 info->setUpcastingOffset(upcastingOffset);
191 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
191 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
192 if (tail) {
192 if (tail) {
193 tail->setNextInfo(info);
193 tail->setNextInfo(info);
194 } else {
194 } else {
195 PythonQtMemberInfo newInfo(info);
195 PythonQtMemberInfo newInfo(info);
196 memberCache.insert(memberName, newInfo);
196 memberCache.insert(memberName, newInfo);
197 }
197 }
198 tail = info;
198 tail = info;
199 }
199 }
200 }
200 }
201 }
201 }
202 }
202 }
203
203
204 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
204 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
205
205
206 return tail;
206 return tail;
207 }
207 }
208
208
209 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
209 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
210 {
210 {
211 bool found = false;
211 bool found = false;
212 int memberNameLen = strlen(memberName);
212 int memberNameLen = strlen(memberName);
213 PythonQtSlotInfo* tail = NULL;
213 PythonQtSlotInfo* tail = NULL;
214 if (_meta) {
214 if (_meta) {
215 int numMethods = _meta->methodCount();
215 int numMethods = _meta->methodCount();
216 for (int i = 0; i < numMethods; i++) {
216 for (int i = 0; i < numMethods; i++) {
217 QMetaMethod m = _meta->method(i);
217 QMetaMethod m = _meta->method(i);
218 if ((m.methodType() == QMetaMethod::Method ||
218 if (((m.methodType() == QMetaMethod::Method ||
219 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
219 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
220 || m.methodType()==QMetaMethod::Signal) {
220
221
221 const char* sigStart = m.signature();
222 const char* sigStart = m.signature();
222 // find the first '('
223 // find the first '('
223 int offset = findCharOffset(sigStart, '(');
224 int offset = findCharOffset(sigStart, '(');
224
225
225 // check if same length and same name
226 // check if same length and same name
226 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
227 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
227 found = true;
228 found = true;
228 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
229 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
229 if (tail) {
230 if (tail) {
230 tail->setNextInfo(info);
231 tail->setNextInfo(info);
231 } else {
232 } else {
232 PythonQtMemberInfo newInfo(info);
233 PythonQtMemberInfo newInfo(info);
233 _cachedMembers.insert(memberName, newInfo);
234 _cachedMembers.insert(memberName, newInfo);
234 }
235 }
235 tail = info;
236 tail = info;
236 }
237 }
237 }
238 }
238 }
239 }
239 }
240 }
240
241
241 // look for dynamic decorators in this class and in derived classes
242 // look for dynamic decorators in this class and in derived classes
242 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
243 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
243
244
244 return found;
245 return found;
245 }
246 }
246
247
247 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
248 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
248 {
249 {
249 bool found = false;
250 bool found = false;
250 // look for enum values
251 // look for enum values
251 int enumCount = meta->enumeratorCount();
252 int enumCount = meta->enumeratorCount();
252 for (int i=0;i<enumCount; i++) {
253 for (int i=0;i<enumCount; i++) {
253 QMetaEnum e = meta->enumerator(i);
254 QMetaEnum e = meta->enumerator(i);
254 // we do not want flags, they will cause our values to appear two times
255 // we do not want flags, they will cause our values to appear two times
255 if (e.isFlag()) continue;
256 if (e.isFlag()) continue;
256
257
257 for (int j=0; j < e.keyCount(); j++) {
258 for (int j=0; j < e.keyCount(); j++) {
258 if (qstrcmp(e.key(j), memberName)==0) {
259 if (qstrcmp(e.key(j), memberName)==0) {
259 PyObject* enumType = findEnumWrapper(e.name());
260 PyObject* enumType = findEnumWrapper(e.name());
260 if (enumType) {
261 if (enumType) {
261 PythonQtObjectPtr enumValuePtr;
262 PythonQtObjectPtr enumValuePtr;
262 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
263 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
263 PythonQtMemberInfo newInfo(enumValuePtr);
264 PythonQtMemberInfo newInfo(enumValuePtr);
264 _cachedMembers.insert(memberName, newInfo);
265 _cachedMembers.insert(memberName, newInfo);
265 #ifdef PYTHONQT_DEBUG
266 #ifdef PYTHONQT_DEBUG
266 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
267 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
267 #endif
268 #endif
268 found = true;
269 found = true;
269 break;
270 break;
270 } else {
271 } else {
271 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
272 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
272 }
273 }
273 }
274 }
274 }
275 }
275 }
276 }
276 return found;
277 return found;
277 }
278 }
278
279
279 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
280 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
280 {
281 {
281 PythonQtMemberInfo info = _cachedMembers.value(memberName);
282 PythonQtMemberInfo info = _cachedMembers.value(memberName);
282 if (info._type != PythonQtMemberInfo::Invalid) {
283 if (info._type != PythonQtMemberInfo::Invalid) {
283 return info;
284 return info;
284 } else {
285 } else {
285 bool found = false;
286 bool found = false;
286
287
287 found = lookForPropertyAndCache(memberName);
288 found = lookForPropertyAndCache(memberName);
288 if (!found) {
289 if (!found) {
289 found = lookForMethodAndCache(memberName);
290 found = lookForMethodAndCache(memberName);
290 }
291 }
291 if (!found) {
292 if (!found) {
292 if (_meta) {
293 if (_meta) {
293 // check enums in our meta object directly
294 // check enums in our meta object directly
294 found = lookForEnumAndCache(_meta, memberName);
295 found = lookForEnumAndCache(_meta, memberName);
295 }
296 }
296 if (!found) {
297 if (!found) {
297 // check enums in the class hierachy of CPP classes
298 // check enums in the class hierachy of CPP classes
298 // look for dynamic decorators in this class and in derived classes
299 // look for dynamic decorators in this class and in derived classes
299 QList<QObject*> decoObjects;
300 QList<QObject*> decoObjects;
300 recursiveCollectDecoratorObjects(decoObjects);
301 recursiveCollectDecoratorObjects(decoObjects);
301 foreach(QObject* deco, decoObjects) {
302 foreach(QObject* deco, decoObjects) {
302 // call on ourself for caching, but with different metaObject():
303 // call on ourself for caching, but with different metaObject():
303 found = lookForEnumAndCache(deco->metaObject(), memberName);
304 found = lookForEnumAndCache(deco->metaObject(), memberName);
304 if (found) {
305 if (found) {
305 break;
306 break;
306 }
307 }
307 }
308 }
308 }
309 }
309 }
310 }
310 if (!found) {
311 if (!found) {
311 // maybe it is an enum wrapper?
312 // maybe it is an enum wrapper?
312 PyObject* p = findEnumWrapper(memberName);
313 PyObject* p = findEnumWrapper(memberName);
313 if (p) {
314 if (p) {
314 info._type = PythonQtMemberInfo::EnumWrapper;
315 info._type = PythonQtMemberInfo::EnumWrapper;
315 info._enumWrapper = p;
316 info._enumWrapper = p;
316 _cachedMembers.insert(memberName, info);
317 _cachedMembers.insert(memberName, info);
317 found = true;
318 found = true;
318 }
319 }
319 }
320 }
320 if (!found) {
321 if (!found) {
321 // since python keywords can not be looked up, we check if the name contains a single trailing _
322 // since python keywords can not be looked up, we check if the name contains a single trailing _
322 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
323 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
323 QByteArray mbrName(memberName);
324 QByteArray mbrName(memberName);
324 if ((mbrName.length()>2) &&
325 if ((mbrName.length()>2) &&
325 (mbrName.at(mbrName.length()-1) == '_') &&
326 (mbrName.at(mbrName.length()-1) == '_') &&
326 (mbrName.at(mbrName.length()-2) != '_')) {
327 (mbrName.at(mbrName.length()-2) != '_')) {
327 mbrName = mbrName.mid(0,mbrName.length()-1);
328 mbrName = mbrName.mid(0,mbrName.length()-1);
328 found = lookForMethodAndCache(mbrName.constData());
329 found = lookForMethodAndCache(mbrName.constData());
329 if (found) {
330 if (found) {
330 return _cachedMembers.value(mbrName);
331 return _cachedMembers.value(mbrName);
331 }
332 }
332 }
333 }
333 }
334 }
334 if (!found) {
335 if (!found) {
335 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
336 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
336 info._type = PythonQtMemberInfo::NotFound;
337 info._type = PythonQtMemberInfo::NotFound;
337 _cachedMembers.insert(memberName, info);
338 _cachedMembers.insert(memberName, info);
338 }
339 }
339 }
340 }
340
341
341 return _cachedMembers.value(memberName);
342 return _cachedMembers.value(memberName);
342 }
343 }
343
344
344 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
345 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
345 QObject* deco = decorator();
346 QObject* deco = decorator();
346 if (deco) {
347 if (deco) {
347 decoratorObjects.append(deco);
348 decoratorObjects.append(deco);
348 }
349 }
349 foreach(const ParentClassInfo& info, _parentClasses) {
350 foreach(const ParentClassInfo& info, _parentClasses) {
350 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
351 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
351 }
352 }
352 }
353 }
353
354
354 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
355 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
355 classInfoObjects.append(this);
356 classInfoObjects.append(this);
356 foreach(const ParentClassInfo& info, _parentClasses) {
357 foreach(const ParentClassInfo& info, _parentClasses) {
357 info._parent->recursiveCollectClassInfos(classInfoObjects);
358 info._parent->recursiveCollectClassInfos(classInfoObjects);
358 }
359 }
359 }
360 }
360
361
361 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
362 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
362 {
363 {
363 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
364 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
364 while (it.hasNext()) {
365 while (it.hasNext()) {
365
366
366 PythonQtSlotInfo* infoOrig = it.next();
367 PythonQtSlotInfo* infoOrig = it.next();
367
368
368 const char* sigStart = infoOrig->metaMethod()->signature();
369 const char* sigStart = infoOrig->metaMethod()->signature();
369 if (qstrncmp("static_", sigStart, 7)==0) {
370 if (qstrncmp("static_", sigStart, 7)==0) {
370 sigStart += 7;
371 sigStart += 7;
371 sigStart += findCharOffset(sigStart, '_')+1;
372 sigStart += findCharOffset(sigStart, '_')+1;
372 }
373 }
373 int offset = findCharOffset(sigStart, '(');
374 int offset = findCharOffset(sigStart, '(');
374 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
375 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
375 //make a copy, otherwise we will have trouble on overloads!
376 //make a copy, otherwise we will have trouble on overloads!
376 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
377 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
377 info->setUpcastingOffset(upcastingOffset);
378 info->setUpcastingOffset(upcastingOffset);
378 found = true;
379 found = true;
379 if (tail) {
380 if (tail) {
380 tail->setNextInfo(info);
381 tail->setNextInfo(info);
381 } else {
382 } else {
382 PythonQtMemberInfo newInfo(info);
383 PythonQtMemberInfo newInfo(info);
383 memberCache.insert(memberName, newInfo);
384 memberCache.insert(memberName, newInfo);
384 }
385 }
385 tail = info;
386 tail = info;
386 }
387 }
387 }
388 }
388 return tail;
389 return tail;
389 }
390 }
390
391
391 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
392 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
392 QObject* decoratorProvider = decorator();
393 QObject* decoratorProvider = decorator();
393 if (decoratorProvider) {
394 if (decoratorProvider) {
394 const QMetaObject* meta = decoratorProvider->metaObject();
395 const QMetaObject* meta = decoratorProvider->metaObject();
395 int numMethods = meta->methodCount();
396 int numMethods = meta->methodCount();
396 int startFrom = QObject::staticMetaObject.methodCount();
397 int startFrom = QObject::staticMetaObject.methodCount();
397 for (int i = startFrom; i < numMethods; i++) {
398 for (int i = startFrom; i < numMethods; i++) {
398 QMetaMethod m = meta->method(i);
399 QMetaMethod m = meta->method(i);
399 if ((m.methodType() == QMetaMethod::Method ||
400 if ((m.methodType() == QMetaMethod::Method ||
400 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
401 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
401
402
402 const char* sigStart = m.signature();
403 const char* sigStart = m.signature();
403 bool isClassDeco = false;
404 bool isClassDeco = false;
404 if (qstrncmp(sigStart, "static_", 7)==0) {
405 if (qstrncmp(sigStart, "static_", 7)==0) {
405 // skip the static_classname_ part of the string
406 // skip the static_classname_ part of the string
406 sigStart += 7 + 1 + strlen(className());
407 sigStart += 7 + 1 + strlen(className());
407 isClassDeco = true;
408 isClassDeco = true;
408 } else if (qstrncmp(sigStart, "new_", 4)==0) {
409 } else if (qstrncmp(sigStart, "new_", 4)==0) {
409 continue;
410 continue;
410 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
411 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
411 continue;
412 continue;
412 }
413 }
413 // find the first '('
414 // find the first '('
414 int offset = findCharOffset(sigStart, '(');
415 int offset = findCharOffset(sigStart, '(');
415
416
416 // XXX no checking is currently done if the slots have correct first argument or not...
417 // XXX no checking is currently done if the slots have correct first argument or not...
417 if (!metaOnly || isClassDeco) {
418 if (!metaOnly || isClassDeco) {
418 list << QString::fromLatin1(sigStart, offset);
419 list << QString::fromLatin1(sigStart, offset);
419 }
420 }
420 }
421 }
421 }
422 }
422 }
423 }
423
424
424 // look for global decorator slots
425 // look for global decorator slots
425 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
426 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
426 while (it.hasNext()) {
427 while (it.hasNext()) {
427 PythonQtSlotInfo* slot = it.next();
428 PythonQtSlotInfo* slot = it.next();
428 if (metaOnly) {
429 if (metaOnly) {
429 if (slot->isClassDecorator()) {
430 if (slot->isClassDecorator()) {
430 QByteArray first = slot->slotName();
431 QByteArray first = slot->slotName();
431 if (first.startsWith("static_")) {
432 if (first.startsWith("static_")) {
432 int idx = first.indexOf('_');
433 int idx = first.indexOf('_');
433 idx = first.indexOf('_', idx+1);
434 idx = first.indexOf('_', idx+1);
434 first = first.mid(idx+1);
435 first = first.mid(idx+1);
435 }
436 }
436 list << first;
437 list << first;
437 }
438 }
438 } else {
439 } else {
439 list << slot->slotName();
440 list << slot->slotName();
440 }
441 }
441 }
442 }
442 }
443 }
443
444
444 QStringList PythonQtClassInfo::propertyList()
445 QStringList PythonQtClassInfo::propertyList()
445 {
446 {
446 QStringList l;
447 QStringList l;
447 if (_isQObject && _meta) {
448 if (_isQObject && _meta) {
448 int i;
449 int i;
449 int numProperties = _meta->propertyCount();
450 int numProperties = _meta->propertyCount();
450 for (i = 0; i < numProperties; i++) {
451 for (i = 0; i < numProperties; i++) {
451 QMetaProperty p = _meta->property(i);
452 QMetaProperty p = _meta->property(i);
452 l << QString(p.name());
453 l << QString(p.name());
453 }
454 }
454 }
455 }
455 return l;
456 return l;
456 }
457 }
457
458
458 QStringList PythonQtClassInfo::memberList(bool metaOnly)
459 QStringList PythonQtClassInfo::memberList(bool metaOnly)
459 {
460 {
460 decorator();
461 decorator();
461
462
462 QStringList l;
463 QStringList l;
463 QString h;
464 QString h;
464 if (_isQObject && _meta && !metaOnly) {
465 if (_isQObject && _meta && !metaOnly) {
465 l = propertyList();
466 l = propertyList();
466 }
467 }
467
468
468 // normal slots of QObject (or wrapper QObject)
469 // normal slots of QObject (or wrapper QObject)
469 if (!metaOnly && _meta) {
470 if (!metaOnly && _meta) {
470 int numMethods = _meta->methodCount();
471 int numMethods = _meta->methodCount();
471 bool skipQObj = !_isQObject;
472 bool skipQObj = !_isQObject;
472 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
473 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
473 QMetaMethod m = _meta->method(i);
474 QMetaMethod m = _meta->method(i);
474 if ((m.methodType() == QMetaMethod::Method ||
475 if (((m.methodType() == QMetaMethod::Method ||
475 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
476 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
477 || m.methodType()==QMetaMethod::Signal) {
476 QByteArray signa(m.signature());
478 QByteArray signa(m.signature());
477 signa = signa.left(signa.indexOf('('));
479 signa = signa.left(signa.indexOf('('));
478 l << signa;
480 l << signa;
479 }
481 }
480 }
482 }
481 }
483 }
482
484
483 {
485 {
484 // look for dynamic decorators in this class and in derived classes
486 // look for dynamic decorators in this class and in derived classes
485 QList<PythonQtClassInfo*> infos;
487 QList<PythonQtClassInfo*> infos;
486 recursiveCollectClassInfos(infos);
488 recursiveCollectClassInfos(infos);
487 foreach(PythonQtClassInfo* info, infos) {
489 foreach(PythonQtClassInfo* info, infos) {
488 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
490 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
489 }
491 }
490 }
492 }
491
493
492 // List enumerator keys...
494 // List enumerator keys...
493 QList<const QMetaObject*> enumMetaObjects;
495 QList<const QMetaObject*> enumMetaObjects;
494 if (_meta) {
496 if (_meta) {
495 enumMetaObjects << _meta;
497 enumMetaObjects << _meta;
496 }
498 }
497 // check enums in the class hierachy of CPP classes
499 // check enums in the class hierachy of CPP classes
498 QList<QObject*> decoObjects;
500 QList<QObject*> decoObjects;
499 recursiveCollectDecoratorObjects(decoObjects);
501 recursiveCollectDecoratorObjects(decoObjects);
500 foreach(QObject* deco, decoObjects) {
502 foreach(QObject* deco, decoObjects) {
501 enumMetaObjects << deco->metaObject();
503 enumMetaObjects << deco->metaObject();
502 }
504 }
503
505
504 foreach(const QMetaObject* meta, enumMetaObjects) {
506 foreach(const QMetaObject* meta, enumMetaObjects) {
505 for (int i = 0; i<meta->enumeratorCount(); i++) {
507 for (int i = 0; i<meta->enumeratorCount(); i++) {
506 QMetaEnum e = meta->enumerator(i);
508 QMetaEnum e = meta->enumerator(i);
507 l << e.name();
509 l << e.name();
508 // we do not want flags, they will cause our values to appear two times
510 // we do not want flags, they will cause our values to appear two times
509 if (e.isFlag()) continue;
511 if (e.isFlag()) continue;
510
512
511 for (int j=0; j < e.keyCount(); j++) {
513 for (int j=0; j < e.keyCount(); j++) {
512 l << QString(e.key(j));
514 l << QString(e.key(j));
513 }
515 }
514 }
516 }
515 }
517 }
516
518
517 return QSet<QString>::fromList(l).toList();
519 return QSet<QString>::fromList(l).toList();
518 }
520 }
519
521
520 const char* PythonQtClassInfo::className()
522 const char* PythonQtClassInfo::className()
521 {
523 {
522 return _wrappedClassName.constData();
524 return _wrappedClassName.constData();
523 }
525 }
524
526
525 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
527 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
526 {
528 {
527 if (ptr==NULL) {
529 if (ptr==NULL) {
528 return NULL;
530 return NULL;
529 }
531 }
530 if (_wrappedClassName == classname) {
532 if (_wrappedClassName == classname) {
531 return ptr;
533 return ptr;
532 }
534 }
533 foreach(const ParentClassInfo& info, _parentClasses) {
535 foreach(const ParentClassInfo& info, _parentClasses) {
534 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
536 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
535 if (result) {
537 if (result) {
536 return result;
538 return result;
537 }
539 }
538 }
540 }
539 return NULL;
541 return NULL;
540 }
542 }
541
543
542 bool PythonQtClassInfo::inherits(const char* name)
544 bool PythonQtClassInfo::inherits(const char* name)
543 {
545 {
544 if (_wrappedClassName == name) {
546 if (_wrappedClassName == name) {
545 return true;
547 return true;
546 }
548 }
547 foreach(const ParentClassInfo& info, _parentClasses) {
549 foreach(const ParentClassInfo& info, _parentClasses) {
548 if (info._parent->inherits(name)) {
550 if (info._parent->inherits(name)) {
549 return true;
551 return true;
550 }
552 }
551 }
553 }
552 return false;
554 return false;
553 }
555 }
554
556
555 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
557 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
556 {
558 {
557 if (classInfo == this) {
559 if (classInfo == this) {
558 return true;
560 return true;
559 }
561 }
560 foreach(const ParentClassInfo& info, _parentClasses) {
562 foreach(const ParentClassInfo& info, _parentClasses) {
561 if (info._parent->inherits(classInfo)) {
563 if (info._parent->inherits(classInfo)) {
562 return true;
564 return true;
563 }
565 }
564 }
566 }
565 return false;
567 return false;
566 }
568 }
567
569
568 QString PythonQtClassInfo::help()
570 QString PythonQtClassInfo::help()
569 {
571 {
570 decorator();
572 decorator();
571 QString h;
573 QString h;
572 h += QString("--- ") + QString(className()) + QString(" ---\n");
574 h += QString("--- ") + QString(className()) + QString(" ---\n");
573
575
574 if (_isQObject) {
576 if (_isQObject) {
575 h += "Properties:\n";
577 h += "Properties:\n";
576
578
577 int i;
579 int i;
578 int numProperties = _meta->propertyCount();
580 int numProperties = _meta->propertyCount();
579 for (i = 0; i < numProperties; i++) {
581 for (i = 0; i < numProperties; i++) {
580 QMetaProperty p = _meta->property(i);
582 QMetaProperty p = _meta->property(i);
581 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
583 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
582 }
584 }
583 }
585 }
584
586
585 if (constructors()) {
587 if (constructors()) {
586 h += "Constructors:\n";
588 h += "Constructors:\n";
587 PythonQtSlotInfo* constr = constructors();
589 PythonQtSlotInfo* constr = constructors();
588 while (constr) {
590 while (constr) {
589 h += constr->fullSignature() + "\n";
591 h += constr->fullSignature() + "\n";
590 constr = constr->nextInfo();
592 constr = constr->nextInfo();
591 }
593 }
592 }
594 }
593
595
594 h += "Slots:\n";
596 h += "Slots:\n";
595 h += "QString help()\n";
597 h += "QString help()\n";
596 h += "QString className()\n";
598 h += "QString className()\n";
597
599
598 if (_meta) {
600 if (_meta) {
599 int numMethods = _meta->methodCount();
601 int numMethods = _meta->methodCount();
600 for (int i = 0; i < numMethods; i++) {
602 for (int i = 0; i < numMethods; i++) {
601 QMetaMethod m = _meta->method(i);
603 QMetaMethod m = _meta->method(i);
602 if ((m.methodType() == QMetaMethod::Method ||
604 if ((m.methodType() == QMetaMethod::Method ||
603 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
605 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
604 PythonQtSlotInfo slot(this, m, i);
606 PythonQtSlotInfo slot(this, m, i);
605 h += slot.fullSignature()+ "\n";
607 h += slot.fullSignature()+ "\n";
606 }
608 }
607 }
609 }
608 }
610 }
609
611
610 // TODO xxx : decorators and enums from decorator() are missing...
612 // TODO xxx : decorators and enums from decorator() are missing...
611 // maybe we can reuse memberlist()?
613 // maybe we can reuse memberlist()?
612
614
613 if (_meta && _meta->enumeratorCount()) {
615 if (_meta && _meta->enumeratorCount()) {
614 h += "Enums:\n";
616 h += "Enums:\n";
615 for (int i = 0; i<_meta->enumeratorCount(); i++) {
617 for (int i = 0; i<_meta->enumeratorCount(); i++) {
616 QMetaEnum e = _meta->enumerator(i);
618 QMetaEnum e = _meta->enumerator(i);
617 h += QString(e.name()) + " {";
619 h += QString(e.name()) + " {";
618 for (int j=0; j < e.keyCount(); j++) {
620 for (int j=0; j < e.keyCount(); j++) {
619 if (j) { h+= ", "; }
621 if (j) { h+= ", "; }
620 h += e.key(j);
622 h += e.key(j);
621 }
623 }
622 h += " }\n";
624 h += " }\n";
623 }
625 }
624 }
626 }
625
627
626 if (_isQObject && _meta) {
628 if (_isQObject && _meta) {
627 int numMethods = _meta->methodCount();
629 int numMethods = _meta->methodCount();
628 if (numMethods>0) {
630 if (numMethods>0) {
629 h += "Signals:\n";
631 h += "Signals:\n";
630 for (int i = 0; i < numMethods; i++) {
632 for (int i = 0; i < numMethods; i++) {
631 QMetaMethod m = _meta->method(i);
633 QMetaMethod m = _meta->method(i);
632 if (m.methodType() == QMetaMethod::Signal) {
634 if (m.methodType() == QMetaMethod::Signal) {
633 h += QString(m.signature()) + "\n";
635 h += QString(m.signature()) + "\n";
634 }
636 }
635 }
637 }
636 }
638 }
637 }
639 }
638 return h;
640 return h;
639 }
641 }
640
642
641 PythonQtSlotInfo* PythonQtClassInfo::constructors()
643 PythonQtSlotInfo* PythonQtClassInfo::constructors()
642 {
644 {
643 if (!_constructors) {
645 if (!_constructors) {
644 // force creation of lazy decorator, which will register the decorators
646 // force creation of lazy decorator, which will register the decorators
645 decorator();
647 decorator();
646 }
648 }
647 return _constructors;
649 return _constructors;
648 }
650 }
649
651
650 PythonQtSlotInfo* PythonQtClassInfo::destructor()
652 PythonQtSlotInfo* PythonQtClassInfo::destructor()
651 {
653 {
652 if (!_destructor) {
654 if (!_destructor) {
653 // force creation of lazy decorator, which will register the decorators
655 // force creation of lazy decorator, which will register the decorators
654 decorator();
656 decorator();
655 }
657 }
656 return _destructor;
658 return _destructor;
657 }
659 }
658
660
659 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
661 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
660 {
662 {
661 PythonQtSlotInfo* prev = constructors();
663 PythonQtSlotInfo* prev = constructors();
662 if (prev) {
664 if (prev) {
663 info->setNextInfo(prev->nextInfo());
665 info->setNextInfo(prev->nextInfo());
664 prev->setNextInfo(info);
666 prev->setNextInfo(info);
665 } else {
667 } else {
666 _constructors = info;
668 _constructors = info;
667 }
669 }
668 }
670 }
669
671
670 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
672 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
671 {
673 {
672 _decoratorSlots.append(info);
674 _decoratorSlots.append(info);
673 }
675 }
674
676
675 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
677 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
676 {
678 {
677 if (_destructor) {
679 if (_destructor) {
678 _destructor->deleteOverloadsAndThis();
680 _destructor->deleteOverloadsAndThis();
679 }
681 }
680 _destructor = info;
682 _destructor = info;
681 }
683 }
682
684
683 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
685 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
684 {
686 {
685 _meta = meta;
687 _meta = meta;
686 clearCachedMembers();
688 clearCachedMembers();
687 }
689 }
688
690
689 QObject* PythonQtClassInfo::decorator()
691 QObject* PythonQtClassInfo::decorator()
690 {
692 {
691 if (!_decoratorProvider && _decoratorProviderCB) {
693 if (!_decoratorProvider && _decoratorProviderCB) {
692 _decoratorProvider = (*_decoratorProviderCB)();
694 _decoratorProvider = (*_decoratorProviderCB)();
693 if (_decoratorProvider) {
695 if (_decoratorProvider) {
694 _decoratorProvider->setParent(PythonQt::priv());
696 _decoratorProvider->setParent(PythonQt::priv());
695 // setup enums early, since they might be needed by the constructor decorators:
697 // setup enums early, since they might be needed by the constructor decorators:
696 if (!_enumsCreated) {
698 if (!_enumsCreated) {
697 createEnumWrappers();
699 createEnumWrappers();
698 }
700 }
699 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
701 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
700 }
702 }
701 }
703 }
702 // check if enums need to be created and create them if they are not yet created
704 // check if enums need to be created and create them if they are not yet created
703 if (!_enumsCreated) {
705 if (!_enumsCreated) {
704 createEnumWrappers();
706 createEnumWrappers();
705 }
707 }
706 return _decoratorProvider;
708 return _decoratorProvider;
707 }
709 }
708
710
709 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
711 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
710 {
712 {
711 PythonQtMemberInfo info = member("hasOwner");
713 PythonQtMemberInfo info = member("hasOwner");
712 if (info._type == PythonQtMemberInfo::Slot) {
714 if (info._type == PythonQtMemberInfo::Slot) {
713 void* obj = object;
715 void* obj = object;
714 bool result = false;
716 bool result = false;
715 void* args[2];
717 void* args[2];
716 args[0] = &result;
718 args[0] = &result;
717 args[1] = &obj;
719 args[1] = &obj;
718 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
720 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
719 return !result;
721 return !result;
720 } else {
722 } else {
721 return false;
723 return false;
722 }
724 }
723 }
725 }
724
726
725 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
727 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
726 {
728 {
727 if (!_polymorphicHandlers.isEmpty()) {
729 if (!_polymorphicHandlers.isEmpty()) {
728 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
730 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
729 void* resultPtr = (*cb)(ptr, resultClassName);
731 void* resultPtr = (*cb)(ptr, resultClassName);
730 if (resultPtr) {
732 if (resultPtr) {
731 return resultPtr;
733 return resultPtr;
732 }
734 }
733 }
735 }
734 }
736 }
735 foreach(const ParentClassInfo& info, _parentClasses) {
737 foreach(const ParentClassInfo& info, _parentClasses) {
736 if (!info._parent->isQObject()) {
738 if (!info._parent->isQObject()) {
737 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
739 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
738 if (resultPtr) {
740 if (resultPtr) {
739 return resultPtr;
741 return resultPtr;
740 }
742 }
741 }
743 }
742 }
744 }
743 return NULL;
745 return NULL;
744 }
746 }
745
747
746 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
748 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
747 {
749 {
748 char* className;
750 char* className;
749 // this would do downcasting recursively...
751 // this would do downcasting recursively...
750 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
752 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
751
753
752 // we only do downcasting on the base object, not on the whole inheritance tree...
754 // we only do downcasting on the base object, not on the whole inheritance tree...
753 void* resultPtr = NULL;
755 void* resultPtr = NULL;
754 if (!_polymorphicHandlers.isEmpty()) {
756 if (!_polymorphicHandlers.isEmpty()) {
755 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
757 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
756 resultPtr = (*cb)(ptr, &className);
758 resultPtr = (*cb)(ptr, &className);
757 if (resultPtr) {
759 if (resultPtr) {
758 break;
760 break;
759 }
761 }
760 }
762 }
761 }
763 }
762 if (resultPtr) {
764 if (resultPtr) {
763 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
765 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
764 } else {
766 } else {
765 *resultClassInfo = this;
767 *resultClassInfo = this;
766 resultPtr = ptr;
768 resultPtr = ptr;
767 }
769 }
768 return resultPtr;
770 return resultPtr;
769 }
771 }
770
772
771 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
773 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
772 {
774 {
773 if (isLocalEnum) {
775 if (isLocalEnum) {
774 *isLocalEnum = true;
776 *isLocalEnum = true;
775 }
777 }
776 int scopePos = name.lastIndexOf("::");
778 int scopePos = name.lastIndexOf("::");
777 if (scopePos != -1) {
779 if (scopePos != -1) {
778 if (isLocalEnum) {
780 if (isLocalEnum) {
779 *isLocalEnum = false;
781 *isLocalEnum = false;
780 }
782 }
781 // split into scope and enum name
783 // split into scope and enum name
782 QByteArray enumScope = name.mid(0,scopePos);
784 QByteArray enumScope = name.mid(0,scopePos);
783 QByteArray enumName = name.mid(scopePos+2);
785 QByteArray enumName = name.mid(scopePos+2);
784 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
786 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
785 if (info) {
787 if (info) {
786 return info->findEnumWrapper(enumName);
788 return info->findEnumWrapper(enumName);
787 } else{
789 } else{
788 return NULL;
790 return NULL;
789 }
791 }
790 }
792 }
791 if (localScope) {
793 if (localScope) {
792 return localScope->findEnumWrapper(name);
794 return localScope->findEnumWrapper(name);
793 } else {
795 } else {
794 return NULL;
796 return NULL;
795 }
797 }
796 }
798 }
797
799
798 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
800 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
799 {
801 {
800 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
802 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
801 QMetaEnum e = meta->enumerator(i);
803 QMetaEnum e = meta->enumerator(i);
802 PythonQtObjectPtr p;
804 PythonQtObjectPtr p;
803 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
805 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
804 _enumWrappers.append(p);
806 _enumWrappers.append(p);
805 }
807 }
806 }
808 }
807
809
808 void PythonQtClassInfo::createEnumWrappers()
810 void PythonQtClassInfo::createEnumWrappers()
809 {
811 {
810 if (!_enumsCreated) {
812 if (!_enumsCreated) {
811 _enumsCreated = true;
813 _enumsCreated = true;
812 if (_meta) {
814 if (_meta) {
813 createEnumWrappers(_meta);
815 createEnumWrappers(_meta);
814 }
816 }
815 if (decorator()) {
817 if (decorator()) {
816 createEnumWrappers(decorator()->metaObject());
818 createEnumWrappers(decorator()->metaObject());
817 }
819 }
818 foreach(const ParentClassInfo& info, _parentClasses) {
820 foreach(const ParentClassInfo& info, _parentClasses) {
819 info._parent->createEnumWrappers();
821 info._parent->createEnumWrappers();
820 }
822 }
821 }
823 }
822 }
824 }
823
825
824 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
826 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
825 // force enum creation
827 // force enum creation
826 if (!_enumsCreated) {
828 if (!_enumsCreated) {
827 createEnumWrappers();
829 createEnumWrappers();
828 }
830 }
829 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
831 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
830 const char* className = ((PyTypeObject*)p.object())->tp_name;
832 const char* className = ((PyTypeObject*)p.object())->tp_name;
831 if (qstrcmp(className, name)==0) {
833 if (qstrcmp(className, name)==0) {
832 return p.object();
834 return p.object();
833 }
835 }
834 }
836 }
835 foreach(const ParentClassInfo& info, _parentClasses) {
837 foreach(const ParentClassInfo& info, _parentClasses) {
836 PyObject* p = info._parent->findEnumWrapper(name);
838 PyObject* p = info._parent->findEnumWrapper(name);
837 if (p) return p;
839 if (p) return p;
838 }
840 }
839 return NULL;
841 return NULL;
840 }
842 }
841
843
General Comments 0
You need to be logged in to leave comments. Login now