##// END OF EJS Templates
adapted to new py_ naming of special methods and added support for py_toString...
florianlink -
r116:806ca936e21a
parent child
Show More
@@ -1,845 +1,848
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 if (!_meta) return false;
121 if (!_meta) return false;
122
122
123 bool found = false;
123 bool found = false;
124 bool nameMapped = false;
124 bool nameMapped = false;
125 const char* attributeName = memberName;
125 const char* attributeName = memberName;
126 // look for properties
126 // look for properties
127 int i = _meta->indexOfProperty(attributeName);
127 int i = _meta->indexOfProperty(attributeName);
128 if (i==-1) {
128 if (i==-1) {
129 // try to map name to objectName
129 // try to map name to objectName
130 if (qstrcmp(attributeName, "name")==0) {
130 if (qstrcmp(attributeName, "name")==0) {
131 attributeName = "objectName";
131 attributeName = "objectName";
132 nameMapped = true;
132 nameMapped = true;
133 i = _meta->indexOfProperty(attributeName);
133 i = _meta->indexOfProperty(attributeName);
134 }
134 }
135 }
135 }
136 if (i!=-1) {
136 if (i!=-1) {
137 PythonQtMemberInfo newInfo(_meta->property(i));
137 PythonQtMemberInfo newInfo(_meta->property(i));
138 _cachedMembers.insert(attributeName, newInfo);
138 _cachedMembers.insert(attributeName, newInfo);
139 if (nameMapped) {
139 if (nameMapped) {
140 _cachedMembers.insert(memberName, newInfo);
140 _cachedMembers.insert(memberName, newInfo);
141 }
141 }
142 #ifdef PYTHONQT_DEBUG
142 #ifdef PYTHONQT_DEBUG
143 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
143 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
144 #endif
144 #endif
145 found = true;
145 found = true;
146 }
146 }
147 return found;
147 return found;
148 }
148 }
149
149
150 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
150 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
151 {
151 {
152 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
152 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
153 foreach(const ParentClassInfo& info, _parentClasses) {
153 foreach(const ParentClassInfo& info, _parentClasses) {
154 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
154 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
155 }
155 }
156 return inputInfo;
156 return inputInfo;
157 }
157 }
158
158
159 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
159 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
160 QObject* decoratorProvider = decorator();
160 QObject* decoratorProvider = decorator();
161 int memberNameLen = strlen(memberName);
161 int memberNameLen = strlen(memberName);
162 if (decoratorProvider) {
162 if (decoratorProvider) {
163 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
163 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
164 const QMetaObject* meta = decoratorProvider->metaObject();
164 const QMetaObject* meta = decoratorProvider->metaObject();
165 int numMethods = meta->methodCount();
165 int numMethods = meta->methodCount();
166 int startFrom = QObject::staticMetaObject.methodCount();
166 int startFrom = QObject::staticMetaObject.methodCount();
167 for (int i = startFrom; i < numMethods; i++) {
167 for (int i = startFrom; i < numMethods; i++) {
168 QMetaMethod m = meta->method(i);
168 QMetaMethod m = meta->method(i);
169 if ((m.methodType() == QMetaMethod::Method ||
169 if ((m.methodType() == QMetaMethod::Method ||
170 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
170 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
171
171
172 const char* sigStart = m.signature();
172 const char* sigStart = m.signature();
173 bool isClassDeco = false;
173 bool isClassDeco = false;
174 if (qstrncmp(sigStart, "static_", 7)==0) {
174 if (qstrncmp(sigStart, "static_", 7)==0) {
175 // skip the static_classname_ part of the string
175 // skip the static_classname_ part of the string
176 sigStart += 7 + 1 + strlen(className());
176 sigStart += 7 + 1 + strlen(className());
177 isClassDeco = true;
177 isClassDeco = true;
178 } else if (qstrncmp(sigStart, "new_", 4)==0) {
178 } else if (qstrncmp(sigStart, "new_", 4)==0) {
179 isClassDeco = true;
179 isClassDeco = true;
180 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
180 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
181 isClassDeco = true;
181 isClassDeco = true;
182 }
182 }
183 // find the first '('
183 // find the first '('
184 int offset = findCharOffset(sigStart, '(');
184 int offset = findCharOffset(sigStart, '(');
185
185
186 // XXX no checking is currently done if the slots have correct first argument or not...
186 // XXX no checking is currently done if the slots have correct first argument or not...
187
187
188 // check if same length and same name
188 // check if same length and same name
189 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
189 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
190 found = true;
190 found = true;
191 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
191 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
192 info->setUpcastingOffset(upcastingOffset);
192 info->setUpcastingOffset(upcastingOffset);
193 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
193 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
194 if (tail) {
194 if (tail) {
195 tail->setNextInfo(info);
195 tail->setNextInfo(info);
196 } else {
196 } else {
197 PythonQtMemberInfo newInfo(info);
197 PythonQtMemberInfo newInfo(info);
198 memberCache.insert(memberName, newInfo);
198 memberCache.insert(memberName, newInfo);
199 }
199 }
200 tail = info;
200 tail = info;
201 }
201 }
202 }
202 }
203 }
203 }
204 }
204 }
205
205
206 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
206 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
207
207
208 return tail;
208 return tail;
209 }
209 }
210
210
211 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
211 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
212 {
212 {
213 bool found = false;
213 bool found = false;
214 int memberNameLen = strlen(memberName);
214 int memberNameLen = strlen(memberName);
215 PythonQtSlotInfo* tail = NULL;
215 PythonQtSlotInfo* tail = NULL;
216 if (_meta) {
216 if (_meta) {
217 int numMethods = _meta->methodCount();
217 int numMethods = _meta->methodCount();
218 for (int i = 0; i < numMethods; i++) {
218 for (int i = 0; i < numMethods; i++) {
219 QMetaMethod m = _meta->method(i);
219 QMetaMethod m = _meta->method(i);
220 if (((m.methodType() == QMetaMethod::Method ||
220 if (((m.methodType() == QMetaMethod::Method ||
221 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
221 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
222 || m.methodType()==QMetaMethod::Signal) {
222 || m.methodType()==QMetaMethod::Signal) {
223
223
224 const char* sigStart = m.signature();
224 const char* sigStart = m.signature();
225 // find the first '('
225 // find the first '('
226 int offset = findCharOffset(sigStart, '(');
226 int offset = findCharOffset(sigStart, '(');
227
227
228 // check if same length and same name
228 // check if same length and same name
229 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
229 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
230 found = true;
230 found = true;
231 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
231 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
232 if (tail) {
232 if (tail) {
233 tail->setNextInfo(info);
233 tail->setNextInfo(info);
234 } else {
234 } else {
235 PythonQtMemberInfo newInfo(info);
235 PythonQtMemberInfo newInfo(info);
236 _cachedMembers.insert(memberName, newInfo);
236 _cachedMembers.insert(memberName, newInfo);
237 }
237 }
238 tail = info;
238 tail = info;
239 }
239 }
240 }
240 }
241 }
241 }
242 }
242 }
243
243
244 // look for dynamic decorators in this class and in derived classes
244 // look for dynamic decorators in this class and in derived classes
245 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
245 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
246
246
247 return found;
247 return found;
248 }
248 }
249
249
250 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
250 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
251 {
251 {
252 bool found = false;
252 bool found = false;
253 // look for enum values
253 // look for enum values
254 int enumCount = meta->enumeratorCount();
254 int enumCount = meta->enumeratorCount();
255 for (int i=0;i<enumCount; i++) {
255 for (int i=0;i<enumCount; i++) {
256 QMetaEnum e = meta->enumerator(i);
256 QMetaEnum e = meta->enumerator(i);
257 // we do not want flags, they will cause our values to appear two times
257 // we do not want flags, they will cause our values to appear two times
258 if (e.isFlag()) continue;
258 if (e.isFlag()) continue;
259
259
260 for (int j=0; j < e.keyCount(); j++) {
260 for (int j=0; j < e.keyCount(); j++) {
261 if (qstrcmp(e.key(j), memberName)==0) {
261 if (qstrcmp(e.key(j), memberName)==0) {
262 PyObject* enumType = findEnumWrapper(e.name());
262 PyObject* enumType = findEnumWrapper(e.name());
263 if (enumType) {
263 if (enumType) {
264 PythonQtObjectPtr enumValuePtr;
264 PythonQtObjectPtr enumValuePtr;
265 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
265 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
266 PythonQtMemberInfo newInfo(enumValuePtr);
266 PythonQtMemberInfo newInfo(enumValuePtr);
267 _cachedMembers.insert(memberName, newInfo);
267 _cachedMembers.insert(memberName, newInfo);
268 #ifdef PYTHONQT_DEBUG
268 #ifdef PYTHONQT_DEBUG
269 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
269 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
270 #endif
270 #endif
271 found = true;
271 found = true;
272 break;
272 break;
273 } else {
273 } else {
274 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
274 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
275 }
275 }
276 }
276 }
277 }
277 }
278 }
278 }
279 return found;
279 return found;
280 }
280 }
281
281
282 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
282 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
283 {
283 {
284 PythonQtMemberInfo info = _cachedMembers.value(memberName);
284 PythonQtMemberInfo info = _cachedMembers.value(memberName);
285 if (info._type != PythonQtMemberInfo::Invalid) {
285 if (info._type != PythonQtMemberInfo::Invalid) {
286 return info;
286 return info;
287 } else {
287 } else {
288 bool found = false;
288 bool found = false;
289
289
290 found = lookForPropertyAndCache(memberName);
290 found = lookForPropertyAndCache(memberName);
291 if (!found) {
291 if (!found) {
292 found = lookForMethodAndCache(memberName);
292 found = lookForMethodAndCache(memberName);
293 }
293 }
294 if (!found) {
294 if (!found) {
295 if (_meta) {
295 if (_meta) {
296 // check enums in our meta object directly
296 // check enums in our meta object directly
297 found = lookForEnumAndCache(_meta, memberName);
297 found = lookForEnumAndCache(_meta, memberName);
298 }
298 }
299 if (!found) {
299 if (!found) {
300 // check enums in the class hierachy of CPP classes
300 // check enums in the class hierachy of CPP classes
301 // look for dynamic decorators in this class and in derived classes
301 // look for dynamic decorators in this class and in derived classes
302 QList<QObject*> decoObjects;
302 QList<QObject*> decoObjects;
303 recursiveCollectDecoratorObjects(decoObjects);
303 recursiveCollectDecoratorObjects(decoObjects);
304 foreach(QObject* deco, decoObjects) {
304 foreach(QObject* deco, decoObjects) {
305 // call on ourself for caching, but with different metaObject():
305 // call on ourself for caching, but with different metaObject():
306 found = lookForEnumAndCache(deco->metaObject(), memberName);
306 found = lookForEnumAndCache(deco->metaObject(), memberName);
307 if (found) {
307 if (found) {
308 break;
308 break;
309 }
309 }
310 }
310 }
311 }
311 }
312 }
312 }
313 if (!found) {
313 if (!found) {
314 // maybe it is an enum wrapper?
314 // maybe it is an enum wrapper?
315 PyObject* p = findEnumWrapper(memberName);
315 PyObject* p = findEnumWrapper(memberName);
316 if (p) {
316 if (p) {
317 info._type = PythonQtMemberInfo::EnumWrapper;
317 info._type = PythonQtMemberInfo::EnumWrapper;
318 info._enumWrapper = p;
318 info._enumWrapper = p;
319 _cachedMembers.insert(memberName, info);
319 _cachedMembers.insert(memberName, info);
320 found = true;
320 found = true;
321 }
321 }
322 }
322 }
323 if (!found) {
323 if (!found) {
324 // since python keywords can not be looked up, we check if the name contains a single trailing _
324 // since python keywords can not be looked up, we check if the name contains a single trailing _
325 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
325 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
326 QByteArray mbrName(memberName);
326 QByteArray mbrName(memberName);
327 if ((mbrName.length()>2) &&
327 if ((mbrName.length()>2) &&
328 (mbrName.at(mbrName.length()-1) == '_') &&
328 (mbrName.at(mbrName.length()-1) == '_') &&
329 (mbrName.at(mbrName.length()-2) != '_')) {
329 (mbrName.at(mbrName.length()-2) != '_')) {
330 mbrName = mbrName.mid(0,mbrName.length()-1);
330 mbrName = mbrName.mid(0,mbrName.length()-1);
331 found = lookForMethodAndCache(mbrName.constData());
331 found = lookForMethodAndCache(mbrName.constData());
332 if (found) {
332 if (found) {
333 return _cachedMembers.value(mbrName);
333 return _cachedMembers.value(mbrName);
334 }
334 }
335 }
335 }
336 }
336 }
337 if (!found) {
337 if (!found) {
338 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
338 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
339 info._type = PythonQtMemberInfo::NotFound;
339 info._type = PythonQtMemberInfo::NotFound;
340 _cachedMembers.insert(memberName, info);
340 _cachedMembers.insert(memberName, info);
341 }
341 }
342 }
342 }
343
343
344 return _cachedMembers.value(memberName);
344 return _cachedMembers.value(memberName);
345 }
345 }
346
346
347 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
347 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
348 QObject* deco = decorator();
348 QObject* deco = decorator();
349 if (deco) {
349 if (deco) {
350 decoratorObjects.append(deco);
350 decoratorObjects.append(deco);
351 }
351 }
352 foreach(const ParentClassInfo& info, _parentClasses) {
352 foreach(const ParentClassInfo& info, _parentClasses) {
353 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
353 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
354 }
354 }
355 }
355 }
356
356
357 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
357 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
358 classInfoObjects.append(this);
358 classInfoObjects.append(this);
359 foreach(const ParentClassInfo& info, _parentClasses) {
359 foreach(const ParentClassInfo& info, _parentClasses) {
360 info._parent->recursiveCollectClassInfos(classInfoObjects);
360 info._parent->recursiveCollectClassInfos(classInfoObjects);
361 }
361 }
362 }
362 }
363
363
364 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
364 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
365 {
365 {
366 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
366 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
367 while (it.hasNext()) {
367 while (it.hasNext()) {
368
368
369 PythonQtSlotInfo* infoOrig = it.next();
369 PythonQtSlotInfo* infoOrig = it.next();
370
370
371 const char* sigStart = infoOrig->metaMethod()->signature();
371 const char* sigStart = infoOrig->metaMethod()->signature();
372 if (qstrncmp("static_", sigStart, 7)==0) {
372 if (qstrncmp("static_", sigStart, 7)==0) {
373 sigStart += 7;
373 sigStart += 7;
374 sigStart += findCharOffset(sigStart, '_')+1;
374 sigStart += findCharOffset(sigStart, '_')+1;
375 }
375 }
376 int offset = findCharOffset(sigStart, '(');
376 int offset = findCharOffset(sigStart, '(');
377 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
377 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
378 //make a copy, otherwise we will have trouble on overloads!
378 //make a copy, otherwise we will have trouble on overloads!
379 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
379 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
380 info->setUpcastingOffset(upcastingOffset);
380 info->setUpcastingOffset(upcastingOffset);
381 found = true;
381 found = true;
382 if (tail) {
382 if (tail) {
383 tail->setNextInfo(info);
383 tail->setNextInfo(info);
384 } else {
384 } else {
385 PythonQtMemberInfo newInfo(info);
385 PythonQtMemberInfo newInfo(info);
386 memberCache.insert(memberName, newInfo);
386 memberCache.insert(memberName, newInfo);
387 }
387 }
388 tail = info;
388 tail = info;
389 }
389 }
390 }
390 }
391 return tail;
391 return tail;
392 }
392 }
393
393
394 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
394 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
395 QObject* decoratorProvider = decorator();
395 QObject* decoratorProvider = decorator();
396 if (decoratorProvider) {
396 if (decoratorProvider) {
397 const QMetaObject* meta = decoratorProvider->metaObject();
397 const QMetaObject* meta = decoratorProvider->metaObject();
398 int numMethods = meta->methodCount();
398 int numMethods = meta->methodCount();
399 int startFrom = QObject::staticMetaObject.methodCount();
399 int startFrom = QObject::staticMetaObject.methodCount();
400 for (int i = startFrom; i < numMethods; i++) {
400 for (int i = startFrom; i < numMethods; i++) {
401 QMetaMethod m = meta->method(i);
401 QMetaMethod m = meta->method(i);
402 if ((m.methodType() == QMetaMethod::Method ||
402 if ((m.methodType() == QMetaMethod::Method ||
403 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
403 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
404
404
405 const char* sigStart = m.signature();
405 const char* sigStart = m.signature();
406 bool isClassDeco = false;
406 bool isClassDeco = false;
407 if (qstrncmp(sigStart, "static_", 7)==0) {
407 if (qstrncmp(sigStart, "static_", 7)==0) {
408 // skip the static_classname_ part of the string
408 // skip the static_classname_ part of the string
409 sigStart += 7 + 1 + strlen(className());
409 sigStart += 7 + 1 + strlen(className());
410 isClassDeco = true;
410 isClassDeco = true;
411 } else if (qstrncmp(sigStart, "new_", 4)==0) {
411 } else if (qstrncmp(sigStart, "new_", 4)==0) {
412 continue;
412 continue;
413 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
413 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
414 continue;
414 continue;
415 } else if (qstrncmp(sigStart, "py_", 3)==0) {
416 // hide everything that starts with py_
417 continue;
415 }
418 }
416 // find the first '('
419 // find the first '('
417 int offset = findCharOffset(sigStart, '(');
420 int offset = findCharOffset(sigStart, '(');
418
421
419 // XXX no checking is currently done if the slots have correct first argument or not...
422 // XXX no checking is currently done if the slots have correct first argument or not...
420 if (!metaOnly || isClassDeco) {
423 if (!metaOnly || isClassDeco) {
421 list << QString::fromLatin1(sigStart, offset);
424 list << QString::fromLatin1(sigStart, offset);
422 }
425 }
423 }
426 }
424 }
427 }
425 }
428 }
426
429
427 // look for global decorator slots
430 // look for global decorator slots
428 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
431 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
429 while (it.hasNext()) {
432 while (it.hasNext()) {
430 PythonQtSlotInfo* slot = it.next();
433 PythonQtSlotInfo* slot = it.next();
431 if (metaOnly) {
434 if (metaOnly) {
432 if (slot->isClassDecorator()) {
435 if (slot->isClassDecorator()) {
433 QByteArray first = slot->slotName();
436 QByteArray first = slot->slotName();
434 if (first.startsWith("static_")) {
437 if (first.startsWith("static_")) {
435 int idx = first.indexOf('_');
438 int idx = first.indexOf('_');
436 idx = first.indexOf('_', idx+1);
439 idx = first.indexOf('_', idx+1);
437 first = first.mid(idx+1);
440 first = first.mid(idx+1);
438 }
441 }
439 list << first;
442 list << first;
440 }
443 }
441 } else {
444 } else {
442 list << slot->slotName();
445 list << slot->slotName();
443 }
446 }
444 }
447 }
445 }
448 }
446
449
447 QStringList PythonQtClassInfo::propertyList()
450 QStringList PythonQtClassInfo::propertyList()
448 {
451 {
449 QStringList l;
452 QStringList l;
450 if (_isQObject && _meta) {
453 if (_isQObject && _meta) {
451 int i;
454 int i;
452 int numProperties = _meta->propertyCount();
455 int numProperties = _meta->propertyCount();
453 for (i = 0; i < numProperties; i++) {
456 for (i = 0; i < numProperties; i++) {
454 QMetaProperty p = _meta->property(i);
457 QMetaProperty p = _meta->property(i);
455 l << QString(p.name());
458 l << QString(p.name());
456 }
459 }
457 }
460 }
458 return l;
461 return l;
459 }
462 }
460
463
461 QStringList PythonQtClassInfo::memberList(bool metaOnly)
464 QStringList PythonQtClassInfo::memberList(bool metaOnly)
462 {
465 {
463 decorator();
466 decorator();
464
467
465 QStringList l;
468 QStringList l;
466 QString h;
469 QString h;
467 if (_isQObject && _meta && !metaOnly) {
470 if (_isQObject && _meta && !metaOnly) {
468 l = propertyList();
471 l = propertyList();
469 }
472 }
470
473
471 // normal slots of QObject (or wrapper QObject)
474 // normal slots of QObject (or wrapper QObject)
472 if (!metaOnly && _meta) {
475 if (!metaOnly && _meta) {
473 int numMethods = _meta->methodCount();
476 int numMethods = _meta->methodCount();
474 bool skipQObj = !_isQObject;
477 bool skipQObj = !_isQObject;
475 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
478 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
476 QMetaMethod m = _meta->method(i);
479 QMetaMethod m = _meta->method(i);
477 if (((m.methodType() == QMetaMethod::Method ||
480 if (((m.methodType() == QMetaMethod::Method ||
478 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
481 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
479 || m.methodType()==QMetaMethod::Signal) {
482 || m.methodType()==QMetaMethod::Signal) {
480 QByteArray signa(m.signature());
483 QByteArray signa(m.signature());
481 signa = signa.left(signa.indexOf('('));
484 signa = signa.left(signa.indexOf('('));
482 l << signa;
485 l << signa;
483 }
486 }
484 }
487 }
485 }
488 }
486
489
487 {
490 {
488 // look for dynamic decorators in this class and in derived classes
491 // look for dynamic decorators in this class and in derived classes
489 QList<PythonQtClassInfo*> infos;
492 QList<PythonQtClassInfo*> infos;
490 recursiveCollectClassInfos(infos);
493 recursiveCollectClassInfos(infos);
491 foreach(PythonQtClassInfo* info, infos) {
494 foreach(PythonQtClassInfo* info, infos) {
492 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
495 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
493 }
496 }
494 }
497 }
495
498
496 // List enumerator keys...
499 // List enumerator keys...
497 QList<const QMetaObject*> enumMetaObjects;
500 QList<const QMetaObject*> enumMetaObjects;
498 if (_meta) {
501 if (_meta) {
499 enumMetaObjects << _meta;
502 enumMetaObjects << _meta;
500 }
503 }
501 // check enums in the class hierachy of CPP classes
504 // check enums in the class hierachy of CPP classes
502 QList<QObject*> decoObjects;
505 QList<QObject*> decoObjects;
503 recursiveCollectDecoratorObjects(decoObjects);
506 recursiveCollectDecoratorObjects(decoObjects);
504 foreach(QObject* deco, decoObjects) {
507 foreach(QObject* deco, decoObjects) {
505 enumMetaObjects << deco->metaObject();
508 enumMetaObjects << deco->metaObject();
506 }
509 }
507
510
508 foreach(const QMetaObject* meta, enumMetaObjects) {
511 foreach(const QMetaObject* meta, enumMetaObjects) {
509 for (int i = 0; i<meta->enumeratorCount(); i++) {
512 for (int i = 0; i<meta->enumeratorCount(); i++) {
510 QMetaEnum e = meta->enumerator(i);
513 QMetaEnum e = meta->enumerator(i);
511 l << e.name();
514 l << e.name();
512 // we do not want flags, they will cause our values to appear two times
515 // we do not want flags, they will cause our values to appear two times
513 if (e.isFlag()) continue;
516 if (e.isFlag()) continue;
514
517
515 for (int j=0; j < e.keyCount(); j++) {
518 for (int j=0; j < e.keyCount(); j++) {
516 l << QString(e.key(j));
519 l << QString(e.key(j));
517 }
520 }
518 }
521 }
519 }
522 }
520
523
521 return QSet<QString>::fromList(l).toList();
524 return QSet<QString>::fromList(l).toList();
522 }
525 }
523
526
524 const char* PythonQtClassInfo::className()
527 const char* PythonQtClassInfo::className()
525 {
528 {
526 return _wrappedClassName.constData();
529 return _wrappedClassName.constData();
527 }
530 }
528
531
529 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
532 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
530 {
533 {
531 if (ptr==NULL) {
534 if (ptr==NULL) {
532 return NULL;
535 return NULL;
533 }
536 }
534 if (_wrappedClassName == classname) {
537 if (_wrappedClassName == classname) {
535 return ptr;
538 return ptr;
536 }
539 }
537 foreach(const ParentClassInfo& info, _parentClasses) {
540 foreach(const ParentClassInfo& info, _parentClasses) {
538 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
541 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
539 if (result) {
542 if (result) {
540 return result;
543 return result;
541 }
544 }
542 }
545 }
543 return NULL;
546 return NULL;
544 }
547 }
545
548
546 bool PythonQtClassInfo::inherits(const char* name)
549 bool PythonQtClassInfo::inherits(const char* name)
547 {
550 {
548 if (_wrappedClassName == name) {
551 if (_wrappedClassName == name) {
549 return true;
552 return true;
550 }
553 }
551 foreach(const ParentClassInfo& info, _parentClasses) {
554 foreach(const ParentClassInfo& info, _parentClasses) {
552 if (info._parent->inherits(name)) {
555 if (info._parent->inherits(name)) {
553 return true;
556 return true;
554 }
557 }
555 }
558 }
556 return false;
559 return false;
557 }
560 }
558
561
559 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
562 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
560 {
563 {
561 if (classInfo == this) {
564 if (classInfo == this) {
562 return true;
565 return true;
563 }
566 }
564 foreach(const ParentClassInfo& info, _parentClasses) {
567 foreach(const ParentClassInfo& info, _parentClasses) {
565 if (info._parent->inherits(classInfo)) {
568 if (info._parent->inherits(classInfo)) {
566 return true;
569 return true;
567 }
570 }
568 }
571 }
569 return false;
572 return false;
570 }
573 }
571
574
572 QString PythonQtClassInfo::help()
575 QString PythonQtClassInfo::help()
573 {
576 {
574 decorator();
577 decorator();
575 QString h;
578 QString h;
576 h += QString("--- ") + QString(className()) + QString(" ---\n");
579 h += QString("--- ") + QString(className()) + QString(" ---\n");
577
580
578 if (_isQObject) {
581 if (_isQObject) {
579 h += "Properties:\n";
582 h += "Properties:\n";
580
583
581 int i;
584 int i;
582 int numProperties = _meta->propertyCount();
585 int numProperties = _meta->propertyCount();
583 for (i = 0; i < numProperties; i++) {
586 for (i = 0; i < numProperties; i++) {
584 QMetaProperty p = _meta->property(i);
587 QMetaProperty p = _meta->property(i);
585 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
588 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
586 }
589 }
587 }
590 }
588
591
589 if (constructors()) {
592 if (constructors()) {
590 h += "Constructors:\n";
593 h += "Constructors:\n";
591 PythonQtSlotInfo* constr = constructors();
594 PythonQtSlotInfo* constr = constructors();
592 while (constr) {
595 while (constr) {
593 h += constr->fullSignature() + "\n";
596 h += constr->fullSignature() + "\n";
594 constr = constr->nextInfo();
597 constr = constr->nextInfo();
595 }
598 }
596 }
599 }
597
600
598 h += "Slots:\n";
601 h += "Slots:\n";
599 h += "QString help()\n";
602 h += "QString help()\n";
600 h += "QString className()\n";
603 h += "QString className()\n";
601
604
602 if (_meta) {
605 if (_meta) {
603 int numMethods = _meta->methodCount();
606 int numMethods = _meta->methodCount();
604 for (int i = 0; i < numMethods; i++) {
607 for (int i = 0; i < numMethods; i++) {
605 QMetaMethod m = _meta->method(i);
608 QMetaMethod m = _meta->method(i);
606 if ((m.methodType() == QMetaMethod::Method ||
609 if ((m.methodType() == QMetaMethod::Method ||
607 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
610 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
608 PythonQtSlotInfo slot(this, m, i);
611 PythonQtSlotInfo slot(this, m, i);
609 h += slot.fullSignature()+ "\n";
612 h += slot.fullSignature()+ "\n";
610 }
613 }
611 }
614 }
612 }
615 }
613
616
614 // TODO xxx : decorators and enums from decorator() are missing...
617 // TODO xxx : decorators and enums from decorator() are missing...
615 // maybe we can reuse memberlist()?
618 // maybe we can reuse memberlist()?
616
619
617 if (_meta && _meta->enumeratorCount()) {
620 if (_meta && _meta->enumeratorCount()) {
618 h += "Enums:\n";
621 h += "Enums:\n";
619 for (int i = 0; i<_meta->enumeratorCount(); i++) {
622 for (int i = 0; i<_meta->enumeratorCount(); i++) {
620 QMetaEnum e = _meta->enumerator(i);
623 QMetaEnum e = _meta->enumerator(i);
621 h += QString(e.name()) + " {";
624 h += QString(e.name()) + " {";
622 for (int j=0; j < e.keyCount(); j++) {
625 for (int j=0; j < e.keyCount(); j++) {
623 if (j) { h+= ", "; }
626 if (j) { h+= ", "; }
624 h += e.key(j);
627 h += e.key(j);
625 }
628 }
626 h += " }\n";
629 h += " }\n";
627 }
630 }
628 }
631 }
629
632
630 if (_isQObject && _meta) {
633 if (_isQObject && _meta) {
631 int numMethods = _meta->methodCount();
634 int numMethods = _meta->methodCount();
632 if (numMethods>0) {
635 if (numMethods>0) {
633 h += "Signals:\n";
636 h += "Signals:\n";
634 for (int i = 0; i < numMethods; i++) {
637 for (int i = 0; i < numMethods; i++) {
635 QMetaMethod m = _meta->method(i);
638 QMetaMethod m = _meta->method(i);
636 if (m.methodType() == QMetaMethod::Signal) {
639 if (m.methodType() == QMetaMethod::Signal) {
637 h += QString(m.signature()) + "\n";
640 h += QString(m.signature()) + "\n";
638 }
641 }
639 }
642 }
640 }
643 }
641 }
644 }
642 return h;
645 return h;
643 }
646 }
644
647
645 PythonQtSlotInfo* PythonQtClassInfo::constructors()
648 PythonQtSlotInfo* PythonQtClassInfo::constructors()
646 {
649 {
647 if (!_constructors) {
650 if (!_constructors) {
648 // force creation of lazy decorator, which will register the decorators
651 // force creation of lazy decorator, which will register the decorators
649 decorator();
652 decorator();
650 }
653 }
651 return _constructors;
654 return _constructors;
652 }
655 }
653
656
654 PythonQtSlotInfo* PythonQtClassInfo::destructor()
657 PythonQtSlotInfo* PythonQtClassInfo::destructor()
655 {
658 {
656 if (!_destructor) {
659 if (!_destructor) {
657 // force creation of lazy decorator, which will register the decorators
660 // force creation of lazy decorator, which will register the decorators
658 decorator();
661 decorator();
659 }
662 }
660 return _destructor;
663 return _destructor;
661 }
664 }
662
665
663 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
666 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
664 {
667 {
665 PythonQtSlotInfo* prev = constructors();
668 PythonQtSlotInfo* prev = constructors();
666 if (prev) {
669 if (prev) {
667 info->setNextInfo(prev->nextInfo());
670 info->setNextInfo(prev->nextInfo());
668 prev->setNextInfo(info);
671 prev->setNextInfo(info);
669 } else {
672 } else {
670 _constructors = info;
673 _constructors = info;
671 }
674 }
672 }
675 }
673
676
674 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
677 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
675 {
678 {
676 _decoratorSlots.append(info);
679 _decoratorSlots.append(info);
677 }
680 }
678
681
679 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
682 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
680 {
683 {
681 if (_destructor) {
684 if (_destructor) {
682 _destructor->deleteOverloadsAndThis();
685 _destructor->deleteOverloadsAndThis();
683 }
686 }
684 _destructor = info;
687 _destructor = info;
685 }
688 }
686
689
687 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
690 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
688 {
691 {
689 _meta = meta;
692 _meta = meta;
690 clearCachedMembers();
693 clearCachedMembers();
691 }
694 }
692
695
693 QObject* PythonQtClassInfo::decorator()
696 QObject* PythonQtClassInfo::decorator()
694 {
697 {
695 if (!_decoratorProvider && _decoratorProviderCB) {
698 if (!_decoratorProvider && _decoratorProviderCB) {
696 _decoratorProvider = (*_decoratorProviderCB)();
699 _decoratorProvider = (*_decoratorProviderCB)();
697 if (_decoratorProvider) {
700 if (_decoratorProvider) {
698 _decoratorProvider->setParent(PythonQt::priv());
701 _decoratorProvider->setParent(PythonQt::priv());
699 // setup enums early, since they might be needed by the constructor decorators:
702 // setup enums early, since they might be needed by the constructor decorators:
700 if (!_enumsCreated) {
703 if (!_enumsCreated) {
701 createEnumWrappers();
704 createEnumWrappers();
702 }
705 }
703 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
706 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
704 }
707 }
705 }
708 }
706 // check if enums need to be created and create them if they are not yet created
709 // check if enums need to be created and create them if they are not yet created
707 if (!_enumsCreated) {
710 if (!_enumsCreated) {
708 createEnumWrappers();
711 createEnumWrappers();
709 }
712 }
710 return _decoratorProvider;
713 return _decoratorProvider;
711 }
714 }
712
715
713 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
716 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
714 {
717 {
715 PythonQtMemberInfo info = member("hasOwner");
718 PythonQtMemberInfo info = member("py_hasOwner");
716 if (info._type == PythonQtMemberInfo::Slot) {
719 if (info._type == PythonQtMemberInfo::Slot) {
717 void* obj = object;
720 void* obj = object;
718 bool result = false;
721 bool result = false;
719 void* args[2];
722 void* args[2];
720 args[0] = &result;
723 args[0] = &result;
721 args[1] = &obj;
724 args[1] = &obj;
722 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
725 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
723 return !result;
726 return !result;
724 } else {
727 } else {
725 return false;
728 return false;
726 }
729 }
727 }
730 }
728
731
729 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
732 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
730 {
733 {
731 if (!_polymorphicHandlers.isEmpty()) {
734 if (!_polymorphicHandlers.isEmpty()) {
732 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
735 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
733 void* resultPtr = (*cb)(ptr, resultClassName);
736 void* resultPtr = (*cb)(ptr, resultClassName);
734 if (resultPtr) {
737 if (resultPtr) {
735 return resultPtr;
738 return resultPtr;
736 }
739 }
737 }
740 }
738 }
741 }
739 foreach(const ParentClassInfo& info, _parentClasses) {
742 foreach(const ParentClassInfo& info, _parentClasses) {
740 if (!info._parent->isQObject()) {
743 if (!info._parent->isQObject()) {
741 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
744 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
742 if (resultPtr) {
745 if (resultPtr) {
743 return resultPtr;
746 return resultPtr;
744 }
747 }
745 }
748 }
746 }
749 }
747 return NULL;
750 return NULL;
748 }
751 }
749
752
750 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
753 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
751 {
754 {
752 char* className;
755 char* className;
753 // this would do downcasting recursively...
756 // this would do downcasting recursively...
754 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
757 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
755
758
756 // we only do downcasting on the base object, not on the whole inheritance tree...
759 // we only do downcasting on the base object, not on the whole inheritance tree...
757 void* resultPtr = NULL;
760 void* resultPtr = NULL;
758 if (!_polymorphicHandlers.isEmpty()) {
761 if (!_polymorphicHandlers.isEmpty()) {
759 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
762 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
760 resultPtr = (*cb)(ptr, &className);
763 resultPtr = (*cb)(ptr, &className);
761 if (resultPtr) {
764 if (resultPtr) {
762 break;
765 break;
763 }
766 }
764 }
767 }
765 }
768 }
766 if (resultPtr) {
769 if (resultPtr) {
767 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
770 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
768 } else {
771 } else {
769 *resultClassInfo = this;
772 *resultClassInfo = this;
770 resultPtr = ptr;
773 resultPtr = ptr;
771 }
774 }
772 return resultPtr;
775 return resultPtr;
773 }
776 }
774
777
775 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
778 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
776 {
779 {
777 if (isLocalEnum) {
780 if (isLocalEnum) {
778 *isLocalEnum = true;
781 *isLocalEnum = true;
779 }
782 }
780 int scopePos = name.lastIndexOf("::");
783 int scopePos = name.lastIndexOf("::");
781 if (scopePos != -1) {
784 if (scopePos != -1) {
782 if (isLocalEnum) {
785 if (isLocalEnum) {
783 *isLocalEnum = false;
786 *isLocalEnum = false;
784 }
787 }
785 // split into scope and enum name
788 // split into scope and enum name
786 QByteArray enumScope = name.mid(0,scopePos);
789 QByteArray enumScope = name.mid(0,scopePos);
787 QByteArray enumName = name.mid(scopePos+2);
790 QByteArray enumName = name.mid(scopePos+2);
788 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
791 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
789 if (info) {
792 if (info) {
790 return info->findEnumWrapper(enumName);
793 return info->findEnumWrapper(enumName);
791 } else{
794 } else{
792 return NULL;
795 return NULL;
793 }
796 }
794 }
797 }
795 if (localScope) {
798 if (localScope) {
796 return localScope->findEnumWrapper(name);
799 return localScope->findEnumWrapper(name);
797 } else {
800 } else {
798 return NULL;
801 return NULL;
799 }
802 }
800 }
803 }
801
804
802 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
805 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
803 {
806 {
804 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
807 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
805 QMetaEnum e = meta->enumerator(i);
808 QMetaEnum e = meta->enumerator(i);
806 PythonQtObjectPtr p;
809 PythonQtObjectPtr p;
807 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
810 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
808 _enumWrappers.append(p);
811 _enumWrappers.append(p);
809 }
812 }
810 }
813 }
811
814
812 void PythonQtClassInfo::createEnumWrappers()
815 void PythonQtClassInfo::createEnumWrappers()
813 {
816 {
814 if (!_enumsCreated) {
817 if (!_enumsCreated) {
815 _enumsCreated = true;
818 _enumsCreated = true;
816 if (_meta) {
819 if (_meta) {
817 createEnumWrappers(_meta);
820 createEnumWrappers(_meta);
818 }
821 }
819 if (decorator()) {
822 if (decorator()) {
820 createEnumWrappers(decorator()->metaObject());
823 createEnumWrappers(decorator()->metaObject());
821 }
824 }
822 foreach(const ParentClassInfo& info, _parentClasses) {
825 foreach(const ParentClassInfo& info, _parentClasses) {
823 info._parent->createEnumWrappers();
826 info._parent->createEnumWrappers();
824 }
827 }
825 }
828 }
826 }
829 }
827
830
828 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
831 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
829 // force enum creation
832 // force enum creation
830 if (!_enumsCreated) {
833 if (!_enumsCreated) {
831 createEnumWrappers();
834 createEnumWrappers();
832 }
835 }
833 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
836 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
834 const char* className = ((PyTypeObject*)p.object())->tp_name;
837 const char* className = ((PyTypeObject*)p.object())->tp_name;
835 if (qstrcmp(className, name)==0) {
838 if (qstrcmp(className, name)==0) {
836 return p.object();
839 return p.object();
837 }
840 }
838 }
841 }
839 foreach(const ParentClassInfo& info, _parentClasses) {
842 foreach(const ParentClassInfo& info, _parentClasses) {
840 PyObject* p = info._parent->findEnumWrapper(name);
843 PyObject* p = info._parent->findEnumWrapper(name);
841 if (p) return p;
844 if (p) return p;
842 }
845 }
843 return NULL;
846 return NULL;
844 }
847 }
845
848
@@ -1,256 +1,256
1 #ifndef _PYTHONQTCLASSINFO_H
1 #ifndef _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 #include <QMetaObject>
36 #include <QMetaObject>
37 #include <QMetaMethod>
37 #include <QMetaMethod>
38 #include <QHash>
38 #include <QHash>
39 #include <QByteArray>
39 #include <QByteArray>
40 #include <QList>
40 #include <QList>
41 #include "PythonQt.h"
41 #include "PythonQt.h"
42
42
43 class PythonQtSlotInfo;
43 class PythonQtSlotInfo;
44
44
45 struct PythonQtMemberInfo {
45 struct PythonQtMemberInfo {
46 enum Type {
46 enum Type {
47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
48 };
48 };
49
49
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
51
51
52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
53 _type = Slot;
53 _type = Slot;
54 _slot = info;
54 _slot = info;
55 _enumValue = NULL;
55 _enumValue = NULL;
56 }
56 }
57
57
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
59 _type = EnumValue;
59 _type = EnumValue;
60 _slot = NULL;
60 _slot = NULL;
61 _enumValue = enumValue;
61 _enumValue = enumValue;
62 _enumWrapper = NULL;
62 _enumWrapper = NULL;
63 }
63 }
64
64
65 PythonQtMemberInfo(const QMetaProperty& prop) {
65 PythonQtMemberInfo(const QMetaProperty& prop) {
66 _type = Property;
66 _type = Property;
67 _slot = NULL;
67 _slot = NULL;
68 _enumValue = NULL;
68 _enumValue = NULL;
69 _property = prop;
69 _property = prop;
70 _enumWrapper = NULL;
70 _enumWrapper = NULL;
71 }
71 }
72
72
73 Type _type;
73 Type _type;
74
74
75 // TODO: this could be a union...
75 // TODO: this could be a union...
76 PythonQtSlotInfo* _slot;
76 PythonQtSlotInfo* _slot;
77 PyObject* _enumWrapper;
77 PyObject* _enumWrapper;
78 PythonQtObjectPtr _enumValue;
78 PythonQtObjectPtr _enumValue;
79 QMetaProperty _property;
79 QMetaProperty _property;
80 };
80 };
81
81
82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
83 /*! for fast lookup of slots when calling the object from Python
83 /*! for fast lookup of slots when calling the object from Python
84 */
84 */
85 class PythonQtClassInfo {
85 class PythonQtClassInfo {
86
86
87 public:
87 public:
88 PythonQtClassInfo();
88 PythonQtClassInfo();
89 ~PythonQtClassInfo();
89 ~PythonQtClassInfo();
90
90
91 //! store information about parent classes
91 //! store information about parent classes
92 struct ParentClassInfo {
92 struct ParentClassInfo {
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
94 {};
94 {};
95
95
96 PythonQtClassInfo* _parent;
96 PythonQtClassInfo* _parent;
97 int _upcastingOffset;
97 int _upcastingOffset;
98 };
98 };
99
99
100
100
101 //! setup as a QObject, taking the meta object as meta information about the QObject
101 //! setup as a QObject, taking the meta object as meta information about the QObject
102 void setupQObject(const QMetaObject* meta);
102 void setupQObject(const QMetaObject* meta);
103
103
104 //! setup as a CPP (non-QObject), taking the classname
104 //! setup as a CPP (non-QObject), taking the classname
105 void setupCPPObject(const QByteArray& classname);
105 void setupCPPObject(const QByteArray& classname);
106
106
107 //! get the Python method definition for a given slot name (without return type and signature)
107 //! get the Python method definition for a given slot name (without return type and signature)
108 PythonQtMemberInfo member(const char* member);
108 PythonQtMemberInfo member(const char* member);
109
109
110 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
110 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
111 PythonQtSlotInfo* constructors();
111 PythonQtSlotInfo* constructors();
112
112
113 //! get access to the destructor slot
113 //! get access to the destructor slot
114 PythonQtSlotInfo* destructor();
114 PythonQtSlotInfo* destructor();
115
115
116 //! add a constructor, ownership is passed to classinfo
116 //! add a constructor, ownership is passed to classinfo
117 void addConstructor(PythonQtSlotInfo* info);
117 void addConstructor(PythonQtSlotInfo* info);
118
118
119 //! set a destructor, ownership is passed to classinfo
119 //! set a destructor, ownership is passed to classinfo
120 void setDestructor(PythonQtSlotInfo* info);
120 void setDestructor(PythonQtSlotInfo* info);
121
121
122 //! add a decorator slot, ownership is passed to classinfo
122 //! add a decorator slot, ownership is passed to classinfo
123 void addDecoratorSlot(PythonQtSlotInfo* info);
123 void addDecoratorSlot(PythonQtSlotInfo* info);
124
124
125 //! get the classname (either of the QObject or of the wrapped CPP object)
125 //! get the classname (either of the QObject or of the wrapped CPP object)
126 const char* className();
126 const char* className();
127
127
128 //! returns if the QObject
128 //! returns if the QObject
129 bool isQObject() { return _isQObject; }
129 bool isQObject() { return _isQObject; }
130
130
131 //! returns if the class is a CPP wrapper
131 //! returns if the class is a CPP wrapper
132 bool isCPPWrapper() { return !_isQObject; }
132 bool isCPPWrapper() { return !_isQObject; }
133
133
134 //! get the meta object
134 //! get the meta object
135 const QMetaObject* metaObject() { return _meta; }
135 const QMetaObject* metaObject() { return _meta; }
136
136
137 //! set the meta object, this will reset the caching
137 //! set the meta object, this will reset the caching
138 void setMetaObject(const QMetaObject* meta);
138 void setMetaObject(const QMetaObject* meta);
139
139
140 //! returns if this class inherits from the given classname
140 //! returns if this class inherits from the given classname
141 bool inherits(const char* classname);
141 bool inherits(const char* classname);
142
142
143 //! returns if this class inherits from the given classinfo
143 //! returns if this class inherits from the given classinfo
144 bool inherits(PythonQtClassInfo* info);
144 bool inherits(PythonQtClassInfo* info);
145
145
146 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
146 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
147 //! which might be different to \c ptr due to C++ multiple inheritance
147 //! which might be different to \c ptr due to C++ multiple inheritance
148 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
148 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
149 void* castTo(void* ptr, const char* classname);
149 void* castTo(void* ptr, const char* classname);
150
150
151 //! get help string for the metaobject
151 //! get help string for the metaobject
152 QString help();
152 QString help();
153
153
154 //! get list of all properties (on QObjects only, otherwise the list is empty)
154 //! get list of all properties (on QObjects only, otherwise the list is empty)
155 QStringList propertyList();
155 QStringList propertyList();
156
156
157 //! get list of all members
157 //! get list of all members
158 QStringList memberList(bool metaOnly = false);
158 QStringList memberList(bool metaOnly = false);
159
159
160 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
160 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
161 int metaTypeId() { return _metaTypeId; }
161 int metaTypeId() { return _metaTypeId; }
162
162
163 //! set an additional decorator provider that offers additional decorator slots for this class
163 //! set an additional decorator provider that offers additional decorator slots for this class
164 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb) { _decoratorProviderCB = cb; _decoratorProvider = NULL; }
164 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb) { _decoratorProviderCB = cb; _decoratorProvider = NULL; }
165
165
166 //! get the decorator qobject instance
166 //! get the decorator qobject instance
167 QObject* decorator();
167 QObject* decorator();
168
168
169 //! add the parent class info of a CPP object
169 //! add the parent class info of a CPP object
170 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
170 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
171
171
172 //! check if the special method "hasOwner" is implemented and if it returns false, which means that the object may be destroyed
172 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
173 bool hasOwnerMethodButNoOwner(void* object);
173 bool hasOwnerMethodButNoOwner(void* object);
174
174
175 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
175 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
176 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
176 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
177
177
178 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
178 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
179 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
179 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
180
180
181 //! set the shell set instance wrapper cb
181 //! set the shell set instance wrapper cb
182 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
182 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
183 _shellSetInstanceWrapperCB = cb;
183 _shellSetInstanceWrapperCB = cb;
184 }
184 }
185
185
186 //! get the shell set instance wrapper cb
186 //! get the shell set instance wrapper cb
187 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
187 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
188 return _shellSetInstanceWrapperCB;
188 return _shellSetInstanceWrapperCB;
189 }
189 }
190
190
191 //! add a handler for polymorphic downcasting
191 //! add a handler for polymorphic downcasting
192 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
192 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
193
193
194 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
194 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
195 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
195 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
196
196
197 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
197 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
198 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
198 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
199
199
200 private:
200 private:
201 void createEnumWrappers();
201 void createEnumWrappers();
202 void createEnumWrappers(const QMetaObject* meta);
202 void createEnumWrappers(const QMetaObject* meta);
203 PyObject* findEnumWrapper(const char* name);
203 PyObject* findEnumWrapper(const char* name);
204
204
205 //! clear all cached members
205 //! clear all cached members
206 void clearCachedMembers();
206 void clearCachedMembers();
207
207
208 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
208 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
209
209
210 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
210 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
211 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
211 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
212 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
212 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
213
213
214 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
214 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
215 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
215 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
216
216
217 bool lookForPropertyAndCache(const char* memberName);
217 bool lookForPropertyAndCache(const char* memberName);
218 bool lookForMethodAndCache(const char* memberName);
218 bool lookForMethodAndCache(const char* memberName);
219 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
219 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
220
220
221 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
221 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
222 int findCharOffset(const char* sigStart, char someChar);
222 int findCharOffset(const char* sigStart, char someChar);
223
223
224 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
224 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
225
225
226 PythonQtSlotInfo* _constructors;
226 PythonQtSlotInfo* _constructors;
227 PythonQtSlotInfo* _destructor;
227 PythonQtSlotInfo* _destructor;
228 QList<PythonQtSlotInfo*> _decoratorSlots;
228 QList<PythonQtSlotInfo*> _decoratorSlots;
229
229
230 QList<PythonQtObjectPtr> _enumWrappers;
230 QList<PythonQtObjectPtr> _enumWrappers;
231
231
232 const QMetaObject* _meta;
232 const QMetaObject* _meta;
233
233
234 QByteArray _wrappedClassName;
234 QByteArray _wrappedClassName;
235 QList<ParentClassInfo> _parentClasses;
235 QList<ParentClassInfo> _parentClasses;
236
236
237 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
237 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
238
238
239 QObject* _decoratorProvider;
239 QObject* _decoratorProvider;
240 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
240 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
241
241
242 PyObject* _pythonQtClassWrapper;
242 PyObject* _pythonQtClassWrapper;
243
243
244 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
244 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
245
245
246 int _metaTypeId;
246 int _metaTypeId;
247
247
248 bool _isQObject;
248 bool _isQObject;
249 bool _enumsCreated;
249 bool _enumsCreated;
250
250
251 };
251 };
252
252
253 //---------------------------------------------------------------
253 //---------------------------------------------------------------
254
254
255
255
256 #endif
256 #endif
@@ -1,641 +1,671
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 PythonQtInstanceWrapper.cpp
35 // \file PythonQtInstanceWrapper.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 "PythonQtInstanceWrapper.h"
42 #include "PythonQtInstanceWrapper.h"
43 #include <QObject>
43 #include <QObject>
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include "PythonQtSlot.h"
45 #include "PythonQtSlot.h"
46 #include "PythonQtClassInfo.h"
46 #include "PythonQtClassInfo.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtClassWrapper.h"
48 #include "PythonQtClassWrapper.h"
49
49
50 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
50 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
51 {
51 {
52 // take the class info from our type object
52 // take the class info from our type object
53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
54 }
54 }
55
55
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
57
57
58 // is this a C++ wrapper?
58 // is this a C++ wrapper?
59 if (self->_wrappedPtr) {
59 if (self->_wrappedPtr) {
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
61
61
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
63 // we own our qobject, so we delete it now:
63 // we own our qobject, so we delete it now:
64 delete self->_obj;
64 delete self->_obj;
65 self->_obj = NULL;
65 self->_obj = NULL;
66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
67 int type = self->classInfo()->metaTypeId();
67 int type = self->classInfo()->metaTypeId();
68 if (self->_useQMetaTypeDestroy && type>=0) {
68 if (self->_useQMetaTypeDestroy && type>=0) {
69 // use QMetaType to destroy the object
69 // use QMetaType to destroy the object
70 QMetaType::destroy(type, self->_wrappedPtr);
70 QMetaType::destroy(type, self->_wrappedPtr);
71 } else {
71 } else {
72 PythonQtSlotInfo* slot = self->classInfo()->destructor();
72 PythonQtSlotInfo* slot = self->classInfo()->destructor();
73 if (slot) {
73 if (slot) {
74 void* args[2];
74 void* args[2];
75 args[0] = NULL;
75 args[0] = NULL;
76 args[1] = &self->_wrappedPtr;
76 args[1] = &self->_wrappedPtr;
77 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
77 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
78 self->_wrappedPtr = NULL;
78 self->_wrappedPtr = NULL;
79 } else {
79 } else {
80 if (type>=0) {
80 if (type>=0) {
81 // use QMetaType to destroy the object
81 // use QMetaType to destroy the object
82 QMetaType::destroy(type, self->_wrappedPtr);
82 QMetaType::destroy(type, self->_wrappedPtr);
83 } else {
83 } else {
84 // TODO: warn about not being able to destroy the object?
84 // TODO: warn about not being able to destroy the object?
85 }
85 }
86 }
86 }
87 }
87 }
88 }
88 }
89 } else {
89 } else {
90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
91 if (self->_objPointerCopy) {
91 if (self->_objPointerCopy) {
92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
93 }
93 }
94 if (self->_obj) {
94 if (self->_obj) {
95 if (force || self->_ownedByPythonQt) {
95 if (force || self->_ownedByPythonQt) {
96 if (force || !self->_obj->parent()) {
96 if (force || !self->_obj->parent()) {
97 delete self->_obj;
97 delete self->_obj;
98 }
98 }
99 } else {
99 } else {
100 if (self->_obj->parent()==NULL) {
100 if (self->_obj->parent()==NULL) {
101 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
101 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
102 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
102 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
103 }
103 }
104 }
104 }
105 }
105 }
106 }
106 }
107 self->_obj = NULL;
107 self->_obj = NULL;
108 }
108 }
109
109
110 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
110 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
111 {
111 {
112 PythonQtInstanceWrapper_deleteObject(self);
112 PythonQtInstanceWrapper_deleteObject(self);
113 self->_obj.~QPointer<QObject>();
113 self->_obj.~QPointer<QObject>();
114 self->ob_type->tp_free((PyObject*)self);
114 self->ob_type->tp_free((PyObject*)self);
115 }
115 }
116
116
117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
118 {
118 {
119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
120 PythonQtInstanceWrapper *self;
120 PythonQtInstanceWrapper *self;
121 static PyObject* emptyTuple = NULL;
121 static PyObject* emptyTuple = NULL;
122 if (emptyTuple==NULL) {
122 if (emptyTuple==NULL) {
123 emptyTuple = PyTuple_New(0);
123 emptyTuple = PyTuple_New(0);
124 }
124 }
125
125
126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
127
127
128 if (self != NULL) {
128 if (self != NULL) {
129 new (&self->_obj) QPointer<QObject>();
129 new (&self->_obj) QPointer<QObject>();
130 self->_wrappedPtr = NULL;
130 self->_wrappedPtr = NULL;
131 self->_ownedByPythonQt = false;
131 self->_ownedByPythonQt = false;
132 self->_useQMetaTypeDestroy = false;
132 self->_useQMetaTypeDestroy = false;
133 self->_isShellInstance = false;
133 self->_isShellInstance = false;
134 }
134 }
135 return (PyObject *)self;
135 return (PyObject *)self;
136 }
136 }
137
137
138 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
138 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
139 {
139 {
140 if (args == PythonQtPrivate::dummyTuple()) {
140 if (args == PythonQtPrivate::dummyTuple()) {
141 // we are called from the internal PythonQt API, so our data will be filled later on...
141 // we are called from the internal PythonQt API, so our data will be filled later on...
142 return 0;
142 return 0;
143 }
143 }
144
144
145 // we are called from python, try to construct our object
145 // we are called from python, try to construct our object
146 if (self->classInfo()->constructors()) {
146 if (self->classInfo()->constructors()) {
147 void* directCPPPointer = NULL;
147 void* directCPPPointer = NULL;
148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
149 if (PyErr_Occurred()) {
149 if (PyErr_Occurred()) {
150 return -1;
150 return -1;
151 }
151 }
152 if (directCPPPointer) {
152 if (directCPPPointer) {
153 // change ownershipflag to be owned by PythonQt
153 // change ownershipflag to be owned by PythonQt
154 self->_ownedByPythonQt = true;
154 self->_ownedByPythonQt = true;
155 self->_useQMetaTypeDestroy = false;
155 self->_useQMetaTypeDestroy = false;
156 if (self->classInfo()->isCPPWrapper()) {
156 if (self->classInfo()->isCPPWrapper()) {
157 self->_wrappedPtr = directCPPPointer;
157 self->_wrappedPtr = directCPPPointer;
158 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
158 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
159 } else {
159 } else {
160 self->setQObject((QObject*)directCPPPointer);
160 self->setQObject((QObject*)directCPPPointer);
161 }
161 }
162 // register with PythonQt
162 // register with PythonQt
163 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
163 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
164
164
165 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
165 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
166 if (cb) {
166 if (cb) {
167 // if we are a derived python class, we set the wrapper
167 // if we are a derived python class, we set the wrapper
168 // to activate the shell class, otherwise we just ignore that it is a shell...
168 // to activate the shell class, otherwise we just ignore that it is a shell...
169 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
169 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
170 // which is the case for all non-python derived types
170 // which is the case for all non-python derived types
171 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
171 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
172 // set the wrapper and remember that we have a shell instance!
172 // set the wrapper and remember that we have a shell instance!
173 (*cb)(directCPPPointer, self);
173 (*cb)(directCPPPointer, self);
174 self->_isShellInstance = true;
174 self->_isShellInstance = true;
175 }
175 }
176 }
176 }
177 }
177 }
178 } else {
178 } else {
179 QString error = QString("No constructors available for ") + self->classInfo()->className();
179 QString error = QString("No constructors available for ") + self->classInfo()->className();
180 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
180 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
181 return -1;
181 return -1;
182 }
182 }
183 return 0;
183 return 0;
184 }
184 }
185
185
186 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
186 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
187 {
187 {
188 return PyString_FromString(obj->ob_type->tp_name);
188 return PyString_FromString(obj->ob_type->tp_name);
189 }
189 }
190
190
191 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
191 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
192 {
192 {
193 return PythonQt::self()->helpCalled(obj->classInfo());
193 return PythonQt::self()->helpCalled(obj->classInfo());
194 }
194 }
195
195
196 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
196 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
197 {
197 {
198 PythonQtInstanceWrapper_deleteObject(self, true);
198 PythonQtInstanceWrapper_deleteObject(self, true);
199 Py_INCREF(Py_None);
199 Py_INCREF(Py_None);
200 return Py_None;
200 return Py_None;
201 }
201 }
202
202
203
203
204 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
204 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
205 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
205 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
206 "Return the classname of the object"
206 "Return the classname of the object"
207 },
207 },
208 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
208 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
209 "Shows the help of available methods for this class"
209 "Shows the help of available methods for this class"
210 },
210 },
211 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
211 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
212 "Deletes the C++ object (at your own risk, my friend!)"
212 "Deletes the C++ object (at your own risk, my friend!)"
213 },
213 },
214 {NULL, NULL, 0, NULL} /* Sentinel */
214 {NULL, NULL, 0, NULL} /* Sentinel */
215 };
215 };
216
216
217
217
218 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
218 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
219 {
219 {
220 const char *attributeName;
220 const char *attributeName;
221 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
221 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
222
222
223 if ((attributeName = PyString_AsString(name)) == NULL) {
223 if ((attributeName = PyString_AsString(name)) == NULL) {
224 return NULL;
224 return NULL;
225 }
225 }
226
226
227 if (qstrcmp(attributeName, "__dict__")==0) {
227 if (qstrcmp(attributeName, "__dict__")==0) {
228 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
228 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
229 dict = PyDict_Copy(dict);
229 dict = PyDict_Copy(dict);
230
230
231 if (wrapper->_obj) {
231 if (wrapper->_obj) {
232 // only the properties are missing, the rest is already available from
232 // only the properties are missing, the rest is already available from
233 // PythonQtClassWrapper...
233 // PythonQtClassWrapper...
234 QStringList l = wrapper->classInfo()->propertyList();
234 QStringList l = wrapper->classInfo()->propertyList();
235 foreach (QString name, l) {
235 foreach (QString name, l) {
236 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
236 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
237 if (o) {
237 if (o) {
238 PyDict_SetItemString(dict, name.toLatin1().data(), o);
238 PyDict_SetItemString(dict, name.toLatin1().data(), o);
239 Py_DECREF(o);
239 Py_DECREF(o);
240 } else {
240 } else {
241 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
241 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
242 }
242 }
243 }
243 }
244
244
245 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
245 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
246 foreach (QByteArray name, dynamicProps) {
246 foreach (QByteArray name, dynamicProps) {
247 PyObject* o = PyObject_GetAttrString(obj, name.data());
247 PyObject* o = PyObject_GetAttrString(obj, name.data());
248 if (o) {
248 if (o) {
249 PyDict_SetItemString(dict, name.data(), o);
249 PyDict_SetItemString(dict, name.data(), o);
250 Py_DECREF(o);
250 Py_DECREF(o);
251 } else {
251 } else {
252 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
252 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
253 }
253 }
254 }
254 }
255 }
255 }
256 // Note: we do not put children into the dict, is would look confusing?!
256 // Note: we do not put children into the dict, is would look confusing?!
257 return dict;
257 return dict;
258 }
258 }
259
259
260 // first look in super, to return derived methods from base object first
260 // first look in super, to return derived methods from base object first
261 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
261 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
262 if (superAttr) {
262 if (superAttr) {
263 return superAttr;
263 return superAttr;
264 }
264 }
265 PyErr_Clear();
265 PyErr_Clear();
266
266
267 // mlabDebugConst("Python","get " << attributeName);
267 // mlabDebugConst("Python","get " << attributeName);
268
268
269 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
269 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
270 switch (member._type) {
270 switch (member._type) {
271 case PythonQtMemberInfo::Property:
271 case PythonQtMemberInfo::Property:
272 if (wrapper->_obj) {
272 if (wrapper->_obj) {
273 if (member._property.userType() != QVariant::Invalid) {
273 if (member._property.userType() != QVariant::Invalid) {
274 return PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
274 return PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
275 } else {
275 } else {
276 Py_INCREF(Py_None);
276 Py_INCREF(Py_None);
277 return Py_None;
277 return Py_None;
278 }
278 }
279 } else {
279 } else {
280 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
280 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
281 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
281 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
282 return NULL;
282 return NULL;
283 }
283 }
284 break;
284 break;
285 case PythonQtMemberInfo::Slot:
285 case PythonQtMemberInfo::Slot:
286 return PythonQtSlotFunction_New(member._slot, obj, NULL);
286 return PythonQtSlotFunction_New(member._slot, obj, NULL);
287 break;
287 break;
288 case PythonQtMemberInfo::EnumValue:
288 case PythonQtMemberInfo::EnumValue:
289 {
289 {
290 PyObject* enumValue = member._enumValue;
290 PyObject* enumValue = member._enumValue;
291 Py_INCREF(enumValue);
291 Py_INCREF(enumValue);
292 return enumValue;
292 return enumValue;
293 }
293 }
294 break;
294 break;
295 case PythonQtMemberInfo::EnumWrapper:
295 case PythonQtMemberInfo::EnumWrapper:
296 {
296 {
297 PyObject* enumWrapper = member._enumWrapper;
297 PyObject* enumWrapper = member._enumWrapper;
298 Py_INCREF(enumWrapper);
298 Py_INCREF(enumWrapper);
299 return enumWrapper;
299 return enumWrapper;
300 }
300 }
301 break;
301 break;
302 case PythonQtMemberInfo::NotFound:
302 case PythonQtMemberInfo::NotFound:
303 {
303 {
304 // check for a getter_
304 static const QByteArray getterString("py_get_");
305 PythonQtMemberInfo member = wrapper->classInfo()->member(QByteArray("getter_") + attributeName);
305 // check for a getter slot
306 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
306 if (member._type == PythonQtMemberInfo::Slot) {
307 if (member._type == PythonQtMemberInfo::Slot) {
307 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
308 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
308 }
309 }
309
310
310 // handle dynamic properties
311 // handle dynamic properties
311 if (wrapper->_obj) {
312 if (wrapper->_obj) {
312 QVariant v = wrapper->_obj->property(attributeName);
313 QVariant v = wrapper->_obj->property(attributeName);
313 if (v.isValid()) {
314 if (v.isValid()) {
314 return PythonQtConv::QVariantToPyObject(v);
315 return PythonQtConv::QVariantToPyObject(v);
315 }
316 }
316 }
317 }
317 }
318 }
318 break;
319 break;
319 default:
320 default:
320 // is an invalid type, go on
321 // is an invalid type, go on
321 break;
322 break;
322 }
323 }
323
324
324 // look for the internal methods (className(), help())
325 // look for the internal methods (className(), help())
325 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
326 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
326 if (internalMethod) {
327 if (internalMethod) {
327 return internalMethod;
328 return internalMethod;
328 }
329 }
329 PyErr_Clear();
330 PyErr_Clear();
330
331
331 if (wrapper->_obj) {
332 if (wrapper->_obj) {
332 // look for a child
333 // look for a child
333 QObjectList children = wrapper->_obj->children();
334 QObjectList children = wrapper->_obj->children();
334 for (int i = 0; i < children.count(); i++) {
335 for (int i = 0; i < children.count(); i++) {
335 QObject *child = children.at(i);
336 QObject *child = children.at(i);
336 if (child->objectName() == attributeName) {
337 if (child->objectName() == attributeName) {
337 return PythonQt::priv()->wrapQObject(child);
338 return PythonQt::priv()->wrapQObject(child);
338 }
339 }
339 }
340 }
340 }
341 }
341
342
342 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
343 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
343 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
344 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
344 return NULL;
345 return NULL;
345 }
346 }
346
347
347 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
348 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
348 {
349 {
349 QString error;
350 QString error;
350 const char *attributeName;
351 const char *attributeName;
351 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
352 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
352
353
353 if ((attributeName = PyString_AsString(name)) == NULL)
354 if ((attributeName = PyString_AsString(name)) == NULL)
354 return -1;
355 return -1;
355
356
356 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
357 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
357 if (member._type == PythonQtMemberInfo::Property) {
358 if (member._type == PythonQtMemberInfo::Property) {
358
359
359 if (!wrapper->_obj) {
360 if (!wrapper->_obj) {
360 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
361 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
361 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
362 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
362 return -1;
363 return -1;
363 }
364 }
364
365
365 QMetaProperty prop = member._property;
366 QMetaProperty prop = member._property;
366 if (prop.isWritable()) {
367 if (prop.isWritable()) {
367 QVariant v;
368 QVariant v;
368 if (prop.isEnumType()) {
369 if (prop.isEnumType()) {
369 // this will give us either a string or an int, everything else will probably be an error
370 // this will give us either a string or an int, everything else will probably be an error
370 v = PythonQtConv::PyObjToQVariant(value);
371 v = PythonQtConv::PyObjToQVariant(value);
371 } else {
372 } else {
372 int t = prop.userType();
373 int t = prop.userType();
373 v = PythonQtConv::PyObjToQVariant(value, t);
374 v = PythonQtConv::PyObjToQVariant(value, t);
374 }
375 }
375 bool success = false;
376 bool success = false;
376 if (v.isValid()) {
377 if (v.isValid()) {
377 success = prop.write(wrapper->_obj, v);
378 success = prop.write(wrapper->_obj, v);
378 }
379 }
379 if (success) {
380 if (success) {
380 return 0;
381 return 0;
381 } else {
382 } else {
382 error = QString("Property '") + attributeName + "' of type '" +
383 error = QString("Property '") + attributeName + "' of type '" +
383 prop.typeName() + "' does not accept an object of type "
384 prop.typeName() + "' does not accept an object of type "
384 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
385 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
385 }
386 }
386 } else {
387 } else {
387 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
388 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
388 }
389 }
389 } else if (member._type == PythonQtMemberInfo::Slot) {
390 } else if (member._type == PythonQtMemberInfo::Slot) {
390 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
391 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
391 } else if (member._type == PythonQtMemberInfo::EnumValue) {
392 } else if (member._type == PythonQtMemberInfo::EnumValue) {
392 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
393 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
393 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
394 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
394 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
395 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
395 } else if (member._type == PythonQtMemberInfo::NotFound) {
396 } else if (member._type == PythonQtMemberInfo::NotFound) {
396 // check for a setter_
397 // check for a setter slot
397 PythonQtMemberInfo setter = wrapper->classInfo()->member(QByteArray("setter_") + attributeName);
398 static const QByteArray setterString("py_set_");
399 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
398 if (setter._type == PythonQtMemberInfo::Slot) {
400 if (setter._type == PythonQtMemberInfo::Slot) {
399 // call the setter and ignore the result value
401 // call the setter and ignore the result value
400 void* result;
402 void* result;
401 PyObject* args = PyTuple_New(1);
403 PyObject* args = PyTuple_New(1);
402 Py_INCREF(value);
404 Py_INCREF(value);
403 PyTuple_SET_ITEM(args, 0, value);
405 PyTuple_SET_ITEM(args, 0, value);
404 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
406 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
405 Py_DECREF(args);
407 Py_DECREF(args);
406 return 0;
408 return 0;
407 }
409 }
408
410
409 // handle dynamic properties
411 // handle dynamic properties
410 if (wrapper->_obj) {
412 if (wrapper->_obj) {
411 QVariant prop = wrapper->_obj->property(attributeName);
413 QVariant prop = wrapper->_obj->property(attributeName);
412 if (prop.isValid()) {
414 if (prop.isValid()) {
413 QVariant v = PythonQtConv::PyObjToQVariant(value);
415 QVariant v = PythonQtConv::PyObjToQVariant(value);
414 if (v.isValid()) {
416 if (v.isValid()) {
415 wrapper->_obj->setProperty(attributeName, v);
417 wrapper->_obj->setProperty(attributeName, v);
416 return 0;
418 return 0;
417 } else {
419 } else {
418 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
420 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
419 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
421 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
420 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
422 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
421 return -1;
423 return -1;
422 }
424 }
423 }
425 }
424 }
426 }
425
427
426 // if we are a derived python class, we allow setting attributes.
428 // if we are a derived python class, we allow setting attributes.
427 // if we are a direct CPP wrapper, we do NOT allow it, since
429 // if we are a direct CPP wrapper, we do NOT allow it, since
428 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
430 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
429 // and when it is recreated from a CPP pointer the attributes are gone...
431 // and when it is recreated from a CPP pointer the attributes are gone...
430 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
432 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
431 return PyBaseObject_Type.tp_setattro(obj,name,value);
433 return PyBaseObject_Type.tp_setattro(obj,name,value);
432 } else {
434 } else {
433 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
435 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
434 }
436 }
435 }
437 }
436
438
437 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
439 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
438 return -1;
440 return -1;
439 }
441 }
440
442
443 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
444 QString result;
445 if (wrapper->_wrappedPtr) {
446 // first try some manually string conversions for some variants
447 int metaid = wrapper->classInfo()->metaTypeId();
448 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
449 if (!result.isEmpty()) {
450 return result;
451 }
452 }
453 // next, try to call py_toString
454 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
455 if (info._type == PythonQtMemberInfo::Slot) {
456 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
457 if (resultObj) {
458 // TODO this is one conversion too much, would be nicer to call the slot directly...
459 result = PythonQtConv::PyObjGetString(resultObj);
460 Py_DECREF(resultObj);
461 }
462 }
463 return result;
464 }
465
441 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
466 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
442 {
467 {
443 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
468 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
444 const char* typeName = obj->ob_type->tp_name;
469 const char* typeName = obj->ob_type->tp_name;
445 QObject *qobj = wrapper->_obj;
470 QObject *qobj = wrapper->_obj;
471 QString str = getStringFromObject(wrapper);
472 if (!str.isEmpty()) {
473 return PyString_FromFormat("%s", str.toLatin1().constData());
474 }
446 if (wrapper->_wrappedPtr) {
475 if (wrapper->_wrappedPtr) {
447 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
448 if (!str.isEmpty()) {
449 return PyString_FromFormat("%s", str.toLatin1().constData());
450 } else
451 if (wrapper->_obj) {
476 if (wrapper->_obj) {
452 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
477 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
453 } else {
478 } else {
454 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
479 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
455 }
480 }
456 } else {
481 } else {
457 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
482 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
458 }
483 }
459 }
484 }
460
485
461 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
486 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
462 {
487 {
463 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
488 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
464 const char* typeName = obj->ob_type->tp_name;
489 const char* typeName = obj->ob_type->tp_name;
465
490
466 QObject *qobj = wrapper->_obj;
491 QObject *qobj = wrapper->_obj;
467 if (wrapper->_wrappedPtr) {
492 QString str = getStringFromObject(wrapper);
468 QString str = PythonQtConv::CPPObjectToString(wrapper->classInfo()->metaTypeId(), wrapper->_wrappedPtr);
493 if (!str.isEmpty()) {
469 if (!str.isEmpty()) {
494 if (str.startsWith(typeName)) {
495 return PyString_FromFormat("%s", str.toLatin1().constData());
496 } else {
470 return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr);
497 return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr);
471 } else
498 }
499 }
500 if (wrapper->_wrappedPtr) {
472 if (wrapper->_obj) {
501 if (wrapper->_obj) {
473 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
502 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
474 } else {
503 } else {
475 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
504 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
476 }
505 }
477 } else {
506 } else {
478 return PyString_FromFormat("%s (%s %p)", typeName, wrapper->classInfo()->className(), qobj);
507 return PyString_FromFormat("%s (%s %p)", typeName, wrapper->classInfo()->className(), qobj);
479 }
508 }
480 }
509 }
481
510
482 static int PythonQtInstanceWrapper_compare(PyObject * obj1, PyObject * obj2)
511 static int PythonQtInstanceWrapper_compare(PyObject * obj1, PyObject * obj2)
483 {
512 {
484 if (PyObject_TypeCheck(obj1, &PythonQtInstanceWrapper_Type) &&
513 if (PyObject_TypeCheck(obj1, &PythonQtInstanceWrapper_Type) &&
485 PyObject_TypeCheck(obj2, &PythonQtInstanceWrapper_Type)) {
514 PyObject_TypeCheck(obj2, &PythonQtInstanceWrapper_Type)) {
486
515
487 PythonQtInstanceWrapper* w1 = (PythonQtInstanceWrapper*)obj1;
516 PythonQtInstanceWrapper* w1 = (PythonQtInstanceWrapper*)obj1;
488 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)obj2;
517 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)obj2;
489 // check pointers directly first:
518 // check pointers directly first:
490 if (w1->_wrappedPtr != NULL) {
519 if (w1->_wrappedPtr != NULL) {
491 if (w1->_wrappedPtr == w2->_wrappedPtr) {
520 if (w1->_wrappedPtr == w2->_wrappedPtr) {
492 return 0;
521 return 0;
493 }
522 }
494 } else if (w1->_obj == w2->_obj) {
523 } else if (w1->_obj == w2->_obj) {
495 return 0;
524 return 0;
496 }
525 }
497 const char* class1 = w1->classInfo()->className();
526 const char* class1 = w1->classInfo()->className();
498 const char* class2 = w2->classInfo()->className();
527 const char* class2 = w2->classInfo()->className();
499 if (strcmp(class1, class2) == 0) {
528 if (strcmp(class1, class2) == 0) {
500 // same class names, so we can try the operator_equal
529 // same class names, so we can try the operator_equal
501 PythonQtMemberInfo info = w1->classInfo()->member("operator_equal");
530 PythonQtMemberInfo info = w1->classInfo()->member("operator_equal");
502 if (info._type == PythonQtMemberInfo::Slot) {
531 if (info._type == PythonQtMemberInfo::Slot) {
503 bool result = false;
532 bool result = false;
504 void* obj1 = w1->_wrappedPtr;
533 void* obj1 = w1->_wrappedPtr;
505 if (!obj1) {
534 if (!obj1) {
506 obj1 = w1->_obj;
535 obj1 = w1->_obj;
507 }
536 }
508 if (!obj1) { return -1; }
537 if (!obj1) { return -1; }
509 void* obj2 = w2->_wrappedPtr;
538 void* obj2 = w2->_wrappedPtr;
510 if (!obj2) {
539 if (!obj2) {
511 obj2 = w2->_obj;
540 obj2 = w2->_obj;
512 }
541 }
513 if (!obj2) { return -1; }
542 if (!obj2) { return -1; }
514 if (info._slot->isInstanceDecorator()) {
543 if (info._slot->isInstanceDecorator()) {
515 // call on decorator QObject
544 // call on decorator QObject
516 void* args[3];
545 void* args[3];
517 args[0] = &result;
546 args[0] = &result;
518 args[1] = &obj1; // this is a pointer, so it needs a pointer to a pointer
547 args[1] = &obj1; // this is a pointer, so it needs a pointer to a pointer
519 args[2] = obj2; // this is a reference, so it needs the direct pointer
548 args[2] = obj2; // this is a reference, so it needs the direct pointer
520 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
549 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
521 return result?0:-1;
550 return result?0:-1;
522 } else {
551 } else {
523 // call directly on QObject
552 // call directly on QObject
524 if (w1->_obj && w2->_obj) {
553 if (w1->_obj && w2->_obj) {
525 void* args[2];
554 void* args[2];
526 args[0] = &result;
555 args[0] = &result;
527 args[1] = obj2; // this is a reference, so it needs the direct pointer
556 args[1] = obj2; // this is a reference, so it needs the direct pointer
528 w1->_obj->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
557 w1->_obj->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
558 return result?0:-1;
529 }
559 }
530 }
560 }
531 }
561 }
532 }
562 }
533 }
563 }
534 return -1;
564 return -1;
535 }
565 }
536
566
537 static int PythonQtInstanceWrapper_nonzero(PyObject *obj)
567 static int PythonQtInstanceWrapper_nonzero(PyObject *obj)
538 {
568 {
539 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
569 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
540 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
570 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
541 }
571 }
542
572
543
573
544 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
574 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
545 {
575 {
546 if (obj->_wrappedPtr != NULL) {
576 if (obj->_wrappedPtr != NULL) {
547 return reinterpret_cast<long>(obj->_wrappedPtr);
577 return reinterpret_cast<long>(obj->_wrappedPtr);
548 } else {
578 } else {
549 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
579 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
550 return reinterpret_cast<long>(qobj);
580 return reinterpret_cast<long>(qobj);
551 }
581 }
552 }
582 }
553
583
554
584
555
585
556 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
586 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
557 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
587 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
558 0, /* nb_add */
588 0, /* nb_add */
559 0, /* nb_subtract */
589 0, /* nb_subtract */
560 0, /* nb_multiply */
590 0, /* nb_multiply */
561 0, /* nb_divide */
591 0, /* nb_divide */
562 0, /* nb_remainder */
592 0, /* nb_remainder */
563 0, /* nb_divmod */
593 0, /* nb_divmod */
564 0, /* nb_power */
594 0, /* nb_power */
565 0, /* nb_negative */
595 0, /* nb_negative */
566 0, /* nb_positive */
596 0, /* nb_positive */
567 0, /* nb_absolute */
597 0, /* nb_absolute */
568 PythonQtInstanceWrapper_nonzero, /* nb_nonzero */
598 PythonQtInstanceWrapper_nonzero, /* nb_nonzero */
569 0, /* nb_invert */
599 0, /* nb_invert */
570 0, /* nb_lshift */
600 0, /* nb_lshift */
571 0, /* nb_rshift */
601 0, /* nb_rshift */
572 0, /* nb_and */
602 0, /* nb_and */
573 0, /* nb_xor */
603 0, /* nb_xor */
574 0, /* nb_or */
604 0, /* nb_or */
575 0, /* nb_coerce */
605 0, /* nb_coerce */
576 0, /* nb_int */
606 0, /* nb_int */
577 0, /* nb_long */
607 0, /* nb_long */
578 0, /* nb_float */
608 0, /* nb_float */
579 0, /* nb_oct */
609 0, /* nb_oct */
580 0, /* nb_hex */
610 0, /* nb_hex */
581 0, /* nb_inplace_add */
611 0, /* nb_inplace_add */
582 0, /* nb_inplace_subtract */
612 0, /* nb_inplace_subtract */
583 0, /* nb_inplace_multiply */
613 0, /* nb_inplace_multiply */
584 0, /* nb_inplace_divide */
614 0, /* nb_inplace_divide */
585 0, /* nb_inplace_remainder */
615 0, /* nb_inplace_remainder */
586 0, /* nb_inplace_power */
616 0, /* nb_inplace_power */
587 0, /* nb_inplace_lshift */
617 0, /* nb_inplace_lshift */
588 0, /* nb_inplace_rshift */
618 0, /* nb_inplace_rshift */
589 0, /* nb_inplace_and */
619 0, /* nb_inplace_and */
590 0, /* nb_inplace_xor */
620 0, /* nb_inplace_xor */
591 0, /* nb_inplace_or */
621 0, /* nb_inplace_or */
592 0, /* nb_floor_divide */
622 0, /* nb_floor_divide */
593 0, /* nb_true_divide */
623 0, /* nb_true_divide */
594 0, /* nb_inplace_floor_divide */
624 0, /* nb_inplace_floor_divide */
595 0, /* nb_inplace_true_divide */
625 0, /* nb_inplace_true_divide */
596 };
626 };
597
627
598 PyTypeObject PythonQtInstanceWrapper_Type = {
628 PyTypeObject PythonQtInstanceWrapper_Type = {
599 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
629 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
600 0, /*ob_size*/
630 0, /*ob_size*/
601 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
631 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
602 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
632 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
603 0, /*tp_itemsize*/
633 0, /*tp_itemsize*/
604 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
634 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
605 0, /*tp_print*/
635 0, /*tp_print*/
606 0, /*tp_getattr*/
636 0, /*tp_getattr*/
607 0, /*tp_setattr*/
637 0, /*tp_setattr*/
608 PythonQtInstanceWrapper_compare, /*tp_compare*/
638 PythonQtInstanceWrapper_compare, /*tp_compare*/
609 PythonQtInstanceWrapper_repr, /*tp_repr*/
639 PythonQtInstanceWrapper_repr, /*tp_repr*/
610 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
640 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
611 0, /*tp_as_sequence*/
641 0, /*tp_as_sequence*/
612 0, /*tp_as_mapping*/
642 0, /*tp_as_mapping*/
613 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
643 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
614 0, /*tp_call*/
644 0, /*tp_call*/
615 PythonQtInstanceWrapper_str, /*tp_str*/
645 PythonQtInstanceWrapper_str, /*tp_str*/
616 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
646 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
617 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
647 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
618 0, /*tp_as_buffer*/
648 0, /*tp_as_buffer*/
619 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
649 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
620 "PythonQtInstanceWrapper object", /* tp_doc */
650 "PythonQtInstanceWrapper object", /* tp_doc */
621 0, /* tp_traverse */
651 0, /* tp_traverse */
622 0, /* tp_clear */
652 0, /* tp_clear */
623 0, /* tp_richcompare */
653 0, /* tp_richcompare */
624 0, /* tp_weaklistoffset */
654 0, /* tp_weaklistoffset */
625 0, /* tp_iter */
655 0, /* tp_iter */
626 0, /* tp_iternext */
656 0, /* tp_iternext */
627 0, /* tp_methods */
657 0, /* tp_methods */
628 0, /* tp_members */
658 0, /* tp_members */
629 0, /* tp_getset */
659 0, /* tp_getset */
630 0, /* tp_base */
660 0, /* tp_base */
631 0, /* tp_dict */
661 0, /* tp_dict */
632 0, /* tp_descr_get */
662 0, /* tp_descr_get */
633 0, /* tp_descr_set */
663 0, /* tp_descr_set */
634 0, /* tp_dictoffset */
664 0, /* tp_dictoffset */
635 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
665 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
636 0, /* tp_alloc */
666 0, /* tp_alloc */
637 PythonQtInstanceWrapper_new, /* tp_new */
667 PythonQtInstanceWrapper_new, /* tp_new */
638 };
668 };
639
669
640 //-------------------------------------------------------
670 //-------------------------------------------------------
641
671
General Comments 0
You need to be logged in to leave comments. Login now