##// END OF EJS Templates
merged in features from the MeVisLab repository...
florianlink -
r4:41816e302524
parent child
Show More
@@ -1,946 +1,1011
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 "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtImporter.h"
43 #include "PythonQtImporter.h"
44 #include "PythonQtClassInfo.h"
44 #include "PythonQtClassInfo.h"
45 #include "PythonQtMethodInfo.h"
45 #include "PythonQtMethodInfo.h"
46 #include "PythonQtSignalReceiver.h"
46 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtStdOut.h"
48 #include "PythonQtStdOut.h"
49 #include "PythonQtCppWrapperFactory.h"
49 #include "PythonQtCppWrapperFactory.h"
50 #include "PythonQtVariants.h"
50 #include "PythonQtVariants.h"
51 #include "PythonQtStdDecorators.h"
51 #include "PythonQtStdDecorators.h"
52 #include <pydebug.h>
52 #include <pydebug.h>
53
53
54 PythonQt* PythonQt::_self = NULL;
54 PythonQt* PythonQt::_self = NULL;
55 int PythonQt::_uniqueModuleCount = 0;
55
56
56
57
57 void PythonQt::init(int flags)
58 void PythonQt::init(int flags)
58 {
59 {
59 if (!_self) {
60 if (!_self) {
60 _self = new PythonQt(flags);
61 _self = new PythonQt(flags);
61 }
62 }
62
63
63 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
64 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
64 qRegisterMetaType<QList<QObject*> >("QList<void*>");
65 qRegisterMetaType<QList<QObject*> >("QList<void*>");
65
66
66 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
67 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
67
68
68 PythonQt::priv()->addVariantWrapper("QBitArray", new PythonQtQBitArrayWrapper);
69 PythonQt::priv()->addVariantWrapper("QBitArray", new PythonQtQBitArrayWrapper);
69 PythonQt::priv()->addVariantWrapper("QDate", new PythonQtQDateWrapper);
70 PythonQt::priv()->addVariantWrapper("QDate", new PythonQtQDateWrapper);
70 PythonQt::priv()->addVariantWrapper("QTime", new PythonQtQTimeWrapper);
71 PythonQt::priv()->addVariantWrapper("QTime", new PythonQtQTimeWrapper);
71 PythonQt::priv()->addVariantWrapper("QDateTime", new PythonQtQDateTimeWrapper);
72 PythonQt::priv()->addVariantWrapper("QDateTime", new PythonQtQDateTimeWrapper);
72 PythonQt::priv()->addVariantWrapper("QUrl", new PythonQtQUrlWrapper);
73 PythonQt::priv()->addVariantWrapper("QUrl", new PythonQtQUrlWrapper);
73 PythonQt::priv()->addVariantWrapper("QLocale", new PythonQtQLocaleWrapper);
74 PythonQt::priv()->addVariantWrapper("QLocale", new PythonQtQLocaleWrapper);
74 PythonQt::priv()->addVariantWrapper("QRect", new PythonQtQRectWrapper);
75 PythonQt::priv()->addVariantWrapper("QRect", new PythonQtQRectWrapper);
75 PythonQt::priv()->addVariantWrapper("QRectF", new PythonQtQRectFWrapper);
76 PythonQt::priv()->addVariantWrapper("QRectF", new PythonQtQRectFWrapper);
76 PythonQt::priv()->addVariantWrapper("QSize", new PythonQtQSizeWrapper);
77 PythonQt::priv()->addVariantWrapper("QSize", new PythonQtQSizeWrapper);
77 PythonQt::priv()->addVariantWrapper("QSizeF", new PythonQtQSizeFWrapper);
78 PythonQt::priv()->addVariantWrapper("QSizeF", new PythonQtQSizeFWrapper);
78 PythonQt::priv()->addVariantWrapper("QLine", new PythonQtQLineWrapper);
79 PythonQt::priv()->addVariantWrapper("QLine", new PythonQtQLineWrapper);
79 PythonQt::priv()->addVariantWrapper("QLineF", new PythonQtQLineFWrapper);
80 PythonQt::priv()->addVariantWrapper("QLineF", new PythonQtQLineFWrapper);
80 PythonQt::priv()->addVariantWrapper("QPoint", new PythonQtQPointWrapper);
81 PythonQt::priv()->addVariantWrapper("QPoint", new PythonQtQPointWrapper);
81 PythonQt::priv()->addVariantWrapper("QPointF", new PythonQtQPointFWrapper);
82 PythonQt::priv()->addVariantWrapper("QPointF", new PythonQtQPointFWrapper);
82 PythonQt::priv()->addVariantWrapper("QRegExp", new PythonQtQRegExpWrapper);
83 PythonQt::priv()->addVariantWrapper("QRegExp", new PythonQtQRegExpWrapper);
83 PythonQt::priv()->addVariantWrapper("QFont", new PythonQtQFontWrapper);
84 PythonQt::priv()->addVariantWrapper("QFont", new PythonQtQFontWrapper);
84 PythonQt::priv()->addVariantWrapper("QPixmap", new PythonQtQPixmapWrapper);
85 PythonQt::priv()->addVariantWrapper("QPixmap", new PythonQtQPixmapWrapper);
85 PythonQt::priv()->addVariantWrapper("QBrush", new PythonQtQBrushWrapper);
86 PythonQt::priv()->addVariantWrapper("QBrush", new PythonQtQBrushWrapper);
86 PythonQt::priv()->addVariantWrapper("QColor", new PythonQtQColorWrapper);
87 PythonQt::priv()->addVariantWrapper("QColor", new PythonQtQColorWrapper);
87 PythonQt::priv()->addVariantWrapper("QPalette", new PythonQtQPaletteWrapper);
88 PythonQt::priv()->addVariantWrapper("QPalette", new PythonQtQPaletteWrapper);
88 PythonQt::priv()->addVariantWrapper("QIcon", new PythonQtQIconWrapper);
89 PythonQt::priv()->addVariantWrapper("QIcon", new PythonQtQIconWrapper);
89 PythonQt::priv()->addVariantWrapper("QImage", new PythonQtQImageWrapper);
90 PythonQt::priv()->addVariantWrapper("QImage", new PythonQtQImageWrapper);
90 PythonQt::priv()->addVariantWrapper("QPolygon", new PythonQtQPolygonWrapper);
91 PythonQt::priv()->addVariantWrapper("QPolygon", new PythonQtQPolygonWrapper);
91 PythonQt::priv()->addVariantWrapper("QRegion", new PythonQtQRegionWrapper);
92 PythonQt::priv()->addVariantWrapper("QRegion", new PythonQtQRegionWrapper);
92 PythonQt::priv()->addVariantWrapper("QBitmap", new PythonQtQBitmapWrapper);
93 PythonQt::priv()->addVariantWrapper("QBitmap", new PythonQtQBitmapWrapper);
93 PythonQt::priv()->addVariantWrapper("QCursor", new PythonQtQCursorWrapper);
94 PythonQt::priv()->addVariantWrapper("QCursor", new PythonQtQCursorWrapper);
94 PythonQt::priv()->addVariantWrapper("QSizePolicy", new PythonQtQSizePolicyWrapper);
95 PythonQt::priv()->addVariantWrapper("QSizePolicy", new PythonQtQSizePolicyWrapper);
95 PythonQt::priv()->addVariantWrapper("QKeySequence", new PythonQtQKeySequenceWrapper);
96 PythonQt::priv()->addVariantWrapper("QKeySequence", new PythonQtQKeySequenceWrapper);
96 PythonQt::priv()->addVariantWrapper("QPen", new PythonQtQPenWrapper);
97 PythonQt::priv()->addVariantWrapper("QPen", new PythonQtQPenWrapper);
97 PythonQt::priv()->addVariantWrapper("QTextLength", new PythonQtQTextLengthWrapper);
98 PythonQt::priv()->addVariantWrapper("QTextLength", new PythonQtQTextLengthWrapper);
98 PythonQt::priv()->addVariantWrapper("QTextFormat", new PythonQtQTextFormatWrapper);
99 PythonQt::priv()->addVariantWrapper("QTextFormat", new PythonQtQTextFormatWrapper);
99 PythonQt::priv()->addVariantWrapper("QMatrix", new PythonQtQMatrixWrapper);
100 PythonQt::priv()->addVariantWrapper("QMatrix", new PythonQtQMatrixWrapper);
100
101
101 }
102 }
102
103
103 void PythonQt::cleanup()
104 void PythonQt::cleanup()
104 {
105 {
105 if (_self) {
106 if (_self) {
106 delete _self;
107 delete _self;
107 _self = NULL;
108 _self = NULL;
108 }
109 }
109 }
110 }
110
111
111 PythonQt::PythonQt(int flags)
112 PythonQt::PythonQt(int flags)
112 {
113 {
113 _p = new PythonQtPrivate;
114 _p = new PythonQtPrivate;
114 _p->_initFlags = flags;
115 _p->_initFlags = flags;
115
116
116 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
117 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
117
118
118 Py_SetProgramName("PythonQt");
119 Py_SetProgramName("PythonQt");
119 if (flags & IgnoreSiteModule) {
120 if (flags & IgnoreSiteModule) {
120 // this prevents the automatic importing of Python site files
121 // this prevents the automatic importing of Python site files
121 Py_NoSiteFlag = 1;
122 Py_NoSiteFlag = 1;
122 }
123 }
123 Py_Initialize();
124 Py_Initialize();
124
125
125 // add our own python object types for qt object slots
126 // add our own python object types for qt object slots
126 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
127 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
127 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
128 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
128 }
129 }
129 Py_INCREF(&PythonQtSlotFunction_Type);
130 Py_INCREF(&PythonQtSlotFunction_Type);
130
131
131 // add our own python object types for qt objects
132 // add our own python object types for qt objects
132 if (PyType_Ready(&PythonQtWrapper_Type) < 0) {
133 if (PyType_Ready(&PythonQtWrapper_Type) < 0) {
133 std::cerr << "could not initialize PythonQtWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
134 std::cerr << "could not initialize PythonQtWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
134 }
135 }
135 Py_INCREF(&PythonQtWrapper_Type);
136 Py_INCREF(&PythonQtWrapper_Type);
136
137
137 // add our own python object types for qt objects
138 // add our own python object types for qt objects
138 if (PyType_Ready(&PythonQtVariantWrapper_Type) < 0) {
139 if (PyType_Ready(&PythonQtVariantWrapper_Type) < 0) {
139 std::cerr << "could not initialize PythonQtVariantWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
140 std::cerr << "could not initialize PythonQtVariantWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
140 }
141 }
141 Py_INCREF(&PythonQtVariantWrapper_Type);
142 Py_INCREF(&PythonQtVariantWrapper_Type);
142
143
143 // add our own python object types for qt objects
144 // add our own python object types for qt objects
144 if (PyType_Ready(&PythonQtMetaObjectWrapper_Type) < 0) {
145 if (PyType_Ready(&PythonQtMetaObjectWrapper_Type) < 0) {
145 std::cerr << "could not initialize PythonQtMetaObjectWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
146 std::cerr << "could not initialize PythonQtMetaObjectWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
146 }
147 }
147 Py_INCREF(&PythonQtMetaObjectWrapper_Type);
148 Py_INCREF(&PythonQtMetaObjectWrapper_Type);
148
149
149 // add our own python object types for redirection of stdout
150 // add our own python object types for redirection of stdout
150 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
151 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
151 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
152 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
152 }
153 }
153 Py_INCREF(&PythonQtStdOutRedirectType);
154 Py_INCREF(&PythonQtStdOutRedirectType);
154
155
155 initPythonQtModule(flags & RedirectStdOut);
156 initPythonQtModule(flags & RedirectStdOut);
156
157
157 }
158 }
158
159
159 PythonQt::~PythonQt() {
160 PythonQt::~PythonQt() {
160 delete _p;
161 delete _p;
161 _p = NULL;
162 _p = NULL;
162 }
163 }
163
164
164 PythonQtPrivate::~PythonQtPrivate() {
165 PythonQtPrivate::~PythonQtPrivate() {
165 {
166 {
166 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownQtClasses);
167 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownQtClasses);
167 while (i.hasNext()) {
168 while (i.hasNext()) {
168 delete i.next().value();
169 delete i.next().value();
169 }
170 }
170 }
171 }
171 {
172 {
172 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownQtWrapperClasses);
173 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownQtWrapperClasses);
173 while (i.hasNext()) {
174 while (i.hasNext()) {
174 delete i.next().value();
175 delete i.next().value();
175 }
176 }
176 }
177 }
177 {
178 {
178 QHashIterator<int , QPair<PythonQtClassInfo*, QObject*> > i(_knownVariantWrappers);
179 QHashIterator<int , QPair<PythonQtClassInfo*, QObject*> > i(_knownVariantWrappers);
179 while (i.hasNext()) {
180 while (i.hasNext()) {
180 delete i.next().value().first;
181 delete i.next().value().first;
181 }
182 }
182 }
183 }
183 {
184 {
184 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_constructorSlots);
185 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_constructorSlots);
185 while (i.hasNext()) {
186 while (i.hasNext()) {
186 delete i.next().value();
187 delete i.next().value();
187 }
188 }
188 }
189 }
189 {
190 {
190 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_destructorSlots);
191 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_destructorSlots);
191 while (i.hasNext()) {
192 while (i.hasNext()) {
192 delete i.next().value();
193 delete i.next().value();
193 }
194 }
194 }
195 }
195 PythonQtConv::global_valueStorage.clear();
196 PythonQtConv::global_valueStorage.clear();
196 PythonQtConv::global_ptrStorage.clear();
197 PythonQtConv::global_ptrStorage.clear();
197 PythonQtConv::global_variantStorage.clear();
198 PythonQtConv::global_variantStorage.clear();
198
199
199 PythonQtMethodInfo::cleanupCachedMethodInfos();
200 PythonQtMethodInfo::cleanupCachedMethodInfos();
200
201
201 delete _qtNamespace;
202 delete _qtNamespace;
202 }
203 }
203
204
204 PythonQtImportFileInterface* PythonQt::importInterface()
205 PythonQtImportFileInterface* PythonQt::importInterface()
205 {
206 {
206 return _self->_p->_importInterface;
207 return _self->_p->_importInterface;
207 }
208 }
208
209
209 void PythonQt::registerClass(const QMetaObject* metaobject)
210 void PythonQt::registerClass(const QMetaObject* metaobject)
210 {
211 {
211 _p->registerClass(metaobject);
212 _p->registerClass(metaobject);
212 }
213 }
213
214
215 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
216 {
217 if (_self->_p->_noLongerWrappedCB) {
218 (*_self->_p->_noLongerWrappedCB)(o);
219 };
220 }
221
214 void PythonQtPrivate::registerClass(const QMetaObject* metaobject)
222 void PythonQtPrivate::registerClass(const QMetaObject* metaobject)
215 {
223 {
216 // we register all classes in the hierarchy
224 // we register all classes in the hierarchy
217 const QMetaObject* m = metaobject;
225 const QMetaObject* m = metaobject;
218 while (m) {
226 while (m) {
219 PythonQtClassInfo* info = _knownQtClasses.value(m->className());
227 PythonQtClassInfo* info = _knownQtClasses.value(m->className());
220 if (!info) {
228 if (!info) {
221 info = new PythonQtClassInfo(m);
229 info = new PythonQtClassInfo(m);
222 _knownQtClasses.insert(m->className(), info);
230 _knownQtClasses.insert(m->className(), info);
223 PyModule_AddObject(_pythonQtModule, m->className(), (PyObject*)createNewPythonQtMetaObjectWrapper(info));
231 PyModule_AddObject(_pythonQtModule, m->className(), (PyObject*)createNewPythonQtMetaObjectWrapper(info));
224 }
232 }
225 m = m->superClass();
233 m = m->superClass();
226 }
234 }
227 }
235 }
228
236
229 bool PythonQtPrivate::isEnumType(const QMetaObject* meta, const QByteArray& name) {
237 bool PythonQtPrivate::isEnumType(const QMetaObject* meta, const QByteArray& name) {
230 int i = meta?meta->indexOfEnumerator(name.constData()):-1;
238 int i = meta?meta->indexOfEnumerator(name.constData()):-1;
231 if (i!=-1) {
239 if (i!=-1) {
232 return true;
240 return true;
233 } else {
241 } else {
234 // look for scope
242 // look for scope
235 int scopePos = name.indexOf("::");
243 int scopePos = name.indexOf("::");
236 if (scopePos != -1) {
244 if (scopePos != -1) {
237 // slit into scope and enum name
245 // slit into scope and enum name
238 QByteArray enumScope = name.mid(0,scopePos);
246 QByteArray enumScope = name.mid(0,scopePos);
239 QByteArray enumName = name.mid(scopePos+2);
247 QByteArray enumName = name.mid(scopePos+2);
240 if (enumScope == "Qt") {
248 if (enumScope == "Qt") {
241 // special qt namespace case
249 // special qt namespace case
242 return isEnumType(&staticQtMetaObject, enumName);
250 return isEnumType(&staticQtMetaObject, enumName);
243 } else {
251 } else {
244 // look for known classes as scope
252 // look for known classes as scope
245 // TODO: Q_GADGETS are not yet handled
253 // TODO: Q_GADGETS are not yet handled
246 PythonQtClassInfo* info = _knownQtClasses.value(enumScope);
254 PythonQtClassInfo* info = _knownQtClasses.value(enumScope);
247 if (info) {
255 if (info) {
248 return isEnumType(info->metaObject(), enumName);
256 return isEnumType(info->metaObject(), enumName);
249 }
257 }
250 }
258 }
251 }
259 }
252 }
260 }
253 return false;
261 return false;
254 }
262 }
255
263
256 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
264 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
257 {
265 {
258 if (!obj) {
266 if (!obj) {
259 Py_INCREF(Py_None);
267 Py_INCREF(Py_None);
260 return Py_None;
268 return Py_None;
261 }
269 }
262 PythonQtWrapper* wrap = _wrappedObjects.value(obj);
270 PythonQtWrapper* wrap = findWrapperAndRemoveUnused(obj);
263 if (!wrap) {
271 if (!wrap) {
264 // smuggling it in...
272 // smuggling it in...
265 PythonQtClassInfo* classInfo = _knownQtClasses.value(obj->metaObject()->className());
273 PythonQtClassInfo* classInfo = _knownQtClasses.value(obj->metaObject()->className());
266 if (!classInfo) {
274 if (!classInfo) {
267 registerClass(obj->metaObject());
275 registerClass(obj->metaObject());
268 classInfo = _knownQtClasses.value(obj->metaObject()->className());
276 classInfo = _knownQtClasses.value(obj->metaObject()->className());
269 }
277 }
270 wrap = createNewPythonQtWrapper(obj, classInfo);
278 wrap = createNewPythonQtWrapper(obj, classInfo);
271 // insert destroyed handler
272 connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(wrappedObjectDestroyed(QObject*)));
273 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
279 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
274 } else {
280 } else {
275 Py_INCREF(wrap);
281 Py_INCREF(wrap);
276 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
282 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
277 }
283 }
278 return (PyObject*)wrap;
284 return (PyObject*)wrap;
279 }
285 }
280
286
281 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
287 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
282 {
288 {
283 if (!ptr) {
289 if (!ptr) {
284 Py_INCREF(Py_None);
290 Py_INCREF(Py_None);
285 return Py_None;
291 return Py_None;
286 }
292 }
287 PythonQtWrapper* wrap = _wrappedObjects.value(ptr);
293 PythonQtWrapper* wrap = findWrapperAndRemoveUnused(ptr);
288 if (!wrap) {
294 if (!wrap) {
289 PythonQtClassInfo* info = _knownQtClasses.value(name);
295 PythonQtClassInfo* info = _knownQtClasses.value(name);
290 if (!info) {
296 if (!info) {
291 // we do not know the metaobject yet, but we might know it by it's name:
297 // we do not know the metaobject yet, but we might know it by it's name:
292 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
298 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
293 // yes, we know it, so we can convert to QObject
299 // yes, we know it, so we can convert to QObject
294 QObject* qptr = (QObject*)ptr;
300 QObject* qptr = (QObject*)ptr;
295 registerClass(qptr->metaObject());
301 registerClass(qptr->metaObject());
296 info = _knownQtClasses.value(qptr->metaObject()->className());
302 info = _knownQtClasses.value(qptr->metaObject()->className());
297 }
303 }
298 }
304 }
299 if (info) {
305 if (info) {
300 QObject* qptr = (QObject*)ptr;
306 QObject* qptr = (QObject*)ptr;
301 // if the object is a derived object, we want to switch the class info to the one of the derived class:
307 // if the object is a derived object, we want to switch the class info to the one of the derived class:
302 if (name!=(qptr->metaObject()->className())) {
308 if (name!=(qptr->metaObject()->className())) {
303 registerClass(qptr->metaObject());
309 registerClass(qptr->metaObject());
304 info = _knownQtClasses.value(qptr->metaObject()->className());
310 info = _knownQtClasses.value(qptr->metaObject()->className());
305 }
311 }
306 wrap = createNewPythonQtWrapper(qptr, info);
312 wrap = createNewPythonQtWrapper(qptr, info);
307 // insert destroyed handler
308 connect(qptr, SIGNAL(destroyed(QObject*)), this, SLOT(wrappedObjectDestroyed(QObject*)));
309 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
313 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
310 } else {
314 } else {
311 // maybe it is a PyObject, which we can return directly
315 // maybe it is a PyObject, which we can return directly
312 if (name == "PyObject") {
316 if (name == "PyObject") {
313 PyObject* p = (PyObject*)ptr;
317 PyObject* p = (PyObject*)ptr;
314 Py_INCREF(p);
318 Py_INCREF(p);
315 return p;
319 return p;
316 }
320 }
317 // not a known QObject, so try our wrapper factory:
321 // not a known QObject, so try our wrapper factory:
318 QObject* wrapper = NULL;
322 QObject* wrapper = NULL;
319 for (int i=0; i<_cppWrapperFactories.size(); i++) {
323 for (int i=0; i<_cppWrapperFactories.size(); i++) {
320 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
324 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
321 if (wrapper) {
325 if (wrapper) {
322 break;
326 break;
323 }
327 }
324 }
328 }
325 PythonQtClassInfo* info = _knownQtWrapperClasses.value(name);
329 PythonQtClassInfo* info = _knownQtWrapperClasses.value(name);
326 if (!info) {
330 if (!info) {
327 info = new PythonQtClassInfo(wrapper?wrapper->metaObject():&QObject::staticQtMetaObject, name);
331 info = new PythonQtClassInfo(wrapper?wrapper->metaObject():&QObject::staticQtMetaObject, name);
328 _knownQtWrapperClasses.insert(name, info);
332 _knownQtWrapperClasses.insert(name, info);
329 PyModule_AddObject(_pythonQtModule, name, (PyObject*)createNewPythonQtMetaObjectWrapper(info));
333 PyModule_AddObject(_pythonQtModule, name, (PyObject*)createNewPythonQtMetaObjectWrapper(info));
330 } else {
334 } else {
331 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
335 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
332 info->setMetaObject(wrapper->metaObject());
336 info->setMetaObject(wrapper->metaObject());
333 }
337 }
334 }
338 }
335 wrap = createNewPythonQtWrapper(wrapper, info, ptr);
339 wrap = createNewPythonQtWrapper(wrapper, info, ptr);
336 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
340 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
337 }
341 }
338 } else {
342 } else {
339 Py_INCREF(wrap);
343 Py_INCREF(wrap);
340 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
344 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
341 }
345 }
342 return (PyObject*)wrap;
346 return (PyObject*)wrap;
343 }
347 }
344
348
345 void PythonQt::registerCPPClassNames(const QStringList& names)
349 void PythonQt::registerCPPClassNames(const QStringList& names)
346 {
350 {
347 foreach ( QString n, names) {
351 foreach ( QString n, names) {
348 QByteArray name = n.toLatin1();
352 QByteArray name = n.toLatin1();
349 PythonQtClassInfo* info = _p->_knownQtWrapperClasses.value(name);
353 PythonQtClassInfo* info = _p->_knownQtWrapperClasses.value(name);
350 if (!info) {
354 if (!info) {
351 info = new PythonQtClassInfo(&QObject::staticMetaObject, name);
355 info = new PythonQtClassInfo(&QObject::staticMetaObject, name);
352 _p->_knownQtWrapperClasses.insert(name, info);
356 _p->_knownQtWrapperClasses.insert(name, info);
353 PyModule_AddObject(_p->_pythonQtModule, name.data(), (PyObject*)_p->createNewPythonQtMetaObjectWrapper(info));
357 PyModule_AddObject(_p->_pythonQtModule, name.data(), (PyObject*)_p->createNewPythonQtMetaObjectWrapper(info));
354 }
358 }
355 }
359 }
356 }
360 }
357
361
358 PythonQtWrapper* PythonQtPrivate::createNewPythonQtWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
362 PythonQtWrapper* PythonQtPrivate::createNewPythonQtWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
359 PythonQtWrapper* result;
363 PythonQtWrapper* result;
360 result = (PythonQtWrapper *)PythonQtWrapper_Type.tp_new(&PythonQtWrapper_Type,
364 result = (PythonQtWrapper *)PythonQtWrapper_Type.tp_new(&PythonQtWrapper_Type,
361 NULL, NULL);
365 NULL, NULL);
362
366
363 result->_obj = obj;
367 result->setQObject(obj);
364 result->_info = info;
368 result->_info = info;
365 result->_wrappedPtr = wrappedPtr;
369 result->_wrappedPtr = wrappedPtr;
366 result->_ownedByPythonQt = false;
370 result->_ownedByPythonQt = false;
367
371
368 if (wrappedPtr) {
372 if (wrappedPtr) {
369 _wrappedObjects.insert(wrappedPtr, result);
373 _wrappedObjects.insert(wrappedPtr, result);
370 } else {
374 } else {
371 _wrappedObjects.insert(obj, result);
375 _wrappedObjects.insert(obj, result);
376 if (obj->parent()== NULL && _wrappedCB) {
377 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
378 (*_wrappedCB)(obj);
379 }
372 }
380 }
373 return result;
381 return result;
374 }
382 }
375
383
376 PythonQtVariantWrapper* PythonQtPrivate::createNewPythonQtVariantWrapper(const QVariant& variant) {
384 PythonQtVariantWrapper* PythonQtPrivate::createNewPythonQtVariantWrapper(const QVariant& variant) {
377 PythonQtVariantWrapper* result;
385 PythonQtVariantWrapper* result;
378 result = (PythonQtVariantWrapper *)PythonQtVariantWrapper_Type.tp_new(&PythonQtVariantWrapper_Type,
386 result = (PythonQtVariantWrapper *)PythonQtVariantWrapper_Type.tp_new(&PythonQtVariantWrapper_Type,
379 NULL, NULL);
387 NULL, NULL);
380
388
381 *result->_variant = variant;
389 *result->_variant = variant;
382 QPair<PythonQtClassInfo*, QObject*> pair = _knownVariantWrappers.value(variant.userType());
390 QPair<PythonQtClassInfo*, QObject*> pair = _knownVariantWrappers.value(variant.userType());
383 result->_wrapper = pair.second;
391 result->_wrapper = pair.second;
384 result->_info = pair.first;
392 result->_info = pair.first;
385 return result;
393 return result;
386 }
394 }
387
395
388 PythonQtMetaObjectWrapper* PythonQtPrivate::createNewPythonQtMetaObjectWrapper(PythonQtClassInfo* info) {
396 PythonQtMetaObjectWrapper* PythonQtPrivate::createNewPythonQtMetaObjectWrapper(PythonQtClassInfo* info) {
389 PythonQtMetaObjectWrapper* result;
397 PythonQtMetaObjectWrapper* result;
390 result = (PythonQtMetaObjectWrapper *)PythonQtMetaObjectWrapper_Type.tp_new(&PythonQtMetaObjectWrapper_Type,
398 result = (PythonQtMetaObjectWrapper *)PythonQtMetaObjectWrapper_Type.tp_new(&PythonQtMetaObjectWrapper_Type,
391 NULL, NULL);
399 NULL, NULL);
392 result->_info = info;
400 result->_info = info;
393 return result;
401 return result;
394 }
402 }
395
403
396
404
397 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
405 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
398 {
406 {
399 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
407 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
400 if (!r) {
408 if (!r) {
401 r = new PythonQtSignalReceiver(obj);
409 r = new PythonQtSignalReceiver(obj);
402 _p->_signalReceivers.insert(obj, r);
410 _p->_signalReceivers.insert(obj, r);
403 // insert destroyed handler
404 connect(obj, SIGNAL(destroyed(QObject*)), _p ,SLOT(destroyedSignalEmitter(QObject*)));
405 }
411 }
406 return r;
412 return r;
407 }
413 }
408
414
409 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
415 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
410 {
416 {
411 bool flag = false;
417 bool flag = false;
412 PythonQtObjectPtr callable = lookupCallable(module, objectname);
418 PythonQtObjectPtr callable = lookupCallable(module, objectname);
413 if (callable) {
419 if (callable) {
414 PythonQtSignalReceiver* r = getSignalReceiver(obj);
420 PythonQtSignalReceiver* r = getSignalReceiver(obj);
415 flag = r->addSignalHandler(signal, callable);
421 flag = r->addSignalHandler(signal, callable);
416 if (!flag) {
422 if (!flag) {
417 // signal not found
423 // signal not found
418 }
424 }
419 } else {
425 } else {
420 // callable not found
426 // callable not found
421 }
427 }
422 return flag;
428 return flag;
423 }
429 }
424
430
425 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
431 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
426 {
432 {
427 bool flag = false;
433 bool flag = false;
428 PythonQtSignalReceiver* r = getSignalReceiver(obj);
434 PythonQtSignalReceiver* r = getSignalReceiver(obj);
429 if (r) {
435 if (r) {
430 flag = r->addSignalHandler(signal, receiver);
436 flag = r->addSignalHandler(signal, receiver);
431 }
437 }
432 return flag;
438 return flag;
433 }
439 }
434
440
435 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
441 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
436 {
442 {
437 bool flag = false;
443 bool flag = false;
438 PythonQtObjectPtr callable = lookupCallable(module, objectname);
444 PythonQtObjectPtr callable = lookupCallable(module, objectname);
439 if (callable) {
445 if (callable) {
440 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
446 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
441 if (r) {
447 if (r) {
442 flag = r->removeSignalHandler(signal, callable);
448 flag = r->removeSignalHandler(signal, callable);
443 }
449 }
444 } else {
450 } else {
445 // callable not found
451 // callable not found
446 }
452 }
447 return flag;
453 return flag;
448 }
454 }
449
455
450 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
456 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
451 {
457 {
452 bool flag = false;
458 bool flag = false;
453 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
459 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
454 if (r) {
460 if (r) {
455 flag = r->removeSignalHandler(signal, receiver);
461 flag = r->removeSignalHandler(signal, receiver);
456 }
462 }
457 return flag;
463 return flag;
458 }
464 }
459
465
460 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
466 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
461 {
467 {
462 PythonQtObjectPtr p = lookupObject(module, name);
468 PythonQtObjectPtr p = lookupObject(module, name);
463 if (p) {
469 if (p) {
464 if (PyCallable_Check(p)) {
470 if (PyCallable_Check(p)) {
465 return p;
471 return p;
466 }
472 }
467 }
473 }
468 PyErr_Clear();
474 PyErr_Clear();
469 return NULL;
475 return NULL;
470 }
476 }
471
477
472 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
478 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
473 {
479 {
474 QStringList l = name.split('.');
480 QStringList l = name.split('.');
475 PythonQtObjectPtr p = module;
481 PythonQtObjectPtr p = module;
476 PythonQtObjectPtr prev;
482 PythonQtObjectPtr prev;
477 QString s;
483 QString s;
478 QByteArray b;
484 QByteArray b;
479 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
485 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
480 prev = p;
486 prev = p;
481 b = (*i).toLatin1();
487 b = (*i).toLatin1();
482 p.setNewRef(PyObject_GetAttrString(p, b.data()));
488 p.setNewRef(PyObject_GetAttrString(p, b.data()));
483 }
489 }
484 PyErr_Clear();
490 PyErr_Clear();
485 return p;
491 return p;
486 }
492 }
487
493
488 PythonQtObjectPtr PythonQt::getMainModule() {
494 PythonQtObjectPtr PythonQt::getMainModule() {
489 //both borrowed
495 //both borrowed
490 PythonQtObjectPtr dict = PyImport_GetModuleDict();
496 PythonQtObjectPtr dict = PyImport_GetModuleDict();
491 return PyDict_GetItemString(dict, "__main__");
497 return PyDict_GetItemString(dict, "__main__");
492 }
498 }
493
499
494 QVariant PythonQt::evalCode(PyObject* module, PyObject* pycode) {
500 QVariant PythonQt::evalCode(PyObject* module, PyObject* pycode) {
495 QVariant result;
501 QVariant result;
496 if (pycode) {
502 if (pycode) {
497 PyObject* r = PyEval_EvalCode((PyCodeObject*)pycode, PyModule_GetDict((PyObject*)module) , PyModule_GetDict((PyObject*)module));
503 PyObject* r = PyEval_EvalCode((PyCodeObject*)pycode, PyModule_GetDict((PyObject*)module) , PyModule_GetDict((PyObject*)module));
498 if (r) {
504 if (r) {
499 result = PythonQtConv::PyObjToQVariant(r);
505 result = PythonQtConv::PyObjToQVariant(r);
500 Py_DECREF(r);
506 Py_DECREF(r);
501 } else {
507 } else {
502 handleError();
508 handleError();
503 }
509 }
504 } else {
510 } else {
505 handleError();
511 handleError();
506 }
512 }
507 return result;
513 return result;
508 }
514 }
509
515
510 QVariant PythonQt::evalScript(PyObject* module, const QString& script, int start)
516 QVariant PythonQt::evalScript(PyObject* module, const QString& script, int start)
511 {
517 {
512 QVariant result;
518 QVariant result;
513 PythonQtObjectPtr p;
519 PythonQtObjectPtr p;
514 p.setNewRef(PyRun_String(script.toLatin1().data(), start, PyModule_GetDict(module), PyModule_GetDict(module)));
520 p.setNewRef(PyRun_String(script.toLatin1().data(), start, PyModule_GetDict(module), PyModule_GetDict(module)));
515 if (p) {
521 if (p) {
516 result = PythonQtConv::PyObjToQVariant(p);
522 result = PythonQtConv::PyObjToQVariant(p);
517 } else {
523 } else {
518 handleError();
524 handleError();
519 }
525 }
520 return result;
526 return result;
521 }
527 }
522
528
523 void PythonQt::evalFile(PyObject* module, const QString& filename)
529 void PythonQt::evalFile(PyObject* module, const QString& filename)
524 {
530 {
525 PythonQtObjectPtr code = parseFile(filename);
531 PythonQtObjectPtr code = parseFile(filename);
526 if (code) {
532 if (code) {
527 evalCode(module, code);
533 evalCode(module, code);
528 } else {
534 } else {
529 handleError();
535 handleError();
530 }
536 }
531 }
537 }
532
538
533 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
539 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
534 {
540 {
535 PythonQtObjectPtr p;
541 PythonQtObjectPtr p;
536 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
542 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
537 if (!p) {
543 if (!p) {
538 handleError();
544 handleError();
539 }
545 }
540 return p;
546 return p;
541 }
547 }
542
548
549 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
550 {
551 PythonQtObjectPtr code = parseFile(filename);
552 PythonQtObjectPtr module = _p->createModule(name, code);
553 return module;
554 }
555
556 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
557 {
558 PyErr_Clear();
559 QString scriptCode = script;
560 if (scriptCode.isEmpty()) {
561 // we always need at least a linefeed
562 scriptCode = "\n";
563 }
564 PythonQtObjectPtr pycode;
565 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
566 PythonQtObjectPtr module = _p->createModule(name, pycode);
567 return module;
568 }
569
570 PythonQtObjectPtr PythonQt::createUniqueModule()
571 {
572 static QString pyQtStr("PythonQt_module");
573 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
574 return createModuleFromScript(moduleName);
575 }
576
543 void PythonQt::addObject(PyObject* module, const QString& name, QObject* object)
577 void PythonQt::addObject(PyObject* module, const QString& name, QObject* object)
544 {
578 {
545 PyModule_AddObject(module, name.toLatin1().data(), _p->wrapQObject(object));
579 PyModule_AddObject(module, name.toLatin1().data(), _p->wrapQObject(object));
546 }
580 }
547
581
548 void PythonQt::addVariable(PyObject* module, const QString& name, const QVariant& v)
582 void PythonQt::addVariable(PyObject* module, const QString& name, const QVariant& v)
549 {
583 {
550 PyModule_AddObject(module, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
584 PyModule_AddObject(module, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
551 }
585 }
552
586
553 void PythonQt::removeVariable(PyObject* module, const QString& name)
587 void PythonQt::removeVariable(PyObject* module, const QString& name)
554 {
588 {
555 PyObject_DelAttrString(module, name.toLatin1().data());
589 PyObject_DelAttrString(module, name.toLatin1().data());
556 }
590 }
557
591
558 QVariant PythonQt::getVariable(PyObject* module, const QString& objectname)
592 QVariant PythonQt::getVariable(PyObject* module, const QString& objectname)
559 {
593 {
560 QVariant result;
594 QVariant result;
561 PythonQtObjectPtr obj = lookupObject(module, objectname);
595 PythonQtObjectPtr obj = lookupObject(module, objectname);
562 if (obj) {
596 if (obj) {
563 result = PythonQtConv::PyObjToQVariant(obj);
597 result = PythonQtConv::PyObjToQVariant(obj);
564 }
598 }
565 return result;
599 return result;
566 }
600 }
567
601
568 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
602 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
569 {
603 {
570 QStringList results;
604 QStringList results;
571
605
572 PythonQtObjectPtr object;
606 PythonQtObjectPtr object;
573 if (objectname.isEmpty()) {
607 if (objectname.isEmpty()) {
574 object = module;
608 object = module;
575 } else {
609 } else {
576 object = lookupObject(module, objectname);
610 object = lookupObject(module, objectname);
577 if (!object && type == CallOverloads) {
611 if (!object && type == CallOverloads) {
578 PyObject* dict = lookupObject(module, "__builtins__");
612 PyObject* dict = lookupObject(module, "__builtins__");
579 if (dict) {
613 if (dict) {
580 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
614 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
581 }
615 }
582 }
616 }
583 }
617 }
584
618
585 if (object) {
619 if (object) {
586 if (type == CallOverloads) {
620 if (type == CallOverloads) {
587 if (PythonQtSlotFunction_Check(object)) {
621 if (PythonQtSlotFunction_Check(object)) {
588 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
622 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
589 PythonQtSlotInfo* info = o->m_ml;
623 PythonQtSlotInfo* info = o->m_ml;
590
624
591 while (info) {
625 while (info) {
592 results << info->fullSignature(info->isInstanceDecorator() || o->m_self->ob_type == &PythonQtVariantWrapper_Type);
626 results << info->fullSignature(info->isInstanceDecorator() || o->m_self->ob_type == &PythonQtVariantWrapper_Type);
593 info = info->nextInfo();
627 info = info->nextInfo();
594 }
628 }
595 } else if (object->ob_type == &PythonQtMetaObjectWrapper_Type) {
629 } else if (object->ob_type == &PythonQtMetaObjectWrapper_Type) {
596 PythonQtMetaObjectWrapper* o = (PythonQtMetaObjectWrapper*)object.object();
630 PythonQtMetaObjectWrapper* o = (PythonQtMetaObjectWrapper*)object.object();
597 PythonQtSlotInfo* info = o->_info->constructors();
631 PythonQtSlotInfo* info = o->_info->constructors();
598
632
599 while (info) {
633 while (info) {
600 results << info->fullSignature(false);
634 results << info->fullSignature(false);
601 info = info->nextInfo();
635 info = info->nextInfo();
602 }
636 }
603 } else {
637 } else {
604 //TODO: use pydoc!
638 //TODO: use pydoc!
605 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
639 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
606 if (doc) {
640 if (doc) {
607 results << PyString_AsString(doc);
641 results << PyString_AsString(doc);
608 Py_DECREF(doc);
642 Py_DECREF(doc);
609 }
643 }
610 }
644 }
611 } else {
645 } else {
612 PyObject* keys = PyObject_Dir(object);
646 PyObject* keys = PyObject_Dir(object);
613 if (keys) {
647 if (keys) {
614 int count = PyList_Size(keys);
648 int count = PyList_Size(keys);
615 PyObject* key;
649 PyObject* key;
616 PyObject* value;
650 PyObject* value;
617 QString keystr;
651 QString keystr;
618 for (int i = 0;i<count;i++) {
652 for (int i = 0;i<count;i++) {
619 key = PyList_GetItem(keys,i);
653 key = PyList_GetItem(keys,i);
620 value = PyObject_GetAttr(object, key);
654 value = PyObject_GetAttr(object, key);
621 if (!value) continue;
655 if (!value) continue;
622 keystr = PyString_AsString(key);
656 keystr = PyString_AsString(key);
623 static const QString underscoreStr("__tmp");
657 static const QString underscoreStr("__tmp");
624 if (!keystr.startsWith(underscoreStr)) {
658 if (!keystr.startsWith(underscoreStr)) {
625 switch (type) {
659 switch (type) {
626 case Anything:
660 case Anything:
627 results << keystr;
661 results << keystr;
628 break;
662 break;
629 case Class:
663 case Class:
630 if (value->ob_type == &PyClass_Type) {
664 if (value->ob_type == &PyClass_Type) {
631 results << keystr;
665 results << keystr;
632 }
666 }
633 break;
667 break;
634 case Variable:
668 case Variable:
635 if (value->ob_type != &PyClass_Type
669 if (value->ob_type != &PyClass_Type
636 && value->ob_type != &PyCFunction_Type
670 && value->ob_type != &PyCFunction_Type
637 && value->ob_type != &PyFunction_Type
671 && value->ob_type != &PyFunction_Type
638 && value->ob_type != &PyModule_Type
672 && value->ob_type != &PyModule_Type
639 ) {
673 ) {
640 results << keystr;
674 results << keystr;
641 }
675 }
642 break;
676 break;
643 case Function:
677 case Function:
644 if (value->ob_type == &PyFunction_Type ||
678 if (value->ob_type == &PyFunction_Type ||
645 value->ob_type == &PyMethod_Type
679 value->ob_type == &PyMethod_Type
646 ) {
680 ) {
647 results << keystr;
681 results << keystr;
648 }
682 }
649 break;
683 break;
650 case Module:
684 case Module:
651 if (value->ob_type == &PyModule_Type) {
685 if (value->ob_type == &PyModule_Type) {
652 results << keystr;
686 results << keystr;
653 }
687 }
654 break;
688 break;
655 default:
689 default:
656 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
690 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
657 }
691 }
658 }
692 }
659 Py_DECREF(value);
693 Py_DECREF(value);
660 }
694 }
661 Py_DECREF(keys);
695 Py_DECREF(keys);
662 }
696 }
663 }
697 }
664 }
698 }
665 return results;
699 return results;
666 }
700 }
667
701
668 QVariant PythonQt::call(PyObject* module, const QString& name, const QVariantList& args)
702 QVariant PythonQt::call(PyObject* module, const QString& name, const QVariantList& args)
669 {
703 {
670 QVariant r;
704 QVariant r;
671
705
672 PythonQtObjectPtr callable = lookupCallable(module, name);
706 PythonQtObjectPtr callable = lookupCallable(module, name);
673 if (callable) {
707 if (callable) {
674 PythonQtObjectPtr pargs;
708 PythonQtObjectPtr pargs;
675 int count = args.size();
709 int count = args.size();
676 if (count>0) {
710 if (count>0) {
677 pargs.setNewRef(PyTuple_New(count));
711 pargs.setNewRef(PyTuple_New(count));
678 }
712 }
679 bool err = false;
713 bool err = false;
680 // transform QVariants to Python
714 // transform QVariants to Python
681 for (int i = 0; i < count; i++) {
715 for (int i = 0; i < count; i++) {
682 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
716 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
683 if (arg) {
717 if (arg) {
684 // steals reference, no unref
718 // steals reference, no unref
685 PyTuple_SetItem(pargs, i,arg);
719 PyTuple_SetItem(pargs, i,arg);
686 } else {
720 } else {
687 err = true;
721 err = true;
688 break;
722 break;
689 }
723 }
690 }
724 }
691
725
692 if (!err) {
726 if (!err) {
693 PyErr_Clear();
727 PyErr_Clear();
694 PythonQtObjectPtr result;
728 PythonQtObjectPtr result;
695 result.setNewRef(PyObject_CallObject(callable, pargs));
729 result.setNewRef(PyObject_CallObject(callable, pargs));
696 if (result) {
730 if (result) {
697 // ok
731 // ok
698 r = PythonQtConv::PyObjToQVariant(result);
732 r = PythonQtConv::PyObjToQVariant(result);
699 } else {
733 } else {
700 PythonQt::self()->handleError();
734 PythonQt::self()->handleError();
701 }
735 }
702 }
736 }
703 }
737 }
704 return r;
738 return r;
705 }
739 }
706
740
707 void PythonQt::addInstanceDecorators(QObject* o)
741 void PythonQt::addInstanceDecorators(QObject* o)
708 {
742 {
709 _p->addDecorators(o, true, false);
743 _p->addDecorators(o, true, false);
710 }
744 }
711
745
712 void PythonQt::addClassDecorators(QObject* o)
746 void PythonQt::addClassDecorators(QObject* o)
713 {
747 {
714 _p->addDecorators(o, false, true);
748 _p->addDecorators(o, false, true);
715 }
749 }
716
750
717 void PythonQt::addDecorators(QObject* o)
751 void PythonQt::addDecorators(QObject* o)
718 {
752 {
719 _p->addDecorators(o, true, true);
753 _p->addDecorators(o, true, true);
720 }
754 }
721
755
722 void PythonQt::registerQObjectClassNames(const QStringList& names)
756 void PythonQt::registerQObjectClassNames(const QStringList& names)
723 {
757 {
724 _p->registerQObjectClassNames(names);
758 _p->registerQObjectClassNames(names);
725 }
759 }
726
760
727 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
761 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
728 {
762 {
729 static bool first = true;
763 static bool first = true;
730 if (first) {
764 if (first) {
731 first = false;
765 first = false;
732 _p->_importInterface = importInterface;
766 _p->_importInterface = importInterface;
733 PythonQtImport::init();
767 PythonQtImport::init();
734 }
768 }
735 }
769 }
736
770
737 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
771 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
738 {
772 {
739 _p->_importIgnorePaths = paths;
773 _p->_importIgnorePaths = paths;
740 }
774 }
741
775
742 const QStringList& PythonQt::getImporterIgnorePaths()
776 const QStringList& PythonQt::getImporterIgnorePaths()
743 {
777 {
744 return _p->_importIgnorePaths;
778 return _p->_importIgnorePaths;
745 }
779 }
746
780
747 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
781 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
748 {
782 {
749 _p->_cppWrapperFactories.append(factory);
783 _p->_cppWrapperFactories.append(factory);
750 }
784 }
751
785
752 void PythonQt::addConstructorHandler(PythonQtConstructorHandler* factory)
786 void PythonQt::addConstructorHandler(PythonQtConstructorHandler* factory)
753 {
787 {
754 _p->_constructorHandlers.append(factory);
788 _p->_constructorHandlers.append(factory);
755 }
789 }
756
790
757 const QList<PythonQtConstructorHandler*>& PythonQt::constructorHandlers()
791 const QList<PythonQtConstructorHandler*>& PythonQt::constructorHandlers()
758 {
792 {
759 return _p->_constructorHandlers;
793 return _p->_constructorHandlers;
760 };
794 };
761
795
762 //---------------------------------------------------------------------------------------------------
796 //---------------------------------------------------------------------------------------------------
763 PythonQtPrivate::PythonQtPrivate()
797 PythonQtPrivate::PythonQtPrivate()
764 {
798 {
765 _importInterface = NULL;
799 _importInterface = NULL;
800 _noLongerWrappedCB = NULL;
801 _wrappedCB = NULL;
766 }
802 }
767
803
768 void PythonQtPrivate::addDecorators(QObject* o, bool instanceDeco, bool classDeco)
804 void PythonQtPrivate::addDecorators(QObject* o, bool instanceDeco, bool classDeco)
769 {
805 {
770 o->setParent(this);
806 o->setParent(this);
771 int numMethods = o->metaObject()->methodCount();
807 int numMethods = o->metaObject()->methodCount();
772 for (int i = 0; i < numMethods; i++) {
808 for (int i = 0; i < numMethods; i++) {
773 QMetaMethod m = o->metaObject()->method(i);
809 QMetaMethod m = o->metaObject()->method(i);
774 if ((m.methodType() == QMetaMethod::Method ||
810 if ((m.methodType() == QMetaMethod::Method ||
775 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
811 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
776 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m);
812 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m);
777 if (qstrncmp(m.signature(), "new_", 4)==0) {
813 if (qstrncmp(m.signature(), "new_", 4)==0) {
778 if (!classDeco) continue;
814 if (!classDeco) continue;
779 // either it returns a * or a QVariant and the name starts with "new_"
815 // either it returns a * or a QVariant and the name starts with "new_"
780 bool isVariantReturn = info->parameters().at(0).typeId == PythonQtMethodInfo::Variant;
816 bool isVariantReturn = info->parameters().at(0).typeId == PythonQtMethodInfo::Variant;
781 if ((info->parameters().at(0).isPointer || isVariantReturn)) {
817 if ((info->parameters().at(0).isPointer || isVariantReturn)) {
782 QByteArray signature = m.signature();
818 QByteArray signature = m.signature();
783 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
819 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
784 PythonQtSlotInfo* prev = _constructorSlots.value(nameOfClass);
820 PythonQtSlotInfo* prev = _constructorSlots.value(nameOfClass);
785 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
821 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
786 if (prev) {
822 if (prev) {
787 newSlot->setNextInfo(prev->nextInfo());
823 newSlot->setNextInfo(prev->nextInfo());
788 prev->setNextInfo(newSlot);
824 prev->setNextInfo(newSlot);
789 } else {
825 } else {
790 _constructorSlots.insert(nameOfClass, newSlot);
826 _constructorSlots.insert(nameOfClass, newSlot);
791 }
827 }
792 }
828 }
793 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
829 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
794 if (!classDeco) continue;
830 if (!classDeco) continue;
795 QByteArray signature = m.signature();
831 QByteArray signature = m.signature();
796 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
832 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
797 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
833 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
798 _destructorSlots.insert(nameOfClass, newSlot);
834 _destructorSlots.insert(nameOfClass, newSlot);
799 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
835 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
800 if (!classDeco) continue;
836 if (!classDeco) continue;
801 QByteArray signature = m.signature();
837 QByteArray signature = m.signature();
802 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
838 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
803 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
839 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
804 PythonQtSlotInfo* slotCopy = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
840 PythonQtSlotInfo* slotCopy = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
805 _knownQtDecoratorSlots.insert(nameOfClass, slotCopy);
841 _knownQtDecoratorSlots.insert(nameOfClass, slotCopy);
806 } else {
842 } else {
807 if (!instanceDeco) continue;
843 if (!instanceDeco) continue;
808 if (info->parameters().count()>1) {
844 if (info->parameters().count()>1) {
809 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
845 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
810 if (p.isPointer) {
846 if (p.isPointer) {
811 PythonQtSlotInfo* slotCopy = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::InstanceDecorator);
847 PythonQtSlotInfo* slotCopy = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::InstanceDecorator);
812 _knownQtDecoratorSlots.insert(p.name, slotCopy);
848 _knownQtDecoratorSlots.insert(p.name, slotCopy);
813 }
849 }
814 }
850 }
815 }
851 }
816 }
852 }
817 }
853 }
818 }
854 }
819
855
820 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
856 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
821 {
857 {
822 foreach(QString name, names) {
858 foreach(QString name, names) {
823 _knownQObjectClassNames.insert(name.toLatin1(), true);
859 _knownQObjectClassNames.insert(name.toLatin1(), true);
824 }
860 }
825 }
861 }
826
862
827 QList<PythonQtSlotInfo*> PythonQtPrivate::getDecoratorSlots(const QByteArray& className)
863 QList<PythonQtSlotInfo*> PythonQtPrivate::getDecoratorSlots(const QByteArray& className)
828 {
864 {
829 return _knownQtDecoratorSlots.values(className);
865 return _knownQtDecoratorSlots.values(className);
830 }
866 }
831
867
832 void PythonQtPrivate::wrappedObjectDestroyed(QObject* obj)
868 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
833 {
869 {
834 // mlabDebugConst("MLABPython","PyWrapper QObject destroyed " << o << " " << o->name() << " " << o->className());
870 _signalReceivers.remove(obj);
835 PythonQtWrapper* wrap = _wrappedObjects[obj];
836 if (wrap) {
837 _wrappedObjects.remove(obj);
838 // remove the pointer but keep the wrapper alive in python
839 wrap->_obj = NULL;
840 }
841 }
842
843 void PythonQtPrivate::destroyedSignalEmitter(QObject* obj)
844 {
845 _signalReceivers.take(obj);
846 }
871 }
847
872
848 bool PythonQt::handleError()
873 bool PythonQt::handleError()
849 {
874 {
850 bool flag = false;
875 bool flag = false;
851 if (PyErr_Occurred()) {
876 if (PyErr_Occurred()) {
852
877
853 // currently we just print the error and the stderr handler parses the errors
878 // currently we just print the error and the stderr handler parses the errors
854 PyErr_Print();
879 PyErr_Print();
855
880
856 /*
881 /*
857 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
882 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
858 PyObject *ptype;
883 PyObject *ptype;
859 PyObject *pvalue;
884 PyObject *pvalue;
860 PyObject *ptraceback;
885 PyObject *ptraceback;
861 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
886 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
862
887
863 Py_XDECREF(ptype);
888 Py_XDECREF(ptype);
864 Py_XDECREF(pvalue);
889 Py_XDECREF(pvalue);
865 Py_XDECREF(ptraceback);
890 Py_XDECREF(ptraceback);
866 */
891 */
867 PyErr_Clear();
892 PyErr_Clear();
868 flag = true;
893 flag = true;
869 }
894 }
870 return flag;
895 return flag;
871 }
896 }
872
897
873 void PythonQt::overwriteSysPath(const QStringList& paths)
898 void PythonQt::overwriteSysPath(const QStringList& paths)
874 {
899 {
875 PythonQtObjectPtr sys;
900 PythonQtObjectPtr sys;
876 sys.setNewRef(PyImport_ImportModule("sys"));
901 sys.setNewRef(PyImport_ImportModule("sys"));
877 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
902 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
878 }
903 }
879
904
880 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
905 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
881 {
906 {
882 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
907 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
883 }
908 }
884
909
885 void PythonQt::stdOutRedirectCB(const QString& str)
910 void PythonQt::stdOutRedirectCB(const QString& str)
886 {
911 {
887 emit PythonQt::self()->pythonStdOut(str);
912 emit PythonQt::self()->pythonStdOut(str);
888 }
913 }
889
914
890 void PythonQt::stdErrRedirectCB(const QString& str)
915 void PythonQt::stdErrRedirectCB(const QString& str)
891 {
916 {
892 emit PythonQt::self()->pythonStdErr(str);
917 emit PythonQt::self()->pythonStdErr(str);
893 }
918 }
894
919
920 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
921 {
922 _p->_wrappedCB = cb;
923 }
924
925 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
926 {
927 _p->_noLongerWrappedCB = cb;
928 }
929
895
930
896
931
897 static PyMethodDef PythonQtMethods[] = {
932 static PyMethodDef PythonQtMethods[] = {
898 {NULL, NULL, 0, NULL}
933 {NULL, NULL, 0, NULL}
899 };
934 };
900
935
901 void PythonQt::initPythonQtModule(bool redirectStdOut)
936 void PythonQt::initPythonQtModule(bool redirectStdOut)
902 {
937 {
903 _p->_pythonQtModule.setNewRef(Py_InitModule("PythonQt", PythonQtMethods));
938 _p->_pythonQtModule.setNewRef(Py_InitModule("PythonQt", PythonQtMethods));
904 _p->_qtNamespace = new PythonQtClassInfo(&staticQtMetaObject);
939 _p->_qtNamespace = new PythonQtClassInfo(&staticQtMetaObject);
905 PyModule_AddObject(_p->_pythonQtModule, "Qt", (PyObject*)_p->createNewPythonQtMetaObjectWrapper(_p->_qtNamespace));
940 PyModule_AddObject(_p->_pythonQtModule, "Qt", (PyObject*)_p->createNewPythonQtMetaObjectWrapper(_p->_qtNamespace));
906
941
907 if (redirectStdOut) {
942 if (redirectStdOut) {
908 PythonQtObjectPtr sys;
943 PythonQtObjectPtr sys;
909 PythonQtObjectPtr out;
944 PythonQtObjectPtr out;
910 PythonQtObjectPtr err;
945 PythonQtObjectPtr err;
911 sys.setNewRef(PyImport_ImportModule("sys"));
946 sys.setNewRef(PyImport_ImportModule("sys"));
912 // create a redirection object for stdout and stderr
947 // create a redirection object for stdout and stderr
913 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
948 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
914 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
949 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
915 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
950 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
916 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
951 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
917 // replace the built in file objects with our own objects
952 // replace the built in file objects with our own objects
918 PyModule_AddObject(sys, "stdout", out);
953 PyModule_AddObject(sys, "stdout", out);
919 PyModule_AddObject(sys, "stderr", err);
954 PyModule_AddObject(sys, "stderr", err);
920 }
955 }
921 }
956 }
922
957
923 void PythonQt::addVariantWrapper(const char* typeName, QObject* wrapper)
958 void PythonQt::addVariantWrapper(const char* typeName, QObject* wrapper)
924 {
959 {
925 _p->addVariantWrapper(typeName, wrapper);
960 _p->addVariantWrapper(typeName, wrapper);
926 }
961 }
927
962
928
963
929 void PythonQtPrivate::addVariantWrapper(const char* typeName, QObject* wrapper)
964 void PythonQtPrivate::addVariantWrapper(const char* typeName, QObject* wrapper)
930 {
965 {
931 int type = QMetaType::type(typeName);
966 int type = QMetaType::type(typeName);
932 PythonQtClassInfo* info = new PythonQtClassInfo(wrapper->metaObject(), typeName);
967 PythonQtClassInfo* info = new PythonQtClassInfo(wrapper->metaObject(), typeName);
933 _knownVariantWrappers.insert(type, qMakePair(info, wrapper));
968 _knownVariantWrappers.insert(type, qMakePair(info, wrapper));
934 addDecorators(wrapper, false, true);
969 addDecorators(wrapper, false, true);
935 PyModule_AddObject(_pythonQtModule, typeName, (PyObject*)createNewPythonQtMetaObjectWrapper(info));
970 PyModule_AddObject(_pythonQtModule, typeName, (PyObject*)createNewPythonQtMetaObjectWrapper(info));
936 }
971 }
937
972
938 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
973 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
939 {
974 {
940 if (_p->_initFlags & ExternalHelp) {
975 if (_p->_initFlags & ExternalHelp) {
941 emit pythonHelpRequest(QByteArray(info->className()));
976 emit pythonHelpRequest(QByteArray(info->className()));
942 return Py_BuildValue("");
977 return Py_BuildValue("");
943 } else {
978 } else {
944 return PyString_FromString(info->help().toLatin1().data());
979 return PyString_FromString(info->help().toLatin1().data());
945 }
980 }
946 }
981 }
982
983 void PythonQtPrivate::removeWrapperPointer(void* obj)
984 {
985 _wrappedObjects.remove(obj);
986 }
987
988 PythonQtWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
989 {
990 PythonQtWrapper* wrap = _wrappedObjects.value(obj);
991 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
992 // this is a wrapper whose QObject was already removed due to destruction
993 // so the obj pointer has to be a new QObject with the same address...
994 // we remove the old one and set the copy to NULL
995 wrap->_objPointerCopy = NULL;
996 removeWrapperPointer(obj);
997 wrap = NULL;
998 }
999 return wrap;
1000 }
1001
1002 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1003 {
1004 PythonQtObjectPtr result;
1005 if (pycode) {
1006 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1007 } else {
1008 PythonQt::self()->handleError();
1009 }
1010 return result;
1011 }
@@ -1,436 +1,469
1 #ifndef _PYTHONQT_H
1 #ifndef _PYTHONQT_H
2 #define _PYTHONQT_H
2 #define _PYTHONQT_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 PythonQt.h
38 // \file PythonQt.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include "PythonQtWrapper.h"
46 #include "PythonQtWrapper.h"
47 #include "PythonQtVariantWrapper.h"
47 #include "PythonQtVariantWrapper.h"
48 #include "PythonQtMetaObjectWrapper.h"
48 #include "PythonQtMetaObjectWrapper.h"
49 #include "PythonQtSlot.h"
49 #include "PythonQtSlot.h"
50 #include "PythonQtObjectPtr.h"
50 #include "PythonQtObjectPtr.h"
51 #include <QObject>
51 #include <QObject>
52 #include <QVariant>
52 #include <QVariant>
53 #include <QList>
53 #include <QList>
54 #include <QHash>
54 #include <QHash>
55 #include <QByteArray>
55 #include <QByteArray>
56 #include <QStringList>
56 #include <QStringList>
57 #include <QtDebug>
57 #include <QtDebug>
58 #include <iostream>
58 #include <iostream>
59
59
60
60
61 class PythonQtClassInfo;
61 class PythonQtClassInfo;
62 class PythonQtPrivate;
62 class PythonQtPrivate;
63 class PythonQtMethodInfo;
63 class PythonQtMethodInfo;
64 class PythonQtSignalReceiver;
64 class PythonQtSignalReceiver;
65 class PythonQtImportFileInterface;
65 class PythonQtImportFileInterface;
66 class PythonQtCppWrapperFactory;
66 class PythonQtCppWrapperFactory;
67 class PythonQtConstructorHandler;
67 class PythonQtConstructorHandler;
68
68
69 typedef void PythonQtQObjectWrappedCB(QObject* object);
70 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
71
69 //! the main interface to the Python Qt binding, realized as a singleton
72 //! the main interface to the Python Qt binding, realized as a singleton
70 class PYTHONQT_EXPORT PythonQt : public QObject {
73 class PYTHONQT_EXPORT PythonQt : public QObject {
71
74
72 Q_OBJECT
75 Q_OBJECT
73
76
74 public:
77 public:
75 enum InitFlags {
78 enum InitFlags {
76 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
79 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
77 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
80 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
78 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
81 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
79 };
82 };
80
83
81 //! initialize the python qt binding (flags are a or combination of InitFlags)
84 //! initialize the python qt binding (flags are a or combination of InitFlags)
82 static void init(int flags = IgnoreSiteModule | RedirectStdOut);
85 static void init(int flags = IgnoreSiteModule | RedirectStdOut);
83
86
84 //! cleanup
87 //! cleanup
85 static void cleanup();
88 static void cleanup();
86
89
87 //! get the singleton instance
90 //! get the singleton instance
88 static PythonQt* self() { return _self; }
91 static PythonQt* self() { return _self; }
89
92
90 //-----------------------------------------------------------------------------
93 //-----------------------------------------------------------------------------
91 // Public API:
94 // Public API:
92
95
93 //! defines the object types for introspection
96 //! defines the object types for introspection
94 enum ObjectType {
97 enum ObjectType {
95 Class,
98 Class,
96 Function,
99 Function,
97 Variable,
100 Variable,
98 Module,
101 Module,
99 Anything,
102 Anything,
100 CallOverloads
103 CallOverloads
101 };
104 };
102
105
103 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
106 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
104 void overwriteSysPath(const QStringList& paths);
107 void overwriteSysPath(const QStringList& paths);
105
108
106 //! sets the __path__ list of a module to the given list (important for local imports)
109 //! sets the __path__ list of a module to the given list (important for local imports)
107 void setModuleImportPath(PyObject* module, const QStringList& paths);
110 void setModuleImportPath(PyObject* module, const QStringList& paths);
108
111
109 //! get the __main__ module of python
112 //! get the __main__ module of python
110 PythonQtObjectPtr getMainModule();
113 PythonQtObjectPtr getMainModule();
111
114
112 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
115 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
113 //! All added metaobjects will be visible under the className in the PythonQt module as MetaObjectWrappers and the enums
116 //! All added metaobjects will be visible under the className in the PythonQt module as MetaObjectWrappers and the enums
114 //! and constructors (added by addConstructors) will be available.
117 //! and constructors (added by addConstructors) will be available.
115 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
118 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
116 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
119 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
117 void registerClass(const QMetaObject* metaobject);
120 void registerClass(const QMetaObject* metaobject);
118
121
119 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
122 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
120 //! and it will register the classes when it first sees a pointer to such a derived class
123 //! and it will register the classes when it first sees a pointer to such a derived class
121 void registerQObjectClassNames(const QStringList& names);
124 void registerQObjectClassNames(const QStringList& names);
122
125
123 //! this will register CPP classnames as known CPP classes (NOT QObjects) and make their MetaObjectWrapper available in
126 //! this will register CPP classnames as known CPP classes (NOT QObjects) and make their MetaObjectWrapper available in
124 //! the PythonQt module. In combination with addConstuctors(), this can be used to create CPP objects from PythonQt
127 //! the PythonQt module. In combination with addConstuctors(), this can be used to create CPP objects from PythonQt
125 void registerCPPClassNames(const QStringList& names);
128 void registerCPPClassNames(const QStringList& names);
126
129
127 //! parses the given file and returns the python code object, this can then be used to call evalCode()
130 //! parses the given file and returns the python code object, this can then be used to call evalCode()
128 PythonQtObjectPtr parseFile(const QString& filename);
131 PythonQtObjectPtr parseFile(const QString& filename);
129
132
130 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
133 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
131 //! If pycode is NULL, a python error is printed.
134 //! If pycode is NULL, a python error is printed.
132 QVariant evalCode(PyObject* module, PyObject* pycode);
135 QVariant evalCode(PyObject* module, PyObject* pycode);
133
136
134 //! evaluates the given script code and returns the result value
137 //! evaluates the given script code and returns the result value
135 QVariant evalScript(PyObject* module, const QString& script, int start = Py_file_input);
138 QVariant evalScript(PyObject* module, const QString& script, int start = Py_file_input);
136
139
137 //! evaluates the given script code from file
140 //! evaluates the given script code from file
138 void evalFile(PyObject* module, const QString& filename);
141 void evalFile(PyObject* module, const QString& filename);
139
142
143 //! creates the new module \c name and evaluates the given file in the context of that module
144 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
145 //! to a module later on.
146 //! The user needs to make sure that the \c name is unique in the python module dictionary.
147 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
148
149 //! creates the new module \c name and evaluates the given script in the context of that module.
150 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
151 //! to a module later on.
152 //! The user needs to make sure that the \c name is unique in the python module dictionary.
153 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
154
155 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
156 //! script code
157 PythonQtObjectPtr createUniqueModule();
158
140 //@{ Signal handlers
159 //@{ Signal handlers
141
160
142 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
161 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
143 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
162 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
144
163
145 //! remove a signal handler from the given \c signal of \c obj
164 //! remove a signal handler from the given \c signal of \c obj
146 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
165 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
147
166
148 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
167 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
149 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
168 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
150
169
151 //! remove a signal handler from the given \c signal of \c obj
170 //! remove a signal handler from the given \c signal of \c obj
152 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
171 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
153
172
154 //@}
173 //@}
155
174
156 //@{ Variable access
175 //@{ Variable access
157
176
158 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
177 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
159 void addObject(PyObject* module, const QString& name, QObject* object);
178 void addObject(PyObject* module, const QString& name, QObject* object);
160
179
161 //! add the given variable to the module
180 //! add the given variable to the module
162 void addVariable(PyObject* module, const QString& name, const QVariant& v);
181 void addVariable(PyObject* module, const QString& name, const QVariant& v);
163
182
164 //! remove the given variable
183 //! remove the given variable
165 void removeVariable(PyObject* module, const QString& name);
184 void removeVariable(PyObject* module, const QString& name);
166
185
167 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
186 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
168 QVariant getVariable(PyObject* module, const QString& name);
187 QVariant getVariable(PyObject* module, const QString& name);
169
188
170 //! read vars etc. in scope of a module, optional looking inside of an object \c objectname
189 //! read vars etc. in scope of a module, optional looking inside of an object \c objectname
171 QStringList introspection(PyObject* module, const QString& objectname, ObjectType type);
190 QStringList introspection(PyObject* module, const QString& objectname, ObjectType type);
172
191
173 //! returns the found callable object or NULL
192 //! returns the found callable object or NULL
174 //! @return new reference
193 //! @return new reference
175 PythonQtObjectPtr lookupCallable(PyObject* module, const QString& name);
194 PythonQtObjectPtr lookupCallable(PyObject* module, const QString& name);
176
195
177 //@}
196 //@}
178
197
179 //@{ Calling of python callables
198 //@{ Calling of python callables
180
199
181 //! call the given python method, returns the result converted to a QVariant
200 //! call the given python method, returns the result converted to a QVariant
182 QVariant call(PyObject* module, const QString& callable, const QVariantList& args);
201 QVariant call(PyObject* module, const QString& callable, const QVariantList& args);
183
202
184 //@}
203 //@}
185
204
186 //@{ Decorations, constructors, wrappers...
205 //@{ Decorations, constructors, wrappers...
187
206
188
207
189 //! add an object whose slots will be used as decorator slots for
208 //! add an object whose slots will be used as decorator slots for
190 //! other QObjects or CPP classes. The slots need to follow the
209 //! other QObjects or CPP classes. The slots need to follow the
191 //! convention that the first argument is a pointer to the wrapped object.
210 //! convention that the first argument is a pointer to the wrapped object.
192 //! (ownership is passed to PythonQt)
211 //! (ownership is passed to PythonQt)
193 /*!
212 /*!
194 Example:
213 Example:
195
214
196 A slot with the signature
215 A slot with the signature
197
216
198 \code
217 \code
199 bool doSomething(QWidget* w, int a)
218 bool doSomething(QWidget* w, int a)
200 \endcode
219 \endcode
201
220
202 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
221 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
203 that will be called with the concrete instance as first argument.
222 that will be called with the concrete instance as first argument.
204 So in Python you can now e.g. call
223 So in Python you can now e.g. call
205
224
206 \code
225 \code
207 someWidget.doSomething(12)
226 someWidget.doSomething(12)
208 \endcode
227 \endcode
209
228
210 without QWidget really having this method. This allows to easily make normal methods
229 without QWidget really having this method. This allows to easily make normal methods
211 of Qt classes callable by forwarding them with such decorator slots
230 of Qt classes callable by forwarding them with such decorator slots
212 or to make CPP classes (which are not derived from QObject) callable from Python.
231 or to make CPP classes (which are not derived from QObject) callable from Python.
213 */
232 */
214 void addInstanceDecorators(QObject* o);
233 void addInstanceDecorators(QObject* o);
215
234
216 //! add an object whose slots will be used as decorator slots for
235 //! add an object whose slots will be used as decorator slots for
217 //! class objects (ownership is passed to PythonQt)
236 //! class objects (ownership is passed to PythonQt)
218 /*!
237 /*!
219 The slots need to follow the following convention:
238 The slots need to follow the following convention:
220 - SomeClass* new_SomeClass(...)
239 - SomeClass* new_SomeClass(...)
221 - QVariant new_SomeClass(...)
240 - QVariant new_SomeClass(...)
222 - void delete_SomeClass(SomeClass*)
241 - void delete_SomeClass(SomeClass*)
223 - ... static_SomeClass_someName(...)
242 - ... static_SomeClass_someName(...)
224
243
225 This will add:
244 This will add:
226 - a constructor
245 - a constructor
227 - a constructor which generates a QVariant
246 - a constructor which generates a QVariant
228 - a destructor (only useful for CPP objects)
247 - a destructor (only useful for CPP objects)
229 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
248 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
230
249
231 */
250 */
232 void addClassDecorators(QObject* o);
251 void addClassDecorators(QObject* o);
233
252
234 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
253 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
235 void addDecorators(QObject* o);
254 void addDecorators(QObject* o);
236
255
237 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
256 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
238 //! (ownership of wrapper is passed to PythonQt)
257 //! (ownership of wrapper is passed to PythonQt)
239 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
258 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
240
259
241 This will add a wrapper object that is used to make calls to the given classname \c typeName.
260 This will add a wrapper object that is used to make calls to the given classname \c typeName.
242 All slots that take a pointer to typeName as the first argument will be callable from Python on
261 All slots that take a pointer to typeName as the first argument will be callable from Python on
243 a variant object that contains such a type.
262 a variant object that contains such a type.
244 */
263 */
245 void addVariantWrapper(const char* typeName, QObject* wrapper);
264 void addVariantWrapper(const char* typeName, QObject* wrapper);
246
265
247 //! add the given factory to PythonQt (ownership stays with caller)
266 //! add the given factory to PythonQt (ownership stays with caller)
248 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
267 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
249
268
250 //! add the given constructor handler to PythonQt (ownership stays with caller)
269 //! add the given constructor handler to PythonQt (ownership stays with caller)
251 void addConstructorHandler(PythonQtConstructorHandler* handler);
270 void addConstructorHandler(PythonQtConstructorHandler* handler);
252
271
253 //! get list of constructor handlers
272 //! get list of constructor handlers
254 const QList<PythonQtConstructorHandler*>& constructorHandlers();
273 const QList<PythonQtConstructorHandler*>& constructorHandlers();
255
274
256 //@}
275 //@}
257
276
258 //@{ Custom importer (to replace internal import implementation of python)
277 //@{ Custom importer (to replace internal import implementation of python)
259
278
260 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
279 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
261 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
280 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
262 //! It can only be called once, further calls will be ignored silently. (ownership stays with caller)
281 //! It can only be called once, further calls will be ignored silently. (ownership stays with caller)
263 void setImporter(PythonQtImportFileInterface* importInterface);
282 void setImporter(PythonQtImportFileInterface* importInterface);
264
283
265 //! set paths that the importer should ignore
284 //! set paths that the importer should ignore
266 void setImporterIgnorePaths(const QStringList& paths);
285 void setImporterIgnorePaths(const QStringList& paths);
267
286
268 //! get paths that the importer should ignore
287 //! get paths that the importer should ignore
269 const QStringList& getImporterIgnorePaths();
288 const QStringList& getImporterIgnorePaths();
270
289
271 //@}
290 //@}
272
291
273 //! get access to internal data (should not be used on the public API, but is used by some C functions)
292 //! get access to internal data (should not be used on the public API, but is used by some C functions)
274 static PythonQtPrivate* priv() { return _self->_p; }
293 static PythonQtPrivate* priv() { return _self->_p; }
275
294
276 //! get access to the file importer (if set)
295 //! get access to the file importer (if set)
277 static PythonQtImportFileInterface* importInterface();
296 static PythonQtImportFileInterface* importInterface();
278
297
279 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
298 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
280 //! The error is currently just output to the python stderr, future version might implement better trace printing
299 //! The error is currently just output to the python stderr, future version might implement better trace printing
281 bool handleError();
300 bool handleError();
282
301
302 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
303 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
304 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
305 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
306
307 //! call the callback if it is set
308 static void qObjectNoLongerWrappedCB(QObject* o);
309
283 signals:
310 signals:
284 //! emitted when python outputs something to stdout (and redirection is turned on)
311 //! emitted when python outputs something to stdout (and redirection is turned on)
285 void pythonStdOut(const QString& str);
312 void pythonStdOut(const QString& str);
286 //! emitted when python outputs something to stderr (and redirection is turned on)
313 //! emitted when python outputs something to stderr (and redirection is turned on)
287 void pythonStdErr(const QString& str);
314 void pythonStdErr(const QString& str);
288
315
289 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
316 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
290 void pythonHelpRequest(const QByteArray& cppClassName);
317 void pythonHelpRequest(const QByteArray& cppClassName);
291
318
292
319
293 public:
320 public:
294 //! called by internal help methods
321 //! called by internal help methods
295 PyObject* helpCalled(PythonQtClassInfo* info);
322 PyObject* helpCalled(PythonQtClassInfo* info);
296
323
297 //! returns the found object or NULL
324 //! returns the found object or NULL
298 //! @return new reference
325 //! @return new reference
299 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
326 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
300
327
301 private:
328 private:
302 void initPythonQtModule(bool redirectStdOut);
329 void initPythonQtModule(bool redirectStdOut);
303
330
304 //! callback for stdout redirection, emits pythonStdOut signal
331 //! callback for stdout redirection, emits pythonStdOut signal
305 static void stdOutRedirectCB(const QString& str);
332 static void stdOutRedirectCB(const QString& str);
306 //! callback for stderr redirection, emits pythonStdErr signal
333 //! callback for stderr redirection, emits pythonStdErr signal
307 static void stdErrRedirectCB(const QString& str);
334 static void stdErrRedirectCB(const QString& str);
308
335
309 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
336 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
310 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
337 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
311
338
312 PythonQt(int flags);
339 PythonQt(int flags);
313 ~PythonQt();
340 ~PythonQt();
314
341
315 static PythonQt* _self;
342 static PythonQt* _self;
343 static int _uniqueModuleCount;
316
344
317 PythonQtPrivate* _p;
345 PythonQtPrivate* _p;
318
346
319 };
347 };
320
348
321 //! internal PythonQt details
349 //! internal PythonQt details
322 class PythonQtPrivate : public QObject {
350 class PythonQtPrivate : public QObject {
323
351
324 Q_OBJECT
352 Q_OBJECT
325
353
326 public:
354 public:
327 PythonQtPrivate();
355 PythonQtPrivate();
328 ~PythonQtPrivate();
356 ~PythonQtPrivate();
329
357
330 //! returns if the id is the id for PythonQtObjectPtr
358 //! returns if the id is the id for PythonQtObjectPtr
331 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
359 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
332
360
333 //! remove the wrapper ptr again
361 //! remove the wrapper ptr again
334 void removeWrapperPointer(void* obj) { _wrappedObjects.take(obj); }
362 void removeWrapperPointer(void* obj);
363
364 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
365 void removeSignalEmitter(QObject* obj);
335
366
336 //! wrap the given QObject into a Python object (or return existing wrapper!)
367 //! wrap the given QObject into a Python object (or return existing wrapper!)
337 PyObject* wrapQObject(QObject* obj);
368 PyObject* wrapQObject(QObject* obj);
338
369
339 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
370 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
340 PyObject* wrapPtr(void* ptr, const QByteArray& name);
371 PyObject* wrapPtr(void* ptr, const QByteArray& name);
341
372
342 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
373 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
343 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
374 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
344 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
375 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
345 void registerClass(const QMetaObject* metaobject);
376 void registerClass(const QMetaObject* metaobject);
346
377
347 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
378 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
348 //! and it will register the classes when it first sees a pointer to such a derived class
379 //! and it will register the classes when it first sees a pointer to such a derived class
349 void registerQObjectClassNames(const QStringList& names);
380 void registerQObjectClassNames(const QStringList& names);
350
381
351 //! add a decorator object
382 //! add a decorator object
352 void addDecorators(QObject* o, bool instanceDeco, bool classDeco);
383 void addDecorators(QObject* o, bool instanceDeco, bool classDeco);
353
384
354 //! add a wrapper object for the given qvariant, also does an addConstructors() to add constructors for variants
385 //! add a wrapper object for the given qvariant, also does an addConstructors() to add constructors for variants
355 void addVariantWrapper(const char* typeName, QObject* wrapper);
386 void addVariantWrapper(const char* typeName, QObject* wrapper);
356
387
357 //! get list of all slots that are available as decorator slots
388 //! get list of all slots that are available as decorator slots
358 QList<PythonQtSlotInfo*> getDecoratorSlots(const QByteArray& className);
389 QList<PythonQtSlotInfo*> getDecoratorSlots(const QByteArray& className);
359
390
360 //! check if the enum is either part of the \c meta class or contains a scope and is
391 //! check if the enum is either part of the \c meta class or contains a scope and is
361 //! an enum of another known metaobject (and as last resort, of the Qt namespace)
392 //! an enum of another known metaobject (and as last resort, of the Qt namespace)
362 bool isEnumType(const QMetaObject* meta, const QByteArray& name);
393 bool isEnumType(const QMetaObject* meta, const QByteArray& name);
363
394
364 //! helper method that creates a PythonQtMetaObjectWrapper object
395 //! helper method that creates a PythonQtMetaObjectWrapper object
365 PythonQtMetaObjectWrapper* createNewPythonQtMetaObjectWrapper(PythonQtClassInfo* info);
396 PythonQtMetaObjectWrapper* createNewPythonQtMetaObjectWrapper(PythonQtClassInfo* info);
366
397
367 //! helper method that creates a PythonQtWrapper object and registers it in the object map
398 //! helper method that creates a PythonQtWrapper object and registers it in the object map
368 PythonQtWrapper* createNewPythonQtWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
399 PythonQtWrapper* createNewPythonQtWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
369
400
370 //! helper method that creates a PythonQtVariantWrapper object
401 //! helper method that creates a PythonQtVariantWrapper object
371 PythonQtVariantWrapper* createNewPythonQtVariantWrapper(const QVariant& variant);
402 PythonQtVariantWrapper* createNewPythonQtVariantWrapper(const QVariant& variant);
372
403
373 //! get the class info for a meta object (if available)
404 //! get the class info for a meta object (if available)
374 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownQtClasses.value(meta->className()); }
405 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownQtClasses.value(meta->className()); }
375
406
376 //! get the constructor slot for the given classname
407 //! get the constructor slot for the given classname
377 PythonQtSlotInfo* getConstructorSlot(const QByteArray& className) { return _constructorSlots.value(className); }
408 PythonQtSlotInfo* getConstructorSlot(const QByteArray& className) { return _constructorSlots.value(className); }
378
409
379 //! get the destructor slot for the given classname
410 //! get the destructor slot for the given classname
380 PythonQtSlotInfo* getDestructorSlot(const QByteArray& className) { return _destructorSlots.value(className); }
411 PythonQtSlotInfo* getDestructorSlot(const QByteArray& className) { return _destructorSlots.value(className); }
381
412
382 protected slots:
413 //! creates the new module from the given pycode
383 //! called when a wrapped QObject is destroyed
414 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
384 void wrappedObjectDestroyed(QObject* obj);
385
386 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
387 void destroyedSignalEmitter(QObject* obj);
388
415
389 private:
416 private:
390
417
418 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
419 PythonQtWrapper* findWrapperAndRemoveUnused(void* obj);
420
391 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
421 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
392 QHash<void* , PythonQtWrapper *> _wrappedObjects;
422 QHash<void* , PythonQtWrapper *> _wrappedObjects;
393
423
394 //! stores the meta info of known Qt classes
424 //! stores the meta info of known Qt classes
395 QHash<QByteArray, PythonQtClassInfo *> _knownQtClasses;
425 QHash<QByteArray, PythonQtClassInfo *> _knownQtClasses;
396
426
397 //! stores the meta info of known Qt classes
427 //! stores the meta info of known Qt classes
398 QHash<QByteArray, PythonQtClassInfo *> _knownQtWrapperClasses;
428 QHash<QByteArray, PythonQtClassInfo *> _knownQtWrapperClasses;
399
429
400 //! stores the meta info of known Qt C++ wrapper classes
430 //! stores the meta info of known Qt C++ wrapper classes
401 QMultiHash<QByteArray, PythonQtSlotInfo *> _knownQtDecoratorSlots;
431 QMultiHash<QByteArray, PythonQtSlotInfo *> _knownQtDecoratorSlots;
402
432
403 //! names of qobject derived classes that can be casted to qobject savely
433 //! names of qobject derived classes that can be casted to qobject savely
404 QHash<QByteArray, bool> _knownQObjectClassNames;
434 QHash<QByteArray, bool> _knownQObjectClassNames;
405
435
406 //! stores signal receivers for QObjects
436 //! stores signal receivers for QObjects
407 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
437 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
408
438
409 //! the PythonQt python module
439 //! the PythonQt python module
410 PythonQtObjectPtr _pythonQtModule;
440 PythonQtObjectPtr _pythonQtModule;
411
441
412 //! the importer interface (if set)
442 //! the importer interface (if set)
413 PythonQtImportFileInterface* _importInterface;
443 PythonQtImportFileInterface* _importInterface;
414
444
445 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
446 PythonQtQObjectWrappedCB* _wrappedCB;
447
415 QStringList _importIgnorePaths;
448 QStringList _importIgnorePaths;
416
449
417 //! the cpp object wrapper factories
450 //! the cpp object wrapper factories
418 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
451 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
419
452
420 //! the cpp object wrapper factories
453 //! the cpp object wrapper factories
421 QList<PythonQtConstructorHandler*> _constructorHandlers;
454 QList<PythonQtConstructorHandler*> _constructorHandlers;
422
455
423 QHash<QByteArray , PythonQtSlotInfo *> _constructorSlots;
456 QHash<QByteArray , PythonQtSlotInfo *> _constructorSlots;
424 QHash<QByteArray , PythonQtSlotInfo *> _destructorSlots;
457 QHash<QByteArray , PythonQtSlotInfo *> _destructorSlots;
425
458
426 QHash<int , QPair<PythonQtClassInfo*, QObject*> > _knownVariantWrappers;
459 QHash<int , QPair<PythonQtClassInfo*, QObject*> > _knownVariantWrappers;
427
460
428 PythonQtClassInfo* _qtNamespace;
461 PythonQtClassInfo* _qtNamespace;
429
462
430 int _initFlags;
463 int _initFlags;
431 int _PythonQtObjectPtr_metaId;
464 int _PythonQtObjectPtr_metaId;
432
465
433 friend class PythonQt;
466 friend class PythonQt;
434 };
467 };
435
468
436 #endif
469 #endif
@@ -1,1012 +1,1017
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtConversion.cpp
35 // \file PythonQtConversion.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtConversion.h"
42 #include "PythonQtConversion.h"
43 #include "PythonQtVariants.h"
43 #include "PythonQtVariants.h"
44 #include "PythonQtVariantWrapper.h"
44 #include "PythonQtVariantWrapper.h"
45 #include <QDateTime>
45 #include <QDateTime>
46 #include <QTime>
46 #include <QTime>
47 #include <QDate>
47 #include <QDate>
48
48
49 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
50 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
51 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
51 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
52
52
53
53
54 PyObject* PythonQtConv::GetPyBool(bool val)
54 PyObject* PythonQtConv::GetPyBool(bool val)
55 {
55 {
56 PyObject* r = val?Py_True:Py_False;
56 PyObject* r = val?Py_True:Py_False;
57 Py_INCREF(r);
57 Py_INCREF(r);
58 return r;
58 return r;
59 }
59 }
60
60
61 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, void* data) {
61 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, void* data) {
62 if (info.typeId == QMetaType::Void) {
62 if (info.typeId == QMetaType::Void) {
63 Py_INCREF(Py_None);
63 Py_INCREF(Py_None);
64 return Py_None;
64 return Py_None;
65 } else {
65 } else {
66 if (info.isPointer && (info.typeId == PythonQtMethodInfo::Unknown)) {
66 if (info.isPointer && (info.typeId == PythonQtMethodInfo::Unknown)) {
67 // try to convert the pointer to a Python Object
67 // try to convert the pointer to a Python Object
68 PyObject* pyObj = PythonQt::priv()->wrapPtr(*((void**)data), info.name);
68 PyObject* pyObj = PythonQt::priv()->wrapPtr(*((void**)data), info.name);
69 if (pyObj) {
69 if (pyObj) {
70 return pyObj;
70 return pyObj;
71 } else {
71 } else {
72 std::cerr << "unknown pointer type " << info.name.data() << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
72 std::cerr << "unknown pointer type " << info.name.data() << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
73 Py_INCREF(Py_None);
73 Py_INCREF(Py_None);
74 return Py_None;
74 return Py_None;
75 }
75 }
76 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
76 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
77 // a char ptr will probably be a null terminated string, so we support that:
77 // a char ptr will probably be a null terminated string, so we support that:
78 return PyString_FromString(*((char**)data));
78 return PyString_FromString(*((char**)data));
79 } else {
79 } else {
80 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
80 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
81 if (info.name.startsWith("QList<")) {
81 if (info.name.startsWith("QList<")) {
82 QByteArray innerType = info.name.mid(6,info.name.length()-7);
82 QByteArray innerType = info.name.mid(6,info.name.length()-7);
83 if (innerType.endsWith("*")) {
83 if (innerType.endsWith("*")) {
84 innerType.truncate(innerType.length()-1);
84 innerType.truncate(innerType.length()-1);
85 return ConvertQListWithPointersToPython((QList<void*>*)data, innerType);
85 return ConvertQListWithPointersToPython((QList<void*>*)data, innerType);
86 }
86 }
87 }
87 }
88 }
88 }
89 // handle values that are not yet handled and not pointers
89 // handle values that are not yet handled and not pointers
90 return ConvertQtValueToPythonInternal(info.typeId, data);
90 return ConvertQtValueToPythonInternal(info.typeId, data);
91 }
91 }
92 }
92 }
93 }
93 }
94
94
95 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, void* data) {
95 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, void* data) {
96 switch (type) {
96 switch (type) {
97 case QMetaType::Void:
97 case QMetaType::Void:
98 Py_INCREF(Py_None);
98 Py_INCREF(Py_None);
99 return Py_None;
99 return Py_None;
100 case QMetaType::Char:
100 case QMetaType::Char:
101 return PyInt_FromLong(*((char*)data));
101 return PyInt_FromLong(*((char*)data));
102 case QMetaType::UChar:
102 case QMetaType::UChar:
103 return PyInt_FromLong(*((unsigned char*)data));
103 return PyInt_FromLong(*((unsigned char*)data));
104 case QMetaType::Short:
104 case QMetaType::Short:
105 return PyInt_FromLong(*((short*)data));
105 return PyInt_FromLong(*((short*)data));
106 case QMetaType::UShort:
106 case QMetaType::UShort:
107 return PyInt_FromLong(*((unsigned short*)data));
107 return PyInt_FromLong(*((unsigned short*)data));
108 case QMetaType::Long:
108 case QMetaType::Long:
109 return PyInt_FromLong(*((long*)data));
109 return PyInt_FromLong(*((long*)data));
110 case QMetaType::ULong:
110 case QMetaType::ULong:
111 // does not fit into simple int of python
111 // does not fit into simple int of python
112 return PyLong_FromUnsignedLong(*((unsigned long*)data));
112 return PyLong_FromUnsignedLong(*((unsigned long*)data));
113 case QMetaType::Bool:
113 case QMetaType::Bool:
114 return PythonQtConv::GetPyBool(*((bool*)data));
114 return PythonQtConv::GetPyBool(*((bool*)data));
115 case QMetaType::Int:
115 case QMetaType::Int:
116 return PyInt_FromLong(*((int*)data));
116 return PyInt_FromLong(*((int*)data));
117 case QMetaType::UInt:
117 case QMetaType::UInt:
118 return PyInt_FromLong(*((unsigned int*)data));
118 return PyInt_FromLong(*((unsigned int*)data));
119 case QMetaType::QChar:
119 case QMetaType::QChar:
120 return PyInt_FromLong(*((short*)data));
120 return PyInt_FromLong(*((short*)data));
121 case QMetaType::Float:
121 case QMetaType::Float:
122 return PyFloat_FromDouble(*((float*)data));
122 return PyFloat_FromDouble(*((float*)data));
123 case QMetaType::Double:
123 case QMetaType::Double:
124 return PyFloat_FromDouble(*((double*)data));
124 return PyFloat_FromDouble(*((double*)data));
125 case QMetaType::LongLong:
125 case QMetaType::LongLong:
126 return PyLong_FromLongLong(*((qint64*)data));
126 return PyLong_FromLongLong(*((qint64*)data));
127 case QMetaType::ULongLong:
127 case QMetaType::ULongLong:
128 return PyLong_FromUnsignedLongLong(*((quint64*)data));
128 return PyLong_FromUnsignedLongLong(*((quint64*)data));
129 case QMetaType::QByteArray: {
129 case QMetaType::QByteArray: {
130 QByteArray* v = (QByteArray*) data;
130 QByteArray* v = (QByteArray*) data;
131 return PyString_FromStringAndSize(*v, v->size());
131 return PyString_FromStringAndSize(*v, v->size());
132 }
132 }
133 case QMetaType::QVariantMap:
133 case QMetaType::QVariantMap:
134 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
134 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
135 case QMetaType::QVariantList:
135 case QMetaType::QVariantList:
136 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
136 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
137 case QMetaType::QString:
137 case QMetaType::QString:
138 return PythonQtConv::QStringToPyObject(*((QString*)data));
138 return PythonQtConv::QStringToPyObject(*((QString*)data));
139 case QMetaType::QStringList:
139 case QMetaType::QStringList:
140 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
140 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
141
141
142 case PythonQtMethodInfo::Variant:
142 case PythonQtMethodInfo::Variant:
143 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
143 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
144 case QMetaType::QObjectStar:
144 case QMetaType::QObjectStar:
145 case QMetaType::QWidgetStar:
145 case QMetaType::QWidgetStar:
146 return PythonQt::priv()->wrapQObject(*((QObject**)data));
146 return PythonQt::priv()->wrapQObject(*((QObject**)data));
147
147
148 // the following cases could be handled by the default case, but it is faster to do it with
148 // the following cases could be handled by the default case, but it is faster to do it with
149 // direct casts:
149 // direct casts:
150 case QMetaType::QDate:
150 case QMetaType::QDate:
151 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QDate*)data)));
151 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QDate*)data)));
152 case QMetaType::QTime:
152 case QMetaType::QTime:
153 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QTime*)data)));
153 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QTime*)data)));
154 case QMetaType::QDateTime:
154 case QMetaType::QDateTime:
155 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QDateTime*)data)));
155 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QDateTime*)data)));
156 case QMetaType::QRect:
156 case QMetaType::QRect:
157 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRect*)data)));
157 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRect*)data)));
158 case QMetaType::QSize:
158 case QMetaType::QSize:
159 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSize*)data)));
159 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSize*)data)));
160 case QMetaType::QPoint:
160 case QMetaType::QPoint:
161 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPoint*)data)));
161 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPoint*)data)));
162 case QMetaType::QColor:
162 case QMetaType::QColor:
163 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QColor*)data)));
163 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QColor*)data)));
164 case QMetaType::QPixmap:
164 case QMetaType::QPixmap:
165 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPixmap*)data)));
165 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPixmap*)data)));
166 case QMetaType::QUrl:
166 case QMetaType::QUrl:
167 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QUrl*)data)));
167 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QUrl*)data)));
168 case QMetaType::QRectF:
168 case QMetaType::QRectF:
169 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRectF*)data)));
169 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRectF*)data)));
170 case QMetaType::QSizeF:
170 case QMetaType::QSizeF:
171 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSizeF*)data)));
171 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSizeF*)data)));
172 case QMetaType::QLine:
172 case QMetaType::QLine:
173 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLine*)data)));
173 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLine*)data)));
174 case QMetaType::QLineF:
174 case QMetaType::QLineF:
175 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLineF*)data)));
175 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLineF*)data)));
176 case QMetaType::QPointF:
176 case QMetaType::QPointF:
177 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPointF*)data)));
177 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPointF*)data)));
178 case QMetaType::QRegExp:
178 case QMetaType::QRegExp:
179 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRegExp*)data)));
179 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRegExp*)data)));
180 case QMetaType::QBitArray:
180 case QMetaType::QBitArray:
181 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QBitArray*)data)));
181 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QBitArray*)data)));
182 case QMetaType::QLocale:
182 case QMetaType::QLocale:
183 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLocale*)data)));
183 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLocale*)data)));
184 case QMetaType::QFont:
184 case QMetaType::QFont:
185 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QFont*)data)));
185 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QFont*)data)));
186 case QMetaType::QBrush:
186 case QMetaType::QBrush:
187 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QBrush*)data)));
187 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QBrush*)data)));
188 case QMetaType::QPalette:
188 case QMetaType::QPalette:
189 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPalette*)data)));
189 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPalette*)data)));
190 case QMetaType::QIcon:
190 case QMetaType::QIcon:
191 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QIcon*)data)));
191 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QIcon*)data)));
192 case QMetaType::QImage:
192 case QMetaType::QImage:
193 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QImage*)data)));
193 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QImage*)data)));
194 case QMetaType::QPolygon:
194 case QMetaType::QPolygon:
195 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPolygon*)data)));
195 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPolygon*)data)));
196 case QMetaType::QRegion:
196 case QMetaType::QRegion:
197 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRegion*)data)));
197 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRegion*)data)));
198 case QMetaType::QBitmap:
198 case QMetaType::QBitmap:
199 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QBitmap*)data)));
199 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QBitmap*)data)));
200 case QMetaType::QCursor:
200 case QMetaType::QCursor:
201 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QCursor*)data)));
201 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QCursor*)data)));
202 case QMetaType::QSizePolicy:
202 case QMetaType::QSizePolicy:
203 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSizePolicy*)data)));
203 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSizePolicy*)data)));
204 case QMetaType::QKeySequence:
204 case QMetaType::QKeySequence:
205 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QKeySequence*)data)));
205 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QKeySequence*)data)));
206 case QMetaType::QPen:
206 case QMetaType::QPen:
207 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QPen*)data)));
207 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QPen*)data)));
208 case QMetaType::QTextLength:
208 case QMetaType::QTextLength:
209 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QTextLength*)data)));
209 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QTextLength*)data)));
210 case QMetaType::QTextFormat:
210 case QMetaType::QTextFormat:
211 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QTextFormat*)data)));
211 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QTextFormat*)data)));
212 case QMetaType::QMatrix:
212 case QMetaType::QMatrix:
213 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QMatrix*)data)));
213 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QMatrix*)data)));
214 default:
214 default:
215 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
215 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
216 PyObject* o = ((PythonQtObjectPtr*)data)->object();
216 PyObject* o = ((PythonQtObjectPtr*)data)->object();
217 Py_INCREF(o);
217 Py_INCREF(o);
218 return o;
218 return o;
219 } else {
219 } else {
220 if (type != PythonQtMethodInfo::Unknown) {
220 if (type != PythonQtMethodInfo::Unknown) {
221 QVariant v(type, data);
221 QVariant v(type, data);
222 if (v.isValid()) {
222 if (v.isValid()) {
223 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(v);
223 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(v);
224 }
224 }
225 }
225 }
226 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
226 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
227 }
227 }
228 }
228 }
229 Py_INCREF(Py_None);
229 Py_INCREF(Py_None);
230 return Py_None;
230 return Py_None;
231 }
231 }
232
232
233 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
233 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
234 void* ptr = NULL;
234 void* ptr = NULL;
235 if (info.isPointer) {
235 if (info.isPointer) {
236 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
236 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
237 } else {
237 } else {
238 switch (info.typeId) {
238 switch (info.typeId) {
239 case QMetaType::Char:
239 case QMetaType::Char:
240 case QMetaType::UChar:
240 case QMetaType::UChar:
241 case QMetaType::Short:
241 case QMetaType::Short:
242 case QMetaType::UShort:
242 case QMetaType::UShort:
243 case QMetaType::Long:
243 case QMetaType::Long:
244 case QMetaType::ULong:
244 case QMetaType::ULong:
245 case QMetaType::Bool:
245 case QMetaType::Bool:
246 case QMetaType::Int:
246 case QMetaType::Int:
247 case QMetaType::UInt:
247 case QMetaType::UInt:
248 case QMetaType::QChar:
248 case QMetaType::QChar:
249 case QMetaType::Float:
249 case QMetaType::Float:
250 case QMetaType::Double:
250 case QMetaType::Double:
251 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
251 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
252 break;
252 break;
253 case PythonQtMethodInfo::Variant:
253 case PythonQtMethodInfo::Variant:
254 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
254 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
255 // return the ptr to the variant
255 // return the ptr to the variant
256 break;
256 break;
257 default:
257 default:
258 if (info.typeId == PythonQtMethodInfo::Unknown) {
258 if (info.typeId == PythonQtMethodInfo::Unknown) {
259 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
259 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
260 if (info.name.startsWith("QList<")) {
260 if (info.name.startsWith("QList<")) {
261 QByteArray innerType = info.name.mid(6,info.name.length()-7);
261 QByteArray innerType = info.name.mid(6,info.name.length()-7);
262 if (innerType.endsWith("*")) {
262 if (innerType.endsWith("*")) {
263 static int id = QMetaType::type("QList<void*>");
263 static int id = QMetaType::type("QList<void*>");
264 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
264 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
265 // return the constData pointer that will be filled with the result value later on
265 // return the constData pointer that will be filled with the result value later on
266 ptr = (void*)((QVariant*)ptr)->constData();
266 ptr = (void*)((QVariant*)ptr)->constData();
267 }
267 }
268 }
268 }
269 }
269 }
270
270
271 if (!ptr) {
271 if (!ptr) {
272 // everything else is stored in a QVariant...
272 // everything else is stored in a QVariant...
273 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
273 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
274 // return the constData pointer that will be filled with the result value later on
274 // return the constData pointer that will be filled with the result value later on
275 ptr = (void*)((QVariant*)ptr)->constData();
275 ptr = (void*)((QVariant*)ptr)->constData();
276 }
276 }
277 }
277 }
278 }
278 }
279 return ptr;
279 return ptr;
280 }
280 }
281
281
282 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, const QMetaObject* meta)
282 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, const QMetaObject* meta)
283 {
283 {
284 bool ok;
284 bool ok;
285 void* ptr = NULL;
285 void* ptr = NULL;
286 if (info.isPointer) {
286 if (info.isPointer) {
287 if (obj->ob_type == &PythonQtWrapper_Type) {
287 if (obj->ob_type == &PythonQtWrapper_Type) {
288 PythonQtWrapper* wrap = (PythonQtWrapper*)obj;
288 PythonQtWrapper* wrap = (PythonQtWrapper*)obj;
289 // c++ wrapper, check if the class names of the c++ objects match
289 // c++ wrapper, check if the class names of the c++ objects match
290 if (wrap->_info->isCPPWrapper()) {
290 if (wrap->_info->isCPPWrapper()) {
291 //TODO: we could support inheritance on cpp wrappers as well
291 //TODO: we could support inheritance on cpp wrappers as well
292 if (wrap->_info->wrappedCPPClassName() == info.name) {
292 if (wrap->_info->wrappedCPPClassName() == info.name) {
293 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, wrap->_wrappedPtr, ptr);
293 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, wrap->_wrappedPtr, ptr);
294 } else {
294 } else {
295 // not matching
295 // not matching
296 }
296 }
297 } else {
297 } else {
298 if (wrap->_info->inherits(info.name)) {
298 if (wrap->_info->inherits(info.name)) {
299 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, wrap->_obj, ptr);
299 QObject* myObject = wrap->_obj;
300 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, myObject, ptr);
300 } else {
301 } else {
301 // not matching
302 // not matching
302 }
303 }
303 }
304 }
304 } else
305 } else
305 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar) {
306 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar) {
306 QString str = PyObjGetString(obj, strict, ok);
307 QString str = PyObjGetString(obj, strict, ok);
307 if (ok) {
308 if (ok) {
308 void* ptr2 = NULL;
309 void* ptr2 = NULL;
309 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
310 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
310 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
311 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
311 }
312 }
312 } else if (info.name == "PyObject") {
313 } else if (info.name == "PyObject") {
313 // handle low level PyObject directly
314 // handle low level PyObject directly
314 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, obj, ptr);
315 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, obj, ptr);
315 } else if (obj == Py_None) {
316 } else if (obj == Py_None) {
316 // None is treated as a NULL ptr
317 // None is treated as a NULL ptr
317 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
318 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
318 } else {
319 } else {
319 // if we are not strict, we try if we are passed a 0 integer
320 // if we are not strict, we try if we are passed a 0 integer
320 if (!strict) {
321 if (!strict) {
321 bool ok;
322 bool ok;
322 int value = PyObjGetInt(obj, true, ok);
323 int value = PyObjGetInt(obj, true, ok);
323 if (ok && value==0) {
324 if (ok && value==0) {
324 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
325 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
325 }
326 }
326 }
327 }
327 // EXTRA: we could support pointers to other simple types, but this would not make sense in most situations
328 // EXTRA: we could support pointers to other simple types, but this would not make sense in most situations
328 }
329 }
329
330
330 } else {
331 } else {
331 // not a pointer
332 // not a pointer
332 switch (info.typeId) {
333 switch (info.typeId) {
333 case QMetaType::Char:
334 case QMetaType::Char:
334 {
335 {
335 int val = PyObjGetInt(obj, strict, ok);
336 int val = PyObjGetInt(obj, strict, ok);
336 if (ok) {
337 if (ok) {
337 PythonQtValueStorage_ADD_VALUE(global_valueStorage, char, val, ptr);
338 PythonQtValueStorage_ADD_VALUE(global_valueStorage, char, val, ptr);
338 }
339 }
339 }
340 }
340 break;
341 break;
341 case QMetaType::UChar:
342 case QMetaType::UChar:
342 {
343 {
343 int val = PyObjGetInt(obj, strict, ok);
344 int val = PyObjGetInt(obj, strict, ok);
344 if (ok) {
345 if (ok) {
345 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned char, val, ptr);
346 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned char, val, ptr);
346 }
347 }
347 }
348 }
348 break;
349 break;
349 case QMetaType::Short:
350 case QMetaType::Short:
350 {
351 {
351 int val = PyObjGetInt(obj, strict, ok);
352 int val = PyObjGetInt(obj, strict, ok);
352 if (ok) {
353 if (ok) {
353 PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
354 PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
354 }
355 }
355 }
356 }
356 break;
357 break;
357 case QMetaType::UShort:
358 case QMetaType::UShort:
358 {
359 {
359 int val = PyObjGetInt(obj, strict, ok);
360 int val = PyObjGetInt(obj, strict, ok);
360 if (ok) {
361 if (ok) {
361 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned short, val, ptr);
362 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned short, val, ptr);
362 }
363 }
363 }
364 }
364 break;
365 break;
365 case QMetaType::Long:
366 case QMetaType::Long:
366 {
367 {
367 long val = (long)PyObjGetLongLong(obj, strict, ok);
368 long val = (long)PyObjGetLongLong(obj, strict, ok);
368 if (ok) {
369 if (ok) {
369 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, val, ptr);
370 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, val, ptr);
370 }
371 }
371 }
372 }
372 break;
373 break;
373 case QMetaType::ULong:
374 case QMetaType::ULong:
374 {
375 {
375 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
376 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
376 if (ok) {
377 if (ok) {
377 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned long, val, ptr);
378 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned long, val, ptr);
378 }
379 }
379 }
380 }
380 break;
381 break;
381 case QMetaType::Bool:
382 case QMetaType::Bool:
382 {
383 {
383 bool val = PyObjGetBool(obj, strict, ok);
384 bool val = PyObjGetBool(obj, strict, ok);
384 if (ok) {
385 if (ok) {
385 PythonQtValueStorage_ADD_VALUE(global_valueStorage, bool, val, ptr);
386 PythonQtValueStorage_ADD_VALUE(global_valueStorage, bool, val, ptr);
386 }
387 }
387 }
388 }
388 break;
389 break;
389 case QMetaType::Int:
390 case QMetaType::Int:
390 {
391 {
391 int val = PyObjGetInt(obj, strict, ok);
392 int val = PyObjGetInt(obj, strict, ok);
392 if (ok) {
393 if (ok) {
393 PythonQtValueStorage_ADD_VALUE(global_valueStorage, int, val, ptr);
394 PythonQtValueStorage_ADD_VALUE(global_valueStorage, int, val, ptr);
394 }
395 }
395 }
396 }
396 break;
397 break;
397 case QMetaType::UInt:
398 case QMetaType::UInt:
398 {
399 {
399 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
400 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
400 if (ok) {
401 if (ok) {
401 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
402 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
402 }
403 }
403 }
404 }
404 break;
405 break;
405 case QMetaType::QChar:
406 case QMetaType::QChar:
406 {
407 {
407 int val = PyObjGetInt(obj, strict, ok);
408 int val = PyObjGetInt(obj, strict, ok);
408 if (ok) {
409 if (ok) {
409 PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
410 PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
410 }
411 }
411 }
412 }
412 break;
413 break;
413 case QMetaType::Float:
414 case QMetaType::Float:
414 {
415 {
415 float val = (float)PyObjGetDouble(obj, strict, ok);
416 float val = (float)PyObjGetDouble(obj, strict, ok);
416 if (ok) {
417 if (ok) {
417 PythonQtValueStorage_ADD_VALUE(global_valueStorage, float, val, ptr);
418 PythonQtValueStorage_ADD_VALUE(global_valueStorage, float, val, ptr);
418 }
419 }
419 }
420 }
420 break;
421 break;
421 case QMetaType::Double:
422 case QMetaType::Double:
422 {
423 {
423 double val = (double)PyObjGetDouble(obj, strict, ok);
424 double val = (double)PyObjGetDouble(obj, strict, ok);
424 if (ok) {
425 if (ok) {
425 PythonQtValueStorage_ADD_VALUE(global_valueStorage, double, val, ptr);
426 PythonQtValueStorage_ADD_VALUE(global_valueStorage, double, val, ptr);
426 }
427 }
427 }
428 }
428 break;
429 break;
429 case QMetaType::LongLong:
430 case QMetaType::LongLong:
430 {
431 {
431 qint64 val = PyObjGetLongLong(obj, strict, ok);
432 qint64 val = PyObjGetLongLong(obj, strict, ok);
432 if (ok) {
433 if (ok) {
433 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, val, ptr);
434 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, val, ptr);
434 }
435 }
435 }
436 }
436 break;
437 break;
437 case QMetaType::ULongLong:
438 case QMetaType::ULongLong:
438 {
439 {
439 quint64 val = PyObjGetULongLong(obj, strict, ok);
440 quint64 val = PyObjGetULongLong(obj, strict, ok);
440 if (ok) {
441 if (ok) {
441 PythonQtValueStorage_ADD_VALUE(global_valueStorage, quint64, val, ptr);
442 PythonQtValueStorage_ADD_VALUE(global_valueStorage, quint64, val, ptr);
442 }
443 }
443 }
444 }
444 break;
445 break;
445 case QMetaType::QByteArray:
446 case QMetaType::QByteArray:
446 {
447 {
447 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
448 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
448 if (ok) {
449 if (ok) {
449 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(bytes), ptr);
450 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(bytes), ptr);
450 ptr = (void*)((QVariant*)ptr)->constData();
451 ptr = (void*)((QVariant*)ptr)->constData();
451 }
452 }
452 }
453 }
453 break;
454 break;
454 case QMetaType::QString:
455 case QMetaType::QString:
455 {
456 {
456 QString str = PyObjGetString(obj, strict, ok);
457 QString str = PyObjGetString(obj, strict, ok);
457 if (ok) {
458 if (ok) {
458 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str), ptr);
459 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str), ptr);
459 ptr = (void*)((QVariant*)ptr)->constData();
460 ptr = (void*)((QVariant*)ptr)->constData();
460 }
461 }
461 }
462 }
462 break;
463 break;
463 case QMetaType::QStringList:
464 case QMetaType::QStringList:
464 {
465 {
465 QStringList l = PyObjToStringList(obj, strict, ok);
466 QStringList l = PyObjToStringList(obj, strict, ok);
466 if (ok) {
467 if (ok) {
467 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(l), ptr);
468 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(l), ptr);
468 ptr = (void*)((QVariant*)ptr)->constData();
469 ptr = (void*)((QVariant*)ptr)->constData();
469 }
470 }
470 }
471 }
471 break;
472 break;
472
473
473 case PythonQtMethodInfo::Variant:
474 case PythonQtMethodInfo::Variant:
474 {
475 {
475 QVariant v = PyObjToQVariant(obj);
476 QVariant v = PyObjToQVariant(obj);
476 if (v.isValid()) {
477 if (v.isValid()) {
477 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
478 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
478 }
479 }
479 }
480 }
480 break;
481 break;
481 default:
482 default:
482 {
483 {
483 if (info.typeId == PythonQtMethodInfo::Unknown) {
484 if (info.typeId == PythonQtMethodInfo::Unknown) {
484 // check for enum case
485 // check for enum case
485 if (PythonQt::priv()->isEnumType(meta, info.name)) {
486 if (PythonQt::priv()->isEnumType(meta, info.name)) {
486 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
487 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
487 if (ok) {
488 if (ok) {
488 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
489 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
489 return ptr;
490 return ptr;
491 } else {
492 return NULL;
490 }
493 }
491 }
494 }
492 }
495 }
493 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
496 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
494 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
497 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
495 if (info.name.startsWith("QList<")) {
498 if (info.name.startsWith("QList<")) {
496 QByteArray innerType = info.name.mid(6,info.name.length()-7);
499 QByteArray innerType = info.name.mid(6,info.name.length()-7);
497 if (innerType.endsWith("*")) {
500 if (innerType.endsWith("*")) {
498 innerType.truncate(innerType.length()-1);
501 innerType.truncate(innerType.length()-1);
499 static int id = QMetaType::type("QList<void*>");
502 static int id = QMetaType::type("QList<void*>");
500 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
503 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
501 ptr = (void*)((QVariant*)ptr)->constData();
504 ptr = (void*)((QVariant*)ptr)->constData();
502 ok = ConvertPythonListToQListOfType(obj, (QList<void*>*)ptr, innerType, strict);
505 ok = ConvertPythonListToQListOfType(obj, (QList<void*>*)ptr, innerType, strict);
503 if (ok) {
506 if (ok) {
504 return ptr;
507 return ptr;
505 } else {
508 } else {
506 return NULL;
509 return NULL;
507 }
510 }
508 }
511 }
509 }
512 }
510 }
513 }
511
514
512 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
515 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
513 QVariant v = PyObjToQVariant(obj, info.typeId);
516 QVariant v = PyObjToQVariant(obj, info.typeId);
514 if (v.isValid()) {
517 if (v.isValid()) {
515 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
518 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
516 ptr = (void*)((QVariant*)ptr)->constData();
519 ptr = (void*)((QVariant*)ptr)->constData();
517 }
520 }
518 }
521 }
519 }
522 }
520 }
523 }
521 return ptr;
524 return ptr;
522 }
525 }
523
526
524
527
525 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
528 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
526 QStringList v;
529 QStringList v;
527 ok = false;
530 ok = false;
528 // if we are strict, we do not want to convert a string to a stringlist
531 // if we are strict, we do not want to convert a string to a stringlist
529 // (strings in python are detected to be sequences)
532 // (strings in python are detected to be sequences)
530 if (strict &&
533 if (strict &&
531 (val->ob_type == &PyString_Type ||
534 (val->ob_type == &PyString_Type ||
532 PyUnicode_Check(val))) {
535 PyUnicode_Check(val))) {
533 ok = false;
536 ok = false;
534 return v;
537 return v;
535 }
538 }
536 if (PySequence_Check(val)) {
539 if (PySequence_Check(val)) {
537 int count = PySequence_Size(val);
540 int count = PySequence_Size(val);
538 for (int i = 0;i<count;i++) {
541 for (int i = 0;i<count;i++) {
539 PyObject* value = PySequence_GetItem(val,i);
542 PyObject* value = PySequence_GetItem(val,i);
540 v.append(PyObjGetString(value,false,ok));
543 v.append(PyObjGetString(value,false,ok));
541 }
544 }
542 ok = true;
545 ok = true;
543 }
546 }
544 return v;
547 return v;
545 }
548 }
546
549
547 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
550 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
548 {
551 {
549 QString r;
552 QString r;
550 PyObject* str = PyObject_Repr(val);
553 PyObject* str = PyObject_Repr(val);
551 if (str) {
554 if (str) {
552 r = QString(PyString_AS_STRING(str));
555 r = QString(PyString_AS_STRING(str));
553 Py_DECREF(str);
556 Py_DECREF(str);
554 }
557 }
555 return r;
558 return r;
556 }
559 }
557
560
558 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
561 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
559 QString r;
562 QString r;
560 ok = true;
563 ok = true;
561 if (val->ob_type == &PyString_Type) {
564 if (val->ob_type == &PyString_Type) {
562 r = QString(PyString_AS_STRING(val));
565 r = QString(PyString_AS_STRING(val));
563 } else if (PyUnicode_Check(val)) {
566 } else if (PyUnicode_Check(val)) {
564 #ifdef WIN32
567 #ifdef WIN32
565 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
568 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
566 #else
569 #else
567 PyObject *ptmp = PyUnicode_AsUTF8String(val);
570 PyObject *ptmp = PyUnicode_AsUTF8String(val);
568 if(ptmp) {
571 if(ptmp) {
569 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
572 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
570 Py_DECREF(ptmp);
573 Py_DECREF(ptmp);
571 }
574 }
572 #endif
575 #endif
573 } else if (!strict) {
576 } else if (!strict) {
574 // EXTRA: could also use _Unicode, but why should we?
577 // EXTRA: could also use _Unicode, but why should we?
575 PyObject* str = PyObject_Str(val);
578 PyObject* str = PyObject_Str(val);
576 if (str) {
579 if (str) {
577 r = QString(PyString_AS_STRING(str));
580 r = QString(PyString_AS_STRING(str));
578 Py_DECREF(str);
581 Py_DECREF(str);
579 } else {
582 } else {
580 ok = false;
583 ok = false;
581 }
584 }
582 } else {
585 } else {
583 ok = false;
586 ok = false;
584 }
587 }
585 return r;
588 return r;
586 }
589 }
587
590
588 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool strict, bool& ok) {
591 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool strict, bool& ok) {
589 QByteArray r;
592 QByteArray r;
590 ok = true;
593 ok = true;
591 if (val->ob_type == &PyString_Type) {
594 if (val->ob_type == &PyString_Type) {
592 long size = PyString_GET_SIZE(val);
595 long size = PyString_GET_SIZE(val);
593 r = QByteArray(PyString_AS_STRING(val), size);
596 r = QByteArray(PyString_AS_STRING(val), size);
594 } else {
597 } else {
595 ok = false;
598 ok = false;
596 }
599 }
597 return r;
600 return r;
598 }
601 }
599
602
600 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
603 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
601 bool d = false;
604 bool d = false;
602 ok = false;
605 ok = false;
603 if (val == Py_False) {
606 if (val == Py_False) {
604 d = false;
607 d = false;
605 ok = true;
608 ok = true;
606 } else if (val == Py_True) {
609 } else if (val == Py_True) {
607 d = true;
610 d = true;
608 ok = true;
611 ok = true;
609 } else if (!strict) {
612 } else if (!strict) {
610 d = PyObjGetInt(val, false, ok)!=0;
613 d = PyObjGetInt(val, false, ok)!=0;
611 ok = true;
614 ok = true;
612 }
615 }
613 return d;
616 return d;
614 }
617 }
615
618
616 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
619 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
617 int d = 0;
620 int d = 0;
618 ok = true;
621 ok = true;
619 if (val->ob_type == &PyInt_Type) {
622 if (val->ob_type == &PyInt_Type) {
620 d = PyInt_AS_LONG(val);
623 d = PyInt_AS_LONG(val);
621 } else if (!strict) {
624 } else if (!strict) {
622 if (val->ob_type == &PyFloat_Type) {
625 if (val->ob_type == &PyFloat_Type) {
623 d = floor(PyFloat_AS_DOUBLE(val));
626 d = floor(PyFloat_AS_DOUBLE(val));
624 } else if (val->ob_type == &PyLong_Type) {
627 } else if (val->ob_type == &PyLong_Type) {
625 // handle error on overflow!
628 // handle error on overflow!
626 d = PyLong_AsLong(val);
629 d = PyLong_AsLong(val);
627 } else if (val == Py_False) {
630 } else if (val == Py_False) {
628 d = 0;
631 d = 0;
629 } else if (val == Py_True) {
632 } else if (val == Py_True) {
630 d = 1;
633 d = 1;
631 } else {
634 } else {
632 ok = false;
635 ok = false;
633 }
636 }
634 } else {
637 } else {
635 ok = false;
638 ok = false;
636 }
639 }
637 return d;
640 return d;
638 }
641 }
639
642
640 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
643 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
641 qint64 d = 0;
644 qint64 d = 0;
642 ok = true;
645 ok = true;
643 if (val->ob_type == &PyInt_Type) {
646 if (val->ob_type == &PyInt_Type) {
644 d = PyInt_AS_LONG(val);
647 d = PyInt_AS_LONG(val);
645 } else if (val->ob_type == &PyLong_Type) {
648 } else if (val->ob_type == &PyLong_Type) {
646 d = PyLong_AsLongLong(val);
649 d = PyLong_AsLongLong(val);
647 } else if (!strict) {
650 } else if (!strict) {
648 if (val->ob_type == &PyFloat_Type) {
651 if (val->ob_type == &PyFloat_Type) {
649 d = floor(PyFloat_AS_DOUBLE(val));
652 d = floor(PyFloat_AS_DOUBLE(val));
650 } else if (val == Py_False) {
653 } else if (val == Py_False) {
651 d = 0;
654 d = 0;
652 } else if (val == Py_True) {
655 } else if (val == Py_True) {
653 d = 1;
656 d = 1;
654 } else {
657 } else {
655 ok = false;
658 ok = false;
656 }
659 }
657 } else {
660 } else {
658 ok = false;
661 ok = false;
659 }
662 }
660 return d;
663 return d;
661 }
664 }
662
665
663 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
666 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
664 quint64 d = 0;
667 quint64 d = 0;
665 ok = true;
668 ok = true;
666 if (val->ob_type == &PyInt_Type) {
669 if (val->ob_type == &PyInt_Type) {
667 d = PyInt_AS_LONG(val);
670 d = PyInt_AS_LONG(val);
668 } else if (val->ob_type == &PyLong_Type) {
671 } else if (val->ob_type == &PyLong_Type) {
669 d = PyLong_AsLongLong(val);
672 d = PyLong_AsLongLong(val);
670 } else if (!strict) {
673 } else if (!strict) {
671 if (val->ob_type == &PyFloat_Type) {
674 if (val->ob_type == &PyFloat_Type) {
672 d = floor(PyFloat_AS_DOUBLE(val));
675 d = floor(PyFloat_AS_DOUBLE(val));
673 } else if (val == Py_False) {
676 } else if (val == Py_False) {
674 d = 0;
677 d = 0;
675 } else if (val == Py_True) {
678 } else if (val == Py_True) {
676 d = 1;
679 d = 1;
677 } else {
680 } else {
678 ok = false;
681 ok = false;
679 }
682 }
680 } else {
683 } else {
681 ok = false;
684 ok = false;
682 }
685 }
683 return d;
686 return d;
684 }
687 }
685
688
686 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
689 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
687 double d = 0;
690 double d = 0;
688 ok = true;
691 ok = true;
689 if (val->ob_type == &PyFloat_Type) {
692 if (val->ob_type == &PyFloat_Type) {
690 d = PyFloat_AS_DOUBLE(val);
693 d = PyFloat_AS_DOUBLE(val);
691 } else if (!strict) {
694 } else if (!strict) {
692 if (val->ob_type == &PyInt_Type) {
695 if (val->ob_type == &PyInt_Type) {
693 d = PyInt_AS_LONG(val);
696 d = PyInt_AS_LONG(val);
694 } else if (val->ob_type == &PyLong_Type) {
697 } else if (val->ob_type == &PyLong_Type) {
695 d = PyLong_AsLong(val);
698 d = PyLong_AsLong(val);
696 } else if (val == Py_False) {
699 } else if (val == Py_False) {
697 d = 0;
700 d = 0;
698 } else if (val == Py_True) {
701 } else if (val == Py_True) {
699 d = 1;
702 d = 1;
700 } else {
703 } else {
701 ok = false;
704 ok = false;
702 }
705 }
703 } else {
706 } else {
704 ok = false;
707 ok = false;
705 }
708 }
706 return d;
709 return d;
707 }
710 }
708
711
709 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
712 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
710 {
713 {
711 QVariant v;
714 QVariant v;
712 bool ok = true;
715 bool ok = true;
713
716
714 if (type==-1) {
717 if (type==-1) {
715 // no special type requested
718 // no special type requested
716 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
719 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
717 type = QVariant::String;
720 type = QVariant::String;
718 } else if (val->ob_type==&PyInt_Type) {
721 } else if (val->ob_type==&PyInt_Type) {
719 type = QVariant::Int;
722 type = QVariant::Int;
720 } else if (val->ob_type==&PyLong_Type) {
723 } else if (val->ob_type==&PyLong_Type) {
721 type = QVariant::LongLong;
724 type = QVariant::LongLong;
722 } else if (val->ob_type==&PyFloat_Type) {
725 } else if (val->ob_type==&PyFloat_Type) {
723 type = QVariant::Double;
726 type = QVariant::Double;
724 } else if (val == Py_False || val == Py_True) {
727 } else if (val == Py_False || val == Py_True) {
725 type = QVariant::Bool;
728 type = QVariant::Bool;
726 } else if (val->ob_type == &PythonQtWrapper_Type) {
729 } else if (val->ob_type == &PythonQtWrapper_Type) {
727 PythonQtWrapper* wrap = (PythonQtWrapper*)val;
730 PythonQtWrapper* wrap = (PythonQtWrapper*)val;
728 // c++ wrapper, check if the class names of the c++ objects match
731 // c++ wrapper, check if the class names of the c++ objects match
729 if (wrap->_info->isCPPWrapper()) {
732 if (wrap->_info->isCPPWrapper()) {
730 // is this worth anything? we loose the knowledge of the cpp object type
733 // is this worth anything? we loose the knowledge of the cpp object type
731 v = qVariantFromValue(wrap->_wrappedPtr);
734 v = qVariantFromValue(wrap->_wrappedPtr);
732 } else {
735 } else {
733 v = qVariantFromValue(wrap->_obj);
736 QObject* myObject = wrap->_obj;
737 v = qVariantFromValue(myObject);
734 }
738 }
735 return v;
739 return v;
736 } else if (val->ob_type==&PyDict_Type) {
740 } else if (val->ob_type==&PyDict_Type) {
737 type = QVariant::Map;
741 type = QVariant::Map;
738 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
742 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
739 type = QVariant::List;
743 type = QVariant::List;
740 } else if (val == Py_None) {
744 } else if (val == Py_None) {
741 // none is invalid
745 // none is invalid
742 type = QVariant::Invalid;
746 type = QVariant::Invalid;
743 } else if (val->ob_type == &PythonQtVariantWrapper_Type) {
747 } else if (val->ob_type == &PythonQtVariantWrapper_Type) {
744 PythonQtVariantWrapper* varWrap = (PythonQtVariantWrapper*)val;
748 PythonQtVariantWrapper* varWrap = (PythonQtVariantWrapper*)val;
745 if (varWrap->_variant->userType() == type) {
749 if (varWrap->_variant->userType() == type) {
746 v = *varWrap->_variant;
750 v = *varWrap->_variant;
747 return v;
751 return v;
748 }
752 }
749 } else {
753 } else {
750 // this used to be:
754 // this used to be:
751 // type = QVariant::String;
755 // type = QVariant::String;
752 // but now we want to transport the Python Objects directly:
756 // but now we want to transport the Python Objects directly:
753 PythonQtObjectPtr o(val);
757 PythonQtObjectPtr o(val);
754 v = qVariantFromValue(o);
758 v = qVariantFromValue(o);
755 return v;
759 return v;
756 }
760 }
757 }
761 }
758 // special type request:
762 // special type request:
759 switch (type) {
763 switch (type) {
760 case QVariant::Invalid:
764 case QVariant::Invalid:
761 return v;
765 return v;
762 break;
766 break;
763 case QVariant::Int:
767 case QVariant::Int:
764 {
768 {
765 int d = PyObjGetInt(val, false, ok);
769 int d = PyObjGetInt(val, false, ok);
766 if (ok) return QVariant(d);
770 if (ok) return QVariant(d);
767 }
771 }
768 break;
772 break;
769 case QVariant::UInt:
773 case QVariant::UInt:
770 {
774 {
771 int d = PyObjGetInt(val, false,ok);
775 int d = PyObjGetInt(val, false,ok);
772 if (ok) v = QVariant((unsigned int)d);
776 if (ok) v = QVariant((unsigned int)d);
773 }
777 }
774 break;
778 break;
775 case QVariant::Bool:
779 case QVariant::Bool:
776 {
780 {
777 int d = PyObjGetBool(val,false,ok);
781 int d = PyObjGetBool(val,false,ok);
778 if (ok) v = QVariant((bool)(d!=0));
782 if (ok) v = QVariant((bool)(d!=0));
779 }
783 }
780 break;
784 break;
781 case QVariant::Double:
785 case QVariant::Double:
782 {
786 {
783 double d = PyObjGetDouble(val,false,ok);
787 double d = PyObjGetDouble(val,false,ok);
784 if (ok) v = QVariant(d);
788 if (ok) v = QVariant(d);
785 break;
789 break;
786 }
790 }
787 case QMetaType::Float:
791 case QMetaType::Float:
788 {
792 {
789 float d = (float) PyObjGetDouble(val,false,ok);
793 float d = (float) PyObjGetDouble(val,false,ok);
790 if (ok) v = qVariantFromValue(d);
794 if (ok) v = qVariantFromValue(d);
791 break;
795 break;
792 }
796 }
793 case QMetaType::Long:
797 case QMetaType::Long:
794 {
798 {
795 long d = (long) PyObjGetLongLong(val,false,ok);
799 long d = (long) PyObjGetLongLong(val,false,ok);
796 if (ok) v = qVariantFromValue(d);
800 if (ok) v = qVariantFromValue(d);
797 break;
801 break;
798 }
802 }
799 case QMetaType::ULong:
803 case QMetaType::ULong:
800 {
804 {
801 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
805 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
802 if (ok) v = qVariantFromValue(d);
806 if (ok) v = qVariantFromValue(d);
803 break;
807 break;
804 }
808 }
805 case QMetaType::Short:
809 case QMetaType::Short:
806 {
810 {
807 short d = (short) PyObjGetInt(val,false,ok);
811 short d = (short) PyObjGetInt(val,false,ok);
808 if (ok) v = qVariantFromValue(d);
812 if (ok) v = qVariantFromValue(d);
809 break;
813 break;
810 }
814 }
811 case QMetaType::UShort:
815 case QMetaType::UShort:
812 {
816 {
813 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
817 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
814 if (ok) v = qVariantFromValue(d);
818 if (ok) v = qVariantFromValue(d);
815 break;
819 break;
816 }
820 }
817 case QMetaType::Char:
821 case QMetaType::Char:
818 {
822 {
819 char d = (char) PyObjGetInt(val,false,ok);
823 char d = (char) PyObjGetInt(val,false,ok);
820 if (ok) v = qVariantFromValue(d);
824 if (ok) v = qVariantFromValue(d);
821 break;
825 break;
822 }
826 }
823 case QMetaType::UChar:
827 case QMetaType::UChar:
824 {
828 {
825 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
829 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
826 if (ok) v = qVariantFromValue(d);
830 if (ok) v = qVariantFromValue(d);
827 break;
831 break;
828 }
832 }
829
833
830 case QVariant::ByteArray:
834 case QVariant::ByteArray:
831 case QVariant::String:
835 case QVariant::String:
832 {
836 {
833 bool ok;
837 bool ok;
834 v = QVariant(PyObjGetString(val, false, ok));
838 v = QVariant(PyObjGetString(val, false, ok));
835 }
839 }
836 break;
840 break;
837
841
838 // these are important for MeVisLab
842 // these are important for MeVisLab
839 case QVariant::Map:
843 case QVariant::Map:
840 {
844 {
841 if (PyMapping_Check(val)) {
845 if (PyMapping_Check(val)) {
842 QMap<QString,QVariant> map;
846 QMap<QString,QVariant> map;
843 PyObject* items = PyMapping_Items(val);
847 PyObject* items = PyMapping_Items(val);
844 if (items) {
848 if (items) {
845 int count = PyList_Size(items);
849 int count = PyList_Size(items);
846 PyObject* value;
850 PyObject* value;
847 PyObject* key;
851 PyObject* key;
848 PyObject* tuple;
852 PyObject* tuple;
849 for (int i = 0;i<count;i++) {
853 for (int i = 0;i<count;i++) {
850 tuple = PyList_GetItem(items,i);
854 tuple = PyList_GetItem(items,i);
851 key = PyTuple_GetItem(tuple, 0);
855 key = PyTuple_GetItem(tuple, 0);
852 value = PyTuple_GetItem(tuple, 1);
856 value = PyTuple_GetItem(tuple, 1);
853 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
857 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
854 }
858 }
855 Py_DECREF(items);
859 Py_DECREF(items);
856 v = map;
860 v = map;
857 }
861 }
858 }
862 }
859 }
863 }
860 break;
864 break;
861 case QVariant::List:
865 case QVariant::List:
862 if (PySequence_Check(val)) {
866 if (PySequence_Check(val)) {
863 QVariantList list;
867 QVariantList list;
864 int count = PySequence_Size(val);
868 int count = PySequence_Size(val);
865 PyObject* value;
869 PyObject* value;
866 for (int i = 0;i<count;i++) {
870 for (int i = 0;i<count;i++) {
867 value = PySequence_GetItem(val,i);
871 value = PySequence_GetItem(val,i);
868 list.append(PyObjToQVariant(value, -1));
872 list.append(PyObjToQVariant(value, -1));
869 }
873 }
870 v = list;
874 v = list;
871 }
875 }
872 break;
876 break;
873 case QVariant::StringList:
877 case QVariant::StringList:
874 {
878 {
875 bool ok;
879 bool ok;
876 QStringList l = PyObjToStringList(val, false, ok);
880 QStringList l = PyObjToStringList(val, false, ok);
877 if (ok) {
881 if (ok) {
878 v = l;
882 v = l;
879 }
883 }
880 }
884 }
881 break;
885 break;
882
886
883 default:
887 default:
884 if (val->ob_type == &PythonQtVariantWrapper_Type) {
888 if (val->ob_type == &PythonQtVariantWrapper_Type) {
885 PythonQtVariantWrapper* varWrap = (PythonQtVariantWrapper*)val;
889 PythonQtVariantWrapper* varWrap = (PythonQtVariantWrapper*)val;
886 if (varWrap->_variant->userType() == type) {
890 if (varWrap->_variant->userType() == type) {
887 v = *varWrap->_variant;
891 v = *varWrap->_variant;
888 }
892 }
889 } else {
893 } else {
890 v = QVariant();
894 v = QVariant();
891 }
895 }
892 }
896 }
893 return v;
897 return v;
894 }
898 }
895
899
896 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
900 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
897 {
901 {
898 if (str.isNull()) {
902 if (str.isNull()) {
899 return PyString_FromString("");
903 return PyString_FromString("");
900 } else {
904 } else {
901 #ifdef WIN32
905 #ifdef WIN32
902 // return PyString_FromString(str.toLatin1().data());
906 // return PyString_FromString(str.toLatin1().data());
903 return PyUnicode_FromUnicode(str.utf16(), str.length());
907 return PyUnicode_FromUnicode(str.utf16(), str.length());
904 #else
908 #else
905 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
909 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
906 #endif
910 #endif
907 }
911 }
908 }
912 }
909
913
910 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
914 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
911 {
915 {
912 PyObject* result = PyTuple_New(list.count());
916 PyObject* result = PyTuple_New(list.count());
913 int i = 0;
917 int i = 0;
914 QString str;
918 QString str;
915 foreach (str, list) {
919 foreach (str, list) {
916 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
920 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
917 i++;
921 i++;
918 }
922 }
919 // why is the error state bad after this?
923 // why is the error state bad after this?
920 PyErr_Clear();
924 PyErr_Clear();
921 return result;
925 return result;
922 }
926 }
923
927
924 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
928 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
925 {
929 {
926 PyObject* result = PyList_New(list.count());
930 PyObject* result = PyList_New(list.count());
927 int i = 0;
931 int i = 0;
928 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
932 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
929 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
933 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
930 i++;
934 i++;
931 }
935 }
932 return result;
936 return result;
933 }
937 }
934
938
935 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
939 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
936 {
940 {
937 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
941 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
938 }
942 }
939
943
940 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
944 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
941 PyObject* result = PyDict_New();
945 PyObject* result = PyDict_New();
942 QVariantMap::const_iterator t = m.constBegin();
946 QVariantMap::const_iterator t = m.constBegin();
943 PyObject* key;
947 PyObject* key;
944 PyObject* val;
948 PyObject* val;
945 for (;t!=m.end();t++) {
949 for (;t!=m.end();t++) {
946 key = QStringToPyObject(t.key());
950 key = QStringToPyObject(t.key());
947 val = QVariantToPyObject(t.value());
951 val = QVariantToPyObject(t.value());
948 PyDict_SetItem(result, key, val);
952 PyDict_SetItem(result, key, val);
949 Py_DECREF(key);
953 Py_DECREF(key);
950 Py_DECREF(val);
954 Py_DECREF(val);
951 }
955 }
952 return result;
956 return result;
953 }
957 }
954
958
955 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
959 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
956 PyObject* result = PyTuple_New(l.count());
960 PyObject* result = PyTuple_New(l.count());
957 int i = 0;
961 int i = 0;
958 QVariant v;
962 QVariant v;
959 foreach (v, l) {
963 foreach (v, l) {
960 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
964 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
961 i++;
965 i++;
962 }
966 }
963 // why is the error state bad after this?
967 // why is the error state bad after this?
964 PyErr_Clear();
968 PyErr_Clear();
965 return result;
969 return result;
966 }
970 }
967
971
968 PyObject* PythonQtConv::ConvertQListWithPointersToPython(QList<void*>* list, const QByteArray& type)
972 PyObject* PythonQtConv::ConvertQListWithPointersToPython(QList<void*>* list, const QByteArray& type)
969 {
973 {
970 PyObject* result = PyTuple_New(list->count());
974 PyObject* result = PyTuple_New(list->count());
971 int i = 0;
975 int i = 0;
972 foreach (void* value, *list) {
976 foreach (void* value, *list) {
973 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, type));
977 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, type));
974 i++;
978 i++;
975 }
979 }
976 return result;
980 return result;
977 }
981 }
978
982
979 bool PythonQtConv::ConvertPythonListToQListOfType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict)
983 bool PythonQtConv::ConvertPythonListToQListOfType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict)
980 {
984 {
981 bool result = false;
985 bool result = false;
982 if (PySequence_Check(obj)) {
986 if (PySequence_Check(obj)) {
983 result = true;
987 result = true;
984 int count = PySequence_Size(obj);
988 int count = PySequence_Size(obj);
985 PyObject* value;
989 PyObject* value;
986 for (int i = 0;i<count;i++) {
990 for (int i = 0;i<count;i++) {
987 value = PySequence_GetItem(obj,i);
991 value = PySequence_GetItem(obj,i);
988 if (value->ob_type == &PythonQtWrapper_Type) {
992 if (value->ob_type == &PythonQtWrapper_Type) {
989 PythonQtWrapper* wrap = (PythonQtWrapper*)value;
993 PythonQtWrapper* wrap = (PythonQtWrapper*)value;
990 // c++ wrapper, check if the class names of the c++ objects match
994 // c++ wrapper, check if the class names of the c++ objects match
991 if (wrap->_info->isCPPWrapper()) {
995 if (wrap->_info->isCPPWrapper()) {
992 //TODO: we could support inheritance on cpp wrappers as well
996 //TODO: we could support inheritance on cpp wrappers as well
993 if (wrap->_info->wrappedCPPClassName() == type) {
997 if (wrap->_info->wrappedCPPClassName() == type) {
994 list->append(wrap->_wrappedPtr);
998 list->append(wrap->_wrappedPtr);
995 } else {
999 } else {
996 result = false;
1000 result = false;
997 break;
1001 break;
998 }
1002 }
999 } else {
1003 } else {
1000 if (wrap->_info->inherits(type)) {
1004 if (wrap->_info->inherits(type)) {
1001 list->append((void*)wrap->_obj);
1005 QObject* myObject = wrap->_obj;
1006 list->append((void*)myObject);
1002 } else {
1007 } else {
1003 result = false;
1008 result = false;
1004 break;
1009 break;
1005 }
1010 }
1006 }
1011 }
1007 }
1012 }
1008 }
1013 }
1009 }
1014 }
1010 return result;
1015 return result;
1011 }
1016 }
1012
1017
@@ -1,788 +1,790
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 PythonQtImporter.h
35 // \file PythonQtImporter.h
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 // This module was inspired by the zipimport.c module of the original
40 // This module was inspired by the zipimport.c module of the original
41 // Python distribution. Most of the functions are identical or slightly
41 // Python distribution. Most of the functions are identical or slightly
42 // modified to do all the loading of Python files via an external file interface.
42 // modified to do all the loading of Python files via an external file interface.
43 // In contrast to zipimport.c, this module also writes *.pyc files
43 // In contrast to zipimport.c, this module also writes *.pyc files
44 // automatically if it has write access/is not inside of a zip file.
44 // automatically if it has write access/is not inside of a zip file.
45 //----------------------------------------------------------------------------------
45 //----------------------------------------------------------------------------------
46
46
47 #include "PythonQtImporter.h"
47 #include "PythonQtImporter.h"
48 #include "PythonQtImportFileInterface.h"
48 #include "PythonQtImportFileInterface.h"
49 #include "PythonQt.h"
49 #include "PythonQt.h"
50 #include <QFile>
50 #include <QFile>
51 #include <QFileInfo>
51 #include <QFileInfo>
52
52
53 #define IS_SOURCE 0x0
53 #define IS_SOURCE 0x0
54 #define IS_BYTECODE 0x1
54 #define IS_BYTECODE 0x1
55 #define IS_PACKAGE 0x2
55 #define IS_PACKAGE 0x2
56
56
57 struct st_mlab_searchorder {
57 struct st_mlab_searchorder {
58 char suffix[14];
58 char suffix[14];
59 int type;
59 int type;
60 };
60 };
61
61
62 /* mlab_searchorder defines how we search for a module in the Zip
62 /* mlab_searchorder defines how we search for a module in the Zip
63 archive: we first search for a package __init__, then for
63 archive: we first search for a package __init__, then for
64 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
64 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
65 are swapped by initmlabimport() if we run in optimized mode. Also,
65 are swapped by initmlabimport() if we run in optimized mode. Also,
66 '/' is replaced by SEP there. */
66 '/' is replaced by SEP there. */
67 struct st_mlab_searchorder mlab_searchorder[] = {
67 struct st_mlab_searchorder mlab_searchorder[] = {
68 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
68 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
69 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
69 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
70 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
70 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
71 {".pyc", IS_BYTECODE},
71 {".pyc", IS_BYTECODE},
72 {".pyo", IS_BYTECODE},
72 {".pyo", IS_BYTECODE},
73 {".py", IS_SOURCE},
73 {".py", IS_SOURCE},
74 {"", 0}
74 {"", 0}
75 };
75 };
76
76
77 extern PyTypeObject PythonQtImporter_Type;
77 extern PyTypeObject PythonQtImporter_Type;
78 PyObject *PythonQtImportError;
78 PyObject *PythonQtImportError;
79
79
80 QString PythonQtImport::getSubName(const QString& str)
80 QString PythonQtImport::getSubName(const QString& str)
81 {
81 {
82 int idx = str.lastIndexOf('.');
82 int idx = str.lastIndexOf('.');
83 if (idx!=-1) {
83 if (idx!=-1) {
84 return str.mid(idx+1);
84 return str.mid(idx+1);
85 } else {
85 } else {
86 return str;
86 return str;
87 }
87 }
88 }
88 }
89
89
90 PythonQtImport::module_info PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
90 PythonQtImport::module_info PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
91 {
91 {
92 QString subname;
92 QString subname;
93 struct st_mlab_searchorder *zso;
93 struct st_mlab_searchorder *zso;
94
94
95 subname = getSubName(fullname);
95 subname = getSubName(fullname);
96 QString path = *self->_path + "/" + subname;
96 QString path = *self->_path + "/" + subname;
97
97
98 QString test;
98 QString test;
99 for (zso = mlab_searchorder; *zso->suffix; zso++) {
99 for (zso = mlab_searchorder; *zso->suffix; zso++) {
100 test = path + zso->suffix;
100 test = path + zso->suffix;
101 if (PythonQt::importInterface()->exists(test)) {
101 if (PythonQt::importInterface()->exists(test)) {
102 if (zso->type & IS_PACKAGE)
102 if (zso->type & IS_PACKAGE)
103 return MI_PACKAGE;
103 return MI_PACKAGE;
104 else
104 else
105 return MI_MODULE;
105 return MI_MODULE;
106 }
106 }
107 }
107 }
108 return MI_NOT_FOUND;
108 return MI_NOT_FOUND;
109 }
109 }
110
110
111
111
112 /* PythonQtImporter.__init__
112 /* PythonQtImporter.__init__
113 Just store the path argument
113 Just store the path argument
114 */
114 */
115 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject *kwds)
115 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject *kwds)
116 {
116 {
117 self->_path = NULL;
117 self->_path = NULL;
118
118
119 const char* path;
119 const char* path;
120 if (!PyArg_ParseTuple(args, "s",
120 if (!PyArg_ParseTuple(args, "s",
121 &path))
121 &path))
122 return -1;
122 return -1;
123
123
124 if (PythonQt::importInterface()->exists(path)) {
124 if (PythonQt::importInterface()->exists(path)) {
125 //qDebug("path %s", path);
125 //qDebug("path %s", path);
126 QString p(path);
126 QString p(path);
127 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
127 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
128 foreach(QString a, ignorePaths) {
128 foreach(QString a, ignorePaths) {
129 if (a==p) {
129 if (a==p) {
130 PyErr_SetString(PythonQtImportError,
130 PyErr_SetString(PythonQtImportError,
131 "path ignored");
131 "path ignored");
132 return -1;
132 return -1;
133 }
133 }
134 }
134 }
135
135
136 self->_path = new QString(p);
136 self->_path = new QString(p);
137
137
138 //mlabDebugConst("MLABPython", "PythonQtImporter init: " << *self->_path);
138 //mlabDebugConst("MLABPython", "PythonQtImporter init: " << *self->_path);
139
139
140 return 0;
140 return 0;
141 } else {
141 } else {
142 PyErr_SetString(PythonQtImportError,
142 PyErr_SetString(PythonQtImportError,
143 "path does not exist error");
143 "path does not exist error");
144 return -1;
144 return -1;
145 }
145 }
146 }
146 }
147
147
148 void
148 void
149 PythonQtImporter_dealloc(PythonQtImporter *self)
149 PythonQtImporter_dealloc(PythonQtImporter *self)
150 {
150 {
151 // free the stored path
151 // free the stored path
152 if (self->_path) delete self->_path;
152 if (self->_path) delete self->_path;
153 // free ourself
153 // free ourself
154 self->ob_type->tp_free((PyObject *)self);
154 self->ob_type->tp_free((PyObject *)self);
155 }
155 }
156
156
157
157
158 /* Check whether we can satisfy the import of the module named by
158 /* Check whether we can satisfy the import of the module named by
159 'fullname'. Return self if we can, None if we can't. */
159 'fullname'. Return self if we can, None if we can't. */
160 PyObject *
160 PyObject *
161 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
161 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
162 {
162 {
163 PythonQtImporter *self = (PythonQtImporter *)obj;
163 PythonQtImporter *self = (PythonQtImporter *)obj;
164 PyObject *path = NULL;
164 PyObject *path = NULL;
165 char *fullname;
165 char *fullname;
166
166
167 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
167 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
168 &fullname, &path))
168 &fullname, &path))
169 return NULL;
169 return NULL;
170
170
171 // mlabDebugConst("MLABPython", "FindModule " << fullname << " in " << *self->_path);
171 // mlabDebugConst("MLABPython", "FindModule " << fullname << " in " << *self->_path);
172
172
173 PythonQtImport::module_info info = PythonQtImport::getModuleInfo(self, fullname);
173 PythonQtImport::module_info info = PythonQtImport::getModuleInfo(self, fullname);
174 if (info == PythonQtImport::MI_MODULE || info == PythonQtImport::MI_PACKAGE) {
174 if (info == PythonQtImport::MI_MODULE || info == PythonQtImport::MI_PACKAGE) {
175 Py_INCREF(self);
175 Py_INCREF(self);
176 return (PyObject *)self;
176 return (PyObject *)self;
177 } else {
177 } else {
178 Py_INCREF(Py_None);
178 Py_INCREF(Py_None);
179 return Py_None;
179 return Py_None;
180 }
180 }
181 }
181 }
182
182
183 /* Load and return the module named by 'fullname'. */
183 /* Load and return the module named by 'fullname'. */
184 PyObject *
184 PyObject *
185 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
185 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
186 {
186 {
187 PythonQtImporter *self = (PythonQtImporter *)obj;
187 PythonQtImporter *self = (PythonQtImporter *)obj;
188 PyObject *code, *mod, *dict;
188 PyObject *code, *mod, *dict;
189 char *fullname;
189 char *fullname;
190 QString modpath;
190 QString modpath;
191 int ispackage;
191 int ispackage;
192
192
193 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
193 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
194 &fullname))
194 &fullname))
195 return NULL;
195 return NULL;
196
196
197 code = PythonQtImport::getModuleCode(self, fullname, &ispackage, modpath);
197 code = PythonQtImport::getModuleCode(self, fullname, &ispackage, modpath);
198 if (code == NULL)
198 if (code == NULL)
199 return NULL;
199 return NULL;
200
200
201 mod = PyImport_AddModule(fullname);
201 mod = PyImport_AddModule(fullname);
202 if (mod == NULL) {
202 if (mod == NULL) {
203 Py_DECREF(code);
203 Py_DECREF(code);
204 return NULL;
204 return NULL;
205 }
205 }
206 dict = PyModule_GetDict(mod);
206 dict = PyModule_GetDict(mod);
207
207
208 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0)
208 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0)
209 goto error;
209 goto error;
210
210
211 if (ispackage) {
211 if (ispackage) {
212 PyObject *pkgpath, *fullpath;
212 PyObject *pkgpath, *fullpath;
213 QString subname = PythonQtImport::getSubName(fullname);
213 QString subname = PythonQtImport::getSubName(fullname);
214 int err;
214 int err;
215
215
216 fullpath = PyString_FromFormat("%s%c%s",
216 fullpath = PyString_FromFormat("%s%c%s",
217 self->_path->toLatin1().constData(),
217 self->_path->toLatin1().constData(),
218 SEP,
218 SEP,
219 subname.toLatin1().constData());
219 subname.toLatin1().constData());
220 if (fullpath == NULL)
220 if (fullpath == NULL)
221 goto error;
221 goto error;
222
222
223 pkgpath = Py_BuildValue("[O]", fullpath);
223 pkgpath = Py_BuildValue("[O]", fullpath);
224 Py_DECREF(fullpath);
224 Py_DECREF(fullpath);
225 if (pkgpath == NULL)
225 if (pkgpath == NULL)
226 goto error;
226 goto error;
227 err = PyDict_SetItemString(dict, "__path__", pkgpath);
227 err = PyDict_SetItemString(dict, "__path__", pkgpath);
228 Py_DECREF(pkgpath);
228 Py_DECREF(pkgpath);
229 if (err != 0)
229 if (err != 0)
230 goto error;
230 goto error;
231 }
231 }
232 mod = PyImport_ExecCodeModuleEx(fullname, code, (char*)modpath.toLatin1().data());
232 mod = PyImport_ExecCodeModuleEx(fullname, code, (char*)modpath.toLatin1().data());
233 Py_DECREF(code);
233 Py_DECREF(code);
234 if (Py_VerboseFlag)
234 if (Py_VerboseFlag)
235 PySys_WriteStderr("import %s # loaded from %s\n",
235 PySys_WriteStderr("import %s # loaded from %s\n",
236 fullname, modpath);
236 fullname, modpath);
237 return mod;
237 return mod;
238 error:
238 error:
239 Py_DECREF(code);
239 Py_DECREF(code);
240 Py_DECREF(mod);
240 Py_DECREF(mod);
241 return NULL;
241 return NULL;
242 }
242 }
243
243
244
244
245 PyObject *
245 PyObject *
246 PythonQtImporter_get_data(PyObject *obj, PyObject *args)
246 PythonQtImporter_get_data(PyObject *obj, PyObject *args)
247 {
247 {
248 // EXTRA, NOT YET IMPLEMENTED
248 // EXTRA, NOT YET IMPLEMENTED
249 return NULL;
249 return NULL;
250 }
250 }
251
251
252 PyObject *
252 PyObject *
253 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
253 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
254 {
254 {
255 PythonQtImporter *self = (PythonQtImporter *)obj;
255 PythonQtImporter *self = (PythonQtImporter *)obj;
256 char *fullname;
256 char *fullname;
257
257
258 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
258 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
259 return NULL;
259 return NULL;
260
260
261 QString notused;
261 QString notused;
262 return PythonQtImport::getModuleCode(self, fullname, NULL, notused);
262 return PythonQtImport::getModuleCode(self, fullname, NULL, notused);
263 }
263 }
264
264
265 PyObject *
265 PyObject *
266 PythonQtImporter_get_source(PyObject *obj, PyObject *args)
266 PythonQtImporter_get_source(PyObject *obj, PyObject *args)
267 {
267 {
268 // EXTRA, NOT YET IMPLEMENTED
268 // EXTRA, NOT YET IMPLEMENTED
269 /*
269 /*
270 PythonQtImporter *self = (PythonQtImporter *)obj;
270 PythonQtImporter *self = (PythonQtImporter *)obj;
271 PyObject *toc_entry;
271 PyObject *toc_entry;
272 char *fullname, *subname, path[MAXPATHLEN+1];
272 char *fullname, *subname, path[MAXPATHLEN+1];
273 int len;
273 int len;
274 enum module_info mi;
274 enum module_info mi;
275
275
276 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_source", &fullname))
276 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_source", &fullname))
277 return NULL;
277 return NULL;
278
278
279 mi = get_module_info(self, fullname);
279 mi = get_module_info(self, fullname);
280 if (mi == MI_ERROR)
280 if (mi == MI_ERROR)
281 return NULL;
281 return NULL;
282 if (mi == MI_NOT_FOUND) {
282 if (mi == MI_NOT_FOUND) {
283 PyErr_Format(PythonQtImportError, "can't find module '%.200s'",
283 PyErr_Format(PythonQtImportError, "can't find module '%.200s'",
284 fullname);
284 fullname);
285 return NULL;
285 return NULL;
286 }
286 }
287 subname = get_subname(fullname);
287 subname = get_subname(fullname);
288
288
289 len = make_filename(PyString_AsString(self->prefix), subname, path);
289 len = make_filename(PyString_AsString(self->prefix), subname, path);
290 if (len < 0)
290 if (len < 0)
291 return NULL;
291 return NULL;
292
292
293 if (mi == MI_PACKAGE) {
293 if (mi == MI_PACKAGE) {
294 path[len] = SEP;
294 path[len] = SEP;
295 strcpy(path + len + 1, "__init__.py");
295 strcpy(path + len + 1, "__init__.py");
296 }
296 }
297 else
297 else
298 strcpy(path + len, ".py");
298 strcpy(path + len, ".py");
299
299
300 toc_entry = PyDict_GetItemString(self->files, path);
300 toc_entry = PyDict_GetItemString(self->files, path);
301 if (toc_entry != NULL)
301 if (toc_entry != NULL)
302 return get_data(PyString_AsString(self->archive), toc_entry);
302 return get_data(PyString_AsString(self->archive), toc_entry);
303
303
304 Py_INCREF(Py_None);
304 Py_INCREF(Py_None);
305 return Py_None;
305 return Py_None;
306 */
306 */
307 return NULL;
307 return NULL;
308 }
308 }
309
309
310 PyDoc_STRVAR(doc_find_module,
310 PyDoc_STRVAR(doc_find_module,
311 "find_module(fullname, path=None) -> self or None.\n\
311 "find_module(fullname, path=None) -> self or None.\n\
312 \n\
312 \n\
313 Search for a module specified by 'fullname'. 'fullname' must be the\n\
313 Search for a module specified by 'fullname'. 'fullname' must be the\n\
314 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
314 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
315 instance itself if the module was found, or None if it wasn't.\n\
315 instance itself if the module was found, or None if it wasn't.\n\
316 The optional 'path' argument is ignored -- it's there for compatibility\n\
316 The optional 'path' argument is ignored -- it's there for compatibility\n\
317 with the importer protocol.");
317 with the importer protocol.");
318
318
319 PyDoc_STRVAR(doc_load_module,
319 PyDoc_STRVAR(doc_load_module,
320 "load_module(fullname) -> module.\n\
320 "load_module(fullname) -> module.\n\
321 \n\
321 \n\
322 Load the module specified by 'fullname'. 'fullname' must be the\n\
322 Load the module specified by 'fullname'. 'fullname' must be the\n\
323 fully qualified (dotted) module name. It returns the imported\n\
323 fully qualified (dotted) module name. It returns the imported\n\
324 module, or raises PythonQtImportError if it wasn't found.");
324 module, or raises PythonQtImportError if it wasn't found.");
325
325
326 PyDoc_STRVAR(doc_get_data,
326 PyDoc_STRVAR(doc_get_data,
327 "get_data(pathname) -> string with file data.\n\
327 "get_data(pathname) -> string with file data.\n\
328 \n\
328 \n\
329 Return the data associated with 'pathname'. Raise IOError if\n\
329 Return the data associated with 'pathname'. Raise IOError if\n\
330 the file wasn't found.");
330 the file wasn't found.");
331
331
332 PyDoc_STRVAR(doc_get_code,
332 PyDoc_STRVAR(doc_get_code,
333 "get_code(fullname) -> code object.\n\
333 "get_code(fullname) -> code object.\n\
334 \n\
334 \n\
335 Return the code object for the specified module. Raise PythonQtImportError\n\
335 Return the code object for the specified module. Raise PythonQtImportError\n\
336 is the module couldn't be found.");
336 is the module couldn't be found.");
337
337
338 PyDoc_STRVAR(doc_get_source,
338 PyDoc_STRVAR(doc_get_source,
339 "get_source(fullname) -> source string.\n\
339 "get_source(fullname) -> source string.\n\
340 \n\
340 \n\
341 Return the source code for the specified module. Raise PythonQtImportError\n\
341 Return the source code for the specified module. Raise PythonQtImportError\n\
342 is the module couldn't be found, return None if the archive does\n\
342 is the module couldn't be found, return None if the archive does\n\
343 contain the module, but has no source for it.");
343 contain the module, but has no source for it.");
344
344
345 PyMethodDef PythonQtImporter_methods[] = {
345 PyMethodDef PythonQtImporter_methods[] = {
346 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
346 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
347 doc_find_module},
347 doc_find_module},
348 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
348 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
349 doc_load_module},
349 doc_load_module},
350 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
350 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
351 doc_get_data},
351 doc_get_data},
352 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
352 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
353 doc_get_code},
353 doc_get_code},
354 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
354 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
355 doc_get_source},
355 doc_get_source},
356 {NULL, NULL} /* sentinel */
356 {NULL, NULL} /* sentinel */
357 };
357 };
358
358
359
359
360 PyDoc_STRVAR(PythonQtImporter_doc,
360 PyDoc_STRVAR(PythonQtImporter_doc,
361 "PythonQtImporter(path) -> PythonQtImporter object\n\
361 "PythonQtImporter(path) -> PythonQtImporter object\n\
362 \n\
362 \n\
363 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
363 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
364 . Every path is accepted.");
364 . Every path is accepted.");
365
365
366 #define DEFERRED_ADDRESS(ADDR) 0
366 #define DEFERRED_ADDRESS(ADDR) 0
367
367
368 PyTypeObject PythonQtImporter_Type = {
368 PyTypeObject PythonQtImporter_Type = {
369 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
369 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
370 0,
370 0,
371 "PythonQtImport.PythonQtImporter",
371 "PythonQtImport.PythonQtImporter",
372 sizeof(PythonQtImporter),
372 sizeof(PythonQtImporter),
373 0, /* tp_itemsize */
373 0, /* tp_itemsize */
374 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
374 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
375 0, /* tp_print */
375 0, /* tp_print */
376 0, /* tp_getattr */
376 0, /* tp_getattr */
377 0, /* tp_setattr */
377 0, /* tp_setattr */
378 0, /* tp_compare */
378 0, /* tp_compare */
379 0, /* tp_repr */
379 0, /* tp_repr */
380 0, /* tp_as_number */
380 0, /* tp_as_number */
381 0, /* tp_as_sequence */
381 0, /* tp_as_sequence */
382 0, /* tp_as_mapping */
382 0, /* tp_as_mapping */
383 0, /* tp_hash */
383 0, /* tp_hash */
384 0, /* tp_call */
384 0, /* tp_call */
385 0, /* tp_str */
385 0, /* tp_str */
386 PyObject_GenericGetAttr, /* tp_getattro */
386 PyObject_GenericGetAttr, /* tp_getattro */
387 0, /* tp_setattro */
387 0, /* tp_setattro */
388 0, /* tp_as_buffer */
388 0, /* tp_as_buffer */
389 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
389 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
390 PythonQtImporter_doc, /* tp_doc */
390 PythonQtImporter_doc, /* tp_doc */
391 0, /* tp_traverse */
391 0, /* tp_traverse */
392 0, /* tp_clear */
392 0, /* tp_clear */
393 0, /* tp_richcompare */
393 0, /* tp_richcompare */
394 0, /* tp_weaklistoffset */
394 0, /* tp_weaklistoffset */
395 0, /* tp_iter */
395 0, /* tp_iter */
396 0, /* tp_iternext */
396 0, /* tp_iternext */
397 PythonQtImporter_methods, /* tp_methods */
397 PythonQtImporter_methods, /* tp_methods */
398 0, /* tp_members */
398 0, /* tp_members */
399 0, /* tp_getset */
399 0, /* tp_getset */
400 0, /* tp_base */
400 0, /* tp_base */
401 0, /* tp_dict */
401 0, /* tp_dict */
402 0, /* tp_descr_get */
402 0, /* tp_descr_get */
403 0, /* tp_descr_set */
403 0, /* tp_descr_set */
404 0, /* tp_dictoffset */
404 0, /* tp_dictoffset */
405 (initproc)PythonQtImporter_init, /* tp_init */
405 (initproc)PythonQtImporter_init, /* tp_init */
406 PyType_GenericAlloc, /* tp_alloc */
406 PyType_GenericAlloc, /* tp_alloc */
407 PyType_GenericNew, /* tp_new */
407 PyType_GenericNew, /* tp_new */
408 PyObject_Del, /* tp_free */
408 PyObject_Del, /* tp_free */
409 };
409 };
410
410
411
411
412 /* Given a buffer, return the long that is represented by the first
412 /* Given a buffer, return the long that is represented by the first
413 4 bytes, encoded as little endian. This partially reimplements
413 4 bytes, encoded as little endian. This partially reimplements
414 marshal.c:r_long() */
414 marshal.c:r_long() */
415 long
415 long
416 PythonQtImport::getLong(unsigned char *buf)
416 PythonQtImport::getLong(unsigned char *buf)
417 {
417 {
418 long x;
418 long x;
419 x = buf[0];
419 x = buf[0];
420 x |= (long)buf[1] << 8;
420 x |= (long)buf[1] << 8;
421 x |= (long)buf[2] << 16;
421 x |= (long)buf[2] << 16;
422 x |= (long)buf[3] << 24;
422 x |= (long)buf[3] << 24;
423 #if SIZEOF_LONG > 4
423 #if SIZEOF_LONG > 4
424 /* Sign extension for 64-bit machines */
424 /* Sign extension for 64-bit machines */
425 x |= -(x & 0x80000000L);
425 x |= -(x & 0x80000000L);
426 #endif
426 #endif
427 return x;
427 return x;
428 }
428 }
429
429
430 FILE *
430 FILE *
431 open_exclusive(const QString& filename)
431 open_exclusive(const QString& filename)
432 {
432 {
433 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
433 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
434 /* Use O_EXCL to avoid a race condition when another process tries to
434 /* Use O_EXCL to avoid a race condition when another process tries to
435 write the same file. When that happens, our open() call fails,
435 write the same file. When that happens, our open() call fails,
436 which is just fine (since it's only a cache).
436 which is just fine (since it's only a cache).
437 XXX If the file exists and is writable but the directory is not
437 XXX If the file exists and is writable but the directory is not
438 writable, the file will never be written. Oh well.
438 writable, the file will never be written. Oh well.
439 */
439 */
440 QFile::remove(filename);
440 QFile::remove(filename);
441
441
442 int fd;
442 int fd;
443 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
443 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
444 #ifdef O_BINARY
444 #ifdef O_BINARY
445 flags |= O_BINARY; /* necessary for Windows */
445 flags |= O_BINARY; /* necessary for Windows */
446 #endif
446 #endif
447 #ifdef WIN32
447 #ifdef WIN32
448 fd = _wopen(filename.ucs2(), flags, 0666);
448 fd = _wopen(filename.ucs2(), flags, 0666);
449 #else
449 #else
450 fd = open(filename.local8Bit(), flags, 0666);
450 fd = open(filename.local8Bit(), flags, 0666);
451 #endif
451 #endif
452 if (fd < 0)
452 if (fd < 0)
453 return NULL;
453 return NULL;
454 return fdopen(fd, "wb");
454 return fdopen(fd, "wb");
455 #else
455 #else
456 /* Best we can do -- on Windows this can't happen anyway */
456 /* Best we can do -- on Windows this can't happen anyway */
457 return fopen(filename.toLocal8Bit().constData(), "wb");
457 return fopen(filename.toLocal8Bit().constData(), "wb");
458 #endif
458 #endif
459 }
459 }
460
460
461
461
462 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
462 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
463 {
463 {
464 FILE *fp;
464 FILE *fp;
465
465
466 fp = open_exclusive(filename);
466 fp = open_exclusive(filename);
467 if (fp == NULL) {
467 if (fp == NULL) {
468 if (Py_VerboseFlag)
468 if (Py_VerboseFlag)
469 PySys_WriteStderr(
469 PySys_WriteStderr(
470 "# can't create %s\n", filename.toLatin1().constData());
470 "# can't create %s\n", filename.toLatin1().constData());
471 return;
471 return;
472 }
472 }
473 #if PY_VERSION_HEX < 0x02040000
473 #if PY_VERSION_HEX < 0x02040000
474 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
474 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
475 #else
475 #else
476 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
476 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
477 #endif
477 #endif
478 /* First write a 0 for mtime */
478 /* First write a 0 for mtime */
479 #if PY_VERSION_HEX < 0x02040000
479 #if PY_VERSION_HEX < 0x02040000
480 PyMarshal_WriteLongToFile(0L, fp);
480 PyMarshal_WriteLongToFile(0L, fp);
481 #else
481 #else
482 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
482 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
483 #endif
483 #endif
484 #if PY_VERSION_HEX < 0x02040000
484 #if PY_VERSION_HEX < 0x02040000
485 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
485 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
486 #else
486 #else
487 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
487 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
488 #endif
488 #endif
489 if (ferror(fp)) {
489 if (ferror(fp)) {
490 if (Py_VerboseFlag)
490 if (Py_VerboseFlag)
491 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
491 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
492 /* Don't keep partial file */
492 /* Don't keep partial file */
493 fclose(fp);
493 fclose(fp);
494 QFile::remove(filename);
494 QFile::remove(filename);
495 return;
495 return;
496 }
496 }
497 /* Now write the true mtime */
497 /* Now write the true mtime */
498 fseek(fp, 4L, 0);
498 fseek(fp, 4L, 0);
499 #if PY_VERSION_HEX < 0x02040000
499 #if PY_VERSION_HEX < 0x02040000
500 PyMarshal_WriteLongToFile(mtime, fp);
500 PyMarshal_WriteLongToFile(mtime, fp);
501 #else
501 #else
502 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
502 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
503 #endif
503 #endif
504 fflush(fp);
504 fflush(fp);
505 fclose(fp);
505 fclose(fp);
506 if (Py_VerboseFlag)
506 if (Py_VerboseFlag)
507 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
507 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
508 //#ifdef macintosh
508 //#ifdef macintosh
509 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
509 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
510 //#endif
510 //#endif
511 }
511 }
512
512
513 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
513 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
514 and return the code object. Return None if it the magic word doesn't
514 and return the code object. Return None if it the magic word doesn't
515 match (we do this instead of raising an exception as we fall back
515 match (we do this instead of raising an exception as we fall back
516 to .py if available and we don't want to mask other errors).
516 to .py if available and we don't want to mask other errors).
517 Returns a new reference. */
517 Returns a new reference. */
518 PyObject *
518 PyObject *
519 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
519 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
520 {
520 {
521 PyObject *code;
521 PyObject *code;
522 // ugly cast, but Python API is not const safe
522 // ugly cast, but Python API is not const safe
523 char *buf = (char*) data.constData();
523 char *buf = (char*) data.constData();
524 int size = data.size();
524 int size = data.size();
525
525
526 if (size <= 9) {
526 if (size <= 9) {
527 PySys_WriteStderr("# %s has bad pyc data\n",
527 PySys_WriteStderr("# %s has bad pyc data\n",
528 path.toLatin1().constData());
528 path.toLatin1().constData());
529 Py_INCREF(Py_None);
529 Py_INCREF(Py_None);
530 return Py_None;
530 return Py_None;
531 }
531 }
532
532
533 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
533 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
534 if (Py_VerboseFlag)
534 if (Py_VerboseFlag)
535 PySys_WriteStderr("# %s has bad magic\n",
535 PySys_WriteStderr("# %s has bad magic\n",
536 path.toLatin1().constData());
536 path.toLatin1().constData());
537 Py_INCREF(Py_None);
537 Py_INCREF(Py_None);
538 return Py_None;
538 return Py_None;
539 }
539 }
540
540
541 if (mtime != 0 && !(getLong((unsigned char *)buf + 4) == mtime)) {
541 if (mtime != 0 && !(getLong((unsigned char *)buf + 4) == mtime)) {
542 if (Py_VerboseFlag)
542 if (Py_VerboseFlag)
543 PySys_WriteStderr("# %s has bad mtime\n",
543 PySys_WriteStderr("# %s has bad mtime\n",
544 path.toLatin1().constData());
544 path.toLatin1().constData());
545 Py_INCREF(Py_None);
545 Py_INCREF(Py_None);
546 return Py_None;
546 return Py_None;
547 }
547 }
548
548
549 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
549 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
550 if (code == NULL)
550 if (code == NULL)
551 return NULL;
551 return NULL;
552 if (!PyCode_Check(code)) {
552 if (!PyCode_Check(code)) {
553 Py_DECREF(code);
553 Py_DECREF(code);
554 PyErr_Format(PyExc_TypeError,
554 PyErr_Format(PyExc_TypeError,
555 "compiled module %.200s is not a code object",
555 "compiled module %.200s is not a code object",
556 path.toLatin1().constData());
556 path.toLatin1().constData());
557 return NULL;
557 return NULL;
558 }
558 }
559 return code;
559 return code;
560 }
560 }
561
561
562
562
563 /* Given a string buffer containing Python source code, compile it
563 /* Given a string buffer containing Python source code, compile it
564 return and return a code object as a new reference. */
564 return and return a code object as a new reference. */
565 PyObject *
565 PyObject *
566 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
566 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
567 {
567 {
568 PyObject *code;
568 PyObject *code;
569 QByteArray data1 = data;
569 QByteArray data1 = data;
570 // in qt4, data is null terminated
570 // in qt4, data is null terminated
571 // data1.resize(data.size()+1);
571 // data1.resize(data.size()+1);
572 // data1.data()[data.size()-1] = 0;
572 // data1.data()[data.size()-1] = 0;
573 code = Py_CompileString(data.data(), path.toLatin1().constData(),
573 code = Py_CompileString(data.data(), path.toLatin1().constData(),
574 Py_file_input);
574 Py_file_input);
575 return code;
575 return code;
576 }
576 }
577
577
578
578
579 /* Return the code object for the module named by 'fullname' from the
579 /* Return the code object for the module named by 'fullname' from the
580 Zip archive as a new reference. */
580 Zip archive as a new reference. */
581 PyObject *
581 PyObject *
582 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int ispackage, time_t mtime)
582 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int ispackage, time_t mtime)
583 {
583 {
584 bool hasImporter = PythonQt::importInterface()!=NULL;
584 bool hasImporter = PythonQt::importInterface()!=NULL;
585
585
586 PyObject *code;
586 PyObject *code;
587
587
588 QByteArray qdata;
588 QByteArray qdata;
589 if (!hasImporter) {
589 if (!hasImporter) {
590 QFile file(path);
590 QFile file(path);
591 QIODevice::OpenMode flags = QIODevice::ReadOnly;
591 QIODevice::OpenMode flags = QIODevice::ReadOnly;
592 if (!isbytecode) {
592 if (!isbytecode) {
593 flags |= QIODevice::Text;
593 flags |= QIODevice::Text;
594 }
594 }
595 if (!file.open(flags)) {
595 if (!file.open(flags)) {
596 return NULL;
596 return NULL;
597 }
597 }
598 qdata = file.readAll();
598 qdata = file.readAll();
599 } else {
599 } else {
600 if (!isbytecode) {
600 if (!isbytecode) {
601 // mlabDebugConst("MLABPython", "reading source " << path);
601 // mlabDebugConst("MLABPython", "reading source " << path);
602 bool ok;
602 bool ok;
603 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
603 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
604 if (!ok) {
604 if (!ok) {
605 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
605 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
606 return NULL;
606 return NULL;
607 }
607 }
608 if (qdata == " ") {
608 if (qdata == " ") {
609 qdata.clear();
609 qdata.clear();
610 }
610 }
611 } else {
611 } else {
612 qdata = PythonQt::importInterface()->readFileAsBytes(path);
612 qdata = PythonQt::importInterface()->readFileAsBytes(path);
613 }
613 }
614 }
614 }
615
615
616 if (isbytecode) {
616 if (isbytecode) {
617 // mlabDebugConst("MLABPython", "reading bytecode " << path);
617 // mlabDebugConst("MLABPython", "reading bytecode " << path);
618 code = unmarshalCode(path, qdata, mtime);
618 code = unmarshalCode(path, qdata, mtime);
619 }
619 }
620 else {
620 else {
621 // mlabDebugConst("MLABPython", "compiling source " << path);
621 // mlabDebugConst("MLABPython", "compiling source " << path);
622 code = compileSource(path, qdata);
622 code = compileSource(path, qdata);
623 if (code) {
623 // save a pyc file if possible
624 // save a pyc file if possible
624 QDateTime time;
625 QDateTime time;
625 time = hasImporter?PythonQt::importInterface()->lastModifiedDate(path):QFileInfo(path).lastModified();
626 time = hasImporter?PythonQt::importInterface()->lastModifiedDate(path):QFileInfo(path).lastModified();
626 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
627 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
627 }
628 }
629 }
628 return code;
630 return code;
629 }
631 }
630
632
631 time_t
633 time_t
632 PythonQtImport::getMTimeOfSource(const QString& path)
634 PythonQtImport::getMTimeOfSource(const QString& path)
633 {
635 {
634 time_t mtime = 0;
636 time_t mtime = 0;
635 QString path2 = path;
637 QString path2 = path;
636 path2.truncate(path.length()-1);
638 path2.truncate(path.length()-1);
637
639
638 bool hasImporter = PythonQt::importInterface()!=NULL;
640 bool hasImporter = PythonQt::importInterface()!=NULL;
639 if (hasImporter) {
641 if (hasImporter) {
640 if (PythonQt::importInterface()->exists(path2)) {
642 if (PythonQt::importInterface()->exists(path2)) {
641 mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t();
643 mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t();
642 }
644 }
643 } else {
645 } else {
644 if (QFile::exists(path2)) {
646 if (QFile::exists(path2)) {
645 mtime = QFileInfo(path2).lastModified().toTime_t();
647 mtime = QFileInfo(path2).lastModified().toTime_t();
646 }
648 }
647 }
649 }
648 return mtime;
650 return mtime;
649 }
651 }
650
652
651 /* Get the code object associated with the module specified by
653 /* Get the code object associated with the module specified by
652 'fullname'. */
654 'fullname'. */
653 PyObject *
655 PyObject *
654 PythonQtImport::getModuleCode(PythonQtImporter *self, char *fullname,
656 PythonQtImport::getModuleCode(PythonQtImporter *self, char *fullname,
655 int *p_ispackage, QString& modpath)
657 int *p_ispackage, QString& modpath)
656 {
658 {
657 QString subname;
659 QString subname;
658 struct st_mlab_searchorder *zso;
660 struct st_mlab_searchorder *zso;
659
661
660 subname = getSubName(fullname);
662 subname = getSubName(fullname);
661 QString path = *self->_path + "/" + subname;
663 QString path = *self->_path + "/" + subname;
662
664
663 QString test;
665 QString test;
664 for (zso = mlab_searchorder; *zso->suffix; zso++) {
666 for (zso = mlab_searchorder; *zso->suffix; zso++) {
665 PyObject *code = NULL;
667 PyObject *code = NULL;
666 test = path + zso->suffix;
668 test = path + zso->suffix;
667
669
668 if (Py_VerboseFlag > 1)
670 if (Py_VerboseFlag > 1)
669 PySys_WriteStderr("# trying %s\n",
671 PySys_WriteStderr("# trying %s\n",
670 test.toLatin1().constData());
672 test.toLatin1().constData());
671 if (PythonQt::importInterface()->exists(test)) {
673 if (PythonQt::importInterface()->exists(test)) {
672 time_t mtime = 0;
674 time_t mtime = 0;
673 int ispackage = zso->type & IS_PACKAGE;
675 int ispackage = zso->type & IS_PACKAGE;
674 int isbytecode = zso->type & IS_BYTECODE;
676 int isbytecode = zso->type & IS_BYTECODE;
675
677
676 if (isbytecode)
678 if (isbytecode)
677 mtime = getMTimeOfSource(test);
679 mtime = getMTimeOfSource(test);
678 if (p_ispackage != NULL)
680 if (p_ispackage != NULL)
679 *p_ispackage = ispackage;
681 *p_ispackage = ispackage;
680 code = getCodeFromData(test, isbytecode, ispackage, mtime);
682 code = getCodeFromData(test, isbytecode, ispackage, mtime);
681 if (code == Py_None) {
683 if (code == Py_None) {
682 Py_DECREF(code);
684 Py_DECREF(code);
683 continue;
685 continue;
684 }
686 }
685 if (code != NULL)
687 if (code != NULL)
686 modpath = test;
688 modpath = test;
687 return code;
689 return code;
688 }
690 }
689 }
691 }
690 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
692 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
691
693
692 return NULL;
694 return NULL;
693 }
695 }
694
696
695 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
697 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
696 {
698 {
697 QString r;
699 QString r;
698 int i = str.lastIndexOf('.');
700 int i = str.lastIndexOf('.');
699 if (i!=-1) {
701 if (i!=-1) {
700 r = str.mid(0,i) + "." + ext;
702 r = str.mid(0,i) + "." + ext;
701 } else {
703 } else {
702 r = str + "." + ext;
704 r = str + "." + ext;
703 }
705 }
704 return r;
706 return r;
705 }
707 }
706
708
707 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
709 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
708 {
710 {
709 bool hasImporter = PythonQt::importInterface()!=NULL;
711 bool hasImporter = PythonQt::importInterface()!=NULL;
710
712
711 PyObject* code;
713 PyObject* code;
712 const static QString pycStr("pyc");
714 const static QString pycStr("pyc");
713 QString pyc = replaceExtension(file, pycStr);
715 QString pyc = replaceExtension(file, pycStr);
714 if ((hasImporter && PythonQt::importInterface()->exists(pyc)) ||
716 if ((hasImporter && PythonQt::importInterface()->exists(pyc)) ||
715 (!hasImporter && QFile::exists(pyc))) {
717 (!hasImporter && QFile::exists(pyc))) {
716 time_t mtime = 0;
718 time_t mtime = 0;
717 mtime = getMTimeOfSource(pyc);
719 mtime = getMTimeOfSource(pyc);
718 code = getCodeFromData(pyc, true, false, mtime);
720 code = getCodeFromData(pyc, true, false, mtime);
719 if (code != Py_None && code != NULL) {
721 if (code != Py_None && code != NULL) {
720 return code;
722 return code;
721 }
723 }
722 if (code) {
724 if (code) {
723 Py_DECREF(code);
725 Py_DECREF(code);
724 }
726 }
725 }
727 }
726 code = getCodeFromData(file,false,false,0);
728 code = getCodeFromData(file,false,false,0);
727 return code;
729 return code;
728 }
730 }
729
731
730 /* Module init */
732 /* Module init */
731
733
732 PyDoc_STRVAR(mlabimport_doc,
734 PyDoc_STRVAR(mlabimport_doc,
733 "Imports python files into MeVisLab, completely replaces internal python import");
735 "Imports python files into MeVisLab, completely replaces internal python import");
734
736
735 void PythonQtImport::init()
737 void PythonQtImport::init()
736 {
738 {
737 PyObject *mod;
739 PyObject *mod;
738
740
739 if (PyType_Ready(&PythonQtImporter_Type) < 0)
741 if (PyType_Ready(&PythonQtImporter_Type) < 0)
740 return;
742 return;
741
743
742 /* Correct directory separator */
744 /* Correct directory separator */
743 mlab_searchorder[0].suffix[0] = SEP;
745 mlab_searchorder[0].suffix[0] = SEP;
744 mlab_searchorder[1].suffix[0] = SEP;
746 mlab_searchorder[1].suffix[0] = SEP;
745 mlab_searchorder[2].suffix[0] = SEP;
747 mlab_searchorder[2].suffix[0] = SEP;
746 if (Py_OptimizeFlag) {
748 if (Py_OptimizeFlag) {
747 /* Reverse *.pyc and *.pyo */
749 /* Reverse *.pyc and *.pyo */
748 struct st_mlab_searchorder tmp;
750 struct st_mlab_searchorder tmp;
749 tmp = mlab_searchorder[0];
751 tmp = mlab_searchorder[0];
750 mlab_searchorder[0] = mlab_searchorder[1];
752 mlab_searchorder[0] = mlab_searchorder[1];
751 mlab_searchorder[1] = tmp;
753 mlab_searchorder[1] = tmp;
752 tmp = mlab_searchorder[3];
754 tmp = mlab_searchorder[3];
753 mlab_searchorder[3] = mlab_searchorder[4];
755 mlab_searchorder[3] = mlab_searchorder[4];
754 mlab_searchorder[4] = tmp;
756 mlab_searchorder[4] = tmp;
755 }
757 }
756
758
757 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
759 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
758 NULL, PYTHON_API_VERSION);
760 NULL, PYTHON_API_VERSION);
759
761
760 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
762 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
761 PyExc_ImportError, NULL);
763 PyExc_ImportError, NULL);
762 if (PythonQtImportError == NULL)
764 if (PythonQtImportError == NULL)
763 return;
765 return;
764
766
765 Py_INCREF(PythonQtImportError);
767 Py_INCREF(PythonQtImportError);
766 if (PyModule_AddObject(mod, "PythonQtImportError",
768 if (PyModule_AddObject(mod, "PythonQtImportError",
767 PythonQtImportError) < 0)
769 PythonQtImportError) < 0)
768 return;
770 return;
769
771
770 Py_INCREF(&PythonQtImporter_Type);
772 Py_INCREF(&PythonQtImporter_Type);
771 if (PyModule_AddObject(mod, "PythonQtImporter",
773 if (PyModule_AddObject(mod, "PythonQtImporter",
772 (PyObject *)&PythonQtImporter_Type) < 0)
774 (PyObject *)&PythonQtImporter_Type) < 0)
773 return;
775 return;
774
776
775 // set our importer into the path_hooks to handle all path on sys.path
777 // set our importer into the path_hooks to handle all path on sys.path
776 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
778 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
777 PyObject* path_hooks = PySys_GetObject("path_hooks");
779 PyObject* path_hooks = PySys_GetObject("path_hooks");
778 PyList_Append(path_hooks, classobj);
780 PyList_Append(path_hooks, classobj);
779
781
780 #ifndef WIN32
782 #ifndef WIN32
781 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
783 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
782 PyObject* modules = PyImport_GetModuleDict();
784 PyObject* modules = PyImport_GetModuleDict();
783 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
785 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
784 if (encodingsModule != NULL) {
786 if (encodingsModule != NULL) {
785 PyImport_ReloadModule(encodingsModule);
787 PyImport_ReloadModule(encodingsModule);
786 }
788 }
787 #endif
789 #endif
788 }
790 }
@@ -1,240 +1,245
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 PythonQtMetaObjectWrapper.cpp
35 // \file PythonQtMetaObjectWrapper.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 "PythonQtMetaObjectWrapper.h"
42 #include "PythonQtMetaObjectWrapper.h"
43 #include <QObject>
43 #include <QObject>
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include "PythonQtSlot.h"
46 #include "PythonQtSlot.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49
49
50 static void PythonQtMetaObjectWrapper_dealloc(PythonQtMetaObjectWrapper* self)
50 static void PythonQtMetaObjectWrapper_dealloc(PythonQtMetaObjectWrapper* self)
51 {
51 {
52 self->ob_type->tp_free((PyObject*)self);
52 self->ob_type->tp_free((PyObject*)self);
53 }
53 }
54
54
55 static PyObject* PythonQtMetaObjectWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
55 static PyObject* PythonQtMetaObjectWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
56 {
56 {
57 PythonQtMetaObjectWrapper *self;
57 PythonQtMetaObjectWrapper *self;
58
58
59 self = (PythonQtMetaObjectWrapper *)type->tp_alloc(type, 0);
59 self = (PythonQtMetaObjectWrapper *)type->tp_alloc(type, 0);
60 if (self != NULL) {
60 if (self != NULL) {
61 self->_info = NULL;
61 self->_info = NULL;
62 }
62 }
63 return (PyObject *)self;
63 return (PyObject *)self;
64 }
64 }
65
65
66 static int PythonQtMetaObjectWrapper_init(PythonQtMetaObjectWrapper *self, PyObject *args, PyObject *kwds)
66 static int PythonQtMetaObjectWrapper_init(PythonQtMetaObjectWrapper *self, PyObject *args, PyObject *kwds)
67 {
67 {
68 return 0;
68 return 0;
69 }
69 }
70
70
71 PyObject *PythonQtMetaObjectWrapper_call(PyObject *func, PyObject *args, PyObject *kw) {
71 PyObject *PythonQtMetaObjectWrapper_call(PyObject *func, PyObject *args, PyObject *kw) {
72 PythonQtMetaObjectWrapper* wrapper = (PythonQtMetaObjectWrapper*)func;
72 PythonQtMetaObjectWrapper* wrapper = (PythonQtMetaObjectWrapper*)func;
73 PyObject* result = NULL;
73 PyObject* result = NULL;
74 QString error;
74 QString error;
75 PyObject* err = NULL;
75 PyObject* err = NULL;
76 if (wrapper->_info->constructors()) {
76 if (wrapper->_info->constructors()) {
77 result = PythonQtSlotFunction_CallImpl(NULL, wrapper->_info->constructors(), args, kw);
77 result = PythonQtSlotFunction_CallImpl(NULL, wrapper->_info->constructors(), args, kw);
78 err = PyErr_Occurred();
78 err = PyErr_Occurred();
79 }
79 }
80 if (!result) {
80 if (!result) {
81 QObject* v = NULL;
81 QObject* v = NULL;
82 QListIterator<PythonQtConstructorHandler*> it(PythonQt::self()->constructorHandlers());
82 QListIterator<PythonQtConstructorHandler*> it(PythonQt::self()->constructorHandlers());
83 while (!v && it.hasNext()) {
83 while (!v && it.hasNext()) {
84 v = it.next()->create(wrapper->_info->metaObject(), args, kw, error);
84 v = it.next()->create(wrapper->_info->metaObject(), args, kw, error);
85 }
85 }
86 if (v) {
86 if (v) {
87 result = PythonQt::priv()->wrapQObject(v);
87 result = PythonQt::priv()->wrapQObject(v);
88 }
88 }
89 }
89 }
90 if (result) {
90 if (result) {
91 // change ownershipflag to be owned by PythonQt
91 // change ownershipflag to be owned by PythonQt
92 if (result->ob_type == &PythonQtWrapper_Type) {
92 if (result->ob_type == &PythonQtWrapper_Type) {
93 ((PythonQtWrapper*)result)->_ownedByPythonQt = true;
93 ((PythonQtWrapper*)result)->_ownedByPythonQt = true;
94 }
94 }
95 } else {
95 } else {
96 if (!wrapper->_info->constructors()) {
96 if (!wrapper->_info->constructors()) {
97 if (!err) {
97 if (!err) {
98 if (error.isEmpty()) {
98 if (error.isEmpty()) {
99 error = QString("No constructors available for ") + wrapper->_info->className();
99 error = QString("No constructors available for ") + wrapper->_info->className();
100 }
100 }
101 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
101 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
102 }
102 }
103 }
103 }
104 }
104 }
105 return result;
105 return result;
106 }
106 }
107
107
108 static PyObject *PythonQtMetaObjectWrapper_classname(PythonQtMetaObjectWrapper* type)
108 static PyObject *PythonQtMetaObjectWrapper_classname(PythonQtMetaObjectWrapper* type)
109 {
109 {
110 return PyString_FromString((QString("Meta_") + type->_info->className()).toLatin1().data());
110 return PyString_FromString((QString("Meta_") + type->_info->className()).toLatin1().data());
111 }
111 }
112
112
113 static PyObject *PythonQtMetaObjectWrapper_help(PythonQtMetaObjectWrapper* type)
113 static PyObject *PythonQtMetaObjectWrapper_help(PythonQtMetaObjectWrapper* type)
114 {
114 {
115 return PythonQt::self()->helpCalled(type->_info);
115 return PythonQt::self()->helpCalled(type->_info);
116 }
116 }
117
117
118
118
119 static PyMethodDef PythonQtMetaObjectWrapper_methods[] = {
119 static PyMethodDef PythonQtMetaObjectWrapper_methods[] = {
120 {"className", (PyCFunction)PythonQtMetaObjectWrapper_classname, METH_NOARGS,
120 {"className", (PyCFunction)PythonQtMetaObjectWrapper_classname, METH_NOARGS,
121 "Return the classname of the object"
121 "Return the classname of the object"
122 },
122 },
123 {"help", (PyCFunction)PythonQtMetaObjectWrapper_help, METH_NOARGS,
123 {"help", (PyCFunction)PythonQtMetaObjectWrapper_help, METH_NOARGS,
124 "Shows the help of available methods for this class"
124 "Shows the help of available methods for this class"
125 },
125 },
126 {NULL} /* Sentinel */
126 {NULL} /* Sentinel */
127 };
127 };
128
128
129
129
130 static PyObject *PythonQtMetaObjectWrapper_getattro(PyObject *obj,PyObject *name)
130 static PyObject *PythonQtMetaObjectWrapper_getattro(PyObject *obj,PyObject *name)
131 {
131 {
132 const char *attributeName;
132 const char *attributeName;
133 PythonQtMetaObjectWrapper *wt = (PythonQtMetaObjectWrapper *)obj;
133 PythonQtMetaObjectWrapper *wt = (PythonQtMetaObjectWrapper *)obj;
134
134
135 if ((attributeName = PyString_AsString(name)) == NULL) {
135 if ((attributeName = PyString_AsString(name)) == NULL) {
136 return NULL;
136 return NULL;
137 }
137 }
138
138
139 PythonQtMemberInfo member = wt->_info->member(attributeName);
139 PythonQtMemberInfo member = wt->_info->member(attributeName);
140 if (member._type == PythonQtMemberInfo::EnumValue) {
140 if (member._type == PythonQtMemberInfo::EnumValue) {
141 return PyInt_FromLong(member._enumValue);
141 return PyInt_FromLong(member._enumValue);
142 }
142 }
143 if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) {
143 if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) {
144 return PythonQtSlotFunction_New(member._slot, obj, NULL);
144 return PythonQtSlotFunction_New(member._slot, obj, NULL);
145 }
145 }
146
146
147 // look for the interal methods (className(), help())
147 // look for the interal methods (className(), help())
148 PyObject* internalMethod = Py_FindMethod( PythonQtMetaObjectWrapper_methods, obj, (char*)attributeName);
148 PyObject* internalMethod = Py_FindMethod( PythonQtMetaObjectWrapper_methods, obj, (char*)attributeName);
149 if (internalMethod) {
149 if (internalMethod) {
150 return internalMethod;
150 return internalMethod;
151 }
151 }
152 PyErr_Clear();
152 PyErr_Clear();
153
153
154 if (qstrcmp(attributeName, "__dict__")==0) {
154 if (qstrcmp(attributeName, "__dict__")==0) {
155 QStringList l = wt->_info->memberList(true);
155 QStringList l = wt->_info->memberList(true);
156 PyObject* dict = PyDict_New();
156 PyObject* dict = PyDict_New();
157 foreach (QString name, l) {
157 foreach (QString name, l) {
158 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
158 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
159 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
159 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
160 //Py_DECREF(o);
160 //Py_DECREF(o);
161 }
161 }
162 return dict;
162 return dict;
163 }
163 }
164
164
165 QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
165 QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
166 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
166 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
167 return NULL;
167 return NULL;
168 }
168 }
169
169
170 static PyObject * PythonQtMetaObjectWrapper_repr(PyObject * obj)
170 static PyObject * PythonQtMetaObjectWrapper_repr(PyObject * obj)
171 {
171 {
172 PythonQtMetaObjectWrapper* wt = (PythonQtMetaObjectWrapper*)obj;
172 PythonQtMetaObjectWrapper* wt = (PythonQtMetaObjectWrapper*)obj;
173 if (wt->_info->isCPPWrapper()) {
173 if (wt->_info->isCPPWrapper()) {
174 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wt->_info->className(), wt->_info->metaObject()->className());
174 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wt->_info->className(), wt->_info->metaObject()->className());
175 } else {
175 } else {
176 return PyString_FromFormat("%s Class", wt->_info->className());
176 return PyString_FromFormat("%s Class", wt->_info->className());
177 }
177 }
178 }
178 }
179
179
180 static int PythonQtMetaObjectWrapper_compare(PyObject * obj1, PyObject * obj2)
180 static int PythonQtMetaObjectWrapper_compare(PyObject * obj1, PyObject * obj2)
181 {
181 {
182 if (obj1->ob_type == &PythonQtMetaObjectWrapper_Type &&
182 if (obj1->ob_type == &PythonQtMetaObjectWrapper_Type &&
183 obj2->ob_type == &PythonQtMetaObjectWrapper_Type) {
183 obj2->ob_type == &PythonQtMetaObjectWrapper_Type) {
184
184
185 PythonQtMetaObjectWrapper* w1 = (PythonQtMetaObjectWrapper*)obj1;
185 PythonQtMetaObjectWrapper* w1 = (PythonQtMetaObjectWrapper*)obj1;
186 PythonQtMetaObjectWrapper* w2 = (PythonQtMetaObjectWrapper*)obj2;
186 PythonQtMetaObjectWrapper* w2 = (PythonQtMetaObjectWrapper*)obj2;
187 if (w1->_info == w2->_info) {
187 if (w1->_info == w2->_info) {
188 return 0;
188 return 0;
189 } else {
189 } else {
190 return -1;
190 return -1;
191 }
191 }
192 } else {
192 } else {
193 return -1;
193 return -1;
194 }
194 }
195 }
195 }
196
196
197 static long PythonQtMetaObjectWrapper_hash(PythonQtMetaObjectWrapper *obj)
198 {
199 return reinterpret_cast<long>(obj->_info);
200 }
201
197 PyTypeObject PythonQtMetaObjectWrapper_Type = {
202 PyTypeObject PythonQtMetaObjectWrapper_Type = {
198 PyObject_HEAD_INIT(NULL)
203 PyObject_HEAD_INIT(NULL)
199 0, /*ob_size*/
204 0, /*ob_size*/
200 "PythonQt.PythonQtMetaObjectWrapper", /*tp_name*/
205 "PythonQt.PythonQtMetaObjectWrapper", /*tp_name*/
201 sizeof(PythonQtMetaObjectWrapper), /*tp_basicsize*/
206 sizeof(PythonQtMetaObjectWrapper), /*tp_basicsize*/
202 0, /*tp_itemsize*/
207 0, /*tp_itemsize*/
203 (destructor)PythonQtMetaObjectWrapper_dealloc, /*tp_dealloc*/
208 (destructor)PythonQtMetaObjectWrapper_dealloc, /*tp_dealloc*/
204 0, /*tp_print*/
209 0, /*tp_print*/
205 0, /*tp_getattr*/
210 0, /*tp_getattr*/
206 0, /*tp_setattr*/
211 0, /*tp_setattr*/
207 PythonQtMetaObjectWrapper_compare, /*tp_compare*/
212 PythonQtMetaObjectWrapper_compare, /*tp_compare*/
208 PythonQtMetaObjectWrapper_repr, /*tp_repr*/
213 PythonQtMetaObjectWrapper_repr, /*tp_repr*/
209 0, /*tp_as_number*/
214 0, /*tp_as_number*/
210 0, /*tp_as_sequence*/
215 0, /*tp_as_sequence*/
211 0, /*tp_as_mapping*/
216 0, /*tp_as_mapping*/
212 0, /*tp_hash */
217 (hashfunc)PythonQtMetaObjectWrapper_hash, /*tp_hash */
213 PythonQtMetaObjectWrapper_call, /*tp_call*/
218 PythonQtMetaObjectWrapper_call, /*tp_call*/
214 0, /*tp_str*/
219 0, /*tp_str*/
215 PythonQtMetaObjectWrapper_getattro, /*tp_getattro*/
220 PythonQtMetaObjectWrapper_getattro, /*tp_getattro*/
216 0, /*tp_setattro*/
221 0, /*tp_setattro*/
217 0, /*tp_as_buffer*/
222 0, /*tp_as_buffer*/
218 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
223 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
219 "PythonQtMetaObjectWrapper object", /* tp_doc */
224 "PythonQtMetaObjectWrapper object", /* tp_doc */
220 0, /* tp_traverse */
225 0, /* tp_traverse */
221 0, /* tp_clear */
226 0, /* tp_clear */
222 0, /* tp_richcompare */
227 0, /* tp_richcompare */
223 0, /* tp_weaklistoffset */
228 0, /* tp_weaklistoffset */
224 0, /* tp_iter */
229 0, /* tp_iter */
225 0, /* tp_iternext */
230 0, /* tp_iternext */
226 0, /* tp_methods */
231 0, /* tp_methods */
227 0, /* tp_members */
232 0, /* tp_members */
228 0, /* tp_getset */
233 0, /* tp_getset */
229 0, /* tp_base */
234 0, /* tp_base */
230 0, /* tp_dict */
235 0, /* tp_dict */
231 0, /* tp_descr_get */
236 0, /* tp_descr_get */
232 0, /* tp_descr_set */
237 0, /* tp_descr_set */
233 0, /* tp_dictoffset */
238 0, /* tp_dictoffset */
234 (initproc)PythonQtMetaObjectWrapper_init, /* tp_init */
239 (initproc)PythonQtMetaObjectWrapper_init, /* tp_init */
235 0, /* tp_alloc */
240 0, /* tp_alloc */
236 PythonQtMetaObjectWrapper_new, /* tp_new */
241 PythonQtMetaObjectWrapper_new, /* tp_new */
237 };
242 };
238
243
239 //-------------------------------------------------------
244 //-------------------------------------------------------
240
245
@@ -1,171 +1,206
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 PythonQtSignalReceiver.cpp
35 // \file PythonQtSignalReceiver.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 "PythonQtSignalReceiver.h"
42 #include "PythonQtSignalReceiver.h"
43 #include "PythonQtClassInfo.h"
43 #include "PythonQtClassInfo.h"
44 #include "PythonQtMethodInfo.h"
44 #include "PythonQtMethodInfo.h"
45 #include "PythonQtConversion.h"
45 #include "PythonQtConversion.h"
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaMethod>
47 #include <QMetaMethod>
48 #include "funcobject.h"
48
49
49 void PythonQtSignalTarget::call(void **arguments) const
50 void PythonQtSignalTarget::call(void **arguments) const
50 {
51 {
52 // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments
53 // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal
54
55 int numPythonArgs = -1;
56 if (PyFunction_Check(_callable)) {
57 PyObject* o = _callable;
58 PyFunctionObject* func = (PyFunctionObject*)o;
59 PyCodeObject* code = (PyCodeObject*)func->func_code;
60 if (!(code->co_flags & 0x04)) {
61 numPythonArgs = code->co_argcount;
62 } else {
63 // variable numbers of arguments allowed
64 }
65 } else if (PyMethod_Check(_callable)) {
66 PyObject* o = _callable;
67 PyMethodObject* method = (PyMethodObject*)o;
68 if (PyFunction_Check(method->im_func)) {
69 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
70 PyCodeObject* code = (PyCodeObject*)func->func_code;
71 if (!(code->co_flags & 0x04)) {
72 numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self"
73 } else {
74 // variable numbers of arguments allowed
75 }
76 }
77 }
78
51 const PythonQtMethodInfo* m = methodInfo();
79 const PythonQtMethodInfo* m = methodInfo();
52 // paramterCount includes return value:
80 // parameterCount includes return value:
53 int count = m->parameterCount();
81 int count = m->parameterCount();
82 if (numPythonArgs!=-1) {
83 if (count>numPythonArgs+1) {
84 // take less arguments
85 count = numPythonArgs+1;
86 }
87 }
54
88
55 PyObject* pargs = NULL;
89 PyObject* pargs = NULL;
56 if (count>1) {
90 if (count>1) {
57 pargs = PyTuple_New(count-1);
91 pargs = PyTuple_New(count-1);
58 }
92 }
59 bool err = false;
93 bool err = false;
60 // transform Qt values to Python
94 // transform Qt values to Python
61 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
95 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
62 for (int i = 1; i < count; i++) {
96 for (int i = 1; i < count; i++) {
63 const PythonQtMethodInfo::ParameterInfo& param = params.at(i);
97 const PythonQtMethodInfo::ParameterInfo& param = params.at(i);
64 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
98 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
65 if (arg) {
99 if (arg) {
66 // steals reference, no unref
100 // steals reference, no unref
67 PyTuple_SetItem(pargs, i-1,arg);
101 PyTuple_SetItem(pargs, i-1,arg);
68 } else {
102 } else {
69 err = true;
103 err = true;
70 break;
104 break;
71 }
105 }
72 }
106 }
73
107
74 if (!err) {
108 if (!err) {
75 PyErr_Clear();
109 PyErr_Clear();
76 PyObject* result = PyObject_CallObject(_callable, pargs);
110 PyObject* result = PyObject_CallObject(_callable, pargs);
77 if (result) {
111 if (result) {
78 // ok
112 // ok
79 Py_DECREF(result);
113 Py_DECREF(result);
80 } else {
114 } else {
81 PythonQt::self()->handleError();
115 PythonQt::self()->handleError();
82 }
116 }
83 }
117 }
84 if (pargs) {
118 if (pargs) {
85 // free the arguments again
119 // free the arguments again
86 Py_DECREF(pargs);
120 Py_DECREF(pargs);
87 }
121 }
88 }
122 }
89
123
90 //------------------------------------------------------------------------------
124 //------------------------------------------------------------------------------
91
125
92 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
126 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
93 {
127 {
94 _obj = obj;
128 _obj = obj;
95 _slotCount = staticMetaObject.methodOffset();
129 _slotCount = staticMetaObject.methodOffset();
96 }
130 }
97
131
98 PythonQtSignalReceiver::~PythonQtSignalReceiver()
132 PythonQtSignalReceiver::~PythonQtSignalReceiver()
99 {
133 {
134 PythonQt::priv()->removeSignalEmitter(_obj);
100 }
135 }
101
136
102
137
103 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
138 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
104 {
139 {
105 bool flag = false;
140 bool flag = false;
106 int sigId = getSignalIndex(signal);
141 int sigId = getSignalIndex(signal);
107 if (sigId>=0) {
142 if (sigId>=0) {
108 // create PythonQtMethodInfo from signal
143 // create PythonQtMethodInfo from signal
109 QMetaMethod meta = _obj->metaObject()->method(sigId);
144 QMetaMethod meta = _obj->metaObject()->method(sigId);
110 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta);
145 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta);
111 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
146 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
112 _targets.append(t);
147 _targets.append(t);
113 // now connect to ourselves with the new slot id
148 // now connect to ourselves with the new slot id
114 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
149 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
115
150
116 _slotCount++;
151 _slotCount++;
117 flag = true;
152 flag = true;
118 }
153 }
119 return flag;
154 return flag;
120 }
155 }
121
156
122 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
157 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
123 {
158 {
124 bool found = false;
159 bool found = false;
125 int sigId = getSignalIndex(signal);
160 int sigId = getSignalIndex(signal);
126 if (sigId>=0) {
161 if (sigId>=0) {
127 QMutableListIterator<PythonQtSignalTarget> i(_targets);
162 QMutableListIterator<PythonQtSignalTarget> i(_targets);
128 while (i.hasNext()) {
163 while (i.hasNext()) {
129 if (i.next().isSame(sigId, callable)) {
164 if (i.next().isSame(sigId, callable)) {
130 i.remove();
165 i.remove();
131 found = true;
166 found = true;
132 break;
167 break;
133 }
168 }
134 }
169 }
135 }
170 }
136 return found;
171 return found;
137 }
172 }
138
173
139 void PythonQtSignalReceiver::removeSignalHandlers()
174 void PythonQtSignalReceiver::removeSignalHandlers()
140 {
175 {
141 _targets.clear();
176 _targets.clear();
142 }
177 }
143
178
144 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
179 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
145 {
180 {
146 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
181 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
147 if (sigId<0) {
182 if (sigId<0) {
148 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
183 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
149 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
184 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
150 }
185 }
151 return sigId;
186 return sigId;
152 }
187 }
153
188
154 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
189 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
155 {
190 {
156 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
191 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
157 if (c != QMetaObject::InvokeMetaMethod) {
192 if (c != QMetaObject::InvokeMetaMethod) {
158 QObject::qt_metacall(c, id, arguments);
193 QObject::qt_metacall(c, id, arguments);
159 }
194 }
160
195
161 bool found = false;
196 bool found = false;
162 foreach(const PythonQtSignalTarget& t, _targets) {
197 foreach(const PythonQtSignalTarget& t, _targets) {
163 if (t.slotId() == id) {
198 if (t.slotId() == id) {
164 found = true;
199 found = true;
165 t.call(arguments);
200 t.call(arguments);
166 break;
201 break;
167 }
202 }
168 }
203 }
169 return 0;
204 return 0;
170 }
205 }
171
206
@@ -1,128 +1,136
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 PythonQtStdOut.cpp
35 // \file PythonQtStdOut.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 "PythonQtStdOut.h"
42 #include "PythonQtStdOut.h"
43
43
44 static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
44 static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
45 {
45 {
46 PythonQtStdOutRedirect *self;
46 PythonQtStdOutRedirect *self;
47 self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
47 self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
48
48
49 self->softspace = 0;
49 self->softspace = 0;
50 self->_cb = NULL;
50 self->_cb = NULL;
51
51
52 return (PyObject *)self;
52 return (PyObject *)self;
53 }
53 }
54
54
55 static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args)
55 static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args)
56 {
56 {
57 PythonQtStdOutRedirect* s = (PythonQtStdOutRedirect*)self;
57 PythonQtStdOutRedirect* s = (PythonQtStdOutRedirect*)self;
58 if (s->_cb) {
58 if (s->_cb) {
59 char *string;
59 char *string;
60 if (!PyArg_ParseTuple(args, "s", &string))
60 if (!PyArg_ParseTuple(args, "s", &string))
61 return NULL;
61 return NULL;
62
62
63 if (s->softspace > 0) {
63 if (s->softspace > 0) {
64 (*s->_cb)(QString(""));
64 (*s->_cb)(QString(""));
65 s->softspace = 0;
65 s->softspace = 0;
66 }
66 }
67
67
68 (*s->_cb)(QString(string));
68 (*s->_cb)(QString(string));
69 }
69 }
70 return Py_BuildValue("");
70 return Py_BuildValue("");
71 }
71 }
72
72
73 static PyObject *PythonQtStdOutRedirect_flush(PyObject *self, PyObject *args)
74 {
75 return Py_BuildValue("");
76 }
77
78
73
79
74 static PyMethodDef PythonQtStdOutRedirect_methods[] = {
80 static PyMethodDef PythonQtStdOutRedirect_methods[] = {
75 {"write", (PyCFunction)PythonQtStdOutRedirect_write, METH_VARARGS,
81 {"write", (PyCFunction)PythonQtStdOutRedirect_write, METH_VARARGS,
76 "redirect the writing to a callback"
82 "redirect the writing to a callback"},
83 {"flush", (PyCFunction)PythonQtStdOutRedirect_flush, METH_VARARGS,
84 "flush the output, currently not implemented but needed for logging framework"
77 },
85 },
78 {NULL} /* Sentinel */
86 {NULL} /* Sentinel */
79 };
87 };
80
88
81 static PyMemberDef PythonQtStdOutRedirect_members[] = {
89 static PyMemberDef PythonQtStdOutRedirect_members[] = {
82 {"softspace", T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
90 {"softspace", T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
83 "soft space flag"
91 "soft space flag"
84 },
92 },
85 {NULL} /* Sentinel */
93 {NULL} /* Sentinel */
86 };
94 };
87
95
88 PyTypeObject PythonQtStdOutRedirectType = {
96 PyTypeObject PythonQtStdOutRedirectType = {
89 PyObject_HEAD_INIT(NULL)
97 PyObject_HEAD_INIT(NULL)
90 0, /*ob_size*/
98 0, /*ob_size*/
91 "PythonQtStdOutRedirect", /*tp_name*/
99 "PythonQtStdOutRedirect", /*tp_name*/
92 sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/
100 sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/
93 0, /*tp_itemsize*/
101 0, /*tp_itemsize*/
94 0, /*tp_dealloc*/
102 0, /*tp_dealloc*/
95 0, /*tp_print*/
103 0, /*tp_print*/
96 0, /*tp_getattr*/
104 0, /*tp_getattr*/
97 0, /*tp_setattr*/
105 0, /*tp_setattr*/
98 0, /*tp_compare*/
106 0, /*tp_compare*/
99 0, /*tp_repr*/
107 0, /*tp_repr*/
100 0, /*tp_as_number*/
108 0, /*tp_as_number*/
101 0, /*tp_as_sequence*/
109 0, /*tp_as_sequence*/
102 0, /*tp_as_mapping*/
110 0, /*tp_as_mapping*/
103 0, /*tp_hash */
111 0, /*tp_hash */
104 0, /*tp_call*/
112 0, /*tp_call*/
105 0, /*tp_str*/
113 0, /*tp_str*/
106 0, /*tp_getattro*/
114 0, /*tp_getattro*/
107 0, /*tp_setattro*/
115 0, /*tp_setattro*/
108 0, /*tp_as_buffer*/
116 0, /*tp_as_buffer*/
109 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
117 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
110 "PythonQtStdOutRedirect", /* tp_doc */
118 "PythonQtStdOutRedirect", /* tp_doc */
111 0, /* tp_traverse */
119 0, /* tp_traverse */
112 0, /* tp_clear */
120 0, /* tp_clear */
113 0, /* tp_richcompare */
121 0, /* tp_richcompare */
114 0, /* tp_weaklistoffset */
122 0, /* tp_weaklistoffset */
115 0, /* tp_iter */
123 0, /* tp_iter */
116 0, /* tp_iternext */
124 0, /* tp_iternext */
117 PythonQtStdOutRedirect_methods, /* tp_methods */
125 PythonQtStdOutRedirect_methods, /* tp_methods */
118 PythonQtStdOutRedirect_members, /* tp_members */
126 PythonQtStdOutRedirect_members, /* tp_members */
119 0, /* tp_getset */
127 0, /* tp_getset */
120 0, /* tp_base */
128 0, /* tp_base */
121 0, /* tp_dict */
129 0, /* tp_dict */
122 0, /* tp_descr_get */
130 0, /* tp_descr_get */
123 0, /* tp_descr_set */
131 0, /* tp_descr_set */
124 0, /* tp_dictoffset */
132 0, /* tp_dictoffset */
125 0, /* tp_init */
133 0, /* tp_init */
126 0, /* tp_alloc */
134 0, /* tp_alloc */
127 PythonQtStdOutRedirect_new, /* tp_new */
135 PythonQtStdOutRedirect_new, /* tp_new */
128 };
136 };
@@ -1,256 +1,271
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 PythonQtVariantWrapper.cpp
35 // \file PythonQtVariantWrapper.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 "PythonQtVariantWrapper.h"
42 #include "PythonQtVariantWrapper.h"
43 #include <QObject>
43 #include <QObject>
44 #include <QDate>
44 #include <QDate>
45 #include <QDateTime>
45 #include <QDateTime>
46 #include <QTime>
46 #include <QTime>
47 #include "PythonQt.h"
47 #include "PythonQt.h"
48 #include "PythonQtSlot.h"
48 #include "PythonQtSlot.h"
49 #include "PythonQtClassInfo.h"
49 #include "PythonQtClassInfo.h"
50 #include "PythonQtConversion.h"
50 #include "PythonQtConversion.h"
51
51
52 static void PythonQtVariantWrapper_dealloc(PythonQtVariantWrapper* self)
52 static void PythonQtVariantWrapper_dealloc(PythonQtVariantWrapper* self)
53 {
53 {
54 if (self->_variant) {
54 if (self->_variant) {
55 delete self->_variant;
55 delete self->_variant;
56 self->_variant = NULL;
56 self->_variant = NULL;
57 }
57 }
58 self->ob_type->tp_free((PyObject*)self);
58 self->ob_type->tp_free((PyObject*)self);
59 }
59 }
60
60
61 static PyObject* PythonQtVariantWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
61 static PyObject* PythonQtVariantWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
62 {
62 {
63 PythonQtVariantWrapper *self;
63 PythonQtVariantWrapper *self;
64
64
65 self = (PythonQtVariantWrapper *)type->tp_alloc(type, 0);
65 self = (PythonQtVariantWrapper *)type->tp_alloc(type, 0);
66 if (self != NULL) {
66 if (self != NULL) {
67 self->_variant = new QVariant();
67 self->_variant = new QVariant();
68 self->_info = NULL;
68 self->_info = NULL;
69 }
69 }
70 return (PyObject *)self;
70 return (PyObject *)self;
71 }
71 }
72
72
73 static int PythonQtVariantWrapper_init(PythonQtVariantWrapper *self, PyObject *args, PyObject *kwds)
73 static int PythonQtVariantWrapper_init(PythonQtVariantWrapper *self, PyObject *args, PyObject *kwds)
74 {
74 {
75 return 0;
75 return 0;
76 }
76 }
77
77
78 static PyObject *PythonQtVariantWrapper_classname(PythonQtVariantWrapper* type)
78 static PyObject *PythonQtVariantWrapper_classname(PythonQtVariantWrapper* type)
79 {
79 {
80 return PyString_FromString(type->_info->className());
80 return PyString_FromString(type->_info->className());
81 }
81 }
82
82
83 static PyObject *PythonQtVariantWrapper_help(PythonQtVariantWrapper* type)
83 static PyObject *PythonQtVariantWrapper_help(PythonQtVariantWrapper* type)
84 {
84 {
85 return PythonQt::self()->helpCalled(type->_info);
85 return PythonQt::self()->helpCalled(type->_info);
86 }
86 }
87
87
88
88
89 static PyMethodDef PythonQtVariantWrapper_methods[] = {
89 static PyMethodDef PythonQtVariantWrapper_methods[] = {
90 {"className", (PyCFunction)PythonQtVariantWrapper_classname, METH_NOARGS,
90 {"className", (PyCFunction)PythonQtVariantWrapper_classname, METH_NOARGS,
91 "Return the classname of the object"
91 "Return the classname of the object"
92 },
92 },
93 {"help", (PyCFunction)PythonQtVariantWrapper_help, METH_NOARGS,
93 {"help", (PyCFunction)PythonQtVariantWrapper_help, METH_NOARGS,
94 "Shows the help of available methods for this class"
94 "Shows the help of available methods for this class"
95 },
95 },
96 {NULL} /* Sentinel */
96 {NULL} /* Sentinel */
97 };
97 };
98
98
99
99
100 static PyObject *PythonQtVariantWrapper_getattro(PyObject *obj,PyObject *name)
100 static PyObject *PythonQtVariantWrapper_getattro(PyObject *obj,PyObject *name)
101 {
101 {
102 const char *attributeName;
102 const char *attributeName;
103 PythonQtVariantWrapper *wt = (PythonQtVariantWrapper *)obj;
103 PythonQtVariantWrapper *wt = (PythonQtVariantWrapper *)obj;
104
104
105 if ((attributeName = PyString_AsString(name)) == NULL) {
105 if ((attributeName = PyString_AsString(name)) == NULL) {
106 return NULL;
106 return NULL;
107 }
107 }
108
108
109 if (wt->_wrapper && wt->_info) {
109 if (wt->_wrapper && wt->_info) {
110 PythonQtMemberInfo member = wt->_info->member(attributeName);
110 PythonQtMemberInfo member = wt->_info->member(attributeName);
111 if (member._type == PythonQtMemberInfo::Slot) {
111 if (member._type == PythonQtMemberInfo::Slot) {
112 return PythonQtSlotFunction_New(member._slot, obj, NULL);
112 return PythonQtSlotFunction_New(member._slot, obj, NULL);
113 } else if (member._type == PythonQtMemberInfo::EnumValue) {
113 } else if (member._type == PythonQtMemberInfo::EnumValue) {
114 return PyInt_FromLong(member._enumValue);
114 return PyInt_FromLong(member._enumValue);
115 }
115 }
116 }
116 }
117
117
118 // look for the interal methods (className(), help())
118 // look for the interal methods (className(), help())
119 PyObject* internalMethod = Py_FindMethod( PythonQtVariantWrapper_methods, obj, (char*)attributeName);
119 PyObject* internalMethod = Py_FindMethod( PythonQtVariantWrapper_methods, obj, (char*)attributeName);
120 if (internalMethod) {
120 if (internalMethod) {
121 return internalMethod;
121 return internalMethod;
122 }
122 }
123 PyErr_Clear();
123 PyErr_Clear();
124
124
125 if (qstrcmp(attributeName, "__dict__")==0) {
125 if (qstrcmp(attributeName, "__dict__")==0) {
126 QStringList l = wt->_info->memberList(false);
126 QStringList l = wt->_info->memberList(false);
127 PyObject* dict = PyDict_New();
127 PyObject* dict = PyDict_New();
128 foreach (QString name, l) {
128 foreach (QString name, l) {
129 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
129 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
130 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
130 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
131 //Py_DECREF(o);
131 //Py_DECREF(o);
132 }
132 }
133 return dict;
133 return dict;
134 }
134 }
135
135
136 QString error = QString(wt->_variant->typeName()) + " has no attribute named '" + QString(attributeName) + "'";
136 QString error = QString(wt->_variant->typeName()) + " has no attribute named '" + QString(attributeName) + "'";
137 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
137 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
138
138
139 return NULL;
139 return NULL;
140 }
140 }
141
141
142 QString qVariantToString(const QVariant& v) {
142 QString qVariantToString(const QVariant& v) {
143 QString r;
143 QString r;
144 switch (v.type()) {
144 switch (v.type()) {
145 case QVariant::Size:
145 case QVariant::Size:
146 r = QString::number(v.toSize().width()) + ", " + QString::number(v.toSize().height());
146 r = QString::number(v.toSize().width()) + ", " + QString::number(v.toSize().height());
147 break;
147 break;
148 case QVariant::SizeF:
148 case QVariant::SizeF:
149 r = QString::number(v.toSizeF().width()) + ", " + QString::number(v.toSizeF().height());
149 r = QString::number(v.toSizeF().width()) + ", " + QString::number(v.toSizeF().height());
150 break;
150 break;
151 case QVariant::Point:
151 case QVariant::Point:
152 r = QString::number(v.toPoint().x()) + ", " + QString::number(v.toPoint().y());
152 r = QString::number(v.toPoint().x()) + ", " + QString::number(v.toPoint().y());
153 break;
153 break;
154 case QVariant::PointF:
154 case QVariant::PointF:
155 r = QString::number(v.toPointF().x()) + ", " + QString::number(v.toPointF().y());
155 r = QString::number(v.toPointF().x()) + ", " + QString::number(v.toPointF().y());
156 break;
156 break;
157 case QVariant::Rect:
157 case QVariant::Rect:
158 r = QString::number(v.toRect().x()) + ", " + QString::number(v.toRect().y());
158 r = QString::number(v.toRect().x()) + ", " + QString::number(v.toRect().y());
159 r += ", " + QString::number(v.toRect().width()) + ", " + QString::number(v.toRect().height());
159 r += ", " + QString::number(v.toRect().width()) + ", " + QString::number(v.toRect().height());
160 break;
160 break;
161 case QVariant::RectF:
161 case QVariant::RectF:
162 r = QString::number(v.toRectF().x()) + ", " + QString::number(v.toRectF().y());
162 r = QString::number(v.toRectF().x()) + ", " + QString::number(v.toRectF().y());
163 r += ", " + QString::number(v.toRectF().width()) + ", " + QString::number(v.toRectF().height());
163 r += ", " + QString::number(v.toRectF().width()) + ", " + QString::number(v.toRectF().height());
164 break;
164 break;
165 case QVariant::Date:
165 case QVariant::Date:
166 r = v.toDate().toString(Qt::ISODate);
166 r = v.toDate().toString(Qt::ISODate);
167 break;
167 break;
168 case QVariant::DateTime:
168 case QVariant::DateTime:
169 r = v.toDateTime().toString(Qt::ISODate);
169 r = v.toDateTime().toString(Qt::ISODate);
170 break;
170 break;
171 case QVariant::Time:
171 case QVariant::Time:
172 r = v.toTime().toString(Qt::ISODate);
172 r = v.toTime().toString(Qt::ISODate);
173 break;
173 break;
174 case QVariant::Pixmap:
175 {
176 QPixmap p = qvariant_cast<QPixmap>(v);
177 r = QString("Pixmap ") + QString::number(p.width()) + ", " + QString::number(p.height());
178 }
179 break;
180 case QVariant::Image:
181 {
182 QImage img = qvariant_cast<QImage>(v);
183 r = QString("Image ") + QString::number(img.width()) + ", " + QString::number(img.height());
184 }
185 break;
174 //TODO: add more printing for other variant types
186 //TODO: add more printing for other variant types
175 default:
187 default:
176 r = v.toString();
188 r = v.toString();
177 }
189 }
178 return r;
190 return r;
179 }
191 }
180
192
181 static PyObject * PythonQtVariantWrapper_str(PyObject * obj)
193 static PyObject * PythonQtVariantWrapper_str(PyObject * obj)
182 {
194 {
183 PythonQtVariantWrapper* wt = (PythonQtVariantWrapper*)obj;
195 PythonQtVariantWrapper* wt = (PythonQtVariantWrapper*)obj;
184 QString val = qVariantToString(*wt->_variant);
196 QString val = qVariantToString(*wt->_variant);
197 if (val.isEmpty()) {
198 val = wt->_variant->typeName();
199 }
185 return PyString_FromFormat("%s", val.toLatin1().constData());
200 return PyString_FromFormat("%s", val.toLatin1().constData());
186 }
201 }
187
202
188 static PyObject * PythonQtVariantWrapper_repr(PyObject * obj)
203 static PyObject * PythonQtVariantWrapper_repr(PyObject * obj)
189 {
204 {
190 PythonQtVariantWrapper* wt = (PythonQtVariantWrapper*)obj;
205 PythonQtVariantWrapper* wt = (PythonQtVariantWrapper*)obj;
191 QString val = qVariantToString(*wt->_variant);
206 QString val = qVariantToString(*wt->_variant);
192 return PyString_FromFormat("%s(%s)", wt->_variant->typeName(), val.toLatin1().constData());
207 return PyString_FromFormat("%s(%s)", wt->_variant->typeName(), val.toLatin1().constData());
193 }
208 }
194
209
195 static int PythonQtVariantWrapper_compare(PyObject * obj1, PyObject * obj2)
210 static int PythonQtVariantWrapper_compare(PyObject * obj1, PyObject * obj2)
196 {
211 {
197 if (obj1->ob_type == &PythonQtVariantWrapper_Type &&
212 if (obj1->ob_type == &PythonQtVariantWrapper_Type &&
198 obj2->ob_type == &PythonQtVariantWrapper_Type) {
213 obj2->ob_type == &PythonQtVariantWrapper_Type) {
199
214
200 PythonQtVariantWrapper* w1 = (PythonQtVariantWrapper*)obj1;
215 PythonQtVariantWrapper* w1 = (PythonQtVariantWrapper*)obj1;
201 PythonQtVariantWrapper* w2 = (PythonQtVariantWrapper*)obj2;
216 PythonQtVariantWrapper* w2 = (PythonQtVariantWrapper*)obj2;
202 if (*w1->_variant == *w2->_variant) {
217 if (*w1->_variant == *w2->_variant) {
203 return 0;
218 return 0;
204 } else {
219 } else {
205 return -1;
220 return -1;
206 }
221 }
207 } else {
222 } else {
208 return -1;
223 return -1;
209 }
224 }
210 }
225 }
211
226
212
227
213 PyTypeObject PythonQtVariantWrapper_Type = {
228 PyTypeObject PythonQtVariantWrapper_Type = {
214 PyObject_HEAD_INIT(NULL)
229 PyObject_HEAD_INIT(NULL)
215 0, /*ob_size*/
230 0, /*ob_size*/
216 "PythonQt.PythonQtVariantWrapper", /*tp_name*/
231 "PythonQt.PythonQtVariantWrapper", /*tp_name*/
217 sizeof(PythonQtVariantWrapper), /*tp_basicsize*/
232 sizeof(PythonQtVariantWrapper), /*tp_basicsize*/
218 0, /*tp_itemsize*/
233 0, /*tp_itemsize*/
219 (destructor)PythonQtVariantWrapper_dealloc, /*tp_dealloc*/
234 (destructor)PythonQtVariantWrapper_dealloc, /*tp_dealloc*/
220 0, /*tp_print*/
235 0, /*tp_print*/
221 0, /*tp_getattr*/
236 0, /*tp_getattr*/
222 0, /*tp_setattr*/
237 0, /*tp_setattr*/
223 PythonQtVariantWrapper_compare, /*tp_compare*/
238 PythonQtVariantWrapper_compare, /*tp_compare*/
224 PythonQtVariantWrapper_repr, /*tp_repr*/
239 PythonQtVariantWrapper_repr, /*tp_repr*/
225 0, /*tp_as_number*/
240 0, /*tp_as_number*/
226 0, /*tp_as_sequence*/
241 0, /*tp_as_sequence*/
227 0, /*tp_as_mapping*/
242 0, /*tp_as_mapping*/
228 0, /*tp_hash */
243 0, /*tp_hash */
229 0, /*tp_call*/
244 0, /*tp_call*/
230 PythonQtVariantWrapper_str, /*tp_str*/
245 PythonQtVariantWrapper_str, /*tp_str*/
231 PythonQtVariantWrapper_getattro, /*tp_getattro*/
246 PythonQtVariantWrapper_getattro, /*tp_getattro*/
232 0, /*tp_setattro*/
247 0, /*tp_setattro*/
233 0, /*tp_as_buffer*/
248 0, /*tp_as_buffer*/
234 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
249 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
235 "PythonQtVariantWrapper object", /* tp_doc */
250 "PythonQtVariantWrapper object", /* tp_doc */
236 0, /* tp_traverse */
251 0, /* tp_traverse */
237 0, /* tp_clear */
252 0, /* tp_clear */
238 0, /* tp_richcompare */
253 0, /* tp_richcompare */
239 0, /* tp_weaklistoffset */
254 0, /* tp_weaklistoffset */
240 0, /* tp_iter */
255 0, /* tp_iter */
241 0, /* tp_iternext */
256 0, /* tp_iternext */
242 0, /* tp_methods */
257 0, /* tp_methods */
243 0, /* tp_members */
258 0, /* tp_members */
244 0, /* tp_getset */
259 0, /* tp_getset */
245 0, /* tp_base */
260 0, /* tp_base */
246 0, /* tp_dict */
261 0, /* tp_dict */
247 0, /* tp_descr_get */
262 0, /* tp_descr_get */
248 0, /* tp_descr_set */
263 0, /* tp_descr_set */
249 0, /* tp_dictoffset */
264 0, /* tp_dictoffset */
250 (initproc)PythonQtVariantWrapper_init, /* tp_init */
265 (initproc)PythonQtVariantWrapper_init, /* tp_init */
251 0, /* tp_alloc */
266 0, /* tp_alloc */
252 PythonQtVariantWrapper_new, /* tp_new */
267 PythonQtVariantWrapper_new, /* tp_new */
253 };
268 };
254
269
255 //-------------------------------------------------------
270 //-------------------------------------------------------
256
271
@@ -1,376 +1,400
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 PythonQtWrapper.cpp
35 // \file PythonQtWrapper.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 "PythonQtWrapper.h"
42 #include "PythonQtWrapper.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
48
49 static void PythonQtWrapper_dealloc(PythonQtWrapper* self)
49 static void PythonQtWrapper_dealloc(PythonQtWrapper* self)
50 {
50 {
51 if (self->_wrappedPtr) {
51 if (self->_wrappedPtr) {
52
52
53 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
53 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
54
54
55 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
55 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
56 // we own our qobject, so we delete it now:
56 // we own our qobject, so we delete it now:
57 delete self->_obj;
57 delete self->_obj;
58 self->_obj = NULL;
58 self->_obj = NULL;
59 if (self->_ownedByPythonQt) {
59 if (self->_ownedByPythonQt) {
60 PythonQtSlotInfo* slot = PythonQt::priv()->getDestructorSlot(self->_info->wrappedCPPClassName());
60 PythonQtSlotInfo* slot = PythonQt::priv()->getDestructorSlot(self->_info->wrappedCPPClassName());
61 if (slot) {
61 if (slot) {
62 void* args[2];
62 void* args[2];
63 args[0] = NULL;
63 args[0] = NULL;
64 args[1] = &self->_wrappedPtr;
64 args[1] = &self->_wrappedPtr;
65 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
65 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
66 self->_wrappedPtr = NULL;
66 self->_wrappedPtr = NULL;
67 } else {
67 } else {
68 // TODO: print a warning? we can not destroy that object
68 // TODO: print a warning? we can not destroy that object
69 }
69 }
70 }
70 }
71 } else if (self->_obj) {
71 } else {
72 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
72 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
73 PythonQt::priv()->removeWrapperPointer(self->_obj);
73 if (self->_objPointerCopy) {
74 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
75 }
76 if (self->_obj) {
74 if (self->_ownedByPythonQt) {
77 if (self->_ownedByPythonQt) {
75 if (!self->_obj->parent()) {
78 if (!self->_obj->parent()) {
76 delete self->_obj;
79 delete self->_obj;
77 self->_obj = NULL;
80 }
81 } else {
82 if (self->_obj->parent()==NULL) {
83 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
84 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
85 }
78 }
86 }
79 }
87 }
80 }
88 }
89 self->_obj = NULL;
90 self->_obj.~QPointer<QObject>();
81 self->ob_type->tp_free((PyObject*)self);
91 self->ob_type->tp_free((PyObject*)self);
82 }
92 }
83
93
84 static PyObject* PythonQtWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
94 static PyObject* PythonQtWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
85 {
95 {
86 PythonQtWrapper *self;
96 PythonQtWrapper *self;
87
97
88 self = (PythonQtWrapper *)type->tp_alloc(type, 0);
98 self = (PythonQtWrapper *)type->tp_alloc(type, 0);
89 if (self != NULL) {
99 if (self != NULL) {
90 self->_info = NULL;
100 self->_info = NULL;
91 self->_obj = NULL;
101 new (&self->_obj) QPointer<QObject>();
92 self->_wrappedPtr = NULL;
102 self->_wrappedPtr = NULL;
93 self->_ownedByPythonQt = false;
103 self->_ownedByPythonQt = false;
94 }
104 }
95 return (PyObject *)self;
105 return (PyObject *)self;
96 }
106 }
97
107
98 static int PythonQtWrapper_init(PythonQtWrapper *self, PyObject *args, PyObject *kwds)
108 static int PythonQtWrapper_init(PythonQtWrapper *self, PyObject *args, PyObject *kwds)
99 {
109 {
100 return 0;
110 return 0;
101 }
111 }
102
112
103 static PyObject *PythonQtWrapper_classname(PythonQtWrapper* type)
113 static PyObject *PythonQtWrapper_classname(PythonQtWrapper* type)
104 {
114 {
105 return PyString_FromString(type->_info->className());
115 return PyString_FromString(type->_info->className());
106 }
116 }
107
117
108 static PyObject *PythonQtWrapper_help(PythonQtWrapper* type)
118 static PyObject *PythonQtWrapper_help(PythonQtWrapper* type)
109 {
119 {
110 return PythonQt::self()->helpCalled(type->_info);
120 return PythonQt::self()->helpCalled(type->_info);
111 }
121 }
112
122
113
123
114 static PyMethodDef PythonQtWrapper_methods[] = {
124 static PyMethodDef PythonQtWrapper_methods[] = {
115 {"className", (PyCFunction)PythonQtWrapper_classname, METH_NOARGS,
125 {"className", (PyCFunction)PythonQtWrapper_classname, METH_NOARGS,
116 "Return the classname of the object"
126 "Return the classname of the object"
117 },
127 },
118 {"help", (PyCFunction)PythonQtWrapper_help, METH_NOARGS,
128 {"help", (PyCFunction)PythonQtWrapper_help, METH_NOARGS,
119 "Shows the help of available methods for this class"
129 "Shows the help of available methods for this class"
120 },
130 },
121 {NULL} /* Sentinel */
131 {NULL} /* Sentinel */
122 };
132 };
123
133
124
134
125 static PyObject *PythonQtWrapper_getattro(PyObject *obj,PyObject *name)
135 static PyObject *PythonQtWrapper_getattro(PyObject *obj,PyObject *name)
126 {
136 {
127 const char *attributeName;
137 const char *attributeName;
128 PythonQtWrapper *wt = (PythonQtWrapper *)obj;
138 PythonQtWrapper *wt = (PythonQtWrapper *)obj;
129
139
130 if ((attributeName = PyString_AsString(name)) == NULL) {
140 if ((attributeName = PyString_AsString(name)) == NULL) {
131 return NULL;
141 return NULL;
132 }
142 }
133
143
134 if (!wt->_obj && !wt->_wrappedPtr) {
144 if (!wt->_obj && !wt->_wrappedPtr) {
135 QString error = QString("Trying to read attribute '") + attributeName + "' from a destroyed " + wt->_info->className() + " object";
145 QString error = QString("Trying to read attribute '") + attributeName + "' from a destroyed " + wt->_info->className() + " object";
136 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
146 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
137 return NULL;
147 return NULL;
138 }
148 }
139
149
140 // mlabDebugConst("Python","get " << attributeName);
150 // mlabDebugConst("Python","get " << attributeName);
141
151
142 // TODO: dynamic properties are missing
152 // TODO: dynamic properties are missing
143
153
144 PythonQtMemberInfo member = wt->_info->member(attributeName);
154 PythonQtMemberInfo member = wt->_info->member(attributeName);
145 switch (member._type) {
155 switch (member._type) {
146 case PythonQtMemberInfo::Property:
156 case PythonQtMemberInfo::Property:
147 if (wt->_obj) {
157 if (wt->_obj) {
148 return PythonQtConv::QVariantToPyObject(member._property.read(wt->_obj));
158 return PythonQtConv::QVariantToPyObject(member._property.read(wt->_obj));
149 }
159 }
150 break;
160 break;
151 case PythonQtMemberInfo::Slot:
161 case PythonQtMemberInfo::Slot:
152 return PythonQtSlotFunction_New(member._slot, obj, NULL);
162 return PythonQtSlotFunction_New(member._slot, obj, NULL);
153 break;
163 break;
154 case PythonQtMemberInfo::EnumValue:
164 case PythonQtMemberInfo::EnumValue:
155 return PyInt_FromLong(member._enumValue);
165 return PyInt_FromLong(member._enumValue);
156 break;
166 break;
157 }
167 }
158
168
159 // look for the interal methods (className(), help())
169 // look for the interal methods (className(), help())
160 PyObject* internalMethod = Py_FindMethod( PythonQtWrapper_methods, obj, (char*)attributeName);
170 PyObject* internalMethod = Py_FindMethod( PythonQtWrapper_methods, obj, (char*)attributeName);
161 if (internalMethod) {
171 if (internalMethod) {
162 return internalMethod;
172 return internalMethod;
163 }
173 }
164 PyErr_Clear();
174 PyErr_Clear();
165
175
166 if (wt->_obj) {
176 if (wt->_obj) {
167 // look for a child
177 // look for a child
168 QObjectList children = wt->_obj->children();
178 QObjectList children = wt->_obj->children();
169 for (int i = 0; i < children.count(); i++) {
179 for (int i = 0; i < children.count(); i++) {
170 QObject *child = children.at(i);
180 QObject *child = children.at(i);
171 if (child->objectName() == attributeName) {
181 if (child->objectName() == attributeName) {
172 return PythonQt::self()->priv()->wrapQObject(child);
182 return PythonQt::self()->priv()->wrapQObject(child);
173 }
183 }
174 }
184 }
175 }
185 }
176
186
177 if (qstrcmp(attributeName, "__dict__")==0) {
187 if (qstrcmp(attributeName, "__dict__")==0) {
178 QStringList l = wt->_info->memberList(false);
188 QStringList l = wt->_info->memberList(false);
179 PyObject* dict = PyDict_New();
189 PyObject* dict = PyDict_New();
180 foreach (QString name, l) {
190 foreach (QString name, l) {
181 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
191 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
182 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
192 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
183 //Py_DECREF(o);
193 //Py_DECREF(o);
184 }
194 }
185 // Note: we do not put children into the dict, is would look confusing?!
195 // Note: we do not put children into the dict, is would look confusing?!
186 return dict;
196 return dict;
187 }
197 }
188
198
189
199
190 QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
200 QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
191 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
201 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
192 return NULL;
202 return NULL;
193 }
203 }
194
204
195 static int PythonQtWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
205 static int PythonQtWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
196 {
206 {
197 QString error;
207 QString error;
198 char *attributeName;
208 char *attributeName;
199 PythonQtWrapper *wt = (PythonQtWrapper *)obj;
209 PythonQtWrapper *wt = (PythonQtWrapper *)obj;
200
210
201 if ((attributeName = PyString_AsString(name)) == NULL)
211 if ((attributeName = PyString_AsString(name)) == NULL)
202 return -1;
212 return -1;
203
213
204 if (!wt->_obj) {
214 if (!wt->_obj) {
205 error = QString("Trying to set attribute '") + attributeName + "' on a destroyed " + wt->_info->className() + " object";
215 error = QString("Trying to set attribute '") + attributeName + "' on a destroyed " + wt->_info->className() + " object";
206 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
216 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
207 return -1;
217 return -1;
208 }
218 }
209
219
210 PythonQtMemberInfo member = wt->_info->member(attributeName);
220 PythonQtMemberInfo member = wt->_info->member(attributeName);
211 if (member._type == PythonQtMemberInfo::Property) {
221 if (member._type == PythonQtMemberInfo::Property) {
212 QMetaProperty prop = member._property;
222 QMetaProperty prop = member._property;
213 if (prop.isWritable()) {
223 if (prop.isWritable()) {
214 QVariant v;
224 QVariant v;
215 if (prop.isEnumType()) {
225 if (prop.isEnumType()) {
216 // this will give us either a string or an int, everything else will probably be an error
226 // this will give us either a string or an int, everything else will probably be an error
217 v = PythonQtConv::PyObjToQVariant(value);
227 v = PythonQtConv::PyObjToQVariant(value);
218 } else {
228 } else {
219 int t = prop.userType();
229 int t = prop.userType();
220 v = PythonQtConv::PyObjToQVariant(value, t);
230 v = PythonQtConv::PyObjToQVariant(value, t);
221 }
231 }
222 bool success = false;
232 bool success = false;
223 if (v.isValid()) {
233 if (v.isValid()) {
224 success = prop.write(wt->_obj, v);
234 success = prop.write(wt->_obj, v);
225 }
235 }
226 if (success) {
236 if (success) {
227 return 0;
237 return 0;
228 } else {
238 } else {
229 error = QString("Property '") + attributeName + "' of type '" +
239 error = QString("Property '") + attributeName + "' of type '" +
230 prop.typeName() + "' does not accept an object of type "
240 prop.typeName() + "' does not accept an object of type "
231 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
241 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
232 }
242 }
233 } else {
243 } else {
234 error = QString("Property '") + attributeName + "' of " + wt->_info->className() + " object is not writable";
244 error = QString("Property '") + attributeName + "' of " + wt->_info->className() + " object is not writable";
235 }
245 }
236 } else {
246 } else {
237 if (member._type == PythonQtMemberInfo::Slot) {
247 if (member._type == PythonQtMemberInfo::Slot) {
238 error = QString("Slot '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
248 error = QString("Slot '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
239 } else if (member._type == PythonQtMemberInfo::EnumValue) {
249 } else if (member._type == PythonQtMemberInfo::EnumValue) {
240 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
250 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
241 }
251 }
242 }
252 }
243
253
244 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
254 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
245 return -1;
255 return -1;
246 }
256 }
247
257
248 static PyObject * PythonQtWrapper_repr(PyObject * obj)
258 static PyObject * PythonQtWrapper_repr(PyObject * obj)
249 {
259 {
250 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
260 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
261 QObject *qobj = wt->_obj;
251 if (wt->_wrappedPtr) {
262 if (wt->_wrappedPtr) {
252 if (wt->_obj) {
263 if (wt->_obj) {
253 return PyString_FromFormat("%s (C++ Object 0x%x wrapped by %s 0x%x))", wt->_info->className(), wt->_wrappedPtr, wt->_obj->metaObject()->className(), wt->_obj);
264 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wt->_info->className(), wt->_wrappedPtr, wt->_obj->metaObject()->className(), qobj);
254 } else {
265 } else {
255 return PyString_FromFormat("%s (C++ Object 0x%x unwrapped)", wt->_info->className(), wt->_wrappedPtr);
266 return PyString_FromFormat("%s (C++ Object %p unwrapped)", wt->_info->className(), wt->_wrappedPtr);
256 }
267 }
257 } else {
268 } else {
258 return PyString_FromFormat("%s (QObject 0x%x)", wt->_info->className(), wt->_obj, wt->_wrappedPtr);
269 return PyString_FromFormat("%s (QObject %p)", wt->_info->className(), qobj);
259 }
270 }
260 }
271 }
261
272
262 static int PythonQtWrapper_compare(PyObject * obj1, PyObject * obj2)
273 static int PythonQtWrapper_compare(PyObject * obj1, PyObject * obj2)
263 {
274 {
264 if (obj1->ob_type == &PythonQtWrapper_Type &&
275 if (obj1->ob_type == &PythonQtWrapper_Type &&
265 obj2->ob_type == &PythonQtWrapper_Type) {
276 obj2->ob_type == &PythonQtWrapper_Type) {
266
277
267 PythonQtWrapper* w1 = (PythonQtWrapper*)obj1;
278 PythonQtWrapper* w1 = (PythonQtWrapper*)obj1;
268 PythonQtWrapper* w2 = (PythonQtWrapper*)obj2;
279 PythonQtWrapper* w2 = (PythonQtWrapper*)obj2;
269 if (w1->_wrappedPtr != NULL) {
280 if (w1->_wrappedPtr != NULL) {
270 if (w1->_wrappedPtr == w1->_wrappedPtr) {
281 if (w1->_wrappedPtr == w1->_wrappedPtr) {
271 return 0;
282 return 0;
272 } else {
283 } else {
273 return -1;
284 return -1;
274 }
285 }
275 } else if (w1->_obj == w2->_obj) {
286 } else if (w1->_obj == w2->_obj) {
276 return 0;
287 return 0;
277 } else {
288 } else {
278 return -1;
289 return -1;
279 }
290 }
280 } else {
291 } else {
281 return -1;
292 return -1;
282 }
293 }
283 }
294 }
284
295
285 static int PythonQtWrapper_nonzero(PyObject *obj)
296 static int PythonQtWrapper_nonzero(PyObject *obj)
286 {
297 {
287 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
298 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
288 return (wt->_wrappedPtr == NULL && wt->_obj == NULL)?0:1;
299 return (wt->_wrappedPtr == NULL && wt->_obj == NULL)?0:1;
289 }
300 }
290
301
302
303 static long PythonQtWrapper_hash(PythonQtWrapper *obj)
304 {
305 if (obj->_wrappedPtr != NULL) {
306 return reinterpret_cast<long>(obj->_wrappedPtr);
307 } else {
308 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
309 return reinterpret_cast<long>(qobj);
310 }
311 }
312
313
314
291 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
315 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
292 static PyNumberMethods PythonQtWrapper_as_number = {
316 static PyNumberMethods PythonQtWrapper_as_number = {
293 0, /* nb_add */
317 0, /* nb_add */
294 0, /* nb_subtract */
318 0, /* nb_subtract */
295 0, /* nb_multiply */
319 0, /* nb_multiply */
296 0, /* nb_divide */
320 0, /* nb_divide */
297 0, /* nb_remainder */
321 0, /* nb_remainder */
298 0, /* nb_divmod */
322 0, /* nb_divmod */
299 0, /* nb_power */
323 0, /* nb_power */
300 0, /* nb_negative */
324 0, /* nb_negative */
301 0, /* nb_positive */
325 0, /* nb_positive */
302 0, /* nb_absolute */
326 0, /* nb_absolute */
303 PythonQtWrapper_nonzero, /* nb_nonzero */
327 PythonQtWrapper_nonzero, /* nb_nonzero */
304 0, /* nb_invert */
328 0, /* nb_invert */
305 0, /* nb_lshift */
329 0, /* nb_lshift */
306 0, /* nb_rshift */
330 0, /* nb_rshift */
307 0, /* nb_and */
331 0, /* nb_and */
308 0, /* nb_xor */
332 0, /* nb_xor */
309 0, /* nb_or */
333 0, /* nb_or */
310 0, /* nb_coerce */
334 0, /* nb_coerce */
311 0, /* nb_int */
335 0, /* nb_int */
312 0, /* nb_long */
336 0, /* nb_long */
313 0, /* nb_float */
337 0, /* nb_float */
314 0, /* nb_oct */
338 0, /* nb_oct */
315 0, /* nb_hex */
339 0, /* nb_hex */
316 0, /* nb_inplace_add */
340 0, /* nb_inplace_add */
317 0, /* nb_inplace_subtract */
341 0, /* nb_inplace_subtract */
318 0, /* nb_inplace_multiply */
342 0, /* nb_inplace_multiply */
319 0, /* nb_inplace_divide */
343 0, /* nb_inplace_divide */
320 0, /* nb_inplace_remainder */
344 0, /* nb_inplace_remainder */
321 0, /* nb_inplace_power */
345 0, /* nb_inplace_power */
322 0, /* nb_inplace_lshift */
346 0, /* nb_inplace_lshift */
323 0, /* nb_inplace_rshift */
347 0, /* nb_inplace_rshift */
324 0, /* nb_inplace_and */
348 0, /* nb_inplace_and */
325 0, /* nb_inplace_xor */
349 0, /* nb_inplace_xor */
326 0, /* nb_inplace_or */
350 0, /* nb_inplace_or */
327 0, /* nb_floor_divide */
351 0, /* nb_floor_divide */
328 0, /* nb_true_divide */
352 0, /* nb_true_divide */
329 0, /* nb_inplace_floor_divide */
353 0, /* nb_inplace_floor_divide */
330 0, /* nb_inplace_true_divide */
354 0, /* nb_inplace_true_divide */
331 };
355 };
332
356
333 PyTypeObject PythonQtWrapper_Type = {
357 PyTypeObject PythonQtWrapper_Type = {
334 PyObject_HEAD_INIT(NULL)
358 PyObject_HEAD_INIT(NULL)
335 0, /*ob_size*/
359 0, /*ob_size*/
336 "PythonQt.PythonQtWrapper", /*tp_name*/
360 "PythonQt.PythonQtWrapper", /*tp_name*/
337 sizeof(PythonQtWrapper), /*tp_basicsize*/
361 sizeof(PythonQtWrapper), /*tp_basicsize*/
338 0, /*tp_itemsize*/
362 0, /*tp_itemsize*/
339 (destructor)PythonQtWrapper_dealloc, /*tp_dealloc*/
363 (destructor)PythonQtWrapper_dealloc, /*tp_dealloc*/
340 0, /*tp_print*/
364 0, /*tp_print*/
341 0, /*tp_getattr*/
365 0, /*tp_getattr*/
342 0, /*tp_setattr*/
366 0, /*tp_setattr*/
343 PythonQtWrapper_compare, /*tp_compare*/
367 PythonQtWrapper_compare, /*tp_compare*/
344 PythonQtWrapper_repr, /*tp_repr*/
368 PythonQtWrapper_repr, /*tp_repr*/
345 &PythonQtWrapper_as_number, /*tp_as_number*/
369 &PythonQtWrapper_as_number, /*tp_as_number*/
346 0, /*tp_as_sequence*/
370 0, /*tp_as_sequence*/
347 0, /*tp_as_mapping*/
371 0, /*tp_as_mapping*/
348 0, /*tp_hash */
372 (hashfunc)PythonQtWrapper_hash, /*tp_hash */
349 0, /*tp_call*/
373 0, /*tp_call*/
350 0, /*tp_str*/
374 0, /*tp_str*/
351 PythonQtWrapper_getattro, /*tp_getattro*/
375 PythonQtWrapper_getattro, /*tp_getattro*/
352 PythonQtWrapper_setattro, /*tp_setattro*/
376 PythonQtWrapper_setattro, /*tp_setattro*/
353 0, /*tp_as_buffer*/
377 0, /*tp_as_buffer*/
354 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
378 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
355 "PythonQtWrapper object", /* tp_doc */
379 "PythonQtWrapper object", /* tp_doc */
356 0, /* tp_traverse */
380 0, /* tp_traverse */
357 0, /* tp_clear */
381 0, /* tp_clear */
358 0, /* tp_richcompare */
382 0, /* tp_richcompare */
359 0, /* tp_weaklistoffset */
383 0, /* tp_weaklistoffset */
360 0, /* tp_iter */
384 0, /* tp_iter */
361 0, /* tp_iternext */
385 0, /* tp_iternext */
362 0, /* tp_methods */
386 0, /* tp_methods */
363 0, /* tp_members */
387 0, /* tp_members */
364 0, /* tp_getset */
388 0, /* tp_getset */
365 0, /* tp_base */
389 0, /* tp_base */
366 0, /* tp_dict */
390 0, /* tp_dict */
367 0, /* tp_descr_get */
391 0, /* tp_descr_get */
368 0, /* tp_descr_set */
392 0, /* tp_descr_set */
369 0, /* tp_dictoffset */
393 0, /* tp_dictoffset */
370 (initproc)PythonQtWrapper_init, /* tp_init */
394 (initproc)PythonQtWrapper_init, /* tp_init */
371 0, /* tp_alloc */
395 0, /* tp_alloc */
372 PythonQtWrapper_new, /* tp_new */
396 PythonQtWrapper_new, /* tp_new */
373 };
397 };
374
398
375 //-------------------------------------------------------
399 //-------------------------------------------------------
376
400
@@ -1,78 +1,89
1 #ifndef _PYTHONQTWRAPPER_H
1 #ifndef _PYTHONQTWRAPPER_H
2 #define _PYTHONQTWRAPPER_H
2 #define _PYTHONQTWRAPPER_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 PythonQtWrapper.h
38 // \file PythonQtWrapper.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <Python.h>
45 #include <Python.h>
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48 #include <QPointer>
48
49
49 #include "structmember.h"
50 #include "structmember.h"
50 #include "methodobject.h"
51 #include "methodobject.h"
51 #include "compile.h"
52 #include "compile.h"
52 #include "eval.h"
53 #include "eval.h"
53
54
54 class PythonQtClassInfo;
55 class PythonQtClassInfo;
55 class QObject;
56 class QObject;
56
57
57 extern PYTHONQT_EXPORT PyTypeObject PythonQtWrapper_Type;
58 extern PYTHONQT_EXPORT PyTypeObject PythonQtWrapper_Type;
58
59
59 //---------------------------------------------------------------
60 //---------------------------------------------------------------
60 //! a Python wrapper object for Qt objects and C++ objects (that are themselves wrapped by wrapper QObjects)
61 //! a Python wrapper object for Qt objects and C++ objects (that are themselves wrapped by wrapper QObjects)
61 typedef struct {
62 typedef struct {
62 PyObject_HEAD
63 PyObject_HEAD
63
64
65 //! set the QObject pointer
66 void setQObject(QObject* object) {
67 _obj = object;
68 _objPointerCopy = object;
69 }
70
64 //! pointer to the wrapped Qt object or if _wrappedPtr is set, the Qt object that wraps the C++ Ptr
71 //! pointer to the wrapped Qt object or if _wrappedPtr is set, the Qt object that wraps the C++ Ptr
65 QObject* _obj;
72 QPointer<QObject> _obj;
73 //! a copy of the _obj pointer, which is required because the wrapper needs to
74 //! deregister itself via the _obj pointer, even when the QPointer<QObject> object was destroyed
75 void* _objPointerCopy;
76
66 //! optional C++ object Ptr that is wrapped by the above _obj
77 //! optional C++ object Ptr that is wrapped by the above _obj
67 void* _wrappedPtr;
78 void* _wrappedPtr;
68
79
69 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
80 //! the class information, this is set even if the _obj or _wrappedPtr is NULL to support typed NULL pointers
70 PythonQtClassInfo* _info;
81 PythonQtClassInfo* _info;
71
82
72 //! flag that stores if the object is owned by pythonQt
83 //! flag that stores if the object is owned by pythonQt
73 bool _ownedByPythonQt;
84 bool _ownedByPythonQt;
74
85
75 } PythonQtWrapper;
86 } PythonQtWrapper;
76
87
77
88
78 #endif No newline at end of file
89 #endif
General Comments 0
You need to be logged in to leave comments. Login now