##// END OF EJS Templates
enabled downcasting only on base classes...
florianlink -
r31:8293debcc536
parent child
Show More
@@ -1,706 +1,718
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
46
47 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
47 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
48
48
49 PythonQtClassInfo::PythonQtClassInfo() {
49 PythonQtClassInfo::PythonQtClassInfo() {
50 _meta = NULL;
50 _meta = NULL;
51 _constructors = NULL;
51 _constructors = NULL;
52 _destructor = NULL;
52 _destructor = NULL;
53 _decoratorProvider = NULL;
53 _decoratorProvider = NULL;
54 _decoratorProviderCB = NULL;
54 _decoratorProviderCB = NULL;
55 _pythonQtClassWrapper = NULL;
55 _pythonQtClassWrapper = NULL;
56 _shellSetInstanceWrapperCB = NULL;
56 _shellSetInstanceWrapperCB = NULL;
57 _metaTypeId = -1;
57 _metaTypeId = -1;
58 _isQObject = false;
58 _isQObject = false;
59 }
59 }
60
60
61 PythonQtClassInfo::~PythonQtClassInfo()
61 PythonQtClassInfo::~PythonQtClassInfo()
62 {
62 {
63 clearCachedMembers();
63 clearCachedMembers();
64
64
65 if (_constructors) {
65 if (_constructors) {
66 _constructors->deleteOverloadsAndThis();
66 _constructors->deleteOverloadsAndThis();
67 }
67 }
68 if (_destructor) {
68 if (_destructor) {
69 _destructor->deleteOverloadsAndThis();
69 _destructor->deleteOverloadsAndThis();
70 }
70 }
71 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
71 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
72 info->deleteOverloadsAndThis();
72 info->deleteOverloadsAndThis();
73 }
73 }
74 }
74 }
75
75
76 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
76 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
77 {
77 {
78 // _wrappedClassName is already set earlier in the class setup
78 // _wrappedClassName is already set earlier in the class setup
79 _isQObject = true;
79 _isQObject = true;
80 _meta = meta;
80 _meta = meta;
81 }
81 }
82
82
83 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
83 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
84 {
84 {
85 _isQObject = false;
85 _isQObject = false;
86 _wrappedClassName = classname;
86 _wrappedClassName = classname;
87 _metaTypeId = QMetaType::type(classname);
87 _metaTypeId = QMetaType::type(classname);
88 }
88 }
89
89
90 void PythonQtClassInfo::clearCachedMembers()
90 void PythonQtClassInfo::clearCachedMembers()
91 {
91 {
92 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
92 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
93 while (i.hasNext()) {
93 while (i.hasNext()) {
94 PythonQtMemberInfo member = i.next().value();
94 PythonQtMemberInfo member = i.next().value();
95 if (member._type== PythonQtMemberInfo::Slot) {
95 if (member._type== PythonQtMemberInfo::Slot) {
96 PythonQtSlotInfo* info = member._slot;
96 PythonQtSlotInfo* info = member._slot;
97 while (info) {
97 while (info) {
98 PythonQtSlotInfo* next = info->nextInfo();
98 PythonQtSlotInfo* next = info->nextInfo();
99 delete info;
99 delete info;
100 info = next;
100 info = next;
101 }
101 }
102 }
102 }
103 }
103 }
104 }
104 }
105
105
106 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
106 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
107 {
107 {
108 const char* sigEnd = sigStart;
108 const char* sigEnd = sigStart;
109 char c;
109 char c;
110 do {
110 do {
111 c = *sigEnd++;
111 c = *sigEnd++;
112 } while (c!=someChar && c!=0);
112 } while (c!=someChar && c!=0);
113 return sigEnd-sigStart-1;
113 return sigEnd-sigStart-1;
114 }
114 }
115
115
116 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
116 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
117 {
117 {
118 bool found = false;
118 bool found = false;
119 bool nameMapped = false;
119 bool nameMapped = false;
120 const char* attributeName = memberName;
120 const char* attributeName = memberName;
121 // look for properties
121 // look for properties
122 int i = _meta->indexOfProperty(attributeName);
122 int i = _meta->indexOfProperty(attributeName);
123 if (i==-1) {
123 if (i==-1) {
124 // try to map name to objectName
124 // try to map name to objectName
125 if (qstrcmp(attributeName, "name")==0) {
125 if (qstrcmp(attributeName, "name")==0) {
126 attributeName = "objectName";
126 attributeName = "objectName";
127 nameMapped = true;
127 nameMapped = true;
128 i = _meta->indexOfProperty(attributeName);
128 i = _meta->indexOfProperty(attributeName);
129 }
129 }
130 }
130 }
131 if (i!=-1) {
131 if (i!=-1) {
132 PythonQtMemberInfo newInfo(_meta->property(i));
132 PythonQtMemberInfo newInfo(_meta->property(i));
133 _cachedMembers.insert(attributeName, newInfo);
133 _cachedMembers.insert(attributeName, newInfo);
134 if (nameMapped) {
134 if (nameMapped) {
135 _cachedMembers.insert(memberName, newInfo);
135 _cachedMembers.insert(memberName, newInfo);
136 }
136 }
137 #ifdef PYTHONQT_DEBUG
137 #ifdef PYTHONQT_DEBUG
138 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
138 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
139 #endif
139 #endif
140 found = true;
140 found = true;
141 }
141 }
142 return found;
142 return found;
143 }
143 }
144
144
145 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
145 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
146 {
146 {
147 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
147 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
148 foreach(const ParentClassInfo& info, _parentClasses) {
148 foreach(const ParentClassInfo& info, _parentClasses) {
149 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
149 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
150 }
150 }
151 return inputInfo;
151 return inputInfo;
152 }
152 }
153
153
154 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
154 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
155 QObject* decoratorProvider = decorator();
155 QObject* decoratorProvider = decorator();
156 int memberNameLen = strlen(memberName);
156 int memberNameLen = strlen(memberName);
157 if (decoratorProvider) {
157 if (decoratorProvider) {
158 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
158 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
159 const QMetaObject* meta = decoratorProvider->metaObject();
159 const QMetaObject* meta = decoratorProvider->metaObject();
160 int numMethods = meta->methodCount();
160 int numMethods = meta->methodCount();
161 int startFrom = QObject::staticMetaObject.methodCount();
161 int startFrom = QObject::staticMetaObject.methodCount();
162 for (int i = startFrom; i < numMethods; i++) {
162 for (int i = startFrom; i < numMethods; i++) {
163 QMetaMethod m = meta->method(i);
163 QMetaMethod m = meta->method(i);
164 if ((m.methodType() == QMetaMethod::Method ||
164 if ((m.methodType() == QMetaMethod::Method ||
165 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
165 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
166
166
167 const char* sigStart = m.signature();
167 const char* sigStart = m.signature();
168 bool isClassDeco = false;
168 bool isClassDeco = false;
169 if (qstrncmp(sigStart, "static_", 7)==0) {
169 if (qstrncmp(sigStart, "static_", 7)==0) {
170 // skip the static_classname_ part of the string
170 // skip the static_classname_ part of the string
171 sigStart += 7 + 1 + strlen(className());
171 sigStart += 7 + 1 + strlen(className());
172 isClassDeco = true;
172 isClassDeco = true;
173 } else if (qstrncmp(sigStart, "new_", 4)==0) {
173 } else if (qstrncmp(sigStart, "new_", 4)==0) {
174 isClassDeco = true;
174 isClassDeco = true;
175 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
175 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
176 isClassDeco = true;
176 isClassDeco = true;
177 }
177 }
178 // find the first '('
178 // find the first '('
179 int offset = findCharOffset(sigStart, '(');
179 int offset = findCharOffset(sigStart, '(');
180
180
181 // XXX no checking is currently done if the slots have correct first argument or not...
181 // XXX no checking is currently done if the slots have correct first argument or not...
182
182
183 // check if same length and same name
183 // check if same length and same name
184 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
184 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
185 found = true;
185 found = true;
186 PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
186 PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
187 info->setUpcastingOffset(upcastingOffset);
187 info->setUpcastingOffset(upcastingOffset);
188 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
188 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
189 if (tail) {
189 if (tail) {
190 tail->setNextInfo(info);
190 tail->setNextInfo(info);
191 } else {
191 } else {
192 PythonQtMemberInfo newInfo(info);
192 PythonQtMemberInfo newInfo(info);
193 memberCache.insert(memberName, newInfo);
193 memberCache.insert(memberName, newInfo);
194 }
194 }
195 tail = info;
195 tail = info;
196 }
196 }
197 }
197 }
198 }
198 }
199 }
199 }
200
200
201 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
201 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
202
202
203 return tail;
203 return tail;
204 }
204 }
205
205
206 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
206 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
207 {
207 {
208 bool found = false;
208 bool found = false;
209 int memberNameLen = strlen(memberName);
209 int memberNameLen = strlen(memberName);
210 PythonQtSlotInfo* tail = NULL;
210 PythonQtSlotInfo* tail = NULL;
211 if (_meta) {
211 if (_meta) {
212 int numMethods = _meta->methodCount();
212 int numMethods = _meta->methodCount();
213 for (int i = 0; i < numMethods; i++) {
213 for (int i = 0; i < numMethods; i++) {
214 QMetaMethod m = _meta->method(i);
214 QMetaMethod m = _meta->method(i);
215 if ((m.methodType() == QMetaMethod::Method ||
215 if ((m.methodType() == QMetaMethod::Method ||
216 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
216 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
217
217
218 const char* sigStart = m.signature();
218 const char* sigStart = m.signature();
219 // find the first '('
219 // find the first '('
220 int offset = findCharOffset(sigStart, '(');
220 int offset = findCharOffset(sigStart, '(');
221
221
222 // check if same length and same name
222 // check if same length and same name
223 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
223 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
224 found = true;
224 found = true;
225 PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i);
225 PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i);
226 if (tail) {
226 if (tail) {
227 tail->setNextInfo(info);
227 tail->setNextInfo(info);
228 } else {
228 } else {
229 PythonQtMemberInfo newInfo(info);
229 PythonQtMemberInfo newInfo(info);
230 _cachedMembers.insert(memberName, newInfo);
230 _cachedMembers.insert(memberName, newInfo);
231 }
231 }
232 tail = info;
232 tail = info;
233 }
233 }
234 }
234 }
235 }
235 }
236 }
236 }
237
237
238 // look for dynamic decorators in this class and in derived classes
238 // look for dynamic decorators in this class and in derived classes
239 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
239 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
240
240
241 return found;
241 return found;
242 }
242 }
243
243
244 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
244 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
245 {
245 {
246 bool found = false;
246 bool found = false;
247 // look for enum values
247 // look for enum values
248 int enumCount = meta->enumeratorCount();
248 int enumCount = meta->enumeratorCount();
249 for (int i=0;i<enumCount; i++) {
249 for (int i=0;i<enumCount; i++) {
250 QMetaEnum e = meta->enumerator(i);
250 QMetaEnum e = meta->enumerator(i);
251 for (int j=0; j < e.keyCount(); j++) {
251 for (int j=0; j < e.keyCount(); j++) {
252 if (qstrcmp(e.key(j), memberName)==0) {
252 if (qstrcmp(e.key(j), memberName)==0) {
253 PythonQtMemberInfo newInfo(e.value(j));
253 PythonQtMemberInfo newInfo(e.value(j));
254 _cachedMembers.insert(memberName, newInfo);
254 _cachedMembers.insert(memberName, newInfo);
255 #ifdef PYTHONQT_DEBUG
255 #ifdef PYTHONQT_DEBUG
256 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
256 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
257 #endif
257 #endif
258 found = true;
258 found = true;
259 break;
259 break;
260 }
260 }
261 }
261 }
262 }
262 }
263 return found;
263 return found;
264 }
264 }
265
265
266 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
266 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
267 {
267 {
268 PythonQtMemberInfo info = _cachedMembers.value(memberName);
268 PythonQtMemberInfo info = _cachedMembers.value(memberName);
269 if (info._type != PythonQtMemberInfo::Invalid) {
269 if (info._type != PythonQtMemberInfo::Invalid) {
270 return info;
270 return info;
271 } else {
271 } else {
272 bool found = false;
272 bool found = false;
273
273
274 found = lookForPropertyAndCache(memberName);
274 found = lookForPropertyAndCache(memberName);
275 if (!found) {
275 if (!found) {
276 found = lookForMethodAndCache(memberName);
276 found = lookForMethodAndCache(memberName);
277 }
277 }
278 if (!found) {
278 if (!found) {
279 if (_meta) {
279 if (_meta) {
280 // check enums in our meta object directly
280 // check enums in our meta object directly
281 found = lookForEnumAndCache(_meta, memberName);
281 found = lookForEnumAndCache(_meta, memberName);
282 }
282 }
283 if (!found) {
283 if (!found) {
284 // check enums in the class hierachy of CPP classes
284 // check enums in the class hierachy of CPP classes
285 // look for dynamic decorators in this class and in derived classes
285 // look for dynamic decorators in this class and in derived classes
286 QList<QObject*> decoObjects;
286 QList<QObject*> decoObjects;
287 recursiveCollectDecoratorObjects(decoObjects);
287 recursiveCollectDecoratorObjects(decoObjects);
288 foreach(QObject* deco, decoObjects) {
288 foreach(QObject* deco, decoObjects) {
289 // call on ourself for caching, but with different metaObject():
289 // call on ourself for caching, but with different metaObject():
290 found = lookForEnumAndCache(deco->metaObject(), memberName);
290 found = lookForEnumAndCache(deco->metaObject(), memberName);
291 if (found) {
291 if (found) {
292 break;
292 break;
293 }
293 }
294 }
294 }
295 }
295 }
296 }
296 }
297 if (!found) {
297 if (!found) {
298 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
298 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
299 info._type = PythonQtMemberInfo::NotFound;
299 info._type = PythonQtMemberInfo::NotFound;
300 _cachedMembers.insert(memberName, info);
300 _cachedMembers.insert(memberName, info);
301 }
301 }
302 }
302 }
303
303
304 return _cachedMembers.value(memberName);
304 return _cachedMembers.value(memberName);
305 }
305 }
306
306
307 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
307 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
308 QObject* deco = decorator();
308 QObject* deco = decorator();
309 if (deco) {
309 if (deco) {
310 decoratorObjects.append(deco);
310 decoratorObjects.append(deco);
311 }
311 }
312 foreach(const ParentClassInfo& info, _parentClasses) {
312 foreach(const ParentClassInfo& info, _parentClasses) {
313 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
313 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
314 }
314 }
315 }
315 }
316
316
317 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
317 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
318 classInfoObjects.append(this);
318 classInfoObjects.append(this);
319 foreach(const ParentClassInfo& info, _parentClasses) {
319 foreach(const ParentClassInfo& info, _parentClasses) {
320 info._parent->recursiveCollectClassInfos(classInfoObjects);
320 info._parent->recursiveCollectClassInfos(classInfoObjects);
321 }
321 }
322 }
322 }
323
323
324 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
324 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
325 {
325 {
326 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
326 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
327 while (it.hasNext()) {
327 while (it.hasNext()) {
328
328
329 PythonQtSlotInfo* infoOrig = it.next();
329 PythonQtSlotInfo* infoOrig = it.next();
330
330
331 const char* sigStart = infoOrig->metaMethod()->signature();
331 const char* sigStart = infoOrig->metaMethod()->signature();
332 if (qstrncmp("static_", sigStart, 7)==0) {
332 if (qstrncmp("static_", sigStart, 7)==0) {
333 sigStart += 7;
333 sigStart += 7;
334 sigStart += findCharOffset(sigStart, '_')+1;
334 sigStart += findCharOffset(sigStart, '_')+1;
335 }
335 }
336 int offset = findCharOffset(sigStart, '(');
336 int offset = findCharOffset(sigStart, '(');
337 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
337 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
338 //make a copy, otherwise we will have trouble on overloads!
338 //make a copy, otherwise we will have trouble on overloads!
339 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
339 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
340 info->setUpcastingOffset(upcastingOffset);
340 info->setUpcastingOffset(upcastingOffset);
341 found = true;
341 found = true;
342 if (tail) {
342 if (tail) {
343 tail->setNextInfo(info);
343 tail->setNextInfo(info);
344 } else {
344 } else {
345 PythonQtMemberInfo newInfo(info);
345 PythonQtMemberInfo newInfo(info);
346 memberCache.insert(memberName, newInfo);
346 memberCache.insert(memberName, newInfo);
347 }
347 }
348 tail = info;
348 tail = info;
349 }
349 }
350 }
350 }
351 return tail;
351 return tail;
352 }
352 }
353
353
354 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
354 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
355 QObject* decoratorProvider = decorator();
355 QObject* decoratorProvider = decorator();
356 if (decoratorProvider) {
356 if (decoratorProvider) {
357 const QMetaObject* meta = decoratorProvider->metaObject();
357 const QMetaObject* meta = decoratorProvider->metaObject();
358 int numMethods = meta->methodCount();
358 int numMethods = meta->methodCount();
359 int startFrom = QObject::staticMetaObject.methodCount();
359 int startFrom = QObject::staticMetaObject.methodCount();
360 for (int i = startFrom; i < numMethods; i++) {
360 for (int i = startFrom; i < numMethods; i++) {
361 QMetaMethod m = meta->method(i);
361 QMetaMethod m = meta->method(i);
362 if ((m.methodType() == QMetaMethod::Method ||
362 if ((m.methodType() == QMetaMethod::Method ||
363 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
363 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
364
364
365 const char* sigStart = m.signature();
365 const char* sigStart = m.signature();
366 bool isClassDeco = false;
366 bool isClassDeco = false;
367 if (qstrncmp(sigStart, "static_", 7)==0) {
367 if (qstrncmp(sigStart, "static_", 7)==0) {
368 // skip the static_classname_ part of the string
368 // skip the static_classname_ part of the string
369 sigStart += 7 + 1 + strlen(className());
369 sigStart += 7 + 1 + strlen(className());
370 isClassDeco = true;
370 isClassDeco = true;
371 } else if (qstrncmp(sigStart, "new_", 4)==0) {
371 } else if (qstrncmp(sigStart, "new_", 4)==0) {
372 continue;
372 continue;
373 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
373 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
374 continue;
374 continue;
375 }
375 }
376 // find the first '('
376 // find the first '('
377 int offset = findCharOffset(sigStart, '(');
377 int offset = findCharOffset(sigStart, '(');
378
378
379 // XXX no checking is currently done if the slots have correct first argument or not...
379 // XXX no checking is currently done if the slots have correct first argument or not...
380 if (!metaOnly || isClassDeco) {
380 if (!metaOnly || isClassDeco) {
381 list << QString::fromLatin1(sigStart, offset);
381 list << QString::fromLatin1(sigStart, offset);
382 }
382 }
383 }
383 }
384 }
384 }
385 }
385 }
386
386
387 // look for global decorator slots
387 // look for global decorator slots
388 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
388 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
389 while (it.hasNext()) {
389 while (it.hasNext()) {
390 PythonQtSlotInfo* slot = it.next();
390 PythonQtSlotInfo* slot = it.next();
391 if (metaOnly) {
391 if (metaOnly) {
392 if (slot->isClassDecorator()) {
392 if (slot->isClassDecorator()) {
393 QByteArray first = slot->slotName();
393 QByteArray first = slot->slotName();
394 if (first.startsWith("static_")) {
394 if (first.startsWith("static_")) {
395 int idx = first.indexOf('_');
395 int idx = first.indexOf('_');
396 idx = first.indexOf('_', idx+1);
396 idx = first.indexOf('_', idx+1);
397 first = first.mid(idx+1);
397 first = first.mid(idx+1);
398 }
398 }
399 list << first;
399 list << first;
400 }
400 }
401 } else {
401 } else {
402 list << slot->slotName();
402 list << slot->slotName();
403 }
403 }
404 }
404 }
405 }
405 }
406
406
407 QStringList PythonQtClassInfo::memberList(bool metaOnly)
407 QStringList PythonQtClassInfo::memberList(bool metaOnly)
408 {
408 {
409 decorator();
409 decorator();
410
410
411 QStringList l;
411 QStringList l;
412 QString h;
412 QString h;
413 if (_isQObject && _meta && !metaOnly) {
413 if (_isQObject && _meta && !metaOnly) {
414 int i;
414 int i;
415 int numProperties = _meta->propertyCount();
415 int numProperties = _meta->propertyCount();
416 for (i = 0; i < numProperties; i++) {
416 for (i = 0; i < numProperties; i++) {
417 QMetaProperty p = _meta->property(i);
417 QMetaProperty p = _meta->property(i);
418 l << QString(p.name());
418 l << QString(p.name());
419 }
419 }
420 }
420 }
421
421
422 // normal slots of QObject (or wrapper QObject)
422 // normal slots of QObject (or wrapper QObject)
423 if (!metaOnly && _meta) {
423 if (!metaOnly && _meta) {
424 int numMethods = _meta->methodCount();
424 int numMethods = _meta->methodCount();
425 bool skipQObj = !_isQObject;
425 bool skipQObj = !_isQObject;
426 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
426 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
427 QMetaMethod m = _meta->method(i);
427 QMetaMethod m = _meta->method(i);
428 if ((m.methodType() == QMetaMethod::Method ||
428 if ((m.methodType() == QMetaMethod::Method ||
429 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
429 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
430 QByteArray signa(m.signature());
430 QByteArray signa(m.signature());
431 if (signa.startsWith("new_")) continue;
431 if (signa.startsWith("new_")) continue;
432 if (signa.startsWith("delete_")) continue;
432 if (signa.startsWith("delete_")) continue;
433 if (signa.startsWith("static_")) continue;
433 if (signa.startsWith("static_")) continue;
434 PythonQtSlotInfo slot(m, i);
434 PythonQtSlotInfo slot(m, i);
435 l << slot.slotName();
435 l << slot.slotName();
436 }
436 }
437 }
437 }
438 }
438 }
439
439
440 {
440 {
441 // look for dynamic decorators in this class and in derived classes
441 // look for dynamic decorators in this class and in derived classes
442 QList<PythonQtClassInfo*> infos;
442 QList<PythonQtClassInfo*> infos;
443 recursiveCollectClassInfos(infos);
443 recursiveCollectClassInfos(infos);
444 foreach(PythonQtClassInfo* info, infos) {
444 foreach(PythonQtClassInfo* info, infos) {
445 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
445 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
446 }
446 }
447 }
447 }
448
448
449 // List enumerator keys...
449 // List enumerator keys...
450 QList<const QMetaObject*> enumMetaObjects;
450 QList<const QMetaObject*> enumMetaObjects;
451 if (_meta) {
451 if (_meta) {
452 enumMetaObjects << _meta;
452 enumMetaObjects << _meta;
453 }
453 }
454 // check enums in the class hierachy of CPP classes
454 // check enums in the class hierachy of CPP classes
455 QList<QObject*> decoObjects;
455 QList<QObject*> decoObjects;
456 recursiveCollectDecoratorObjects(decoObjects);
456 recursiveCollectDecoratorObjects(decoObjects);
457 foreach(QObject* deco, decoObjects) {
457 foreach(QObject* deco, decoObjects) {
458 enumMetaObjects << deco->metaObject();
458 enumMetaObjects << deco->metaObject();
459 }
459 }
460
460
461 foreach(const QMetaObject* meta, enumMetaObjects) {
461 foreach(const QMetaObject* meta, enumMetaObjects) {
462 for (int i = 0; i<meta->enumeratorCount(); i++) {
462 for (int i = 0; i<meta->enumeratorCount(); i++) {
463 QMetaEnum e = meta->enumerator(i);
463 QMetaEnum e = meta->enumerator(i);
464 for (int j=0; j < e.keyCount(); j++) {
464 for (int j=0; j < e.keyCount(); j++) {
465 l << QString(e.key(j));
465 l << QString(e.key(j));
466 }
466 }
467 }
467 }
468 }
468 }
469
469
470 return QSet<QString>::fromList(l).toList();
470 return QSet<QString>::fromList(l).toList();
471 }
471 }
472
472
473 const char* PythonQtClassInfo::className()
473 const char* PythonQtClassInfo::className()
474 {
474 {
475 return _wrappedClassName.constData();
475 return _wrappedClassName.constData();
476 }
476 }
477
477
478 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
478 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
479 {
479 {
480 if (ptr==NULL) {
480 if (ptr==NULL) {
481 return NULL;
481 return NULL;
482 }
482 }
483 if (_wrappedClassName == classname) {
483 if (_wrappedClassName == classname) {
484 return ptr;
484 return ptr;
485 }
485 }
486 foreach(const ParentClassInfo& info, _parentClasses) {
486 foreach(const ParentClassInfo& info, _parentClasses) {
487 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
487 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
488 if (result) {
488 if (result) {
489 return result;
489 return result;
490 }
490 }
491 }
491 }
492 return NULL;
492 return NULL;
493 }
493 }
494
494
495 bool PythonQtClassInfo::inherits(const char* name)
495 bool PythonQtClassInfo::inherits(const char* name)
496 {
496 {
497 if (_wrappedClassName == name) {
497 if (_wrappedClassName == name) {
498 return true;
498 return true;
499 }
499 }
500 foreach(const ParentClassInfo& info, _parentClasses) {
500 foreach(const ParentClassInfo& info, _parentClasses) {
501 if (info._parent->inherits(name)) {
501 if (info._parent->inherits(name)) {
502 return true;
502 return true;
503 }
503 }
504 }
504 }
505 return false;
505 return false;
506 }
506 }
507
507
508 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
508 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
509 {
509 {
510 if (classInfo == this) {
510 if (classInfo == this) {
511 return true;
511 return true;
512 }
512 }
513 foreach(const ParentClassInfo& info, _parentClasses) {
513 foreach(const ParentClassInfo& info, _parentClasses) {
514 if (info._parent->inherits(classInfo)) {
514 if (info._parent->inherits(classInfo)) {
515 return true;
515 return true;
516 }
516 }
517 }
517 }
518 return false;
518 return false;
519 }
519 }
520
520
521 QString PythonQtClassInfo::help()
521 QString PythonQtClassInfo::help()
522 {
522 {
523 decorator();
523 decorator();
524 QString h;
524 QString h;
525 h += QString("--- ") + QString(className()) + QString(" ---\n");
525 h += QString("--- ") + QString(className()) + QString(" ---\n");
526
526
527 if (_isQObject) {
527 if (_isQObject) {
528 h += "Properties:\n";
528 h += "Properties:\n";
529
529
530 int i;
530 int i;
531 int numProperties = _meta->propertyCount();
531 int numProperties = _meta->propertyCount();
532 for (i = 0; i < numProperties; i++) {
532 for (i = 0; i < numProperties; i++) {
533 QMetaProperty p = _meta->property(i);
533 QMetaProperty p = _meta->property(i);
534 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
534 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
535 }
535 }
536 }
536 }
537
537
538 if (constructors()) {
538 if (constructors()) {
539 h += "Constructors:\n";
539 h += "Constructors:\n";
540 PythonQtSlotInfo* constr = constructors();
540 PythonQtSlotInfo* constr = constructors();
541 while (constr) {
541 while (constr) {
542 h += constr->fullSignature() + "\n";
542 h += constr->fullSignature() + "\n";
543 constr = constr->nextInfo();
543 constr = constr->nextInfo();
544 }
544 }
545 }
545 }
546
546
547 h += "Slots:\n";
547 h += "Slots:\n";
548 h += "QString help()\n";
548 h += "QString help()\n";
549 h += "QString className()\n";
549 h += "QString className()\n";
550
550
551 if (_meta) {
551 if (_meta) {
552 int numMethods = _meta->methodCount();
552 int numMethods = _meta->methodCount();
553 for (int i = 0; i < numMethods; i++) {
553 for (int i = 0; i < numMethods; i++) {
554 QMetaMethod m = _meta->method(i);
554 QMetaMethod m = _meta->method(i);
555 if ((m.methodType() == QMetaMethod::Method ||
555 if ((m.methodType() == QMetaMethod::Method ||
556 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
556 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
557 QByteArray signa(m.signature());
557 QByteArray signa(m.signature());
558 if (signa.startsWith("new_")) continue;
558 if (signa.startsWith("new_")) continue;
559 if (signa.startsWith("delete_")) continue;
559 if (signa.startsWith("delete_")) continue;
560 if (signa.startsWith("static_")) continue;
560 if (signa.startsWith("static_")) continue;
561 PythonQtSlotInfo slot(m, i);
561 PythonQtSlotInfo slot(m, i);
562 h += slot.fullSignature()+ "\n";
562 h += slot.fullSignature()+ "\n";
563 }
563 }
564 }
564 }
565 }
565 }
566
566
567 // TODO xxx : decorators and enums from decorator() are missing...
567 // TODO xxx : decorators and enums from decorator() are missing...
568 // maybe we can reuse memberlist()?
568 // maybe we can reuse memberlist()?
569
569
570 if (_meta && _meta->enumeratorCount()) {
570 if (_meta && _meta->enumeratorCount()) {
571 h += "Enums:\n";
571 h += "Enums:\n";
572 for (int i = 0; i<_meta->enumeratorCount(); i++) {
572 for (int i = 0; i<_meta->enumeratorCount(); i++) {
573 QMetaEnum e = _meta->enumerator(i);
573 QMetaEnum e = _meta->enumerator(i);
574 h += QString(e.name()) + " {";
574 h += QString(e.name()) + " {";
575 for (int j=0; j < e.keyCount(); j++) {
575 for (int j=0; j < e.keyCount(); j++) {
576 if (j) { h+= ", "; }
576 if (j) { h+= ", "; }
577 h += e.key(j);
577 h += e.key(j);
578 }
578 }
579 h += " }\n";
579 h += " }\n";
580 }
580 }
581 }
581 }
582
582
583 if (_isQObject && _meta) {
583 if (_isQObject && _meta) {
584 int numMethods = _meta->methodCount();
584 int numMethods = _meta->methodCount();
585 if (numMethods>0) {
585 if (numMethods>0) {
586 h += "Signals:\n";
586 h += "Signals:\n";
587 for (int i = 0; i < numMethods; i++) {
587 for (int i = 0; i < numMethods; i++) {
588 QMetaMethod m = _meta->method(i);
588 QMetaMethod m = _meta->method(i);
589 if (m.methodType() == QMetaMethod::Signal) {
589 if (m.methodType() == QMetaMethod::Signal) {
590 h += QString(m.signature()) + "\n";
590 h += QString(m.signature()) + "\n";
591 }
591 }
592 }
592 }
593 }
593 }
594 }
594 }
595 return h;
595 return h;
596 }
596 }
597
597
598 PythonQtSlotInfo* PythonQtClassInfo::constructors()
598 PythonQtSlotInfo* PythonQtClassInfo::constructors()
599 {
599 {
600 if (!_constructors) {
600 if (!_constructors) {
601 // force creation of lazy decorator, which will register the decorators
601 // force creation of lazy decorator, which will register the decorators
602 decorator();
602 decorator();
603 }
603 }
604 return _constructors;
604 return _constructors;
605 }
605 }
606
606
607 PythonQtSlotInfo* PythonQtClassInfo::destructor()
607 PythonQtSlotInfo* PythonQtClassInfo::destructor()
608 {
608 {
609 if (!_destructor) {
609 if (!_destructor) {
610 // force creation of lazy decorator, which will register the decorators
610 // force creation of lazy decorator, which will register the decorators
611 decorator();
611 decorator();
612 }
612 }
613 return _destructor;
613 return _destructor;
614 }
614 }
615
615
616 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
616 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
617 {
617 {
618 PythonQtSlotInfo* prev = constructors();
618 PythonQtSlotInfo* prev = constructors();
619 if (prev) {
619 if (prev) {
620 info->setNextInfo(prev->nextInfo());
620 info->setNextInfo(prev->nextInfo());
621 prev->setNextInfo(info);
621 prev->setNextInfo(info);
622 } else {
622 } else {
623 _constructors = info;
623 _constructors = info;
624 }
624 }
625 }
625 }
626
626
627 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
627 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
628 {
628 {
629 _decoratorSlots.append(info);
629 _decoratorSlots.append(info);
630 }
630 }
631
631
632 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
632 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
633 {
633 {
634 if (_destructor) {
634 if (_destructor) {
635 _destructor->deleteOverloadsAndThis();
635 _destructor->deleteOverloadsAndThis();
636 }
636 }
637 _destructor = info;
637 _destructor = info;
638 }
638 }
639
639
640 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
640 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
641 {
641 {
642 _meta = meta;
642 _meta = meta;
643 clearCachedMembers();
643 clearCachedMembers();
644 }
644 }
645
645
646 QObject* PythonQtClassInfo::decorator()
646 QObject* PythonQtClassInfo::decorator()
647 {
647 {
648 if (!_decoratorProvider && _decoratorProviderCB) {
648 if (!_decoratorProvider && _decoratorProviderCB) {
649 _decoratorProvider = (*_decoratorProviderCB)();
649 _decoratorProvider = (*_decoratorProviderCB)();
650 if (_decoratorProvider) {
650 if (_decoratorProvider) {
651 _decoratorProvider->setParent(PythonQt::priv());
651 _decoratorProvider->setParent(PythonQt::priv());
652 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
652 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
653 }
653 }
654 }
654 }
655 return _decoratorProvider;
655 return _decoratorProvider;
656 }
656 }
657
657
658 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
658 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
659 {
659 {
660 PythonQtMemberInfo info = member("hasOwner");
660 PythonQtMemberInfo info = member("hasOwner");
661 if (info._type == PythonQtMemberInfo::Slot) {
661 if (info._type == PythonQtMemberInfo::Slot) {
662 void* obj = object;
662 void* obj = object;
663 bool result = false;
663 bool result = false;
664 void* args[2];
664 void* args[2];
665 args[0] = &result;
665 args[0] = &result;
666 args[1] = &obj;
666 args[1] = &obj;
667 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
667 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
668 return !result;
668 return !result;
669 } else {
669 } else {
670 return false;
670 return false;
671 }
671 }
672 }
672 }
673
673
674 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
674 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
675 {
675 {
676 if (!_polymorphicHandlers.isEmpty()) {
676 if (!_polymorphicHandlers.isEmpty()) {
677 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
677 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
678 void* resultPtr = (*cb)(ptr, resultClassName);
678 void* resultPtr = (*cb)(ptr, resultClassName);
679 if (resultPtr) {
679 if (resultPtr) {
680 return resultPtr;
680 return resultPtr;
681 }
681 }
682 }
682 }
683 }
683 }
684 foreach(const ParentClassInfo& info, _parentClasses) {
684 foreach(const ParentClassInfo& info, _parentClasses) {
685 if (!info._parent->isQObject()) {
685 if (!info._parent->isQObject()) {
686 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
686 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
687 if (resultPtr) {
687 if (resultPtr) {
688 return resultPtr;
688 return resultPtr;
689 }
689 }
690 }
690 }
691 }
691 }
692 return NULL;
692 return NULL;
693 }
693 }
694
694
695 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
695 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
696 {
696 {
697 char* className;
697 char* className;
698 void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
698 // this would do downcasting recursively...
699 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
700
701 // we only do downcasting on the base object, not on the whole inheritance tree...
702 void* resultPtr = NULL;
703 if (!_polymorphicHandlers.isEmpty()) {
704 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
705 resultPtr = (*cb)(ptr, &className);
706 if (resultPtr) {
707 break;
708 }
709 }
710 }
699 if (resultPtr) {
711 if (resultPtr) {
700 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
712 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
701 } else {
713 } else {
702 *resultClassInfo = this;
714 *resultClassInfo = this;
703 resultPtr = ptr;
715 resultPtr = ptr;
704 }
716 }
705 return resultPtr;
717 return resultPtr;
706 }
718 }
General Comments 0
You need to be logged in to leave comments. Login now