##// END OF EJS Templates
added automatic conversion to QColor,QPen,QCursor and QBrush from enums and colors...
florianlink -
r64:3ef1598f6c5e
parent child
Show More
@@ -1,822 +1,826
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtClassInfo.h"
42 #include "PythonQtClassInfo.h"
43 #include "PythonQtMethodInfo.h"
43 #include "PythonQtMethodInfo.h"
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include <QMetaMethod>
45 #include <QMetaMethod>
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaEnum>
47 #include <QMetaEnum>
48
48
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
50
50
51 PythonQtClassInfo::PythonQtClassInfo() {
51 PythonQtClassInfo::PythonQtClassInfo() {
52 _meta = NULL;
52 _meta = NULL;
53 _constructors = NULL;
53 _constructors = NULL;
54 _destructor = NULL;
54 _destructor = NULL;
55 _decoratorProvider = NULL;
55 _decoratorProvider = NULL;
56 _decoratorProviderCB = NULL;
56 _decoratorProviderCB = NULL;
57 _pythonQtClassWrapper = NULL;
57 _pythonQtClassWrapper = NULL;
58 _shellSetInstanceWrapperCB = NULL;
58 _shellSetInstanceWrapperCB = NULL;
59 _metaTypeId = -1;
59 _metaTypeId = -1;
60 _isQObject = false;
60 _isQObject = false;
61 _enumsCreated = false;
61 _enumsCreated = false;
62 }
62 }
63
63
64 PythonQtClassInfo::~PythonQtClassInfo()
64 PythonQtClassInfo::~PythonQtClassInfo()
65 {
65 {
66 clearCachedMembers();
66 clearCachedMembers();
67
67
68 if (_constructors) {
68 if (_constructors) {
69 _constructors->deleteOverloadsAndThis();
69 _constructors->deleteOverloadsAndThis();
70 }
70 }
71 if (_destructor) {
71 if (_destructor) {
72 _destructor->deleteOverloadsAndThis();
72 _destructor->deleteOverloadsAndThis();
73 }
73 }
74 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
74 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 info->deleteOverloadsAndThis();
75 info->deleteOverloadsAndThis();
76 }
76 }
77 }
77 }
78
78
79 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
79 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 {
80 {
81 // _wrappedClassName is already set earlier in the class setup
81 // _wrappedClassName is already set earlier in the class setup
82 _isQObject = true;
82 _isQObject = true;
83 _meta = meta;
83 _meta = meta;
84 }
84 }
85
85
86 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
86 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 {
87 {
88 _isQObject = false;
88 _isQObject = false;
89 _wrappedClassName = classname;
89 _wrappedClassName = classname;
90 _metaTypeId = QMetaType::type(classname);
90 _metaTypeId = QMetaType::type(classname);
91 }
91 }
92
92
93 void PythonQtClassInfo::clearCachedMembers()
93 void PythonQtClassInfo::clearCachedMembers()
94 {
94 {
95 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
95 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 while (i.hasNext()) {
96 while (i.hasNext()) {
97 PythonQtMemberInfo member = i.next().value();
97 PythonQtMemberInfo member = i.next().value();
98 if (member._type== PythonQtMemberInfo::Slot) {
98 if (member._type== PythonQtMemberInfo::Slot) {
99 PythonQtSlotInfo* info = member._slot;
99 PythonQtSlotInfo* info = member._slot;
100 while (info) {
100 while (info) {
101 PythonQtSlotInfo* next = info->nextInfo();
101 PythonQtSlotInfo* next = info->nextInfo();
102 delete info;
102 delete info;
103 info = next;
103 info = next;
104 }
104 }
105 }
105 }
106 }
106 }
107 }
107 }
108
108
109 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
109 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 {
110 {
111 const char* sigEnd = sigStart;
111 const char* sigEnd = sigStart;
112 char c;
112 char c;
113 do {
113 do {
114 c = *sigEnd++;
114 c = *sigEnd++;
115 } while (c!=someChar && c!=0);
115 } while (c!=someChar && c!=0);
116 return sigEnd-sigStart-1;
116 return sigEnd-sigStart-1;
117 }
117 }
118
118
119 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
119 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 {
120 {
121 bool found = false;
121 bool found = false;
122 bool nameMapped = false;
122 bool nameMapped = false;
123 const char* attributeName = memberName;
123 const char* attributeName = memberName;
124 // look for properties
124 // look for properties
125 int i = _meta->indexOfProperty(attributeName);
125 int i = _meta->indexOfProperty(attributeName);
126 if (i==-1) {
126 if (i==-1) {
127 // try to map name to objectName
127 // try to map name to objectName
128 if (qstrcmp(attributeName, "name")==0) {
128 if (qstrcmp(attributeName, "name")==0) {
129 attributeName = "objectName";
129 attributeName = "objectName";
130 nameMapped = true;
130 nameMapped = true;
131 i = _meta->indexOfProperty(attributeName);
131 i = _meta->indexOfProperty(attributeName);
132 }
132 }
133 }
133 }
134 if (i!=-1) {
134 if (i!=-1) {
135 PythonQtMemberInfo newInfo(_meta->property(i));
135 PythonQtMemberInfo newInfo(_meta->property(i));
136 _cachedMembers.insert(attributeName, newInfo);
136 _cachedMembers.insert(attributeName, newInfo);
137 if (nameMapped) {
137 if (nameMapped) {
138 _cachedMembers.insert(memberName, newInfo);
138 _cachedMembers.insert(memberName, newInfo);
139 }
139 }
140 #ifdef PYTHONQT_DEBUG
140 #ifdef PYTHONQT_DEBUG
141 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
141 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
142 #endif
142 #endif
143 found = true;
143 found = true;
144 }
144 }
145 return found;
145 return found;
146 }
146 }
147
147
148 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
148 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
149 {
149 {
150 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
150 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
151 foreach(const ParentClassInfo& info, _parentClasses) {
151 foreach(const ParentClassInfo& info, _parentClasses) {
152 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
152 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
153 }
153 }
154 return inputInfo;
154 return inputInfo;
155 }
155 }
156
156
157 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
157 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
158 QObject* decoratorProvider = decorator();
158 QObject* decoratorProvider = decorator();
159 int memberNameLen = strlen(memberName);
159 int memberNameLen = strlen(memberName);
160 if (decoratorProvider) {
160 if (decoratorProvider) {
161 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
161 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
162 const QMetaObject* meta = decoratorProvider->metaObject();
162 const QMetaObject* meta = decoratorProvider->metaObject();
163 int numMethods = meta->methodCount();
163 int numMethods = meta->methodCount();
164 int startFrom = QObject::staticMetaObject.methodCount();
164 int startFrom = QObject::staticMetaObject.methodCount();
165 for (int i = startFrom; i < numMethods; i++) {
165 for (int i = startFrom; i < numMethods; i++) {
166 QMetaMethod m = meta->method(i);
166 QMetaMethod m = meta->method(i);
167 if ((m.methodType() == QMetaMethod::Method ||
167 if ((m.methodType() == QMetaMethod::Method ||
168 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
168 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
169
169
170 const char* sigStart = m.signature();
170 const char* sigStart = m.signature();
171 bool isClassDeco = false;
171 bool isClassDeco = false;
172 if (qstrncmp(sigStart, "static_", 7)==0) {
172 if (qstrncmp(sigStart, "static_", 7)==0) {
173 // skip the static_classname_ part of the string
173 // skip the static_classname_ part of the string
174 sigStart += 7 + 1 + strlen(className());
174 sigStart += 7 + 1 + strlen(className());
175 isClassDeco = true;
175 isClassDeco = true;
176 } else if (qstrncmp(sigStart, "new_", 4)==0) {
176 } else if (qstrncmp(sigStart, "new_", 4)==0) {
177 isClassDeco = true;
177 isClassDeco = true;
178 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
178 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
179 isClassDeco = true;
179 isClassDeco = true;
180 }
180 }
181 // find the first '('
181 // find the first '('
182 int offset = findCharOffset(sigStart, '(');
182 int offset = findCharOffset(sigStart, '(');
183
183
184 // XXX no checking is currently done if the slots have correct first argument or not...
184 // XXX no checking is currently done if the slots have correct first argument or not...
185
185
186 // check if same length and same name
186 // check if same length and same name
187 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
187 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
188 found = true;
188 found = true;
189 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
189 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
190 info->setUpcastingOffset(upcastingOffset);
190 info->setUpcastingOffset(upcastingOffset);
191 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
191 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
192 if (tail) {
192 if (tail) {
193 tail->setNextInfo(info);
193 tail->setNextInfo(info);
194 } else {
194 } else {
195 PythonQtMemberInfo newInfo(info);
195 PythonQtMemberInfo newInfo(info);
196 memberCache.insert(memberName, newInfo);
196 memberCache.insert(memberName, newInfo);
197 }
197 }
198 tail = info;
198 tail = info;
199 }
199 }
200 }
200 }
201 }
201 }
202 }
202 }
203
203
204 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
204 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
205
205
206 return tail;
206 return tail;
207 }
207 }
208
208
209 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
209 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
210 {
210 {
211 bool found = false;
211 bool found = false;
212 int memberNameLen = strlen(memberName);
212 int memberNameLen = strlen(memberName);
213 PythonQtSlotInfo* tail = NULL;
213 PythonQtSlotInfo* tail = NULL;
214 if (_meta) {
214 if (_meta) {
215 int numMethods = _meta->methodCount();
215 int numMethods = _meta->methodCount();
216 for (int i = 0; i < numMethods; i++) {
216 for (int i = 0; i < numMethods; i++) {
217 QMetaMethod m = _meta->method(i);
217 QMetaMethod m = _meta->method(i);
218 if ((m.methodType() == QMetaMethod::Method ||
218 if ((m.methodType() == QMetaMethod::Method ||
219 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
219 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
220
220
221 const char* sigStart = m.signature();
221 const char* sigStart = m.signature();
222 // find the first '('
222 // find the first '('
223 int offset = findCharOffset(sigStart, '(');
223 int offset = findCharOffset(sigStart, '(');
224
224
225 // check if same length and same name
225 // check if same length and same name
226 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
226 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
227 found = true;
227 found = true;
228 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
228 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
229 if (tail) {
229 if (tail) {
230 tail->setNextInfo(info);
230 tail->setNextInfo(info);
231 } else {
231 } else {
232 PythonQtMemberInfo newInfo(info);
232 PythonQtMemberInfo newInfo(info);
233 _cachedMembers.insert(memberName, newInfo);
233 _cachedMembers.insert(memberName, newInfo);
234 }
234 }
235 tail = info;
235 tail = info;
236 }
236 }
237 }
237 }
238 }
238 }
239 }
239 }
240
240
241 // look for dynamic decorators in this class and in derived classes
241 // look for dynamic decorators in this class and in derived classes
242 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
242 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
243
243
244 return found;
244 return found;
245 }
245 }
246
246
247 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
247 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
248 {
248 {
249 bool found = false;
249 bool found = false;
250 // look for enum values
250 // look for enum values
251 int enumCount = meta->enumeratorCount();
251 int enumCount = meta->enumeratorCount();
252 for (int i=0;i<enumCount; i++) {
252 for (int i=0;i<enumCount; i++) {
253 QMetaEnum e = meta->enumerator(i);
253 QMetaEnum e = meta->enumerator(i);
254 // we do not want flags, they will cause our values to appear two times
254 // we do not want flags, they will cause our values to appear two times
255 if (e.isFlag()) continue;
255 if (e.isFlag()) continue;
256
256
257 for (int j=0; j < e.keyCount(); j++) {
257 for (int j=0; j < e.keyCount(); j++) {
258 if (qstrcmp(e.key(j), memberName)==0) {
258 if (qstrcmp(e.key(j), memberName)==0) {
259 PyObject* enumType = findEnumWrapper(e.name());
259 PyObject* enumType = findEnumWrapper(e.name());
260 if (enumType) {
260 if (enumType) {
261 PythonQtObjectPtr enumValuePtr;
261 PythonQtObjectPtr enumValuePtr;
262 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
262 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
263 PythonQtMemberInfo newInfo(enumValuePtr);
263 PythonQtMemberInfo newInfo(enumValuePtr);
264 _cachedMembers.insert(memberName, newInfo);
264 _cachedMembers.insert(memberName, newInfo);
265 #ifdef PYTHONQT_DEBUG
265 #ifdef PYTHONQT_DEBUG
266 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
266 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
267 #endif
267 #endif
268 found = true;
268 found = true;
269 break;
269 break;
270 } else {
270 } else {
271 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
271 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
272 }
272 }
273 }
273 }
274 }
274 }
275 }
275 }
276 return found;
276 return found;
277 }
277 }
278
278
279 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
279 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
280 {
280 {
281 PythonQtMemberInfo info = _cachedMembers.value(memberName);
281 PythonQtMemberInfo info = _cachedMembers.value(memberName);
282 if (info._type != PythonQtMemberInfo::Invalid) {
282 if (info._type != PythonQtMemberInfo::Invalid) {
283 return info;
283 return info;
284 } else {
284 } else {
285 bool found = false;
285 bool found = false;
286
286
287 found = lookForPropertyAndCache(memberName);
287 found = lookForPropertyAndCache(memberName);
288 if (!found) {
288 if (!found) {
289 found = lookForMethodAndCache(memberName);
289 found = lookForMethodAndCache(memberName);
290 }
290 }
291 if (!found) {
291 if (!found) {
292 if (_meta) {
292 if (_meta) {
293 // check enums in our meta object directly
293 // check enums in our meta object directly
294 found = lookForEnumAndCache(_meta, memberName);
294 found = lookForEnumAndCache(_meta, memberName);
295 }
295 }
296 if (!found) {
296 if (!found) {
297 // check enums in the class hierachy of CPP classes
297 // check enums in the class hierachy of CPP classes
298 // look for dynamic decorators in this class and in derived classes
298 // look for dynamic decorators in this class and in derived classes
299 QList<QObject*> decoObjects;
299 QList<QObject*> decoObjects;
300 recursiveCollectDecoratorObjects(decoObjects);
300 recursiveCollectDecoratorObjects(decoObjects);
301 foreach(QObject* deco, decoObjects) {
301 foreach(QObject* deco, decoObjects) {
302 // call on ourself for caching, but with different metaObject():
302 // call on ourself for caching, but with different metaObject():
303 found = lookForEnumAndCache(deco->metaObject(), memberName);
303 found = lookForEnumAndCache(deco->metaObject(), memberName);
304 if (found) {
304 if (found) {
305 break;
305 break;
306 }
306 }
307 }
307 }
308 }
308 }
309 }
309 }
310 if (!found) {
310 if (!found) {
311 PyObject* p = findEnumWrapper(memberName);
311 PyObject* p = findEnumWrapper(memberName);
312 if (p) {
312 if (p) {
313 info._type = PythonQtMemberInfo::EnumWrapper;
313 info._type = PythonQtMemberInfo::EnumWrapper;
314 info._enumWrapper = p;
314 info._enumWrapper = p;
315 _cachedMembers.insert(memberName, info);
315 _cachedMembers.insert(memberName, info);
316 found = true;
316 found = true;
317 }
317 }
318 }
318 }
319 if (!found) {
319 if (!found) {
320 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
320 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
321 info._type = PythonQtMemberInfo::NotFound;
321 info._type = PythonQtMemberInfo::NotFound;
322 _cachedMembers.insert(memberName, info);
322 _cachedMembers.insert(memberName, info);
323 }
323 }
324 }
324 }
325
325
326 return _cachedMembers.value(memberName);
326 return _cachedMembers.value(memberName);
327 }
327 }
328
328
329 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
329 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
330 QObject* deco = decorator();
330 QObject* deco = decorator();
331 if (deco) {
331 if (deco) {
332 decoratorObjects.append(deco);
332 decoratorObjects.append(deco);
333 }
333 }
334 foreach(const ParentClassInfo& info, _parentClasses) {
334 foreach(const ParentClassInfo& info, _parentClasses) {
335 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
335 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
336 }
336 }
337 }
337 }
338
338
339 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
339 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
340 classInfoObjects.append(this);
340 classInfoObjects.append(this);
341 foreach(const ParentClassInfo& info, _parentClasses) {
341 foreach(const ParentClassInfo& info, _parentClasses) {
342 info._parent->recursiveCollectClassInfos(classInfoObjects);
342 info._parent->recursiveCollectClassInfos(classInfoObjects);
343 }
343 }
344 }
344 }
345
345
346 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
346 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
347 {
347 {
348 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
348 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
349 while (it.hasNext()) {
349 while (it.hasNext()) {
350
350
351 PythonQtSlotInfo* infoOrig = it.next();
351 PythonQtSlotInfo* infoOrig = it.next();
352
352
353 const char* sigStart = infoOrig->metaMethod()->signature();
353 const char* sigStart = infoOrig->metaMethod()->signature();
354 if (qstrncmp("static_", sigStart, 7)==0) {
354 if (qstrncmp("static_", sigStart, 7)==0) {
355 sigStart += 7;
355 sigStart += 7;
356 sigStart += findCharOffset(sigStart, '_')+1;
356 sigStart += findCharOffset(sigStart, '_')+1;
357 }
357 }
358 int offset = findCharOffset(sigStart, '(');
358 int offset = findCharOffset(sigStart, '(');
359 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
359 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
360 //make a copy, otherwise we will have trouble on overloads!
360 //make a copy, otherwise we will have trouble on overloads!
361 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
361 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
362 info->setUpcastingOffset(upcastingOffset);
362 info->setUpcastingOffset(upcastingOffset);
363 found = true;
363 found = true;
364 if (tail) {
364 if (tail) {
365 tail->setNextInfo(info);
365 tail->setNextInfo(info);
366 } else {
366 } else {
367 PythonQtMemberInfo newInfo(info);
367 PythonQtMemberInfo newInfo(info);
368 memberCache.insert(memberName, newInfo);
368 memberCache.insert(memberName, newInfo);
369 }
369 }
370 tail = info;
370 tail = info;
371 }
371 }
372 }
372 }
373 return tail;
373 return tail;
374 }
374 }
375
375
376 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
376 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
377 QObject* decoratorProvider = decorator();
377 QObject* decoratorProvider = decorator();
378 if (decoratorProvider) {
378 if (decoratorProvider) {
379 const QMetaObject* meta = decoratorProvider->metaObject();
379 const QMetaObject* meta = decoratorProvider->metaObject();
380 int numMethods = meta->methodCount();
380 int numMethods = meta->methodCount();
381 int startFrom = QObject::staticMetaObject.methodCount();
381 int startFrom = QObject::staticMetaObject.methodCount();
382 for (int i = startFrom; i < numMethods; i++) {
382 for (int i = startFrom; i < numMethods; i++) {
383 QMetaMethod m = meta->method(i);
383 QMetaMethod m = meta->method(i);
384 if ((m.methodType() == QMetaMethod::Method ||
384 if ((m.methodType() == QMetaMethod::Method ||
385 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
385 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
386
386
387 const char* sigStart = m.signature();
387 const char* sigStart = m.signature();
388 bool isClassDeco = false;
388 bool isClassDeco = false;
389 if (qstrncmp(sigStart, "static_", 7)==0) {
389 if (qstrncmp(sigStart, "static_", 7)==0) {
390 // skip the static_classname_ part of the string
390 // skip the static_classname_ part of the string
391 sigStart += 7 + 1 + strlen(className());
391 sigStart += 7 + 1 + strlen(className());
392 isClassDeco = true;
392 isClassDeco = true;
393 } else if (qstrncmp(sigStart, "new_", 4)==0) {
393 } else if (qstrncmp(sigStart, "new_", 4)==0) {
394 continue;
394 continue;
395 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
395 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
396 continue;
396 continue;
397 }
397 }
398 // find the first '('
398 // find the first '('
399 int offset = findCharOffset(sigStart, '(');
399 int offset = findCharOffset(sigStart, '(');
400
400
401 // XXX no checking is currently done if the slots have correct first argument or not...
401 // XXX no checking is currently done if the slots have correct first argument or not...
402 if (!metaOnly || isClassDeco) {
402 if (!metaOnly || isClassDeco) {
403 list << QString::fromLatin1(sigStart, offset);
403 list << QString::fromLatin1(sigStart, offset);
404 }
404 }
405 }
405 }
406 }
406 }
407 }
407 }
408
408
409 // look for global decorator slots
409 // look for global decorator slots
410 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
410 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
411 while (it.hasNext()) {
411 while (it.hasNext()) {
412 PythonQtSlotInfo* slot = it.next();
412 PythonQtSlotInfo* slot = it.next();
413 if (metaOnly) {
413 if (metaOnly) {
414 if (slot->isClassDecorator()) {
414 if (slot->isClassDecorator()) {
415 QByteArray first = slot->slotName();
415 QByteArray first = slot->slotName();
416 if (first.startsWith("static_")) {
416 if (first.startsWith("static_")) {
417 int idx = first.indexOf('_');
417 int idx = first.indexOf('_');
418 idx = first.indexOf('_', idx+1);
418 idx = first.indexOf('_', idx+1);
419 first = first.mid(idx+1);
419 first = first.mid(idx+1);
420 }
420 }
421 list << first;
421 list << first;
422 }
422 }
423 } else {
423 } else {
424 list << slot->slotName();
424 list << slot->slotName();
425 }
425 }
426 }
426 }
427 }
427 }
428
428
429 QStringList PythonQtClassInfo::propertyList()
429 QStringList PythonQtClassInfo::propertyList()
430 {
430 {
431 QStringList l;
431 QStringList l;
432 if (_isQObject && _meta) {
432 if (_isQObject && _meta) {
433 int i;
433 int i;
434 int numProperties = _meta->propertyCount();
434 int numProperties = _meta->propertyCount();
435 for (i = 0; i < numProperties; i++) {
435 for (i = 0; i < numProperties; i++) {
436 QMetaProperty p = _meta->property(i);
436 QMetaProperty p = _meta->property(i);
437 l << QString(p.name());
437 l << QString(p.name());
438 }
438 }
439 }
439 }
440 return l;
440 return l;
441 }
441 }
442
442
443 QStringList PythonQtClassInfo::memberList(bool metaOnly)
443 QStringList PythonQtClassInfo::memberList(bool metaOnly)
444 {
444 {
445 decorator();
445 decorator();
446
446
447 QStringList l;
447 QStringList l;
448 QString h;
448 QString h;
449 if (_isQObject && _meta && !metaOnly) {
449 if (_isQObject && _meta && !metaOnly) {
450 l = propertyList();
450 l = propertyList();
451 }
451 }
452
452
453 // normal slots of QObject (or wrapper QObject)
453 // normal slots of QObject (or wrapper QObject)
454 if (!metaOnly && _meta) {
454 if (!metaOnly && _meta) {
455 int numMethods = _meta->methodCount();
455 int numMethods = _meta->methodCount();
456 bool skipQObj = !_isQObject;
456 bool skipQObj = !_isQObject;
457 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
457 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
458 QMetaMethod m = _meta->method(i);
458 QMetaMethod m = _meta->method(i);
459 if ((m.methodType() == QMetaMethod::Method ||
459 if ((m.methodType() == QMetaMethod::Method ||
460 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
460 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
461 QByteArray signa(m.signature());
461 QByteArray signa(m.signature());
462 signa = signa.left(signa.indexOf('('));
462 signa = signa.left(signa.indexOf('('));
463 l << signa;
463 l << signa;
464 }
464 }
465 }
465 }
466 }
466 }
467
467
468 {
468 {
469 // look for dynamic decorators in this class and in derived classes
469 // look for dynamic decorators in this class and in derived classes
470 QList<PythonQtClassInfo*> infos;
470 QList<PythonQtClassInfo*> infos;
471 recursiveCollectClassInfos(infos);
471 recursiveCollectClassInfos(infos);
472 foreach(PythonQtClassInfo* info, infos) {
472 foreach(PythonQtClassInfo* info, infos) {
473 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
473 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
474 }
474 }
475 }
475 }
476
476
477 // List enumerator keys...
477 // List enumerator keys...
478 QList<const QMetaObject*> enumMetaObjects;
478 QList<const QMetaObject*> enumMetaObjects;
479 if (_meta) {
479 if (_meta) {
480 enumMetaObjects << _meta;
480 enumMetaObjects << _meta;
481 }
481 }
482 // check enums in the class hierachy of CPP classes
482 // check enums in the class hierachy of CPP classes
483 QList<QObject*> decoObjects;
483 QList<QObject*> decoObjects;
484 recursiveCollectDecoratorObjects(decoObjects);
484 recursiveCollectDecoratorObjects(decoObjects);
485 foreach(QObject* deco, decoObjects) {
485 foreach(QObject* deco, decoObjects) {
486 enumMetaObjects << deco->metaObject();
486 enumMetaObjects << deco->metaObject();
487 }
487 }
488
488
489 foreach(const QMetaObject* meta, enumMetaObjects) {
489 foreach(const QMetaObject* meta, enumMetaObjects) {
490 for (int i = 0; i<meta->enumeratorCount(); i++) {
490 for (int i = 0; i<meta->enumeratorCount(); i++) {
491 QMetaEnum e = meta->enumerator(i);
491 QMetaEnum e = meta->enumerator(i);
492 l << e.name();
492 l << e.name();
493 // we do not want flags, they will cause our values to appear two times
493 // we do not want flags, they will cause our values to appear two times
494 if (e.isFlag()) continue;
494 if (e.isFlag()) continue;
495
495
496 for (int j=0; j < e.keyCount(); j++) {
496 for (int j=0; j < e.keyCount(); j++) {
497 l << QString(e.key(j));
497 l << QString(e.key(j));
498 }
498 }
499 }
499 }
500 }
500 }
501
501
502 return QSet<QString>::fromList(l).toList();
502 return QSet<QString>::fromList(l).toList();
503 }
503 }
504
504
505 const char* PythonQtClassInfo::className()
505 const char* PythonQtClassInfo::className()
506 {
506 {
507 return _wrappedClassName.constData();
507 return _wrappedClassName.constData();
508 }
508 }
509
509
510 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
510 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
511 {
511 {
512 if (ptr==NULL) {
512 if (ptr==NULL) {
513 return NULL;
513 return NULL;
514 }
514 }
515 if (_wrappedClassName == classname) {
515 if (_wrappedClassName == classname) {
516 return ptr;
516 return ptr;
517 }
517 }
518 foreach(const ParentClassInfo& info, _parentClasses) {
518 foreach(const ParentClassInfo& info, _parentClasses) {
519 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
519 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
520 if (result) {
520 if (result) {
521 return result;
521 return result;
522 }
522 }
523 }
523 }
524 return NULL;
524 return NULL;
525 }
525 }
526
526
527 bool PythonQtClassInfo::inherits(const char* name)
527 bool PythonQtClassInfo::inherits(const char* name)
528 {
528 {
529 if (_wrappedClassName == name) {
529 if (_wrappedClassName == name) {
530 return true;
530 return true;
531 }
531 }
532 foreach(const ParentClassInfo& info, _parentClasses) {
532 foreach(const ParentClassInfo& info, _parentClasses) {
533 if (info._parent->inherits(name)) {
533 if (info._parent->inherits(name)) {
534 return true;
534 return true;
535 }
535 }
536 }
536 }
537 return false;
537 return false;
538 }
538 }
539
539
540 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
540 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
541 {
541 {
542 if (classInfo == this) {
542 if (classInfo == this) {
543 return true;
543 return true;
544 }
544 }
545 foreach(const ParentClassInfo& info, _parentClasses) {
545 foreach(const ParentClassInfo& info, _parentClasses) {
546 if (info._parent->inherits(classInfo)) {
546 if (info._parent->inherits(classInfo)) {
547 return true;
547 return true;
548 }
548 }
549 }
549 }
550 return false;
550 return false;
551 }
551 }
552
552
553 QString PythonQtClassInfo::help()
553 QString PythonQtClassInfo::help()
554 {
554 {
555 decorator();
555 decorator();
556 QString h;
556 QString h;
557 h += QString("--- ") + QString(className()) + QString(" ---\n");
557 h += QString("--- ") + QString(className()) + QString(" ---\n");
558
558
559 if (_isQObject) {
559 if (_isQObject) {
560 h += "Properties:\n";
560 h += "Properties:\n";
561
561
562 int i;
562 int i;
563 int numProperties = _meta->propertyCount();
563 int numProperties = _meta->propertyCount();
564 for (i = 0; i < numProperties; i++) {
564 for (i = 0; i < numProperties; i++) {
565 QMetaProperty p = _meta->property(i);
565 QMetaProperty p = _meta->property(i);
566 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
566 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
567 }
567 }
568 }
568 }
569
569
570 if (constructors()) {
570 if (constructors()) {
571 h += "Constructors:\n";
571 h += "Constructors:\n";
572 PythonQtSlotInfo* constr = constructors();
572 PythonQtSlotInfo* constr = constructors();
573 while (constr) {
573 while (constr) {
574 h += constr->fullSignature() + "\n";
574 h += constr->fullSignature() + "\n";
575 constr = constr->nextInfo();
575 constr = constr->nextInfo();
576 }
576 }
577 }
577 }
578
578
579 h += "Slots:\n";
579 h += "Slots:\n";
580 h += "QString help()\n";
580 h += "QString help()\n";
581 h += "QString className()\n";
581 h += "QString className()\n";
582
582
583 if (_meta) {
583 if (_meta) {
584 int numMethods = _meta->methodCount();
584 int numMethods = _meta->methodCount();
585 for (int i = 0; i < numMethods; i++) {
585 for (int i = 0; i < numMethods; i++) {
586 QMetaMethod m = _meta->method(i);
586 QMetaMethod m = _meta->method(i);
587 if ((m.methodType() == QMetaMethod::Method ||
587 if ((m.methodType() == QMetaMethod::Method ||
588 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
588 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
589 PythonQtSlotInfo slot(this, m, i);
589 PythonQtSlotInfo slot(this, m, i);
590 h += slot.fullSignature()+ "\n";
590 h += slot.fullSignature()+ "\n";
591 }
591 }
592 }
592 }
593 }
593 }
594
594
595 // TODO xxx : decorators and enums from decorator() are missing...
595 // TODO xxx : decorators and enums from decorator() are missing...
596 // maybe we can reuse memberlist()?
596 // maybe we can reuse memberlist()?
597
597
598 if (_meta && _meta->enumeratorCount()) {
598 if (_meta && _meta->enumeratorCount()) {
599 h += "Enums:\n";
599 h += "Enums:\n";
600 for (int i = 0; i<_meta->enumeratorCount(); i++) {
600 for (int i = 0; i<_meta->enumeratorCount(); i++) {
601 QMetaEnum e = _meta->enumerator(i);
601 QMetaEnum e = _meta->enumerator(i);
602 h += QString(e.name()) + " {";
602 h += QString(e.name()) + " {";
603 for (int j=0; j < e.keyCount(); j++) {
603 for (int j=0; j < e.keyCount(); j++) {
604 if (j) { h+= ", "; }
604 if (j) { h+= ", "; }
605 h += e.key(j);
605 h += e.key(j);
606 }
606 }
607 h += " }\n";
607 h += " }\n";
608 }
608 }
609 }
609 }
610
610
611 if (_isQObject && _meta) {
611 if (_isQObject && _meta) {
612 int numMethods = _meta->methodCount();
612 int numMethods = _meta->methodCount();
613 if (numMethods>0) {
613 if (numMethods>0) {
614 h += "Signals:\n";
614 h += "Signals:\n";
615 for (int i = 0; i < numMethods; i++) {
615 for (int i = 0; i < numMethods; i++) {
616 QMetaMethod m = _meta->method(i);
616 QMetaMethod m = _meta->method(i);
617 if (m.methodType() == QMetaMethod::Signal) {
617 if (m.methodType() == QMetaMethod::Signal) {
618 h += QString(m.signature()) + "\n";
618 h += QString(m.signature()) + "\n";
619 }
619 }
620 }
620 }
621 }
621 }
622 }
622 }
623 return h;
623 return h;
624 }
624 }
625
625
626 PythonQtSlotInfo* PythonQtClassInfo::constructors()
626 PythonQtSlotInfo* PythonQtClassInfo::constructors()
627 {
627 {
628 if (!_constructors) {
628 if (!_constructors) {
629 // force creation of lazy decorator, which will register the decorators
629 // force creation of lazy decorator, which will register the decorators
630 decorator();
630 decorator();
631 }
631 }
632 return _constructors;
632 return _constructors;
633 }
633 }
634
634
635 PythonQtSlotInfo* PythonQtClassInfo::destructor()
635 PythonQtSlotInfo* PythonQtClassInfo::destructor()
636 {
636 {
637 if (!_destructor) {
637 if (!_destructor) {
638 // force creation of lazy decorator, which will register the decorators
638 // force creation of lazy decorator, which will register the decorators
639 decorator();
639 decorator();
640 }
640 }
641 return _destructor;
641 return _destructor;
642 }
642 }
643
643
644 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
644 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
645 {
645 {
646 PythonQtSlotInfo* prev = constructors();
646 PythonQtSlotInfo* prev = constructors();
647 if (prev) {
647 if (prev) {
648 info->setNextInfo(prev->nextInfo());
648 info->setNextInfo(prev->nextInfo());
649 prev->setNextInfo(info);
649 prev->setNextInfo(info);
650 } else {
650 } else {
651 _constructors = info;
651 _constructors = info;
652 }
652 }
653 }
653 }
654
654
655 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
655 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
656 {
656 {
657 _decoratorSlots.append(info);
657 _decoratorSlots.append(info);
658 }
658 }
659
659
660 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
660 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
661 {
661 {
662 if (_destructor) {
662 if (_destructor) {
663 _destructor->deleteOverloadsAndThis();
663 _destructor->deleteOverloadsAndThis();
664 }
664 }
665 _destructor = info;
665 _destructor = info;
666 }
666 }
667
667
668 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
668 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
669 {
669 {
670 _meta = meta;
670 _meta = meta;
671 clearCachedMembers();
671 clearCachedMembers();
672 }
672 }
673
673
674 QObject* PythonQtClassInfo::decorator()
674 QObject* PythonQtClassInfo::decorator()
675 {
675 {
676 if (!_decoratorProvider && _decoratorProviderCB) {
676 if (!_decoratorProvider && _decoratorProviderCB) {
677 _decoratorProvider = (*_decoratorProviderCB)();
677 _decoratorProvider = (*_decoratorProviderCB)();
678 if (_decoratorProvider) {
678 if (_decoratorProvider) {
679 _decoratorProvider->setParent(PythonQt::priv());
679 _decoratorProvider->setParent(PythonQt::priv());
680 // setup enums early, since they might be needed by the constructor decorators:
680 // setup enums early, since they might be needed by the constructor decorators:
681 if (!_enumsCreated) {
681 if (!_enumsCreated) {
682 createEnumWrappers();
682 createEnumWrappers();
683 }
683 }
684 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
684 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
685 }
685 }
686 }
686 }
687 // check if enums need to be created and create them if they are not yet created
687 // check if enums need to be created and create them if they are not yet created
688 if (!_enumsCreated) {
688 if (!_enumsCreated) {
689 createEnumWrappers();
689 createEnumWrappers();
690 }
690 }
691 return _decoratorProvider;
691 return _decoratorProvider;
692 }
692 }
693
693
694 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
694 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
695 {
695 {
696 PythonQtMemberInfo info = member("hasOwner");
696 PythonQtMemberInfo info = member("hasOwner");
697 if (info._type == PythonQtMemberInfo::Slot) {
697 if (info._type == PythonQtMemberInfo::Slot) {
698 void* obj = object;
698 void* obj = object;
699 bool result = false;
699 bool result = false;
700 void* args[2];
700 void* args[2];
701 args[0] = &result;
701 args[0] = &result;
702 args[1] = &obj;
702 args[1] = &obj;
703 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
703 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
704 return !result;
704 return !result;
705 } else {
705 } else {
706 return false;
706 return false;
707 }
707 }
708 }
708 }
709
709
710 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
710 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
711 {
711 {
712 if (!_polymorphicHandlers.isEmpty()) {
712 if (!_polymorphicHandlers.isEmpty()) {
713 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
713 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
714 void* resultPtr = (*cb)(ptr, resultClassName);
714 void* resultPtr = (*cb)(ptr, resultClassName);
715 if (resultPtr) {
715 if (resultPtr) {
716 return resultPtr;
716 return resultPtr;
717 }
717 }
718 }
718 }
719 }
719 }
720 foreach(const ParentClassInfo& info, _parentClasses) {
720 foreach(const ParentClassInfo& info, _parentClasses) {
721 if (!info._parent->isQObject()) {
721 if (!info._parent->isQObject()) {
722 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
722 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
723 if (resultPtr) {
723 if (resultPtr) {
724 return resultPtr;
724 return resultPtr;
725 }
725 }
726 }
726 }
727 }
727 }
728 return NULL;
728 return NULL;
729 }
729 }
730
730
731 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
731 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
732 {
732 {
733 char* className;
733 char* className;
734 // this would do downcasting recursively...
734 // this would do downcasting recursively...
735 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
735 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
736
736
737 // we only do downcasting on the base object, not on the whole inheritance tree...
737 // we only do downcasting on the base object, not on the whole inheritance tree...
738 void* resultPtr = NULL;
738 void* resultPtr = NULL;
739 if (!_polymorphicHandlers.isEmpty()) {
739 if (!_polymorphicHandlers.isEmpty()) {
740 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
740 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
741 resultPtr = (*cb)(ptr, &className);
741 resultPtr = (*cb)(ptr, &className);
742 if (resultPtr) {
742 if (resultPtr) {
743 break;
743 break;
744 }
744 }
745 }
745 }
746 }
746 }
747 if (resultPtr) {
747 if (resultPtr) {
748 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
748 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
749 } else {
749 } else {
750 *resultClassInfo = this;
750 *resultClassInfo = this;
751 resultPtr = ptr;
751 resultPtr = ptr;
752 }
752 }
753 return resultPtr;
753 return resultPtr;
754 }
754 }
755
755
756 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool& isLocalEnum)
756 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
757 {
757 {
758 isLocalEnum = true;
758 if (isLocalEnum) {
759 *isLocalEnum = true;
760 }
759 int scopePos = name.lastIndexOf("::");
761 int scopePos = name.lastIndexOf("::");
760 if (scopePos != -1) {
762 if (scopePos != -1) {
761 isLocalEnum = false;
763 if (isLocalEnum) {
762 // slit into scope and enum name
764 *isLocalEnum = false;
765 }
766 // split into scope and enum name
763 QByteArray enumScope = name.mid(0,scopePos);
767 QByteArray enumScope = name.mid(0,scopePos);
764 QByteArray enumName = name.mid(scopePos+2);
768 QByteArray enumName = name.mid(scopePos+2);
765 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
769 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
766 if (info) {
770 if (info) {
767 return info->findEnumWrapper(enumName);
771 return info->findEnumWrapper(enumName);
768 } else{
772 } else{
769 return NULL;
773 return NULL;
770 }
774 }
771 }
775 }
772 if (localScope) {
776 if (localScope) {
773 return localScope->findEnumWrapper(name);
777 return localScope->findEnumWrapper(name);
774 } else {
778 } else {
775 return NULL;
779 return NULL;
776 }
780 }
777 }
781 }
778
782
779 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
783 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
780 {
784 {
781 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
785 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
782 QMetaEnum e = meta->enumerator(i);
786 QMetaEnum e = meta->enumerator(i);
783 PythonQtObjectPtr p;
787 PythonQtObjectPtr p;
784 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
788 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
785 _enumWrappers.append(p);
789 _enumWrappers.append(p);
786 }
790 }
787 }
791 }
788
792
789 void PythonQtClassInfo::createEnumWrappers()
793 void PythonQtClassInfo::createEnumWrappers()
790 {
794 {
791 if (!_enumsCreated) {
795 if (!_enumsCreated) {
792 _enumsCreated = true;
796 _enumsCreated = true;
793 if (_meta) {
797 if (_meta) {
794 createEnumWrappers(_meta);
798 createEnumWrappers(_meta);
795 }
799 }
796 if (decorator()) {
800 if (decorator()) {
797 createEnumWrappers(decorator()->metaObject());
801 createEnumWrappers(decorator()->metaObject());
798 }
802 }
799 foreach(const ParentClassInfo& info, _parentClasses) {
803 foreach(const ParentClassInfo& info, _parentClasses) {
800 info._parent->createEnumWrappers();
804 info._parent->createEnumWrappers();
801 }
805 }
802 }
806 }
803 }
807 }
804
808
805 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
809 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
806 // force enum creation
810 // force enum creation
807 if (!_enumsCreated) {
811 if (!_enumsCreated) {
808 createEnumWrappers();
812 createEnumWrappers();
809 }
813 }
810 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
814 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
811 const char* className = ((PyTypeObject*)p.object())->tp_name;
815 const char* className = ((PyTypeObject*)p.object())->tp_name;
812 if (qstrcmp(className, name)==0) {
816 if (qstrcmp(className, name)==0) {
813 return p.object();
817 return p.object();
814 }
818 }
815 }
819 }
816 foreach(const ParentClassInfo& info, _parentClasses) {
820 foreach(const ParentClassInfo& info, _parentClasses) {
817 PyObject* p = info._parent->findEnumWrapper(name);
821 PyObject* p = info._parent->findEnumWrapper(name);
818 if (p) return p;
822 if (p) return p;
819 }
823 }
820 return NULL;
824 return NULL;
821 }
825 }
822
826
@@ -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 "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);
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,1131 +1,1213
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 PythonQtConversion.cpp
35 // \file PythonQtConversion.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 "PythonQtConversion.h"
42 #include "PythonQtConversion.h"
43 #include "PythonQtVariants.h"
43 #include "PythonQtVariants.h"
44 #include <QDateTime>
44 #include <QDateTime>
45 #include <QTime>
45 #include <QTime>
46 #include <QDate>
46 #include <QDate>
47
47
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
51
51
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
54
54
55 PyObject* PythonQtConv::GetPyBool(bool val)
55 PyObject* PythonQtConv::GetPyBool(bool val)
56 {
56 {
57 PyObject* r = val?Py_True:Py_False;
57 PyObject* r = val?Py_True:Py_False;
58 Py_INCREF(r);
58 Py_INCREF(r);
59 return r;
59 return r;
60 }
60 }
61
61
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
63 // is it an enum value?
63 // is it an enum value?
64 if (info.enumWrapper) {
64 if (info.enumWrapper) {
65 if (!info.isPointer) {
65 if (!info.isPointer) {
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
67 } else {
67 } else {
68 // we do not support pointers to enums (who needs them?)
68 // we do not support pointers to enums (who needs them?)
69 Py_INCREF(Py_None);
69 Py_INCREF(Py_None);
70 return Py_None;
70 return Py_None;
71 }
71 }
72 }
72 }
73
73
74 if (info.typeId == QMetaType::Void) {
74 if (info.typeId == QMetaType::Void) {
75 Py_INCREF(Py_None);
75 Py_INCREF(Py_None);
76 return Py_None;
76 return Py_None;
77 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
77 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
78 // a char ptr will probably be a null terminated string, so we support that:
78 // a char ptr will probably be a null terminated string, so we support that:
79 return PyString_FromString(*((char**)data));
79 return PyString_FromString(*((char**)data));
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
81 info.name.startsWith("QList<")) {
81 info.name.startsWith("QList<")) {
82 // it is a QList template:
82 // it is a QList template:
83 // (TODO: check what happens if this is a pointer type?!)
83 // (TODO: check what happens if this is a pointer type?!)
84 QByteArray innerType = info.name.mid(6,info.name.length()-7);
84 QByteArray innerType = info.name.mid(6,info.name.length()-7);
85 if (innerType.endsWith("*")) {
85 if (innerType.endsWith("*")) {
86 innerType.truncate(innerType.length()-1);
86 innerType.truncate(innerType.length()-1);
87 return ConvertQListOfPointerTypeToPythonList((QList<void*>*)data, innerType);
87 return ConvertQListOfPointerTypeToPythonList((QList<void*>*)data, innerType);
88 }
88 }
89 }
89 }
90
90
91 if (info.typeId >= QMetaType::User) {
91 if (info.typeId >= QMetaType::User) {
92 // if a converter is registered, we use is:
92 // if a converter is registered, we use is:
93 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
93 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
94 if (converter) {
94 if (converter) {
95 return (*converter)(data, info.typeId);
95 return (*converter)(data, info.typeId);
96 }
96 }
97 }
97 }
98
98
99 // special handling did not match, so we convert the usual way (either pointer or value version):
99 // special handling did not match, so we convert the usual way (either pointer or value version):
100 if (info.isPointer) {
100 if (info.isPointer) {
101 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
101 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
102 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
102 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
103 } else {
103 } else {
104 // handle values that are not yet handled and not pointers
104 // handle values that are not yet handled and not pointers
105 return ConvertQtValueToPythonInternal(info.typeId, data);
105 return ConvertQtValueToPythonInternal(info.typeId, data);
106 }
106 }
107 }
107 }
108
108
109 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
109 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
110 switch (type) {
110 switch (type) {
111 case QMetaType::Void:
111 case QMetaType::Void:
112 Py_INCREF(Py_None);
112 Py_INCREF(Py_None);
113 return Py_None;
113 return Py_None;
114 case QMetaType::Char:
114 case QMetaType::Char:
115 return PyInt_FromLong(*((char*)data));
115 return PyInt_FromLong(*((char*)data));
116 case QMetaType::UChar:
116 case QMetaType::UChar:
117 return PyInt_FromLong(*((unsigned char*)data));
117 return PyInt_FromLong(*((unsigned char*)data));
118 case QMetaType::Short:
118 case QMetaType::Short:
119 return PyInt_FromLong(*((short*)data));
119 return PyInt_FromLong(*((short*)data));
120 case QMetaType::UShort:
120 case QMetaType::UShort:
121 return PyInt_FromLong(*((unsigned short*)data));
121 return PyInt_FromLong(*((unsigned short*)data));
122 case QMetaType::Long:
122 case QMetaType::Long:
123 return PyInt_FromLong(*((long*)data));
123 return PyInt_FromLong(*((long*)data));
124 case QMetaType::ULong:
124 case QMetaType::ULong:
125 // does not fit into simple int of python
125 // does not fit into simple int of python
126 return PyLong_FromUnsignedLong(*((unsigned long*)data));
126 return PyLong_FromUnsignedLong(*((unsigned long*)data));
127 case QMetaType::Bool:
127 case QMetaType::Bool:
128 return PythonQtConv::GetPyBool(*((bool*)data));
128 return PythonQtConv::GetPyBool(*((bool*)data));
129 case QMetaType::Int:
129 case QMetaType::Int:
130 return PyInt_FromLong(*((int*)data));
130 return PyInt_FromLong(*((int*)data));
131 case QMetaType::UInt:
131 case QMetaType::UInt:
132 return PyInt_FromLong(*((unsigned int*)data));
132 return PyInt_FromLong(*((unsigned int*)data));
133 case QMetaType::QChar:
133 case QMetaType::QChar:
134 return PyInt_FromLong(*((short*)data));
134 return PyInt_FromLong(*((short*)data));
135 case QMetaType::Float:
135 case QMetaType::Float:
136 return PyFloat_FromDouble(*((float*)data));
136 return PyFloat_FromDouble(*((float*)data));
137 case QMetaType::Double:
137 case QMetaType::Double:
138 return PyFloat_FromDouble(*((double*)data));
138 return PyFloat_FromDouble(*((double*)data));
139 case QMetaType::LongLong:
139 case QMetaType::LongLong:
140 return PyLong_FromLongLong(*((qint64*)data));
140 return PyLong_FromLongLong(*((qint64*)data));
141 case QMetaType::ULongLong:
141 case QMetaType::ULongLong:
142 return PyLong_FromUnsignedLongLong(*((quint64*)data));
142 return PyLong_FromUnsignedLongLong(*((quint64*)data));
143 case QMetaType::QByteArray: {
143 case QMetaType::QByteArray: {
144 QByteArray* v = (QByteArray*) data;
144 QByteArray* v = (QByteArray*) data;
145 return PyString_FromStringAndSize(*v, v->size());
145 return PyString_FromStringAndSize(*v, v->size());
146 }
146 }
147 case QMetaType::QVariantMap:
147 case QMetaType::QVariantMap:
148 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
148 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
149 case QMetaType::QVariantList:
149 case QMetaType::QVariantList:
150 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
150 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
151 case QMetaType::QString:
151 case QMetaType::QString:
152 return PythonQtConv::QStringToPyObject(*((QString*)data));
152 return PythonQtConv::QStringToPyObject(*((QString*)data));
153 case QMetaType::QStringList:
153 case QMetaType::QStringList:
154 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
154 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
155
155
156 case PythonQtMethodInfo::Variant:
156 case PythonQtMethodInfo::Variant:
157 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
157 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
158 case QMetaType::QObjectStar:
158 case QMetaType::QObjectStar:
159 case QMetaType::QWidgetStar:
159 case QMetaType::QWidgetStar:
160 return PythonQt::priv()->wrapQObject(*((QObject**)data));
160 return PythonQt::priv()->wrapQObject(*((QObject**)data));
161
161
162 default:
162 default:
163 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
163 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
164 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
164 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
165 PyObject* o = ((PythonQtObjectPtr*)data)->object();
165 PyObject* o = ((PythonQtObjectPtr*)data)->object();
166 Py_INCREF(o);
166 Py_INCREF(o);
167 return o;
167 return o;
168 } else {
168 } else {
169 if (type > 0) {
169 if (type > 0) {
170 // if the type is known, we can construct it via QMetaType::construct
170 // if the type is known, we can construct it via QMetaType::construct
171 void* newCPPObject = QMetaType::construct(type, data);
171 void* newCPPObject = QMetaType::construct(type, data);
172 // XXX this could be optimized by using metatypeid directly
172 // XXX this could be optimized by using metatypeid directly
173 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
173 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
174 wrap->_ownedByPythonQt = true;
174 wrap->_ownedByPythonQt = true;
175 wrap->_useQMetaTypeDestroy = true;
175 wrap->_useQMetaTypeDestroy = true;
176 return (PyObject*)wrap;
176 return (PyObject*)wrap;
177 }
177 }
178 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
178 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
179 }
179 }
180 }
180 }
181 Py_INCREF(Py_None);
181 Py_INCREF(Py_None);
182 return Py_None;
182 return Py_None;
183 }
183 }
184
184
185 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
185 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
186 void* ptr = NULL;
186 void* ptr = NULL;
187 if (info.isPointer) {
187 if (info.isPointer) {
188 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
188 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
189 } else if (info.enumWrapper) {
189 } else if (info.enumWrapper) {
190 // create enum return value
190 // create enum return value
191 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
191 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
192 } else {
192 } else {
193 switch (info.typeId) {
193 switch (info.typeId) {
194 case QMetaType::Char:
194 case QMetaType::Char:
195 case QMetaType::UChar:
195 case QMetaType::UChar:
196 case QMetaType::Short:
196 case QMetaType::Short:
197 case QMetaType::UShort:
197 case QMetaType::UShort:
198 case QMetaType::Long:
198 case QMetaType::Long:
199 case QMetaType::ULong:
199 case QMetaType::ULong:
200 case QMetaType::Bool:
200 case QMetaType::Bool:
201 case QMetaType::Int:
201 case QMetaType::Int:
202 case QMetaType::UInt:
202 case QMetaType::UInt:
203 case QMetaType::QChar:
203 case QMetaType::QChar:
204 case QMetaType::Float:
204 case QMetaType::Float:
205 case QMetaType::Double:
205 case QMetaType::Double:
206 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
206 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
207 break;
207 break;
208 case PythonQtMethodInfo::Variant:
208 case PythonQtMethodInfo::Variant:
209 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
209 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
210 // return the ptr to the variant
210 // return the ptr to the variant
211 break;
211 break;
212 default:
212 default:
213 if (info.typeId == PythonQtMethodInfo::Unknown) {
213 if (info.typeId == PythonQtMethodInfo::Unknown) {
214 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
214 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
215 if (info.name.startsWith("QList<")) {
215 if (info.name.startsWith("QList<")) {
216 QByteArray innerType = info.name.mid(6,info.name.length()-7);
216 QByteArray innerType = info.name.mid(6,info.name.length()-7);
217 if (innerType.endsWith("*")) {
217 if (innerType.endsWith("*")) {
218 static int id = QMetaType::type("QList<void*>");
218 static int id = QMetaType::type("QList<void*>");
219 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
219 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
220 // return the constData pointer that will be filled with the result value later on
220 // return the constData pointer that will be filled with the result value later on
221 ptr = (void*)((QVariant*)ptr)->constData();
221 ptr = (void*)((QVariant*)ptr)->constData();
222 }
222 }
223 }
223 }
224 }
224 }
225
225
226 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
226 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
227 // everything else is stored in a QVariant, if we know the meta type...
227 // everything else is stored in a QVariant, if we know the meta type...
228 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
228 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
229 // return the constData pointer that will be filled with the result value later on
229 // return the constData pointer that will be filled with the result value later on
230 ptr = (void*)((QVariant*)ptr)->constData();
230 ptr = (void*)((QVariant*)ptr)->constData();
231 }
231 }
232 }
232 }
233 }
233 }
234 return ptr;
234 return ptr;
235 }
235 }
236
236
237 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
237 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
238 {
238 {
239 void* object;
239 void* object;
240 if (wrapper->classInfo()->isCPPWrapper()) {
240 if (wrapper->classInfo()->isCPPWrapper()) {
241 object = wrapper->_wrappedPtr;
241 object = wrapper->_wrappedPtr;
242 } else {
242 } else {
243 QObject* tmp = wrapper->_obj;
243 QObject* tmp = wrapper->_obj;
244 object = tmp;
244 object = tmp;
245 }
245 }
246 if (object) {
246 if (object) {
247 // if we can be upcasted to the given name, we pass the casted pointer in:
247 // if we can be upcasted to the given name, we pass the casted pointer in:
248 object = wrapper->classInfo()->castTo(object, className);
248 object = wrapper->classInfo()->castTo(object, className);
249 ok = object!=NULL;
249 ok = object!=NULL;
250 } else {
250 } else {
251 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
251 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
252 ok = wrapper->classInfo()->inherits(className);
252 ok = wrapper->classInfo()->inherits(className);
253 }
253 }
254 return object;
254 return object;
255 }
255 }
256
256
257 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
258 {
259 void* ptr = alreadyAllocatedCPPObject;
260
261 static int penId = QMetaType::type("QPen");
262 static int brushId = QMetaType::type("QBrush");
263 static int cursorId = QMetaType::type("QCursor");
264 static int colorId = QMetaType::type("QColor");
265 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
266 if (typeId == cursorId) {
267 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
268 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
269 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
270 if (!ptr) {
271 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
272 ptr = (void*)((QVariant*)ptr)->constData();
273 }
274 *((QCursor*)ptr) = QCursor(val);
275 return ptr;
276 }
277 } else if (typeId == penId) {
278 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
279 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
280 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
281 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
282 if (!ptr) {
283 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
284 ptr = (void*)((QVariant*)ptr)->constData();
285 }
286 *((QPen*)ptr) = QPen(QColor(val));
287 return ptr;
288 } else if ((PyObject*)obj->ob_type == qtColorClass) {
289 if (!ptr) {
290 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
291 ptr = (void*)((QVariant*)ptr)->constData();
292 }
293 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
294 return ptr;
295 }
296 } else if (typeId == brushId) {
297 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
298 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
299 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
300 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
301 if (!ptr) {
302 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
303 ptr = (void*)((QVariant*)ptr)->constData();
304 }
305 *((QBrush*)ptr) = QBrush(QColor(val));
306 return ptr;
307 } else if ((PyObject*)obj->ob_type == qtColorClass) {
308 if (!ptr) {
309 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
310 ptr = (void*)((QVariant*)ptr)->constData();
311 }
312 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
313 return ptr;
314 }
315 } else if (typeId == colorId) {
316 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
317 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
318 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
319 if (!ptr) {
320 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
321 ptr = (void*)((QVariant*)ptr)->constData();
322 }
323 *((QColor*)ptr) = QColor(val);
324 return ptr;
325 }
326 }
327 return NULL;
328 }
329
257 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
330 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
258 {
331 {
259 bool ok = false;
332 bool ok = false;
260 void* ptr = NULL;
333 void* ptr = NULL;
334
335 // autoconversion of QPen/QBrush/QCursor/QColor from different type
336 if (!info.isPointer && !strict) {
337 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
338 if (ptr) {
339 return ptr;
340 }
341 }
342
261 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
343 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
262 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
344 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
263 // (the Variant case is handled below in a switch)
345 // (the Variant case is handled below in a switch)
264
346
265 // a C++ wrapper (can be passed as pointer or reference)
347 // a C++ wrapper (can be passed as pointer or reference)
266 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
348 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
267 void* object = castWrapperTo(wrap, info.name, ok);
349 void* object = castWrapperTo(wrap, info.name, ok);
268 if (ok) {
350 if (ok) {
269 if (info.isPointer) {
351 if (info.isPointer) {
270 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
352 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
271 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
353 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
272 } else {
354 } else {
273 // store the wrapped pointer directly, since we are a reference
355 // store the wrapped pointer directly, since we are a reference
274 ptr = object;
356 ptr = object;
275 }
357 }
276 } else {
358 } else {
277 // not matching
359 // not matching
278 }
360 }
279 } else if (info.isPointer) {
361 } else if (info.isPointer) {
280 // a pointer
362 // a pointer
281 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
363 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
282 {
364 {
283 QString str = PyObjGetString(obj, strict, ok);
365 QString str = PyObjGetString(obj, strict, ok);
284 if (ok) {
366 if (ok) {
285 void* ptr2 = NULL;
367 void* ptr2 = NULL;
286 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
368 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
287 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
369 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
288 }
370 }
289 } else if (info.name == "PyObject") {
371 } else if (info.name == "PyObject") {
290 // handle low level PyObject directly
372 // handle low level PyObject directly
291 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
373 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
292 } else if (obj == Py_None) {
374 } else if (obj == Py_None) {
293 // None is treated as a NULL ptr
375 // None is treated as a NULL ptr
294 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
376 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
295 } else {
377 } else {
296 // if we are not strict, we try if we are passed a 0 integer
378 // if we are not strict, we try if we are passed a 0 integer
297 if (!strict) {
379 if (!strict) {
298 bool ok;
380 bool ok;
299 int value = PyObjGetInt(obj, true, ok);
381 int value = PyObjGetInt(obj, true, ok);
300 if (ok && value==0) {
382 if (ok && value==0) {
301 // TODOXXX is this wise? or should it be expected from the programmer to use None?
383 // TODOXXX is this wise? or should it be expected from the programmer to use None?
302 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
384 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
303 }
385 }
304 }
386 }
305 }
387 }
306 } else {
388 } else {
307 // not a pointer
389 // not a pointer
308 switch (info.typeId) {
390 switch (info.typeId) {
309 case QMetaType::Char:
391 case QMetaType::Char:
310 {
392 {
311 int val = PyObjGetInt(obj, strict, ok);
393 int val = PyObjGetInt(obj, strict, ok);
312 if (ok) {
394 if (ok) {
313 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
395 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
314 }
396 }
315 }
397 }
316 break;
398 break;
317 case QMetaType::UChar:
399 case QMetaType::UChar:
318 {
400 {
319 int val = PyObjGetInt(obj, strict, ok);
401 int val = PyObjGetInt(obj, strict, ok);
320 if (ok) {
402 if (ok) {
321 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
403 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
322 }
404 }
323 }
405 }
324 break;
406 break;
325 case QMetaType::Short:
407 case QMetaType::Short:
326 {
408 {
327 int val = PyObjGetInt(obj, strict, ok);
409 int val = PyObjGetInt(obj, strict, ok);
328 if (ok) {
410 if (ok) {
329 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
411 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
330 }
412 }
331 }
413 }
332 break;
414 break;
333 case QMetaType::UShort:
415 case QMetaType::UShort:
334 {
416 {
335 int val = PyObjGetInt(obj, strict, ok);
417 int val = PyObjGetInt(obj, strict, ok);
336 if (ok) {
418 if (ok) {
337 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
419 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
338 }
420 }
339 }
421 }
340 break;
422 break;
341 case QMetaType::Long:
423 case QMetaType::Long:
342 {
424 {
343 long val = (long)PyObjGetLongLong(obj, strict, ok);
425 long val = (long)PyObjGetLongLong(obj, strict, ok);
344 if (ok) {
426 if (ok) {
345 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
427 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
346 }
428 }
347 }
429 }
348 break;
430 break;
349 case QMetaType::ULong:
431 case QMetaType::ULong:
350 {
432 {
351 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
433 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
352 if (ok) {
434 if (ok) {
353 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
435 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
354 }
436 }
355 }
437 }
356 break;
438 break;
357 case QMetaType::Bool:
439 case QMetaType::Bool:
358 {
440 {
359 bool val = PyObjGetBool(obj, strict, ok);
441 bool val = PyObjGetBool(obj, strict, ok);
360 if (ok) {
442 if (ok) {
361 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
443 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
362 }
444 }
363 }
445 }
364 break;
446 break;
365 case QMetaType::Int:
447 case QMetaType::Int:
366 {
448 {
367 int val = PyObjGetInt(obj, strict, ok);
449 int val = PyObjGetInt(obj, strict, ok);
368 if (ok) {
450 if (ok) {
369 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
451 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
370 }
452 }
371 }
453 }
372 break;
454 break;
373 case QMetaType::UInt:
455 case QMetaType::UInt:
374 {
456 {
375 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
457 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
376 if (ok) {
458 if (ok) {
377 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
459 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
378 }
460 }
379 }
461 }
380 break;
462 break;
381 case QMetaType::QChar:
463 case QMetaType::QChar:
382 {
464 {
383 int val = PyObjGetInt(obj, strict, ok);
465 int val = PyObjGetInt(obj, strict, ok);
384 if (ok) {
466 if (ok) {
385 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
467 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
386 }
468 }
387 }
469 }
388 break;
470 break;
389 case QMetaType::Float:
471 case QMetaType::Float:
390 {
472 {
391 float val = (float)PyObjGetDouble(obj, strict, ok);
473 float val = (float)PyObjGetDouble(obj, strict, ok);
392 if (ok) {
474 if (ok) {
393 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
475 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
394 }
476 }
395 }
477 }
396 break;
478 break;
397 case QMetaType::Double:
479 case QMetaType::Double:
398 {
480 {
399 double val = (double)PyObjGetDouble(obj, strict, ok);
481 double val = (double)PyObjGetDouble(obj, strict, ok);
400 if (ok) {
482 if (ok) {
401 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
483 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
402 }
484 }
403 }
485 }
404 break;
486 break;
405 case QMetaType::LongLong:
487 case QMetaType::LongLong:
406 {
488 {
407 qint64 val = PyObjGetLongLong(obj, strict, ok);
489 qint64 val = PyObjGetLongLong(obj, strict, ok);
408 if (ok) {
490 if (ok) {
409 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
491 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
410 }
492 }
411 }
493 }
412 break;
494 break;
413 case QMetaType::ULongLong:
495 case QMetaType::ULongLong:
414 {
496 {
415 quint64 val = PyObjGetULongLong(obj, strict, ok);
497 quint64 val = PyObjGetULongLong(obj, strict, ok);
416 if (ok) {
498 if (ok) {
417 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
499 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
418 }
500 }
419 }
501 }
420 break;
502 break;
421 case QMetaType::QByteArray:
503 case QMetaType::QByteArray:
422 {
504 {
423 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
505 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
424 if (ok) {
506 if (ok) {
425 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
507 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
426 ptr = (void*)((QVariant*)ptr)->constData();
508 ptr = (void*)((QVariant*)ptr)->constData();
427 }
509 }
428 }
510 }
429 break;
511 break;
430 case QMetaType::QString:
512 case QMetaType::QString:
431 {
513 {
432 QString str = PyObjGetString(obj, strict, ok);
514 QString str = PyObjGetString(obj, strict, ok);
433 if (ok) {
515 if (ok) {
434 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
516 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
435 ptr = (void*)((QVariant*)ptr)->constData();
517 ptr = (void*)((QVariant*)ptr)->constData();
436 }
518 }
437 }
519 }
438 break;
520 break;
439 case QMetaType::QStringList:
521 case QMetaType::QStringList:
440 {
522 {
441 QStringList l = PyObjToStringList(obj, strict, ok);
523 QStringList l = PyObjToStringList(obj, strict, ok);
442 if (ok) {
524 if (ok) {
443 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
525 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
444 ptr = (void*)((QVariant*)ptr)->constData();
526 ptr = (void*)((QVariant*)ptr)->constData();
445 }
527 }
446 }
528 }
447 break;
529 break;
448
530
449 case PythonQtMethodInfo::Variant:
531 case PythonQtMethodInfo::Variant:
450 {
532 {
451 QVariant v = PyObjToQVariant(obj);
533 QVariant v = PyObjToQVariant(obj);
452 if (v.isValid()) {
534 if (v.isValid()) {
453 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
535 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
454 }
536 }
455 }
537 }
456 break;
538 break;
457 default:
539 default:
458 {
540 {
459 // check for enum case
541 // check for enum case
460 if (info.enumWrapper) {
542 if (info.enumWrapper) {
461 unsigned int val;
543 unsigned int val;
462 ok = false;
544 ok = false;
463 if ((PyObject*)obj->ob_type == info.enumWrapper) {
545 if ((PyObject*)obj->ob_type == info.enumWrapper) {
464 // we have a exact enum type match:
546 // we have a exact enum type match:
465 val = PyInt_AS_LONG(obj);
547 val = PyInt_AS_LONG(obj);
466 ok = true;
548 ok = true;
467 } else if (!strict) {
549 } else if (!strict) {
468 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
550 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
469 // we want an integer overload to be taken first!
551 // we want an integer overload to be taken first!
470 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
552 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
471 }
553 }
472 if (ok) {
554 if (ok) {
473 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
555 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
474 return ptr;
556 return ptr;
475 } else {
557 } else {
476 return NULL;
558 return NULL;
477 }
559 }
478 }
560 }
479
561
480 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
562 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
481 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
563 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
482 if (info.name.startsWith("QList<")) {
564 if (info.name.startsWith("QList<")) {
483 QByteArray innerType = info.name.mid(6,info.name.length()-7);
565 QByteArray innerType = info.name.mid(6,info.name.length()-7);
484 if (innerType.endsWith("*")) {
566 if (innerType.endsWith("*")) {
485 innerType.truncate(innerType.length()-1);
567 innerType.truncate(innerType.length()-1);
486 static int id = QMetaType::type("QList<void*>");
568 static int id = QMetaType::type("QList<void*>");
487 if (!alreadyAllocatedCPPObject) {
569 if (!alreadyAllocatedCPPObject) {
488 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
570 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
489 ptr = (void*)((QVariant*)ptr)->constData();
571 ptr = (void*)((QVariant*)ptr)->constData();
490 } else {
572 } else {
491 ptr = alreadyAllocatedCPPObject;
573 ptr = alreadyAllocatedCPPObject;
492 }
574 }
493 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
575 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
494 if (ok) {
576 if (ok) {
495 return ptr;
577 return ptr;
496 } else {
578 } else {
497 return NULL;
579 return NULL;
498 }
580 }
499 }
581 }
500 }
582 }
501 }
583 }
502
584
503 // We only do this for registered type > QMetaType::User for performance reasons.
585 // We only do this for registered type > QMetaType::User for performance reasons.
504 if (info.typeId >= QMetaType::User) {
586 if (info.typeId >= QMetaType::User) {
505 // Maybe we have a special converter that is registered for that type:
587 // Maybe we have a special converter that is registered for that type:
506 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
588 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
507 if (converter) {
589 if (converter) {
508 if (!alreadyAllocatedCPPObject) {
590 if (!alreadyAllocatedCPPObject) {
509 // create a new empty variant of concrete type:
591 // create a new empty variant of concrete type:
510 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
592 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
511 ptr = (void*)((QVariant*)ptr)->constData();
593 ptr = (void*)((QVariant*)ptr)->constData();
512 } else {
594 } else {
513 ptr = alreadyAllocatedCPPObject;
595 ptr = alreadyAllocatedCPPObject;
514 }
596 }
515 // now call the converter, passing the internal object of the variant
597 // now call the converter, passing the internal object of the variant
516 ok = (*converter)(obj, ptr, info.typeId, strict);
598 ok = (*converter)(obj, ptr, info.typeId, strict);
517 if (ok) {
599 if (ok) {
518 return ptr;
600 return ptr;
519 } else {
601 } else {
520 return NULL;
602 return NULL;
521 }
603 }
522 }
604 }
523 }
605 }
524 // if no type id is available, conversion to a QVariant makes no sense/is not possible
606 // if no type id is available, conversion to a QVariant makes no sense/is not possible
525 if (info.typeId != PythonQtMethodInfo::Unknown) {
607 if (info.typeId != PythonQtMethodInfo::Unknown) {
526 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
608 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
527 QVariant v = PyObjToQVariant(obj, info.typeId);
609 QVariant v = PyObjToQVariant(obj, info.typeId);
528 if (v.isValid()) {
610 if (v.isValid()) {
529 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
611 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
530 ptr = (void*)((QVariant*)ptr)->constData();
612 ptr = (void*)((QVariant*)ptr)->constData();
531 }
613 }
532 }
614 }
533 }
615 }
534 }
616 }
535 }
617 }
536 return ptr;
618 return ptr;
537 }
619 }
538
620
539
621
540 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
622 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
541 QStringList v;
623 QStringList v;
542 ok = false;
624 ok = false;
543 // if we are strict, we do not want to convert a string to a stringlist
625 // if we are strict, we do not want to convert a string to a stringlist
544 // (strings in python are detected to be sequences)
626 // (strings in python are detected to be sequences)
545 if (strict &&
627 if (strict &&
546 (val->ob_type == &PyString_Type ||
628 (val->ob_type == &PyString_Type ||
547 PyUnicode_Check(val))) {
629 PyUnicode_Check(val))) {
548 ok = false;
630 ok = false;
549 return v;
631 return v;
550 }
632 }
551 if (PySequence_Check(val)) {
633 if (PySequence_Check(val)) {
552 int count = PySequence_Size(val);
634 int count = PySequence_Size(val);
553 for (int i = 0;i<count;i++) {
635 for (int i = 0;i<count;i++) {
554 PyObject* value = PySequence_GetItem(val,i);
636 PyObject* value = PySequence_GetItem(val,i);
555 v.append(PyObjGetString(value,false,ok));
637 v.append(PyObjGetString(value,false,ok));
556 }
638 }
557 ok = true;
639 ok = true;
558 }
640 }
559 return v;
641 return v;
560 }
642 }
561
643
562 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
644 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
563 {
645 {
564 QString r;
646 QString r;
565 PyObject* str = PyObject_Repr(val);
647 PyObject* str = PyObject_Repr(val);
566 if (str) {
648 if (str) {
567 r = QString(PyString_AS_STRING(str));
649 r = QString(PyString_AS_STRING(str));
568 Py_DECREF(str);
650 Py_DECREF(str);
569 }
651 }
570 return r;
652 return r;
571 }
653 }
572
654
573 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
655 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
574 QString r;
656 QString r;
575 ok = true;
657 ok = true;
576 if (val->ob_type == &PyString_Type) {
658 if (val->ob_type == &PyString_Type) {
577 r = QString(PyString_AS_STRING(val));
659 r = QString(PyString_AS_STRING(val));
578 } else if (PyUnicode_Check(val)) {
660 } else if (PyUnicode_Check(val)) {
579 #ifdef WIN32
661 #ifdef WIN32
580 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
662 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
581 #else
663 #else
582 PyObject *ptmp = PyUnicode_AsUTF8String(val);
664 PyObject *ptmp = PyUnicode_AsUTF8String(val);
583 if(ptmp) {
665 if(ptmp) {
584 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
666 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
585 Py_DECREF(ptmp);
667 Py_DECREF(ptmp);
586 }
668 }
587 #endif
669 #endif
588 } else if (!strict) {
670 } else if (!strict) {
589 // EXTRA: could also use _Unicode, but why should we?
671 // EXTRA: could also use _Unicode, but why should we?
590 PyObject* str = PyObject_Str(val);
672 PyObject* str = PyObject_Str(val);
591 if (str) {
673 if (str) {
592 r = QString(PyString_AS_STRING(str));
674 r = QString(PyString_AS_STRING(str));
593 Py_DECREF(str);
675 Py_DECREF(str);
594 } else {
676 } else {
595 ok = false;
677 ok = false;
596 }
678 }
597 } else {
679 } else {
598 ok = false;
680 ok = false;
599 }
681 }
600 return r;
682 return r;
601 }
683 }
602
684
603 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
685 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
604 QByteArray r;
686 QByteArray r;
605 ok = true;
687 ok = true;
606 if (val->ob_type == &PyString_Type) {
688 if (val->ob_type == &PyString_Type) {
607 long size = PyString_GET_SIZE(val);
689 long size = PyString_GET_SIZE(val);
608 r = QByteArray(PyString_AS_STRING(val), size);
690 r = QByteArray(PyString_AS_STRING(val), size);
609 } else {
691 } else {
610 ok = false;
692 ok = false;
611 }
693 }
612 return r;
694 return r;
613 }
695 }
614
696
615 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
697 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
616 bool d = false;
698 bool d = false;
617 ok = false;
699 ok = false;
618 if (val == Py_False) {
700 if (val == Py_False) {
619 d = false;
701 d = false;
620 ok = true;
702 ok = true;
621 } else if (val == Py_True) {
703 } else if (val == Py_True) {
622 d = true;
704 d = true;
623 ok = true;
705 ok = true;
624 } else if (!strict) {
706 } else if (!strict) {
625 d = PyObjGetInt(val, false, ok)!=0;
707 d = PyObjGetInt(val, false, ok)!=0;
626 ok = true;
708 ok = true;
627 }
709 }
628 return d;
710 return d;
629 }
711 }
630
712
631 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
713 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
632 int d = 0;
714 int d = 0;
633 ok = true;
715 ok = true;
634 if (val->ob_type == &PyInt_Type) {
716 if (val->ob_type == &PyInt_Type) {
635 d = PyInt_AS_LONG(val);
717 d = PyInt_AS_LONG(val);
636 } else if (!strict) {
718 } else if (!strict) {
637 if (PyObject_TypeCheck(val, &PyInt_Type)) {
719 if (PyObject_TypeCheck(val, &PyInt_Type)) {
638 // support for derived int classes, e.g. for our enums
720 // support for derived int classes, e.g. for our enums
639 d = PyInt_AS_LONG(val);
721 d = PyInt_AS_LONG(val);
640 } else if (val->ob_type == &PyFloat_Type) {
722 } else if (val->ob_type == &PyFloat_Type) {
641 d = floor(PyFloat_AS_DOUBLE(val));
723 d = floor(PyFloat_AS_DOUBLE(val));
642 } else if (val->ob_type == &PyLong_Type) {
724 } else if (val->ob_type == &PyLong_Type) {
643 // handle error on overflow!
725 // handle error on overflow!
644 d = PyLong_AsLong(val);
726 d = PyLong_AsLong(val);
645 } else if (val == Py_False) {
727 } else if (val == Py_False) {
646 d = 0;
728 d = 0;
647 } else if (val == Py_True) {
729 } else if (val == Py_True) {
648 d = 1;
730 d = 1;
649 } else {
731 } else {
650 ok = false;
732 ok = false;
651 }
733 }
652 } else {
734 } else {
653 ok = false;
735 ok = false;
654 }
736 }
655 return d;
737 return d;
656 }
738 }
657
739
658 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
740 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
659 qint64 d = 0;
741 qint64 d = 0;
660 ok = true;
742 ok = true;
661 if (val->ob_type == &PyInt_Type) {
743 if (val->ob_type == &PyInt_Type) {
662 d = PyInt_AS_LONG(val);
744 d = PyInt_AS_LONG(val);
663 } else if (val->ob_type == &PyLong_Type) {
745 } else if (val->ob_type == &PyLong_Type) {
664 d = PyLong_AsLongLong(val);
746 d = PyLong_AsLongLong(val);
665 } else if (!strict) {
747 } else if (!strict) {
666 if (PyObject_TypeCheck(val, &PyInt_Type)) {
748 if (PyObject_TypeCheck(val, &PyInt_Type)) {
667 // support for derived int classes, e.g. for our enums
749 // support for derived int classes, e.g. for our enums
668 d = PyInt_AS_LONG(val);
750 d = PyInt_AS_LONG(val);
669 } else if (val->ob_type == &PyFloat_Type) {
751 } else if (val->ob_type == &PyFloat_Type) {
670 d = floor(PyFloat_AS_DOUBLE(val));
752 d = floor(PyFloat_AS_DOUBLE(val));
671 } else if (val == Py_False) {
753 } else if (val == Py_False) {
672 d = 0;
754 d = 0;
673 } else if (val == Py_True) {
755 } else if (val == Py_True) {
674 d = 1;
756 d = 1;
675 } else {
757 } else {
676 ok = false;
758 ok = false;
677 }
759 }
678 } else {
760 } else {
679 ok = false;
761 ok = false;
680 }
762 }
681 return d;
763 return d;
682 }
764 }
683
765
684 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
766 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
685 quint64 d = 0;
767 quint64 d = 0;
686 ok = true;
768 ok = true;
687 if (PyObject_TypeCheck(val, &PyInt_Type)) {
769 if (PyObject_TypeCheck(val, &PyInt_Type)) {
688 d = PyInt_AS_LONG(val);
770 d = PyInt_AS_LONG(val);
689 } else if (val->ob_type == &PyLong_Type) {
771 } else if (val->ob_type == &PyLong_Type) {
690 d = PyLong_AsLongLong(val);
772 d = PyLong_AsLongLong(val);
691 } else if (!strict) {
773 } else if (!strict) {
692 if (PyObject_TypeCheck(val, &PyInt_Type)) {
774 if (PyObject_TypeCheck(val, &PyInt_Type)) {
693 // support for derived int classes, e.g. for our enums
775 // support for derived int classes, e.g. for our enums
694 d = PyInt_AS_LONG(val);
776 d = PyInt_AS_LONG(val);
695 } else if (val->ob_type == &PyFloat_Type) {
777 } else if (val->ob_type == &PyFloat_Type) {
696 d = floor(PyFloat_AS_DOUBLE(val));
778 d = floor(PyFloat_AS_DOUBLE(val));
697 } else if (val == Py_False) {
779 } else if (val == Py_False) {
698 d = 0;
780 d = 0;
699 } else if (val == Py_True) {
781 } else if (val == Py_True) {
700 d = 1;
782 d = 1;
701 } else {
783 } else {
702 ok = false;
784 ok = false;
703 }
785 }
704 } else {
786 } else {
705 ok = false;
787 ok = false;
706 }
788 }
707 return d;
789 return d;
708 }
790 }
709
791
710 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
792 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
711 double d = 0;
793 double d = 0;
712 ok = true;
794 ok = true;
713 if (val->ob_type == &PyFloat_Type) {
795 if (val->ob_type == &PyFloat_Type) {
714 d = PyFloat_AS_DOUBLE(val);
796 d = PyFloat_AS_DOUBLE(val);
715 } else if (!strict) {
797 } else if (!strict) {
716 if (PyObject_TypeCheck(val, &PyInt_Type)) {
798 if (PyObject_TypeCheck(val, &PyInt_Type)) {
717 d = PyInt_AS_LONG(val);
799 d = PyInt_AS_LONG(val);
718 } else if (val->ob_type == &PyLong_Type) {
800 } else if (val->ob_type == &PyLong_Type) {
719 d = PyLong_AsLong(val);
801 d = PyLong_AsLong(val);
720 } else if (val == Py_False) {
802 } else if (val == Py_False) {
721 d = 0;
803 d = 0;
722 } else if (val == Py_True) {
804 } else if (val == Py_True) {
723 d = 1;
805 d = 1;
724 } else {
806 } else {
725 ok = false;
807 ok = false;
726 }
808 }
727 } else {
809 } else {
728 ok = false;
810 ok = false;
729 }
811 }
730 return d;
812 return d;
731 }
813 }
732
814
733 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
815 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
734 {
816 {
735 QVariant v;
817 QVariant v;
736 bool ok = true;
818 bool ok = true;
737
819
738 if (type==-1) {
820 if (type==-1) {
739 // no special type requested
821 // no special type requested
740 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
822 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
741 type = QVariant::String;
823 type = QVariant::String;
742 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
824 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
743 type = QVariant::Int;
825 type = QVariant::Int;
744 } else if (val->ob_type==&PyLong_Type) {
826 } else if (val->ob_type==&PyLong_Type) {
745 type = QVariant::LongLong;
827 type = QVariant::LongLong;
746 } else if (val->ob_type==&PyFloat_Type) {
828 } else if (val->ob_type==&PyFloat_Type) {
747 type = QVariant::Double;
829 type = QVariant::Double;
748 } else if (val == Py_False || val == Py_True) {
830 } else if (val == Py_False || val == Py_True) {
749 type = QVariant::Bool;
831 type = QVariant::Bool;
750 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
832 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
751 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
833 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
752 // c++ wrapper, check if the class names of the c++ objects match
834 // c++ wrapper, check if the class names of the c++ objects match
753 if (wrap->classInfo()->isCPPWrapper()) {
835 if (wrap->classInfo()->isCPPWrapper()) {
754 if (wrap->classInfo()->metaTypeId()>0) {
836 if (wrap->classInfo()->metaTypeId()>0) {
755 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
837 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
756 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
838 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
757 } else {
839 } else {
758 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
840 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
759 // the pointer here...
841 // the pointer here...
760 // is this worth anything? we loose the knowledge of the cpp object type
842 // is this worth anything? we loose the knowledge of the cpp object type
761 v = qVariantFromValue(wrap->_wrappedPtr);
843 v = qVariantFromValue(wrap->_wrappedPtr);
762 }
844 }
763 } else {
845 } else {
764 // this gives us a QObject pointer
846 // this gives us a QObject pointer
765 QObject* myObject = wrap->_obj;
847 QObject* myObject = wrap->_obj;
766 v = qVariantFromValue(myObject);
848 v = qVariantFromValue(myObject);
767 }
849 }
768 return v;
850 return v;
769 } else if (val->ob_type==&PyDict_Type) {
851 } else if (val->ob_type==&PyDict_Type) {
770 type = QVariant::Map;
852 type = QVariant::Map;
771 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
853 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
772 type = QVariant::List;
854 type = QVariant::List;
773 } else if (val == Py_None) {
855 } else if (val == Py_None) {
774 // none is invalid
856 // none is invalid
775 type = QVariant::Invalid;
857 type = QVariant::Invalid;
776 } else {
858 } else {
777 // this used to be:
859 // this used to be:
778 // type = QVariant::String;
860 // type = QVariant::String;
779 // but now we want to transport the Python Objects directly:
861 // but now we want to transport the Python Objects directly:
780 PythonQtObjectPtr o(val);
862 PythonQtObjectPtr o(val);
781 v = qVariantFromValue(o);
863 v = qVariantFromValue(o);
782 return v;
864 return v;
783 }
865 }
784 }
866 }
785 // special type request:
867 // special type request:
786 switch (type) {
868 switch (type) {
787 case QVariant::Invalid:
869 case QVariant::Invalid:
788 return v;
870 return v;
789 break;
871 break;
790 case QVariant::Int:
872 case QVariant::Int:
791 {
873 {
792 int d = PyObjGetInt(val, false, ok);
874 int d = PyObjGetInt(val, false, ok);
793 if (ok) return QVariant(d);
875 if (ok) return QVariant(d);
794 }
876 }
795 break;
877 break;
796 case QVariant::UInt:
878 case QVariant::UInt:
797 {
879 {
798 int d = PyObjGetInt(val, false,ok);
880 int d = PyObjGetInt(val, false,ok);
799 if (ok) v = QVariant((unsigned int)d);
881 if (ok) v = QVariant((unsigned int)d);
800 }
882 }
801 break;
883 break;
802 case QVariant::Bool:
884 case QVariant::Bool:
803 {
885 {
804 int d = PyObjGetBool(val,false,ok);
886 int d = PyObjGetBool(val,false,ok);
805 if (ok) v = QVariant((bool)(d!=0));
887 if (ok) v = QVariant((bool)(d!=0));
806 }
888 }
807 break;
889 break;
808 case QVariant::Double:
890 case QVariant::Double:
809 {
891 {
810 double d = PyObjGetDouble(val,false,ok);
892 double d = PyObjGetDouble(val,false,ok);
811 if (ok) v = QVariant(d);
893 if (ok) v = QVariant(d);
812 break;
894 break;
813 }
895 }
814 case QMetaType::Float:
896 case QMetaType::Float:
815 {
897 {
816 float d = (float) PyObjGetDouble(val,false,ok);
898 float d = (float) PyObjGetDouble(val,false,ok);
817 if (ok) v = qVariantFromValue(d);
899 if (ok) v = qVariantFromValue(d);
818 break;
900 break;
819 }
901 }
820 case QMetaType::Long:
902 case QMetaType::Long:
821 {
903 {
822 long d = (long) PyObjGetLongLong(val,false,ok);
904 long d = (long) PyObjGetLongLong(val,false,ok);
823 if (ok) v = qVariantFromValue(d);
905 if (ok) v = qVariantFromValue(d);
824 break;
906 break;
825 }
907 }
826 case QMetaType::ULong:
908 case QMetaType::ULong:
827 {
909 {
828 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
910 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
829 if (ok) v = qVariantFromValue(d);
911 if (ok) v = qVariantFromValue(d);
830 break;
912 break;
831 }
913 }
832 case QMetaType::Short:
914 case QMetaType::Short:
833 {
915 {
834 short d = (short) PyObjGetInt(val,false,ok);
916 short d = (short) PyObjGetInt(val,false,ok);
835 if (ok) v = qVariantFromValue(d);
917 if (ok) v = qVariantFromValue(d);
836 break;
918 break;
837 }
919 }
838 case QMetaType::UShort:
920 case QMetaType::UShort:
839 {
921 {
840 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
922 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
841 if (ok) v = qVariantFromValue(d);
923 if (ok) v = qVariantFromValue(d);
842 break;
924 break;
843 }
925 }
844 case QMetaType::Char:
926 case QMetaType::Char:
845 {
927 {
846 char d = (char) PyObjGetInt(val,false,ok);
928 char d = (char) PyObjGetInt(val,false,ok);
847 if (ok) v = qVariantFromValue(d);
929 if (ok) v = qVariantFromValue(d);
848 break;
930 break;
849 }
931 }
850 case QMetaType::UChar:
932 case QMetaType::UChar:
851 {
933 {
852 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
934 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
853 if (ok) v = qVariantFromValue(d);
935 if (ok) v = qVariantFromValue(d);
854 break;
936 break;
855 }
937 }
856
938
857 case QVariant::ByteArray:
939 case QVariant::ByteArray:
858 case QVariant::String:
940 case QVariant::String:
859 {
941 {
860 bool ok;
942 bool ok;
861 v = QVariant(PyObjGetString(val, false, ok));
943 v = QVariant(PyObjGetString(val, false, ok));
862 }
944 }
863 break;
945 break;
864
946
865 // these are important for MeVisLab
947 // these are important for MeVisLab
866 case QVariant::Map:
948 case QVariant::Map:
867 {
949 {
868 if (PyMapping_Check(val)) {
950 if (PyMapping_Check(val)) {
869 QMap<QString,QVariant> map;
951 QMap<QString,QVariant> map;
870 PyObject* items = PyMapping_Items(val);
952 PyObject* items = PyMapping_Items(val);
871 if (items) {
953 if (items) {
872 int count = PyList_Size(items);
954 int count = PyList_Size(items);
873 PyObject* value;
955 PyObject* value;
874 PyObject* key;
956 PyObject* key;
875 PyObject* tuple;
957 PyObject* tuple;
876 for (int i = 0;i<count;i++) {
958 for (int i = 0;i<count;i++) {
877 tuple = PyList_GetItem(items,i);
959 tuple = PyList_GetItem(items,i);
878 key = PyTuple_GetItem(tuple, 0);
960 key = PyTuple_GetItem(tuple, 0);
879 value = PyTuple_GetItem(tuple, 1);
961 value = PyTuple_GetItem(tuple, 1);
880 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
962 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
881 }
963 }
882 Py_DECREF(items);
964 Py_DECREF(items);
883 v = map;
965 v = map;
884 }
966 }
885 }
967 }
886 }
968 }
887 break;
969 break;
888 case QVariant::List:
970 case QVariant::List:
889 if (PySequence_Check(val)) {
971 if (PySequence_Check(val)) {
890 QVariantList list;
972 QVariantList list;
891 int count = PySequence_Size(val);
973 int count = PySequence_Size(val);
892 PyObject* value;
974 PyObject* value;
893 for (int i = 0;i<count;i++) {
975 for (int i = 0;i<count;i++) {
894 value = PySequence_GetItem(val,i);
976 value = PySequence_GetItem(val,i);
895 list.append(PyObjToQVariant(value, -1));
977 list.append(PyObjToQVariant(value, -1));
896 }
978 }
897 v = list;
979 v = list;
898 }
980 }
899 break;
981 break;
900 case QVariant::StringList:
982 case QVariant::StringList:
901 {
983 {
902 bool ok;
984 bool ok;
903 QStringList l = PyObjToStringList(val, false, ok);
985 QStringList l = PyObjToStringList(val, false, ok);
904 if (ok) {
986 if (ok) {
905 v = l;
987 v = l;
906 }
988 }
907 }
989 }
908 break;
990 break;
909
991
910 default:
992 default:
911 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
993 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
912 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
994 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
913 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
995 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
914 // construct a new variant from the C++ object if it has the same meta type
996 // construct a new variant from the C++ object if it has the same meta type
915 v = QVariant(type, wrap->_wrappedPtr);
997 v = QVariant(type, wrap->_wrappedPtr);
916 } else {
998 } else {
917 v = QVariant();
999 v = QVariant();
918 }
1000 }
919 } else {
1001 } else {
920 v = QVariant();
1002 v = QVariant();
921 }
1003 }
922 }
1004 }
923 return v;
1005 return v;
924 }
1006 }
925
1007
926 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1008 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
927 {
1009 {
928 if (str.isNull()) {
1010 if (str.isNull()) {
929 return PyString_FromString("");
1011 return PyString_FromString("");
930 } else {
1012 } else {
931 #ifdef WIN32
1013 #ifdef WIN32
932 // return PyString_FromString(str.toLatin1().data());
1014 // return PyString_FromString(str.toLatin1().data());
933 return PyUnicode_FromUnicode(str.utf16(), str.length());
1015 return PyUnicode_FromUnicode(str.utf16(), str.length());
934 #else
1016 #else
935 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1017 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
936 #endif
1018 #endif
937 }
1019 }
938 }
1020 }
939
1021
940 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1022 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
941 {
1023 {
942 PyObject* result = PyTuple_New(list.count());
1024 PyObject* result = PyTuple_New(list.count());
943 int i = 0;
1025 int i = 0;
944 QString str;
1026 QString str;
945 foreach (str, list) {
1027 foreach (str, list) {
946 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1028 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
947 i++;
1029 i++;
948 }
1030 }
949 // why is the error state bad after this?
1031 // why is the error state bad after this?
950 PyErr_Clear();
1032 PyErr_Clear();
951 return result;
1033 return result;
952 }
1034 }
953
1035
954 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1036 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
955 {
1037 {
956 PyObject* result = PyList_New(list.count());
1038 PyObject* result = PyList_New(list.count());
957 int i = 0;
1039 int i = 0;
958 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1040 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
959 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1041 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
960 i++;
1042 i++;
961 }
1043 }
962 return result;
1044 return result;
963 }
1045 }
964
1046
965 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1047 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
966 {
1048 {
967 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1049 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
968 }
1050 }
969
1051
970 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1052 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
971 PyObject* result = PyDict_New();
1053 PyObject* result = PyDict_New();
972 QVariantMap::const_iterator t = m.constBegin();
1054 QVariantMap::const_iterator t = m.constBegin();
973 PyObject* key;
1055 PyObject* key;
974 PyObject* val;
1056 PyObject* val;
975 for (;t!=m.end();t++) {
1057 for (;t!=m.end();t++) {
976 key = QStringToPyObject(t.key());
1058 key = QStringToPyObject(t.key());
977 val = QVariantToPyObject(t.value());
1059 val = QVariantToPyObject(t.value());
978 PyDict_SetItem(result, key, val);
1060 PyDict_SetItem(result, key, val);
979 Py_DECREF(key);
1061 Py_DECREF(key);
980 Py_DECREF(val);
1062 Py_DECREF(val);
981 }
1063 }
982 return result;
1064 return result;
983 }
1065 }
984
1066
985 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1067 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
986 PyObject* result = PyTuple_New(l.count());
1068 PyObject* result = PyTuple_New(l.count());
987 int i = 0;
1069 int i = 0;
988 QVariant v;
1070 QVariant v;
989 foreach (v, l) {
1071 foreach (v, l) {
990 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1072 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
991 i++;
1073 i++;
992 }
1074 }
993 // why is the error state bad after this?
1075 // why is the error state bad after this?
994 PyErr_Clear();
1076 PyErr_Clear();
995 return result;
1077 return result;
996 }
1078 }
997
1079
998 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1080 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
999 {
1081 {
1000 PyObject* result = PyTuple_New(list->count());
1082 PyObject* result = PyTuple_New(list->count());
1001 int i = 0;
1083 int i = 0;
1002 foreach (void* value, *list) {
1084 foreach (void* value, *list) {
1003 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1085 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1004 i++;
1086 i++;
1005 }
1087 }
1006 return result;
1088 return result;
1007 }
1089 }
1008
1090
1009 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1091 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1010 {
1092 {
1011 bool result = false;
1093 bool result = false;
1012 if (PySequence_Check(obj)) {
1094 if (PySequence_Check(obj)) {
1013 result = true;
1095 result = true;
1014 int count = PySequence_Size(obj);
1096 int count = PySequence_Size(obj);
1015 PyObject* value;
1097 PyObject* value;
1016 for (int i = 0;i<count;i++) {
1098 for (int i = 0;i<count;i++) {
1017 value = PySequence_GetItem(obj,i);
1099 value = PySequence_GetItem(obj,i);
1018 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1100 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1019 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1101 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1020 bool ok;
1102 bool ok;
1021 void* object = castWrapperTo(wrap, type, ok);
1103 void* object = castWrapperTo(wrap, type, ok);
1022 if (ok) {
1104 if (ok) {
1023 list->append(object);
1105 list->append(object);
1024 } else {
1106 } else {
1025 result = false;
1107 result = false;
1026 break;
1108 break;
1027 }
1109 }
1028 }
1110 }
1029 }
1111 }
1030 }
1112 }
1031 return result;
1113 return result;
1032 }
1114 }
1033
1115
1034 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1116 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1035 {
1117 {
1036 int idx = typeName.indexOf("<");
1118 int idx = typeName.indexOf("<");
1037 if (idx>0) {
1119 if (idx>0) {
1038 int idx2 = typeName.indexOf(">");
1120 int idx2 = typeName.indexOf(">");
1039 if (idx2>0) {
1121 if (idx2>0) {
1040 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1122 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1041 return QMetaType::type(innerType.constData());
1123 return QMetaType::type(innerType.constData());
1042 }
1124 }
1043 }
1125 }
1044 return QMetaType::Void;
1126 return QMetaType::Void;
1045 }
1127 }
1046
1128
1047
1129
1048
1130
1049 QString PythonQtConv::qVariantToString(const QVariant& v) {
1131 QString PythonQtConv::qVariantToString(const QVariant& v) {
1050 return CPPObjectToString(v.userType(), v.constData());
1132 return CPPObjectToString(v.userType(), v.constData());
1051 }
1133 }
1052
1134
1053 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1135 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1054 QString r;
1136 QString r;
1055 switch (type) {
1137 switch (type) {
1056 case QVariant::Size: {
1138 case QVariant::Size: {
1057 const QSize* s = static_cast<const QSize*>(data);
1139 const QSize* s = static_cast<const QSize*>(data);
1058 r = QString::number(s->width()) + ", " + QString::number(s->height());
1140 r = QString::number(s->width()) + ", " + QString::number(s->height());
1059 }
1141 }
1060 break;
1142 break;
1061 case QVariant::SizeF: {
1143 case QVariant::SizeF: {
1062 const QSizeF* s = static_cast<const QSizeF*>(data);
1144 const QSizeF* s = static_cast<const QSizeF*>(data);
1063 r = QString::number(s->width()) + ", " + QString::number(s->height());
1145 r = QString::number(s->width()) + ", " + QString::number(s->height());
1064 }
1146 }
1065 break;
1147 break;
1066 case QVariant::Point: {
1148 case QVariant::Point: {
1067 const QPoint* s = static_cast<const QPoint*>(data);
1149 const QPoint* s = static_cast<const QPoint*>(data);
1068 r = QString::number(s->x()) + ", " + QString::number(s->y());
1150 r = QString::number(s->x()) + ", " + QString::number(s->y());
1069 }
1151 }
1070 break;
1152 break;
1071 case QVariant::PointF: {
1153 case QVariant::PointF: {
1072 const QPointF* s = static_cast<const QPointF*>(data);
1154 const QPointF* s = static_cast<const QPointF*>(data);
1073 r = QString::number(s->x()) + ", " + QString::number(s->y());
1155 r = QString::number(s->x()) + ", " + QString::number(s->y());
1074 }
1156 }
1075 break;
1157 break;
1076 case QVariant::Rect: {
1158 case QVariant::Rect: {
1077 const QRect* s = static_cast<const QRect*>(data);
1159 const QRect* s = static_cast<const QRect*>(data);
1078 r = QString::number(s->x()) + ", " + QString::number(s->y());
1160 r = QString::number(s->x()) + ", " + QString::number(s->y());
1079 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1161 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1080 }
1162 }
1081 break;
1163 break;
1082 case QVariant::RectF: {
1164 case QVariant::RectF: {
1083 const QRectF* s = static_cast<const QRectF*>(data);
1165 const QRectF* s = static_cast<const QRectF*>(data);
1084 r = QString::number(s->x()) + ", " + QString::number(s->y());
1166 r = QString::number(s->x()) + ", " + QString::number(s->y());
1085 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1167 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1086 }
1168 }
1087 break;
1169 break;
1088 case QVariant::Date: {
1170 case QVariant::Date: {
1089 const QDate* s = static_cast<const QDate*>(data);
1171 const QDate* s = static_cast<const QDate*>(data);
1090 r = s->toString(Qt::ISODate);
1172 r = s->toString(Qt::ISODate);
1091 }
1173 }
1092 break;
1174 break;
1093 case QVariant::DateTime: {
1175 case QVariant::DateTime: {
1094 const QDateTime* s = static_cast<const QDateTime*>(data);
1176 const QDateTime* s = static_cast<const QDateTime*>(data);
1095 r = s->toString(Qt::ISODate);
1177 r = s->toString(Qt::ISODate);
1096 }
1178 }
1097 break;
1179 break;
1098 case QVariant::Time: {
1180 case QVariant::Time: {
1099 const QTime* s = static_cast<const QTime*>(data);
1181 const QTime* s = static_cast<const QTime*>(data);
1100 r = s->toString(Qt::ISODate);
1182 r = s->toString(Qt::ISODate);
1101 }
1183 }
1102 break;
1184 break;
1103 case QVariant::Pixmap:
1185 case QVariant::Pixmap:
1104 {
1186 {
1105 const QPixmap* s = static_cast<const QPixmap*>(data);
1187 const QPixmap* s = static_cast<const QPixmap*>(data);
1106 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1188 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1107 }
1189 }
1108 break;
1190 break;
1109 case QVariant::Image:
1191 case QVariant::Image:
1110 {
1192 {
1111 const QImage* s = static_cast<const QImage*>(data);
1193 const QImage* s = static_cast<const QImage*>(data);
1112 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1194 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1113 }
1195 }
1114 break;
1196 break;
1115 case QVariant::Url:
1197 case QVariant::Url:
1116 {
1198 {
1117 const QUrl* s = static_cast<const QUrl*>(data);
1199 const QUrl* s = static_cast<const QUrl*>(data);
1118 r = s->toString();
1200 r = s->toString();
1119 }
1201 }
1120 break;
1202 break;
1121 //TODO: add more printing for other variant types
1203 //TODO: add more printing for other variant types
1122 default:
1204 default:
1123 // this creates a copy, but that should not be expensive for typical simple variants
1205 // this creates a copy, but that should not be expensive for typical simple variants
1124 // (but we do not want to do this for our won user types!
1206 // (but we do not want to do this for our won user types!
1125 if (type>0 && type < (int)QVariant::UserType) {
1207 if (type>0 && type < (int)QVariant::UserType) {
1126 QVariant v(type, data);
1208 QVariant v(type, data);
1127 r = v.toString();
1209 r = v.toString();
1128 }
1210 }
1129 }
1211 }
1130 return r;
1212 return r;
1131 }
1213 }
@@ -1,204 +1,207
1 #ifndef _PYTHONQTCONVERSION_H
1 #ifndef _PYTHONQTCONVERSION_H
2 #define _PYTHONQTCONVERSION_H
2 #define _PYTHONQTCONVERSION_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 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtConversion.h
38 // \file PythonQtConversion.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include "PythonQtMisc.h"
46 #include "PythonQtMisc.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtMethodInfo.h"
48 #include "PythonQtMethodInfo.h"
49
49
50 #include <QWidget>
50 #include <QWidget>
51 #include <QList>
51 #include <QList>
52 #include <vector>
52 #include <vector>
53
53
54 typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId);
54 typedef PyObject* PythonQtConvertMetaTypeToPythonCB(const void* inObject, int metaTypeId);
55 typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict);
55 typedef bool PythonQtConvertPythonToMetaTypeCB(PyObject* inObject, void* outObject, int metaTypeId, bool strict);
56
56
57 #define PythonQtRegisterListTemplateConverter(type, innertype) \
57 #define PythonQtRegisterListTemplateConverter(type, innertype) \
58 { int typeId = qRegisterMetaType<type<innertype> >(#type"<"#innertype">"); \
58 { int typeId = qRegisterMetaType<type<innertype> >(#type"<"#innertype">"); \
59 PythonQtConv::registerPythonToMetaTypeConverter(typeId, PythonQtConvertPythonListToListOfValueType<type<innertype>, innertype>); \
59 PythonQtConv::registerPythonToMetaTypeConverter(typeId, PythonQtConvertPythonListToListOfValueType<type<innertype>, innertype>); \
60 PythonQtConv::registerMetaTypeToPythonConverter(typeId, PythonQtConvertListOfValueTypeToPythonList<type<innertype>, innertype>); \
60 PythonQtConv::registerMetaTypeToPythonConverter(typeId, PythonQtConvertListOfValueTypeToPythonList<type<innertype>, innertype>); \
61 }
61 }
62
62
63 #define PythonQtRegisterToolClassesTemplateConverter(innertype) \
63 #define PythonQtRegisterToolClassesTemplateConverter(innertype) \
64 PythonQtRegisterListTemplateConverter(QList, innertype); \
64 PythonQtRegisterListTemplateConverter(QList, innertype); \
65 PythonQtRegisterListTemplateConverter(QVector, innertype); \
65 PythonQtRegisterListTemplateConverter(QVector, innertype); \
66 PythonQtRegisterListTemplateConverter(std::vector, innertype);
66 PythonQtRegisterListTemplateConverter(std::vector, innertype);
67 // TODO: add QHash etc. here!
67 // TODO: add QHash etc. here!
68
68
69 //! a static class that offers methods for type conversion
69 //! a static class that offers methods for type conversion
70 class PYTHONQT_EXPORT PythonQtConv {
70 class PYTHONQT_EXPORT PythonQtConv {
71
71
72 public:
72 public:
73
73
74 //! get a ref counted True or False Python object
74 //! get a ref counted True or False Python object
75 static PyObject* GetPyBool(bool val);
75 static PyObject* GetPyBool(bool val);
76
76
77 //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object,
77 //! converts the Qt parameter given in \c data, interpreting it as a \c info parameter, into a Python object,
78 static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data);
78 static PyObject* ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data);
79
79
80 //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore)
80 //! convert python object to Qt (according to the given parameter) and if the conversion should be strict (classInfo is currently not used anymore)
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject = NULL);
81 static void* ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* classInfo, void* alreadyAllocatedCPPObject = NULL);
82
82
83 //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall
83 //! creates a data storage for the passed parameter type and returns a void pointer to be set as arg[0] of qt_metacall
84 static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info);
84 static void* CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info);
85
85
86 //! converts QString to Python string (unicode!)
86 //! converts QString to Python string (unicode!)
87 static PyObject* QStringToPyObject(const QString& str);
87 static PyObject* QStringToPyObject(const QString& str);
88
88
89 //! converts QStringList to Python tuple
89 //! converts QStringList to Python tuple
90 static PyObject* QStringListToPyObject(const QStringList& list);
90 static PyObject* QStringListToPyObject(const QStringList& list);
91
91
92 //! converts QStringList to Python list
92 //! converts QStringList to Python list
93 static PyObject* QStringListToPyList(const QStringList& list);
93 static PyObject* QStringListToPyList(const QStringList& list);
94
94
95 //! get string representation of py object
95 //! get string representation of py object
96 static QString PyObjGetRepresentation(PyObject* val);
96 static QString PyObjGetRepresentation(PyObject* val);
97
97
98 //! get string value from py object
98 //! get string value from py object
99 static QString PyObjGetString(PyObject* val) { bool ok; QString s = PyObjGetString(val, false, ok); return s; }
99 static QString PyObjGetString(PyObject* val) { bool ok; QString s = PyObjGetString(val, false, ok); return s; }
100 //! get string value from py object
100 //! get string value from py object
101 static QString PyObjGetString(PyObject* val, bool strict, bool &ok);
101 static QString PyObjGetString(PyObject* val, bool strict, bool &ok);
102 //! get bytes from py object
102 //! get bytes from py object
103 static QByteArray PyObjGetBytes(PyObject* val, bool strict, bool &ok);
103 static QByteArray PyObjGetBytes(PyObject* val, bool strict, bool &ok);
104 //! get int from py object
104 //! get int from py object
105 static int PyObjGetInt(PyObject* val, bool strict, bool &ok);
105 static int PyObjGetInt(PyObject* val, bool strict, bool &ok);
106 //! get int64 from py object
106 //! get int64 from py object
107 static qint64 PyObjGetLongLong(PyObject* val, bool strict, bool &ok);
107 static qint64 PyObjGetLongLong(PyObject* val, bool strict, bool &ok);
108 //! get int64 from py object
108 //! get int64 from py object
109 static quint64 PyObjGetULongLong(PyObject* val, bool strict, bool &ok);
109 static quint64 PyObjGetULongLong(PyObject* val, bool strict, bool &ok);
110 //! get double from py object
110 //! get double from py object
111 static double PyObjGetDouble(PyObject* val, bool strict, bool &ok);
111 static double PyObjGetDouble(PyObject* val, bool strict, bool &ok);
112 //! get bool from py object
112 //! get bool from py object
113 static bool PyObjGetBool(PyObject* val, bool strict, bool &ok);
113 static bool PyObjGetBool(PyObject* val, bool strict, bool &ok);
114
114
115 //! create a string list from python sequence
115 //! create a string list from python sequence
116 static QStringList PyObjToStringList(PyObject* val, bool strict, bool& ok);
116 static QStringList PyObjToStringList(PyObject* val, bool strict, bool& ok);
117
117
118 //! convert python object to qvariant, if type is given it will try to create a qvariant of that type, otherwise
118 //! convert python object to qvariant, if type is given it will try to create a qvariant of that type, otherwise
119 //! it will guess from the python type
119 //! it will guess from the python type
120 static QVariant PyObjToQVariant(PyObject* val, int type = -1);
120 static QVariant PyObjToQVariant(PyObject* val, int type = -1);
121
121
122 //! convert QVariant from PyObject
122 //! convert QVariant from PyObject
123 static PyObject* QVariantToPyObject(const QVariant& v);
123 static PyObject* QVariantToPyObject(const QVariant& v);
124
124
125 static PyObject* QVariantMapToPyObject(const QVariantMap& m);
125 static PyObject* QVariantMapToPyObject(const QVariantMap& m);
126 static PyObject* QVariantListToPyObject(const QVariantList& l);
126 static PyObject* QVariantListToPyObject(const QVariantList& l);
127
127
128 //! get human readable string from qvariant
128 //! get human readable string from qvariant
129 static QString qVariantToString(const QVariant& v);
129 static QString qVariantToString(const QVariant& v);
130
130
131 //! get human readable string from CPP object (when the metatype is known)
131 //! get human readable string from CPP object (when the metatype is known)
132 static QString CPPObjectToString(int type, const void* data);
132 static QString CPPObjectToString(int type, const void* data);
133
133
134 //! register a converter callback from python to cpp for given metatype
134 //! register a converter callback from python to cpp for given metatype
135 static void registerPythonToMetaTypeConverter(int metaTypeId, PythonQtConvertPythonToMetaTypeCB* cb) { _pythonToMetaTypeConverters.insert(metaTypeId, cb); }
135 static void registerPythonToMetaTypeConverter(int metaTypeId, PythonQtConvertPythonToMetaTypeCB* cb) { _pythonToMetaTypeConverters.insert(metaTypeId, cb); }
136
136
137 //! register a converter callback from cpp to python for given metatype
137 //! register a converter callback from cpp to python for given metatype
138 static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); }
138 static void registerMetaTypeToPythonConverter(int metaTypeId, PythonQtConvertMetaTypeToPythonCB* cb) { _metaTypeToPythonConverters.insert(metaTypeId, cb); }
139
139
140 //! returns the inner type id of a simple template of the form SomeObject<InnerType>
140 //! returns the inner type id of a simple template of the form SomeObject<InnerType>
141 static int getInnerTemplateMetaType(const QByteArray& typeName);
141 static int getInnerTemplateMetaType(const QByteArray& typeName);
142
142
143 //! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object,
143 //! converts the Qt parameter given in \c data, interpreting it as a \c type registered qvariant/meta type, into a Python object,
144 static PyObject* ConvertQtValueToPythonInternal(int type, const void* data);
144 static PyObject* ConvertQtValueToPythonInternal(int type, const void* data);
145
145
146 public:
146 public:
147
147
148 static PythonQtValueStorage<qint64, 128> global_valueStorage;
148 static PythonQtValueStorage<qint64, 128> global_valueStorage;
149 static PythonQtValueStorage<void*, 128> global_ptrStorage;
149 static PythonQtValueStorage<void*, 128> global_ptrStorage;
150 static PythonQtValueStorage<QVariant, 32> global_variantStorage;
150 static PythonQtValueStorage<QVariant, 32> global_variantStorage;
151
151
152 protected:
152 protected:
153 static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters;
153 static QHash<int, PythonQtConvertMetaTypeToPythonCB*> _metaTypeToPythonConverters;
154 static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters;
154 static QHash<int, PythonQtConvertPythonToMetaTypeCB*> _pythonToMetaTypeConverters;
155
155
156 //! handle automatic conversion of some special types (QColor, QBrush, ...)
157 static void* handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject);
158
156 //! converts the list of pointers of given type to Python
159 //! converts the list of pointers of given type to Python
157 static PyObject* ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& type);
160 static PyObject* ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& type);
158 //! tries to convert the python object to a QList of pointers to \c type objects, returns true on success
161 //! tries to convert the python object to a QList of pointers to \c type objects, returns true on success
159 static bool ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict);
162 static bool ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict);
160
163
161 //! cast wrapper to given className if possible
164 //! cast wrapper to given className if possible
162 static void* castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok);
165 static void* castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok);
163 };
166 };
164
167
165 template<class ListType, class T>
168 template<class ListType, class T>
166 PyObject* PythonQtConvertListOfValueTypeToPythonList(const void* /*QList<T>* */ inList, int metaTypeId)
169 PyObject* PythonQtConvertListOfValueTypeToPythonList(const void* /*QList<T>* */ inList, int metaTypeId)
167 {
170 {
168 ListType* list = (ListType*)inList;
171 ListType* list = (ListType*)inList;
169 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
172 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
170 PyObject* result = PyTuple_New(list->size());
173 PyObject* result = PyTuple_New(list->size());
171 int i = 0;
174 int i = 0;
172 foreach (const T& value, *list) {
175 foreach (const T& value, *list) {
173 PyTuple_SET_ITEM(result, i, PythonQtConv::ConvertQtValueToPythonInternal(innerType, &value));
176 PyTuple_SET_ITEM(result, i, PythonQtConv::ConvertQtValueToPythonInternal(innerType, &value));
174 i++;
177 i++;
175 }
178 }
176 return result;
179 return result;
177 }
180 }
178
181
179 template<class ListType, class T>
182 template<class ListType, class T>
180 bool PythonQtConvertPythonListToListOfValueType(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/)
183 bool PythonQtConvertPythonListToListOfValueType(PyObject* obj, void* /*QList<T>* */ outList, int metaTypeId, bool /*strict*/)
181 {
184 {
182 ListType* list = (ListType*)outList;
185 ListType* list = (ListType*)outList;
183 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
186 static const int innerType = PythonQtConv::getInnerTemplateMetaType(QByteArray(QMetaType::typeName(metaTypeId)));
184 bool result = false;
187 bool result = false;
185 if (PySequence_Check(obj)) {
188 if (PySequence_Check(obj)) {
186 result = true;
189 result = true;
187 int count = PySequence_Size(obj);
190 int count = PySequence_Size(obj);
188 PyObject* value;
191 PyObject* value;
189 for (int i = 0;i<count;i++) {
192 for (int i = 0;i<count;i++) {
190 value = PySequence_GetItem(obj,i);
193 value = PySequence_GetItem(obj,i);
191 // this is quite some overhead, but it avoids having another large switch...
194 // this is quite some overhead, but it avoids having another large switch...
192 QVariant v = PythonQtConv::PyObjToQVariant(value, innerType);
195 QVariant v = PythonQtConv::PyObjToQVariant(value, innerType);
193 if (v.isValid()) {
196 if (v.isValid()) {
194 list->push_back(qVariantValue<T>(v));
197 list->push_back(qVariantValue<T>(v));
195 } else {
198 } else {
196 result = false;
199 result = false;
197 break;
200 break;
198 }
201 }
199 }
202 }
200 }
203 }
201 return result;
204 return result;
202 }
205 }
203
206
204 #endif
207 #endif
@@ -1,328 +1,328
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 PythonQtMethodInfo.cpp
35 // \file PythonQtMethodInfo.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 "PythonQtMethodInfo.h"
42 #include "PythonQtMethodInfo.h"
43 #include "PythonQtClassInfo.h"
43 #include "PythonQtClassInfo.h"
44 #include <iostream>
44 #include <iostream>
45
45
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
48
48
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
50 {
50 {
51 #ifdef PYTHONQT_DEBUG
51 #ifdef PYTHONQT_DEBUG
52 QByteArray sig(meta.signature());
52 QByteArray sig(meta.signature());
53 sig = sig.mid(sig.indexOf('('));
53 sig = sig.mid(sig.indexOf('('));
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
55 std::cout << "caching " << fullSig.data() << std::endl;
55 std::cout << "caching " << fullSig.data() << std::endl;
56 #endif
56 #endif
57
57
58 ParameterInfo type;
58 ParameterInfo type;
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
60 _parameters.append(type);
60 _parameters.append(type);
61 QByteArray name;
61 QByteArray name;
62 QList<QByteArray> names = meta.parameterTypes();
62 QList<QByteArray> names = meta.parameterTypes();
63 foreach (name, names) {
63 foreach (name, names) {
64 fillParameterInfo(type, name, classInfo);
64 fillParameterInfo(type, name, classInfo);
65 _parameters.append(type);
65 _parameters.append(type);
66 }
66 }
67 }
67 }
68
68
69 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
69 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
70 {
70 {
71 QByteArray sig(signal.signature());
71 QByteArray sig(signal.signature());
72 sig = sig.mid(sig.indexOf('('));
72 sig = sig.mid(sig.indexOf('('));
73 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
73 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
74 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
74 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
75 if (!result) {
75 if (!result) {
76 result = new PythonQtMethodInfo(signal, classInfo);
76 result = new PythonQtMethodInfo(signal, classInfo);
77 _cachedSignatures.insert(fullSig, result);
77 _cachedSignatures.insert(fullSig, result);
78 }
78 }
79 return result;
79 return result;
80 }
80 }
81
81
82 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromMetaObjectAndSignature(const QMetaObject* metaObject, const char* signature)
82 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromMetaObjectAndSignature(const QMetaObject* metaObject, const char* signature)
83 {
83 {
84 QByteArray sig = QMetaObject::normalizedSignature(signature);
84 QByteArray sig = QMetaObject::normalizedSignature(signature);
85 int idx = metaObject->indexOfMethod(sig);
85 int idx = metaObject->indexOfMethod(sig);
86 QMetaMethod meta = metaObject->method(idx);
86 QMetaMethod meta = metaObject->method(idx);
87 return PythonQtMethodInfo::getCachedMethodInfo(meta, NULL);
87 return PythonQtMethodInfo::getCachedMethodInfo(meta, NULL);
88 }
88 }
89
89
90 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
90 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
91 {
91 {
92 QByteArray name = orgName;
92 QByteArray name = orgName;
93
93
94 type.enumWrapper = NULL;
94 type.enumWrapper = NULL;
95
95
96 int len = name.length();
96 int len = name.length();
97 if (len>0) {
97 if (len>0) {
98 if (strncmp(name.constData(), "const ", 6)==0) {
98 if (strncmp(name.constData(), "const ", 6)==0) {
99 name = name.mid(6);
99 name = name.mid(6);
100 len -= 6;
100 len -= 6;
101 type.isConst = true;
101 type.isConst = true;
102 } else {
102 } else {
103 type.isConst = false;
103 type.isConst = false;
104 }
104 }
105 bool hadPointer = false;
105 bool hadPointer = false;
106 bool hadReference = false;
106 bool hadReference = false;
107 // remove * and & from the end of the string, handle & and * the same way
107 // remove * and & from the end of the string, handle & and * the same way
108 while (name.at(len-1) == '*') {
108 while (name.at(len-1) == '*') {
109 len--;
109 len--;
110 hadPointer = true;
110 hadPointer = true;
111 }
111 }
112 while (name.at(len-1) == '&') {
112 while (name.at(len-1) == '&') {
113 len--;
113 len--;
114 hadReference = true;
114 hadReference = true;
115 }
115 }
116 if (len!=name.length()) {
116 if (len!=name.length()) {
117 name = name.left(len);
117 name = name.left(len);
118 }
118 }
119 type.isPointer = hadPointer;
119 type.isPointer = hadPointer;
120
120
121 QByteArray alias = _parameterNameAliases.value(name);
121 QByteArray alias = _parameterNameAliases.value(name);
122 if (!alias.isEmpty()) {
122 if (!alias.isEmpty()) {
123 name = alias;
123 name = alias;
124 }
124 }
125
125
126 type.typeId = nameToType(name);
126 type.typeId = nameToType(name);
127 if (!type.isPointer && type.typeId == Unknown) {
127 if (!type.isPointer && type.typeId == Unknown) {
128 type.typeId = QMetaType::type(name.constData());
128 type.typeId = QMetaType::type(name.constData());
129 if (type.typeId == QMetaType::Void) {
129 if (type.typeId == QMetaType::Void) {
130 type.typeId = Unknown;
130 type.typeId = Unknown;
131 }
131 }
132 }
132 }
133 type.name = name;
133 type.name = name;
134
134
135 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
135 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
136 bool isLocalEnum;
136 bool isLocalEnum;
137 // TODOXXX: make use of this flag!
137 // TODOXXX: make use of this flag!
138 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, isLocalEnum);
138 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
139 }
139 }
140 } else {
140 } else {
141 type.typeId = QMetaType::Void;
141 type.typeId = QMetaType::Void;
142 type.isPointer = false;
142 type.isPointer = false;
143 type.isConst = false;
143 type.isConst = false;
144 }
144 }
145 }
145 }
146
146
147 int PythonQtMethodInfo::nameToType(const char* name)
147 int PythonQtMethodInfo::nameToType(const char* name)
148 {
148 {
149 if (_parameterTypeDict.isEmpty()) {
149 if (_parameterTypeDict.isEmpty()) {
150 // we could also use QMetaType::nameToType, but that does a string compare search
150 // we could also use QMetaType::nameToType, but that does a string compare search
151 // and does not support QVariant
151 // and does not support QVariant
152
152
153 // QMetaType names
153 // QMetaType names
154 _parameterTypeDict.insert("long", QMetaType::Long);
154 _parameterTypeDict.insert("long", QMetaType::Long);
155 _parameterTypeDict.insert("int", QMetaType::Int);
155 _parameterTypeDict.insert("int", QMetaType::Int);
156 _parameterTypeDict.insert("short", QMetaType::Short);
156 _parameterTypeDict.insert("short", QMetaType::Short);
157 _parameterTypeDict.insert("char", QMetaType::Char);
157 _parameterTypeDict.insert("char", QMetaType::Char);
158 _parameterTypeDict.insert("ulong", QMetaType::ULong);
158 _parameterTypeDict.insert("ulong", QMetaType::ULong);
159 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
159 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
160 _parameterTypeDict.insert("uint", QMetaType::UInt);
160 _parameterTypeDict.insert("uint", QMetaType::UInt);
161 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
161 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
162 _parameterTypeDict.insert("ushort", QMetaType::UShort);
162 _parameterTypeDict.insert("ushort", QMetaType::UShort);
163 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
163 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
164 _parameterTypeDict.insert("uchar", QMetaType::UChar);
164 _parameterTypeDict.insert("uchar", QMetaType::UChar);
165 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
165 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
166 _parameterTypeDict.insert("bool", QMetaType::Bool);
166 _parameterTypeDict.insert("bool", QMetaType::Bool);
167 _parameterTypeDict.insert("float", QMetaType::Float);
167 _parameterTypeDict.insert("float", QMetaType::Float);
168 _parameterTypeDict.insert("double", QMetaType::Double);
168 _parameterTypeDict.insert("double", QMetaType::Double);
169 _parameterTypeDict.insert("qreal", QMetaType::Double);
169 _parameterTypeDict.insert("qreal", QMetaType::Double);
170 _parameterTypeDict.insert("QChar", QMetaType::QChar);
170 _parameterTypeDict.insert("QChar", QMetaType::QChar);
171 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
171 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
172 _parameterTypeDict.insert("Q3CString", QMetaType::QByteArray);
172 _parameterTypeDict.insert("Q3CString", QMetaType::QByteArray);
173 _parameterTypeDict.insert("QString", QMetaType::QString);
173 _parameterTypeDict.insert("QString", QMetaType::QString);
174 _parameterTypeDict.insert("", QMetaType::Void);
174 _parameterTypeDict.insert("", QMetaType::Void);
175 _parameterTypeDict.insert("void", QMetaType::Void);
175 _parameterTypeDict.insert("void", QMetaType::Void);
176 // QVariant names
176 // QVariant names
177 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
177 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
178 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
178 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
179 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
179 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
180 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
180 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
181 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
181 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
182 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
182 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
183 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
183 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
184 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
184 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
185 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
185 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
186 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
186 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
187 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
187 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
188 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
188 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
189 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
189 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
190 _parameterTypeDict.insert("QDate", QMetaType::QDate);
190 _parameterTypeDict.insert("QDate", QMetaType::QDate);
191 _parameterTypeDict.insert("QTime", QMetaType::QTime);
191 _parameterTypeDict.insert("QTime", QMetaType::QTime);
192 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
192 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
193 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
193 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
194 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
194 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
195 _parameterTypeDict.insert("QRect", QMetaType::QRect);
195 _parameterTypeDict.insert("QRect", QMetaType::QRect);
196 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
196 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
197 _parameterTypeDict.insert("QSize", QMetaType::QSize);
197 _parameterTypeDict.insert("QSize", QMetaType::QSize);
198 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
198 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
199 _parameterTypeDict.insert("QLine", QMetaType::QLine);
199 _parameterTypeDict.insert("QLine", QMetaType::QLine);
200 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
200 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
201 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
201 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
202 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
202 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
203 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
203 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
204 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
204 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
205 _parameterTypeDict.insert("QFont", QMetaType::QFont);
205 _parameterTypeDict.insert("QFont", QMetaType::QFont);
206 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
206 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
207 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
207 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
208 _parameterTypeDict.insert("QColor", QMetaType::QColor);
208 _parameterTypeDict.insert("QColor", QMetaType::QColor);
209 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
209 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
210 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
210 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
211 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
211 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
212 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
212 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
213 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
213 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
214 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
214 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
215 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
215 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
216 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
216 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
217 _parameterTypeDict.insert("QPen", QMetaType::QPen);
217 _parameterTypeDict.insert("QPen", QMetaType::QPen);
218 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
218 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
219 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
219 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
220 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
220 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
221 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
221 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
222 // own special types... (none so far, could be e.g. ObjectList
222 // own special types... (none so far, could be e.g. ObjectList
223 }
223 }
224 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
224 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
225 if (it!=_parameterTypeDict.end()) {
225 if (it!=_parameterTypeDict.end()) {
226 return it.value();
226 return it.value();
227 } else {
227 } else {
228 return PythonQtMethodInfo::Unknown;
228 return PythonQtMethodInfo::Unknown;
229 }
229 }
230 }
230 }
231
231
232 void PythonQtMethodInfo::cleanupCachedMethodInfos()
232 void PythonQtMethodInfo::cleanupCachedMethodInfos()
233 {
233 {
234 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
234 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
235 while (i.hasNext()) {
235 while (i.hasNext()) {
236 delete i.next().value();
236 delete i.next().value();
237 }
237 }
238 }
238 }
239
239
240 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
240 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
241 {
241 {
242 _parameterNameAliases.insert(alias, name);
242 _parameterNameAliases.insert(alias, name);
243 }
243 }
244
244
245 //-------------------------------------------------------------------------------------------------
245 //-------------------------------------------------------------------------------------------------
246
246
247 void PythonQtSlotInfo::deleteOverloadsAndThis()
247 void PythonQtSlotInfo::deleteOverloadsAndThis()
248 {
248 {
249 PythonQtSlotInfo* cur = this;
249 PythonQtSlotInfo* cur = this;
250 while(cur->nextInfo()) {
250 while(cur->nextInfo()) {
251 PythonQtSlotInfo* next = cur->nextInfo();
251 PythonQtSlotInfo* next = cur->nextInfo();
252 delete cur;
252 delete cur;
253 cur = next;
253 cur = next;
254 }
254 }
255 }
255 }
256
256
257
257
258 QString PythonQtSlotInfo::fullSignature()
258 QString PythonQtSlotInfo::fullSignature()
259 {
259 {
260 bool skipFirstArg = isInstanceDecorator();
260 bool skipFirstArg = isInstanceDecorator();
261 QString result = _meta.typeName();
261 QString result = _meta.typeName();
262 QByteArray sig = slotName();
262 QByteArray sig = slotName();
263 QList<QByteArray> names = _meta.parameterNames();
263 QList<QByteArray> names = _meta.parameterNames();
264
264
265 bool isStatic = false;
265 bool isStatic = false;
266 bool isConstructor = false;
266 bool isConstructor = false;
267 bool isDestructor = false;
267 bool isDestructor = false;
268
268
269 if (_type == ClassDecorator) {
269 if (_type == ClassDecorator) {
270 if (sig.startsWith("new_")) {
270 if (sig.startsWith("new_")) {
271 sig = sig.mid(strlen("new_"));
271 sig = sig.mid(strlen("new_"));
272 isConstructor = true;
272 isConstructor = true;
273 } else if (sig.startsWith("delete_")) {
273 } else if (sig.startsWith("delete_")) {
274 sig = sig.mid(strlen("delete_"));
274 sig = sig.mid(strlen("delete_"));
275 isDestructor = true;
275 isDestructor = true;
276 } else if(sig.startsWith("static_")) {
276 } else if(sig.startsWith("static_")) {
277 isStatic = true;
277 isStatic = true;
278 sig = sig.mid(strlen("static_"));
278 sig = sig.mid(strlen("static_"));
279 int idx = sig.indexOf("_");
279 int idx = sig.indexOf("_");
280 if (idx>=0) {
280 if (idx>=0) {
281 sig = sig.mid(idx+1);
281 sig = sig.mid(idx+1);
282 }
282 }
283 }
283 }
284 }
284 }
285
285
286 result += QByteArray(" ") + sig;
286 result += QByteArray(" ") + sig;
287 result += "(";
287 result += "(";
288
288
289 int lastEntry = _parameters.count()-1;
289 int lastEntry = _parameters.count()-1;
290 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
290 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
291 if (_parameters.at(i).isConst) {
291 if (_parameters.at(i).isConst) {
292 result += "const ";
292 result += "const ";
293 }
293 }
294 result += _parameters.at(i).name;
294 result += _parameters.at(i).name;
295 if (_parameters.at(i).isPointer) {
295 if (_parameters.at(i).isPointer) {
296 result += "*";
296 result += "*";
297 }
297 }
298 if (!names.at(i-1).isEmpty()) {
298 if (!names.at(i-1).isEmpty()) {
299 result += " ";
299 result += " ";
300 result += names.at(i-1);
300 result += names.at(i-1);
301 }
301 }
302 if (i!=lastEntry) {
302 if (i!=lastEntry) {
303 result += ", ";
303 result += ", ";
304 }
304 }
305 }
305 }
306 result += ")";
306 result += ")";
307
307
308 if (isStatic) {
308 if (isStatic) {
309 result = QString("static ") + result;
309 result = QString("static ") + result;
310 }
310 }
311 if (isConstructor) {
311 if (isConstructor) {
312 // result = QString("constructor ") + result;
312 // result = QString("constructor ") + result;
313 }
313 }
314 if (isDestructor) {
314 if (isDestructor) {
315 result = QString("~") + result;
315 result = QString("~") + result;
316 }
316 }
317 return result;
317 return result;
318 }
318 }
319
319
320
320
321 QByteArray PythonQtSlotInfo::slotName()
321 QByteArray PythonQtSlotInfo::slotName()
322 {
322 {
323 QByteArray sig(_meta.signature());
323 QByteArray sig(_meta.signature());
324 int idx = sig.indexOf('(');
324 int idx = sig.indexOf('(');
325 sig = sig.left(idx);
325 sig = sig.left(idx);
326 return sig;
326 return sig;
327 }
327 }
328
328
General Comments 0
You need to be logged in to leave comments. Login now