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