##// END OF EJS Templates
merged various changes from MeVisLab repository...
florianlink -
r180:a63222bd6a1b
parent child
Show More
@@ -1,1692 +1,1721
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, 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 "PythonQtSignal.h"
46 #include "PythonQtSignal.h"
47 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtSignalReceiver.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49 #include "PythonQtStdIn.h"
49 #include "PythonQtStdIn.h"
50 #include "PythonQtStdOut.h"
50 #include "PythonQtStdOut.h"
51 #include "PythonQtCppWrapperFactory.h"
51 #include "PythonQtCppWrapperFactory.h"
52 #include "PythonQtVariants.h"
52 #include "PythonQtVariants.h"
53 #include "PythonQtStdDecorators.h"
53 #include "PythonQtStdDecorators.h"
54 #include "PythonQtQFileImporter.h"
54 #include "PythonQtQFileImporter.h"
55 #include <pydebug.h>
55 #include <pydebug.h>
56 #include <vector>
56 #include <vector>
57
57
58 PythonQt* PythonQt::_self = NULL;
58 PythonQt* PythonQt::_self = NULL;
59 int PythonQt::_uniqueModuleCount = 0;
59 int PythonQt::_uniqueModuleCount = 0;
60
60
61 void PythonQt_init_QtGuiBuiltin(PyObject*);
61 void PythonQt_init_QtGuiBuiltin(PyObject*);
62 void PythonQt_init_QtCoreBuiltin(PyObject*);
62 void PythonQt_init_QtCoreBuiltin(PyObject*);
63
63
64 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
64 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
65 {
65 {
66 if (!_self) {
66 if (!_self) {
67 _self = new PythonQt(flags, pythonQtModuleName);
67 _self = new PythonQt(flags, pythonQtModuleName);
68
68
69 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
69 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
70 qRegisterMetaType<QList<QObject*> >("QList<void*>");
70 qRegisterMetaType<QList<QObject*> >("QList<void*>");
71
71
72 PythonQtRegisterToolClassesTemplateConverter(int);
72 PythonQtRegisterToolClassesTemplateConverter(int);
73 PythonQtRegisterToolClassesTemplateConverter(float);
73 PythonQtRegisterToolClassesTemplateConverter(float);
74 PythonQtRegisterToolClassesTemplateConverter(double);
74 PythonQtRegisterToolClassesTemplateConverter(double);
75 PythonQtRegisterToolClassesTemplateConverter(qint32);
75 PythonQtRegisterToolClassesTemplateConverter(qint32);
76 PythonQtRegisterToolClassesTemplateConverter(quint32);
76 PythonQtRegisterToolClassesTemplateConverter(quint32);
77 PythonQtRegisterToolClassesTemplateConverter(qint64);
77 PythonQtRegisterToolClassesTemplateConverter(qint64);
78 PythonQtRegisterToolClassesTemplateConverter(quint64);
78 PythonQtRegisterToolClassesTemplateConverter(quint64);
79 // TODO: which other POD types should be available for QList etc.
79 // TODO: which other POD types should be available for QList etc.
80
80
81 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
82
83 PythonQt_init_QtCoreBuiltin(NULL);
81 PythonQt_init_QtCoreBuiltin(NULL);
84 PythonQt_init_QtGuiBuiltin(NULL);
82 PythonQt_init_QtGuiBuiltin(NULL);
85
83
84 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
85 PythonQt::self()->registerCPPClass("QMetaObject",0, "QtCore", PythonQtCreateObject<PythonQtWrapper_QMetaObject>);
86
86 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
87 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
87 PythonQtRegisterToolClassesTemplateConverter(QDate);
88 PythonQtRegisterToolClassesTemplateConverter(QDate);
88 PythonQtRegisterToolClassesTemplateConverter(QTime);
89 PythonQtRegisterToolClassesTemplateConverter(QTime);
89 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
90 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
90 PythonQtRegisterToolClassesTemplateConverter(QUrl);
91 PythonQtRegisterToolClassesTemplateConverter(QUrl);
91 PythonQtRegisterToolClassesTemplateConverter(QLocale);
92 PythonQtRegisterToolClassesTemplateConverter(QLocale);
92 PythonQtRegisterToolClassesTemplateConverter(QRect);
93 PythonQtRegisterToolClassesTemplateConverter(QRect);
93 PythonQtRegisterToolClassesTemplateConverter(QRectF);
94 PythonQtRegisterToolClassesTemplateConverter(QRectF);
94 PythonQtRegisterToolClassesTemplateConverter(QSize);
95 PythonQtRegisterToolClassesTemplateConverter(QSize);
95 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
96 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
96 PythonQtRegisterToolClassesTemplateConverter(QLine);
97 PythonQtRegisterToolClassesTemplateConverter(QLine);
97 PythonQtRegisterToolClassesTemplateConverter(QLineF);
98 PythonQtRegisterToolClassesTemplateConverter(QLineF);
98 PythonQtRegisterToolClassesTemplateConverter(QPoint);
99 PythonQtRegisterToolClassesTemplateConverter(QPoint);
99 PythonQtRegisterToolClassesTemplateConverter(QPointF);
100 PythonQtRegisterToolClassesTemplateConverter(QPointF);
100 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
101 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
101
102
102 PythonQtRegisterToolClassesTemplateConverter(QFont);
103 PythonQtRegisterToolClassesTemplateConverter(QFont);
103 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
104 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
104 PythonQtRegisterToolClassesTemplateConverter(QBrush);
105 PythonQtRegisterToolClassesTemplateConverter(QBrush);
105 PythonQtRegisterToolClassesTemplateConverter(QColor);
106 PythonQtRegisterToolClassesTemplateConverter(QColor);
106 PythonQtRegisterToolClassesTemplateConverter(QPalette);
107 PythonQtRegisterToolClassesTemplateConverter(QPalette);
107 PythonQtRegisterToolClassesTemplateConverter(QIcon);
108 PythonQtRegisterToolClassesTemplateConverter(QIcon);
108 PythonQtRegisterToolClassesTemplateConverter(QImage);
109 PythonQtRegisterToolClassesTemplateConverter(QImage);
109 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
110 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
110 PythonQtRegisterToolClassesTemplateConverter(QRegion);
111 PythonQtRegisterToolClassesTemplateConverter(QRegion);
111 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
112 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
112 PythonQtRegisterToolClassesTemplateConverter(QCursor);
113 PythonQtRegisterToolClassesTemplateConverter(QCursor);
113 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
114 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
114 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
115 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
115 PythonQtRegisterToolClassesTemplateConverter(QPen);
116 PythonQtRegisterToolClassesTemplateConverter(QPen);
116 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
117 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
117 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
118 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
118 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
119 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
119
120
120
121
121 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
122 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
122 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
123 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
123 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
124 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
124 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
125 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
125 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
126 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
126 for (unsigned int i = 0;i<16; i++) {
127 for (unsigned int i = 0;i<16; i++) {
127 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
128 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
128 if (obj) {
129 if (obj) {
129 PyModule_AddObject(pack, names[i], obj);
130 PyModule_AddObject(pack, names[i], obj);
130 Py_INCREF(obj);
131 Py_INCREF(obj);
131 PyModule_AddObject(pack2, names[i], obj);
132 PyModule_AddObject(pack2, names[i], obj);
132 } else {
133 } else {
133 std::cerr << "method not found " << names[i];
134 std::cerr << "method not found " << names[i];
134 }
135 }
135 }
136 }
136 }
137 }
137 }
138 }
138
139
139 void PythonQt::cleanup()
140 void PythonQt::cleanup()
140 {
141 {
141 if (_self) {
142 if (_self) {
142 delete _self;
143 delete _self;
143 _self = NULL;
144 _self = NULL;
144 }
145 }
145 }
146 }
146
147
147 PythonQt* PythonQt::self() { return _self; }
148 PythonQt* PythonQt::self() { return _self; }
148
149
149 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
150 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
150 {
151 {
151 _p = new PythonQtPrivate;
152 _p = new PythonQtPrivate;
152 _p->_initFlags = flags;
153 _p->_initFlags = flags;
153
154
154 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
155 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
155
156
156 if ((flags & PythonAlreadyInitialized) == 0) {
157 if ((flags & PythonAlreadyInitialized) == 0) {
157 Py_SetProgramName(const_cast<char*>("PythonQt"));
158 Py_SetProgramName(const_cast<char*>("PythonQt"));
158 if (flags & IgnoreSiteModule) {
159 if (flags & IgnoreSiteModule) {
159 // this prevents the automatic importing of Python site files
160 // this prevents the automatic importing of Python site files
160 Py_NoSiteFlag = 1;
161 Py_NoSiteFlag = 1;
161 }
162 }
162 Py_Initialize();
163 Py_Initialize();
163 }
164 }
164
165
165 // add our own python object types for qt object slots
166 // add our own python object types for qt object slots
166 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
167 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
167 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
168 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
168 }
169 }
169 Py_INCREF(&PythonQtSlotFunction_Type);
170 Py_INCREF(&PythonQtSlotFunction_Type);
170
171
171 if (PyType_Ready(&PythonQtSignalFunction_Type) < 0) {
172 if (PyType_Ready(&PythonQtSignalFunction_Type) < 0) {
172 std::cerr << "could not initialize PythonQtSignalFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
173 std::cerr << "could not initialize PythonQtSignalFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
173 }
174 }
174 Py_INCREF(&PythonQtSignalFunction_Type);
175 Py_INCREF(&PythonQtSignalFunction_Type);
175
176
176 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
177 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
177 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
178 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
178 // add our own python object types for classes
179 // add our own python object types for classes
179 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
180 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
180 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
181 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
181 }
182 }
182 Py_INCREF(&PythonQtClassWrapper_Type);
183 Py_INCREF(&PythonQtClassWrapper_Type);
183
184
184 // add our own python object types for CPP instances
185 // add our own python object types for CPP instances
185 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
186 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
186 PythonQt::handleError();
187 PythonQt::handleError();
187 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
188 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
188 }
189 }
189 Py_INCREF(&PythonQtInstanceWrapper_Type);
190 Py_INCREF(&PythonQtInstanceWrapper_Type);
190
191
191 // add our own python object types for redirection of stdout
192 // add our own python object types for redirection of stdout
192 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
193 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
193 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
194 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
194 }
195 }
195 Py_INCREF(&PythonQtStdOutRedirectType);
196 Py_INCREF(&PythonQtStdOutRedirectType);
196
197
197 // add our own python object types for redirection of stdin
198 // add our own python object types for redirection of stdin
198 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
199 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
199 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
200 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
200 }
201 }
201 Py_INCREF(&PythonQtStdInRedirectType);
202 Py_INCREF(&PythonQtStdInRedirectType);
202
203
203 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
204 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
204
205
205 _p->setupSharedLibrarySuffixes();
206 _p->setupSharedLibrarySuffixes();
206
207
207 }
208 }
208
209
209 PythonQt::~PythonQt() {
210 PythonQt::~PythonQt() {
210 delete _p;
211 delete _p;
211 _p = NULL;
212 _p = NULL;
212 }
213 }
213
214
214 PythonQtPrivate::~PythonQtPrivate() {
215 PythonQtPrivate::~PythonQtPrivate() {
215 delete _defaultImporter;
216 delete _defaultImporter;
216 _defaultImporter = NULL;
217 _defaultImporter = NULL;
217
218
218 {
219 {
219 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
220 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
220 while (i.hasNext()) {
221 while (i.hasNext()) {
221 delete i.next().value();
222 delete i.next().value();
222 }
223 }
223 }
224 }
224 PythonQtConv::global_valueStorage.clear();
225 PythonQtConv::global_valueStorage.clear();
225 PythonQtConv::global_ptrStorage.clear();
226 PythonQtConv::global_ptrStorage.clear();
226 PythonQtConv::global_variantStorage.clear();
227 PythonQtConv::global_variantStorage.clear();
227
228
228 PythonQtMethodInfo::cleanupCachedMethodInfos();
229 PythonQtMethodInfo::cleanupCachedMethodInfos();
229 }
230 }
230
231
231 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
232 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
232 {
233 {
233 if (!callback)
234 if (!callback)
234 {
235 {
235 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
236 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
236 return;
237 return;
237 }
238 }
238
239
239 PythonQtObjectPtr sys;
240 PythonQtObjectPtr sys;
240 PythonQtObjectPtr in;
241 PythonQtObjectPtr in;
241 sys.setNewRef(PyImport_ImportModule("sys"));
242 sys.setNewRef(PyImport_ImportModule("sys"));
242
243
243 // Backup original 'sys.stdin' if not yet done
244 // Backup original 'sys.stdin' if not yet done
244 PyRun_SimpleString("if not hasattr(sys, 'pythonqt_original_stdin'):"
245 PyRun_SimpleString("if not hasattr(sys, 'pythonqt_original_stdin'):"
245 "sys.pythonqt_original_stdin = sys.stdin");
246 "sys.pythonqt_original_stdin = sys.stdin");
246
247
247 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
248 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
248 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
249 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
249 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
250 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
250 // replace the built in file objects with our own objects
251 // replace the built in file objects with our own objects
251 PyModule_AddObject(sys, "stdin", in);
252 PyModule_AddObject(sys, "stdin", in);
252
253
253 // Backup custom 'stdin' into 'pythonqt_stdin'
254 // Backup custom 'stdin' into 'pythonqt_stdin'
254 PyRun_SimpleString("sys.pythonqt_stdin = sys.stdin");
255 PyRun_SimpleString("sys.pythonqt_stdin = sys.stdin");
255 }
256 }
256
257
257 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
258 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
258 {
259 {
259 if (enabled)
260 if (enabled)
260 {
261 {
261 PyRun_SimpleString("if hasattr(sys, 'pythonqt_stdin'):"
262 PyRun_SimpleString("if hasattr(sys, 'pythonqt_stdin'):"
262 "sys.stdin = sys.pythonqt_stdin");
263 "sys.stdin = sys.pythonqt_stdin");
263 }
264 }
264 else
265 else
265 {
266 {
266 PyRun_SimpleString("if hasattr(sys,'pythonqt_original_stdin'):"
267 PyRun_SimpleString("if hasattr(sys,'pythonqt_original_stdin'):"
267 "sys.stdin = sys.pythonqt_original_stdin");
268 "sys.stdin = sys.pythonqt_original_stdin");
268 }
269 }
269 }
270 }
270
271
271 PythonQtImportFileInterface* PythonQt::importInterface()
272 PythonQtImportFileInterface* PythonQt::importInterface()
272 {
273 {
273 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
274 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
274 }
275 }
275
276
276 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
277 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
277 {
278 {
278 if (_self->_p->_noLongerWrappedCB) {
279 if (_self->_p->_noLongerWrappedCB) {
279 (*_self->_p->_noLongerWrappedCB)(o);
280 (*_self->_p->_noLongerWrappedCB)(o);
280 };
281 };
281 }
282 }
282
283
283 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
284 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
284 {
285 {
285 _p->registerClass(metaobject, package, wrapperCreator, shell);
286 _p->registerClass(metaobject, package, wrapperCreator, shell);
286 }
287 }
287
288
288 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
289 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
289 {
290 {
290 // we register all classes in the hierarchy
291 // we register all classes in the hierarchy
291 const QMetaObject* m = metaobject;
292 const QMetaObject* m = metaobject;
292 bool first = true;
293 bool first = true;
293 while (m) {
294 while (m) {
294 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
295 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
295 if (!info->pythonQtClassWrapper()) {
296 if (!info->pythonQtClassWrapper()) {
296 info->setTypeSlots(typeSlots);
297 info->setTypeSlots(typeSlots);
297 info->setupQObject(m);
298 info->setupQObject(m);
298 createPythonQtClassWrapper(info, package, module);
299 createPythonQtClassWrapper(info, package, module);
299 if (m->superClass()) {
300 if (m->superClass()) {
300 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
301 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
301 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
302 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
302 }
303 }
303 } else if (first && module) {
304 } else if (first && module) {
304 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
305 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
305 // since it might have been placed into "private" earlier on.
306 // since it might have been placed into "private" earlier on.
306 // If the wrapper was already added to module before, it is just readded, which does no harm.
307 // If the wrapper was already added to module before, it is just readded, which does no harm.
307 PyObject* classWrapper = info->pythonQtClassWrapper();
308 PyObject* classWrapper = info->pythonQtClassWrapper();
308 // AddObject steals a reference, so we need to INCREF
309 // AddObject steals a reference, so we need to INCREF
309 Py_INCREF(classWrapper);
310 Py_INCREF(classWrapper);
310 PyModule_AddObject(module, info->className(), classWrapper);
311 PyModule_AddObject(module, info->className(), classWrapper);
311 }
312 }
312 if (first) {
313 if (first) {
313 first = false;
314 first = false;
314 if (wrapperCreator) {
315 if (wrapperCreator) {
315 info->setDecoratorProvider(wrapperCreator);
316 info->setDecoratorProvider(wrapperCreator);
316 }
317 }
317 if (shell) {
318 if (shell) {
318 info->setShellSetInstanceWrapperCB(shell);
319 info->setShellSetInstanceWrapperCB(shell);
319 }
320 }
320 }
321 }
321 m = m->superClass();
322 m = m->superClass();
322 }
323 }
323 }
324 }
324
325
325 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
326 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
326 {
327 {
327 PyObject* pack = module?module:packageByName(package);
328 PyObject* pack = module?module:packageByName(package);
328 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
329 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
329 PyModule_AddObject(pack, info->className(), pyobj);
330 PyModule_AddObject(pack, info->className(), pyobj);
330 if (!module && package && strncmp(package,"Qt",2)==0) {
331 if (!module && package && strncmp(package,"Qt",2)==0) {
331 // since PyModule_AddObject steals the reference, we need a incref once more...
332 // since PyModule_AddObject steals the reference, we need a incref once more...
332 Py_INCREF(pyobj);
333 Py_INCREF(pyobj);
333 // put all qt objects into Qt as well
334 // put all qt objects into Qt as well
334 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
335 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
335 }
336 }
336 info->setPythonQtClassWrapper(pyobj);
337 info->setPythonQtClassWrapper(pyobj);
337 }
338 }
338
339
339 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
340 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
340 {
341 {
341 if (!obj) {
342 if (!obj) {
342 Py_INCREF(Py_None);
343 Py_INCREF(Py_None);
343 return Py_None;
344 return Py_None;
344 }
345 }
345 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
346 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
346 if (!wrap) {
347 if (!wrap) {
347 // smuggling it in...
348 // smuggling it in...
348 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
349 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
349 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
350 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
350 registerClass(obj->metaObject());
351 registerClass(obj->metaObject());
351 classInfo = _knownClassInfos.value(obj->metaObject()->className());
352 classInfo = _knownClassInfos.value(obj->metaObject()->className());
352 }
353 }
353 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
354 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
354 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
355 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
355 } else {
356 } else {
356 Py_INCREF(wrap);
357 Py_INCREF(wrap);
357 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
358 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
358 }
359 }
359 return (PyObject*)wrap;
360 return (PyObject*)wrap;
360 }
361 }
361
362
362 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
363 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
363 {
364 {
364 if (!ptr) {
365 if (!ptr) {
365 Py_INCREF(Py_None);
366 Py_INCREF(Py_None);
366 return Py_None;
367 return Py_None;
367 }
368 }
368
369
369 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
370 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
370 if (!wrap) {
371 if (!wrap) {
371 PythonQtClassInfo* info = _knownClassInfos.value(name);
372 PythonQtClassInfo* info = _knownClassInfos.value(name);
372 if (!info) {
373 if (!info) {
373 // maybe it is a PyObject, which we can return directly
374 // maybe it is a PyObject, which we can return directly
374 if (name == "PyObject") {
375 if (name == "PyObject") {
375 PyObject* p = (PyObject*)ptr;
376 PyObject* p = (PyObject*)ptr;
376 Py_INCREF(p);
377 Py_INCREF(p);
377 return p;
378 return p;
378 }
379 }
379
380
380 // we do not know the metaobject yet, but we might know it by it's name:
381 // we do not know the metaobject yet, but we might know it by it's name:
381 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
382 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
382 // yes, we know it, so we can convert to QObject
383 // yes, we know it, so we can convert to QObject
383 QObject* qptr = (QObject*)ptr;
384 QObject* qptr = (QObject*)ptr;
384 registerClass(qptr->metaObject());
385 registerClass(qptr->metaObject());
385 info = _knownClassInfos.value(qptr->metaObject()->className());
386 info = _knownClassInfos.value(qptr->metaObject()->className());
386 }
387 }
387 }
388 }
388 if (info && info->isQObject()) {
389 if (info && info->isQObject()) {
389 QObject* qptr = (QObject*)ptr;
390 QObject* qptr = (QObject*)ptr;
390 // if the object is a derived object, we want to switch the class info to the one of the derived class:
391 // if the object is a derived object, we want to switch the class info to the one of the derived class:
391 if (name!=(qptr->metaObject()->className())) {
392 if (name!=(qptr->metaObject()->className())) {
392 registerClass(qptr->metaObject());
393 registerClass(qptr->metaObject());
393 info = _knownClassInfos.value(qptr->metaObject()->className());
394 info = _knownClassInfos.value(qptr->metaObject()->className());
394 }
395 }
395 wrap = createNewPythonQtInstanceWrapper(qptr, info);
396 wrap = createNewPythonQtInstanceWrapper(qptr, info);
396 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
397 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
397 return (PyObject*)wrap;
398 return (PyObject*)wrap;
398 }
399 }
399
400
400 // not a known QObject, try to wrap via foreign wrapper factories
401 // not a known QObject, try to wrap via foreign wrapper factories
401 PyObject* foreignWrapper = NULL;
402 PyObject* foreignWrapper = NULL;
402 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
403 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
403 foreignWrapper = _foreignWrapperFactories.at(i)->wrap(name, ptr);
404 foreignWrapper = _foreignWrapperFactories.at(i)->wrap(name, ptr);
404 if (foreignWrapper) {
405 if (foreignWrapper) {
405 return foreignWrapper;
406 return foreignWrapper;
406 }
407 }
407 }
408 }
408
409
409 // not a known QObject, so try our wrapper factory:
410 // not a known QObject, so try our wrapper factory:
410 QObject* wrapper = NULL;
411 QObject* wrapper = NULL;
411 for (int i=0; i<_cppWrapperFactories.size(); i++) {
412 for (int i=0; i<_cppWrapperFactories.size(); i++) {
412 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
413 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
413 if (wrapper) {
414 if (wrapper) {
414 break;
415 break;
415 }
416 }
416 }
417 }
417
418
418 if (info) {
419 if (info) {
419 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
420 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
420 ptr = info->castDownIfPossible(ptr, &info);
421 ptr = info->castDownIfPossible(ptr, &info);
421
422
422 // if downcasting found out that the object is a QObject,
423 // if downcasting found out that the object is a QObject,
423 // handle it like one:
424 // handle it like one:
424 if (info && info->isQObject()) {
425 if (info && info->isQObject()) {
425 QObject* qptr = (QObject*)ptr;
426 QObject* qptr = (QObject*)ptr;
426 // if the object is a derived object, we want to switch the class info to the one of the derived class:
427 // if the object is a derived object, we want to switch the class info to the one of the derived class:
427 if (name!=(qptr->metaObject()->className())) {
428 if (name!=(qptr->metaObject()->className())) {
428 registerClass(qptr->metaObject());
429 registerClass(qptr->metaObject());
429 info = _knownClassInfos.value(qptr->metaObject()->className());
430 info = _knownClassInfos.value(qptr->metaObject()->className());
430 }
431 }
431 wrap = createNewPythonQtInstanceWrapper(qptr, info);
432 wrap = createNewPythonQtInstanceWrapper(qptr, info);
432 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
433 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
433 return (PyObject*)wrap;
434 return (PyObject*)wrap;
434 }
435 }
435 }
436 }
436
437
437 if (!info || info->pythonQtClassWrapper()==NULL) {
438 if (!info || info->pythonQtClassWrapper()==NULL) {
438 // still unknown, register as CPP class
439 // still unknown, register as CPP class
439 registerCPPClass(name.constData());
440 registerCPPClass(name.constData());
440 info = _knownClassInfos.value(name);
441 info = _knownClassInfos.value(name);
441 }
442 }
442 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
443 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
443 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
444 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
444 info->setMetaObject(wrapper->metaObject());
445 info->setMetaObject(wrapper->metaObject());
445 }
446 }
446
447
447 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
448 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
448 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
449 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
449 } else {
450 } else {
450 Py_INCREF(wrap);
451 Py_INCREF(wrap);
451 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
452 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
452 }
453 }
453 return (PyObject*)wrap;
454 return (PyObject*)wrap;
454 }
455 }
455
456
456 PyObject* PythonQtPrivate::dummyTuple() {
457 PyObject* PythonQtPrivate::dummyTuple() {
457 static PyObject* dummyTuple = NULL;
458 static PyObject* dummyTuple = NULL;
458 if (dummyTuple==NULL) {
459 if (dummyTuple==NULL) {
459 dummyTuple = PyTuple_New(1);
460 dummyTuple = PyTuple_New(1);
460 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
461 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
461 }
462 }
462 return dummyTuple;
463 return dummyTuple;
463 }
464 }
464
465
465
466
466 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
467 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
467 // call the associated class type to create a new instance...
468 // call the associated class type to create a new instance...
468 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
469 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
469
470
470 result->setQObject(obj);
471 result->setQObject(obj);
471 result->_wrappedPtr = wrappedPtr;
472 result->_wrappedPtr = wrappedPtr;
472 result->_ownedByPythonQt = false;
473 result->_ownedByPythonQt = false;
473 result->_useQMetaTypeDestroy = false;
474 result->_useQMetaTypeDestroy = false;
474
475
475 if (wrappedPtr) {
476 if (wrappedPtr) {
476 _wrappedObjects.insert(wrappedPtr, result);
477 _wrappedObjects.insert(wrappedPtr, result);
477 } else {
478 } else {
478 _wrappedObjects.insert(obj, result);
479 _wrappedObjects.insert(obj, result);
479 if (obj->parent()== NULL && _wrappedCB) {
480 if (obj->parent()== NULL && _wrappedCB) {
480 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
481 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
481 (*_wrappedCB)(obj);
482 (*_wrappedCB)(obj);
482 }
483 }
483 }
484 }
484 return result;
485 return result;
485 }
486 }
486
487
487 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
488 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
488 PythonQtClassWrapper* result;
489 PythonQtClassWrapper* result;
489
490
490 PyObject* className = PyString_FromString(info->className());
491 PyObject* className = PyString_FromString(info->className());
491
492
492 PyObject* baseClasses = PyTuple_New(1);
493 PyObject* baseClasses = PyTuple_New(1);
493 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
494 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
494
495
495 PyObject* typeDict = PyDict_New();
496 PyObject* typeDict = PyDict_New();
496 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
497 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
497 PyDict_SetItemString(typeDict, "__module__", moduleName);
498 PyDict_SetItemString(typeDict, "__module__", moduleName);
498
499
499 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
500 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
500
501
501 // set the class info so that PythonQtClassWrapper_new can read it
502 // set the class info so that PythonQtClassWrapper_new can read it
502 _currentClassInfoForClassWrapperCreation = info;
503 _currentClassInfoForClassWrapperCreation = info;
503 // create the new type object by calling the type
504 // create the new type object by calling the type
504 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
505 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
505
506
506 Py_DECREF(baseClasses);
507 Py_DECREF(baseClasses);
507 Py_DECREF(typeDict);
508 Py_DECREF(typeDict);
508 Py_DECREF(args);
509 Py_DECREF(args);
509 Py_DECREF(className);
510 Py_DECREF(className);
510
511
511 return result;
512 return result;
512 }
513 }
513
514
514 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
515 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
515 {
516 {
516 PyObject* args = Py_BuildValue("(i)", enumValue);
517 PyObject* args = Py_BuildValue("(i)", enumValue);
517 PyObject* result = PyObject_Call(enumType, args, NULL);
518 PyObject* result = PyObject_Call(enumType, args, NULL);
518 Py_DECREF(args);
519 Py_DECREF(args);
519 return result;
520 return result;
520 }
521 }
521
522
522 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
523 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
523 PyObject* result;
524 PyObject* result;
524
525
525 PyObject* className = PyString_FromString(enumName);
526 PyObject* className = PyString_FromString(enumName);
526
527
527 PyObject* baseClasses = PyTuple_New(1);
528 PyObject* baseClasses = PyTuple_New(1);
528 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
529 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
529
530
530 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
531 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
531 PyObject* typeDict = PyDict_New();
532 PyObject* typeDict = PyDict_New();
532 PyDict_SetItemString(typeDict, "__module__", module);
533 PyDict_SetItemString(typeDict, "__module__", module);
533
534
534 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
535 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
535
536
536 // create the new int derived type object by calling the core type
537 // create the new int derived type object by calling the core type
537 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
538 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
538
539
539 Py_DECREF(baseClasses);
540 Py_DECREF(baseClasses);
540 Py_DECREF(typeDict);
541 Py_DECREF(typeDict);
541 Py_DECREF(args);
542 Py_DECREF(args);
542 Py_DECREF(className);
543 Py_DECREF(className);
543
544
544 return result;
545 return result;
545 }
546 }
546
547
547 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
548 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
548 {
549 {
549 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
550 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
550 if (!r) {
551 if (!r) {
551 r = new PythonQtSignalReceiver(obj);
552 r = new PythonQtSignalReceiver(obj);
552 _p->_signalReceivers.insert(obj, r);
553 _p->_signalReceivers.insert(obj, r);
553 }
554 }
554 return r;
555 return r;
555 }
556 }
556
557
557 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
558 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
558 {
559 {
559 bool flag = false;
560 bool flag = false;
560 PythonQtObjectPtr callable = lookupCallable(module, objectname);
561 PythonQtObjectPtr callable = lookupCallable(module, objectname);
561 if (callable) {
562 if (callable) {
562 PythonQtSignalReceiver* r = getSignalReceiver(obj);
563 PythonQtSignalReceiver* r = getSignalReceiver(obj);
563 flag = r->addSignalHandler(signal, callable);
564 flag = r->addSignalHandler(signal, callable);
564 if (!flag) {
565 if (!flag) {
565 // signal not found
566 // signal not found
566 }
567 }
567 } else {
568 } else {
568 // callable not found
569 // callable not found
569 }
570 }
570 return flag;
571 return flag;
571 }
572 }
572
573
573 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
574 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
574 {
575 {
575 bool flag = false;
576 bool flag = false;
576 PythonQtSignalReceiver* r = getSignalReceiver(obj);
577 PythonQtSignalReceiver* r = getSignalReceiver(obj);
577 if (r) {
578 if (r) {
578 flag = r->addSignalHandler(signal, receiver);
579 flag = r->addSignalHandler(signal, receiver);
579 }
580 }
580 return flag;
581 return flag;
581 }
582 }
582
583
583 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
584 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
584 {
585 {
585 bool flag = false;
586 bool flag = false;
586 PythonQtObjectPtr callable = lookupCallable(module, objectname);
587 PythonQtObjectPtr callable = lookupCallable(module, objectname);
587 if (callable) {
588 if (callable) {
588 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
589 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
589 if (r) {
590 if (r) {
590 flag = r->removeSignalHandler(signal, callable);
591 flag = r->removeSignalHandler(signal, callable);
591 }
592 }
592 } else {
593 } else {
593 // callable not found
594 // callable not found
594 }
595 }
595 return flag;
596 return flag;
596 }
597 }
597
598
598 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
599 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
599 {
600 {
600 bool flag = false;
601 bool flag = false;
601 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
602 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
602 if (r) {
603 if (r) {
603 flag = r->removeSignalHandler(signal, receiver);
604 flag = r->removeSignalHandler(signal, receiver);
604 }
605 }
605 return flag;
606 return flag;
606 }
607 }
607
608
608 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
609 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
609 {
610 {
610 PythonQtObjectPtr p = lookupObject(module, name);
611 PythonQtObjectPtr p = lookupObject(module, name);
611 if (p) {
612 if (p) {
612 if (PyCallable_Check(p)) {
613 if (PyCallable_Check(p)) {
613 return p;
614 return p;
614 }
615 }
615 }
616 }
616 PyErr_Clear();
617 PyErr_Clear();
617 return NULL;
618 return NULL;
618 }
619 }
619
620
620 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
621 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
621 {
622 {
622 QStringList l = name.split('.');
623 QStringList l = name.split('.');
623 PythonQtObjectPtr p = module;
624 PythonQtObjectPtr p = module;
624 PythonQtObjectPtr prev;
625 PythonQtObjectPtr prev;
625 QByteArray b;
626 QByteArray b;
626 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
627 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
627 prev = p;
628 prev = p;
628 b = (*i).toLatin1();
629 b = (*i).toLatin1();
629 if (PyDict_Check(p)) {
630 if (PyDict_Check(p)) {
630 p = PyDict_GetItemString(p, b.data());
631 p = PyDict_GetItemString(p, b.data());
631 } else {
632 } else {
632 p.setNewRef(PyObject_GetAttrString(p, b.data()));
633 p.setNewRef(PyObject_GetAttrString(p, b.data()));
633 }
634 }
634 }
635 }
635 PyErr_Clear();
636 PyErr_Clear();
636 return p;
637 return p;
637 }
638 }
638
639
639 PythonQtObjectPtr PythonQt::getMainModule() {
640 PythonQtObjectPtr PythonQt::getMainModule() {
640 //both borrowed
641 //both borrowed
641 PythonQtObjectPtr dict = PyImport_GetModuleDict();
642 PythonQtObjectPtr dict = PyImport_GetModuleDict();
642 return PyDict_GetItemString(dict, "__main__");
643 return PyDict_GetItemString(dict, "__main__");
643 }
644 }
644
645
645 PythonQtObjectPtr PythonQt::importModule(const QString& name)
646 PythonQtObjectPtr PythonQt::importModule(const QString& name)
646 {
647 {
647 PythonQtObjectPtr mod;
648 PythonQtObjectPtr mod;
648 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
649 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
649 return mod;
650 return mod;
650 }
651 }
651
652
652
653
653 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
654 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
654 QVariant result;
655 QVariant result;
655 if (pycode) {
656 if (pycode) {
656 PyObject* dict = NULL;
657 PyObject* dict = NULL;
657 if (PyModule_Check(object)) {
658 if (PyModule_Check(object)) {
658 dict = PyModule_GetDict(object);
659 dict = PyModule_GetDict(object);
659 } else if (PyDict_Check(object)) {
660 } else if (PyDict_Check(object)) {
660 dict = object;
661 dict = object;
661 }
662 }
662 PyObject* r = NULL;
663 PyObject* r = NULL;
663 if (dict) {
664 if (dict) {
664 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
665 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
665 }
666 }
666 if (r) {
667 if (r) {
667 result = PythonQtConv::PyObjToQVariant(r);
668 result = PythonQtConv::PyObjToQVariant(r);
668 Py_DECREF(r);
669 Py_DECREF(r);
669 } else {
670 } else {
670 handleError();
671 handleError();
671 }
672 }
672 } else {
673 } else {
673 handleError();
674 handleError();
674 }
675 }
675 return result;
676 return result;
676 }
677 }
677
678
678 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
679 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
679 {
680 {
680 QVariant result;
681 QVariant result;
681 PythonQtObjectPtr p;
682 PythonQtObjectPtr p;
682 PyObject* dict = NULL;
683 PyObject* dict = NULL;
683 if (PyModule_Check(object)) {
684 if (PyModule_Check(object)) {
684 dict = PyModule_GetDict(object);
685 dict = PyModule_GetDict(object);
685 } else if (PyDict_Check(object)) {
686 } else if (PyDict_Check(object)) {
686 dict = object;
687 dict = object;
687 }
688 }
688 if (dict) {
689 if (dict) {
689 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
690 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
690 }
691 }
691 if (p) {
692 if (p) {
692 result = PythonQtConv::PyObjToQVariant(p);
693 result = PythonQtConv::PyObjToQVariant(p);
693 } else {
694 } else {
694 handleError();
695 handleError();
695 }
696 }
696 return result;
697 return result;
697 }
698 }
698
699
699 void PythonQt::evalFile(PyObject* module, const QString& filename)
700 void PythonQt::evalFile(PyObject* module, const QString& filename)
700 {
701 {
701 PythonQtObjectPtr code = parseFile(filename);
702 PythonQtObjectPtr code = parseFile(filename);
702 if (code) {
703 if (code) {
703 evalCode(module, code);
704 evalCode(module, code);
704 } else {
705 } else {
705 handleError();
706 handleError();
706 }
707 }
707 }
708 }
708
709
709 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
710 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
710 {
711 {
711 PythonQtObjectPtr p;
712 PythonQtObjectPtr p;
712 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
713 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
713 if (!p) {
714 if (!p) {
714 handleError();
715 handleError();
715 }
716 }
716 return p;
717 return p;
717 }
718 }
718
719
719 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
720 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
720 {
721 {
721 PythonQtObjectPtr code = parseFile(filename);
722 PythonQtObjectPtr code = parseFile(filename);
722 PythonQtObjectPtr module = _p->createModule(name, code);
723 PythonQtObjectPtr module = _p->createModule(name, code);
723 return module;
724 return module;
724 }
725 }
725
726
726 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
727 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
727 {
728 {
728 PyErr_Clear();
729 PyErr_Clear();
729 QString scriptCode = script;
730 QString scriptCode = script;
730 if (scriptCode.isEmpty()) {
731 if (scriptCode.isEmpty()) {
731 // we always need at least a linefeed
732 // we always need at least a linefeed
732 scriptCode = "\n";
733 scriptCode = "\n";
733 }
734 }
734 PythonQtObjectPtr pycode;
735 PythonQtObjectPtr pycode;
735 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
736 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
736 PythonQtObjectPtr module = _p->createModule(name, pycode);
737 PythonQtObjectPtr module = _p->createModule(name, pycode);
737 return module;
738 return module;
738 }
739 }
739
740
740 PythonQtObjectPtr PythonQt::createUniqueModule()
741 PythonQtObjectPtr PythonQt::createUniqueModule()
741 {
742 {
742 static QString pyQtStr("PythonQt_module");
743 static QString pyQtStr("PythonQt_module");
743 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
744 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
744 return createModuleFromScript(moduleName);
745 return createModuleFromScript(moduleName);
745 }
746 }
746
747
747 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
748 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
748 {
749 {
749 if (PyModule_Check(object)) {
750 if (PyModule_Check(object)) {
750 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
751 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
751 } else if (PyDict_Check(object)) {
752 } else if (PyDict_Check(object)) {
752 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
753 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
753 } else {
754 } else {
754 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
755 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
755 }
756 }
756 }
757 }
757
758
758 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
759 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
759 {
760 {
760 if (PyModule_Check(object)) {
761 if (PyModule_Check(object)) {
761 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
762 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
762 } else if (PyDict_Check(object)) {
763 } else if (PyDict_Check(object)) {
763 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
764 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
764 } else {
765 } else {
765 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
766 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
766 }
767 }
767 }
768 }
768
769
769 void PythonQt::removeVariable(PyObject* object, const QString& name)
770 void PythonQt::removeVariable(PyObject* object, const QString& name)
770 {
771 {
771 if (PyDict_Check(object)) {
772 if (PyDict_Check(object)) {
772 PyDict_DelItemString(object, name.toLatin1().data());
773 PyDict_DelItemString(object, name.toLatin1().data());
773 } else {
774 } else {
774 PyObject_DelAttrString(object, name.toLatin1().data());
775 PyObject_DelAttrString(object, name.toLatin1().data());
775 }
776 }
776 }
777 }
777
778
778 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
779 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
779 {
780 {
780 QVariant result;
781 QVariant result;
781 PythonQtObjectPtr obj = lookupObject(object, objectname);
782 PythonQtObjectPtr obj = lookupObject(object, objectname);
782 if (obj) {
783 if (obj) {
783 result = PythonQtConv::PyObjToQVariant(obj);
784 result = PythonQtConv::PyObjToQVariant(obj);
784 }
785 }
785 return result;
786 return result;
786 }
787 }
787
788
788 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
789 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
789 {
790 {
790 QStringList results;
791 QStringList results;
791
792
792 PythonQtObjectPtr object;
793 PythonQtObjectPtr object;
793 if (objectname.isEmpty()) {
794 if (objectname.isEmpty()) {
794 object = module;
795 object = module;
795 } else {
796 } else {
796 object = lookupObject(module, objectname);
797 object = lookupObject(module, objectname);
797 if (!object && type == CallOverloads) {
798 if (!object && type == CallOverloads) {
798 PyObject* dict = lookupObject(module, "__builtins__");
799 PyObject* dict = lookupObject(module, "__builtins__");
799 if (dict) {
800 if (dict) {
800 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
801 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
801 }
802 }
802 }
803 }
803 }
804 }
804
805
805 if (object) {
806 if (object) {
806 results = introspectObject(object, type);
807 results = introspectObject(object, type);
807 }
808 }
808
809
809 return results;
810 return results;
810 }
811 }
811
812
812 QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
813 QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
813 {
814 {
814 QStringList results;
815 QStringList results;
815
816
816 if (type == CallOverloads) {
817 if (type == CallOverloads) {
817 if (PythonQtSlotFunction_Check(object)) {
818 if (PythonQtSlotFunction_Check(object)) {
818 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object;
819 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object;
819 PythonQtSlotInfo* info = o->m_ml;
820 PythonQtSlotInfo* info = o->m_ml;
820
821
821 while (info) {
822 while (info) {
822 results << info->fullSignature();
823 results << info->fullSignature();
823 info = info->nextInfo();
824 info = info->nextInfo();
824 }
825 }
825 } else if (PythonQtSignalFunction_Check(object)) {
826 } else if (PythonQtSignalFunction_Check(object)) {
826 PythonQtSignalFunctionObject* o = (PythonQtSignalFunctionObject*)object;
827 PythonQtSignalFunctionObject* o = (PythonQtSignalFunctionObject*)object;
827 PythonQtSlotInfo* info = o->m_ml;
828 PythonQtSlotInfo* info = o->m_ml;
828
829
829 while (info) {
830 while (info) {
830 results << info->fullSignature();
831 results << info->fullSignature();
831 info = info->nextInfo();
832 info = info->nextInfo();
832 }
833 }
833 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
834 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
834 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
835 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
835 PythonQtSlotInfo* info = o->classInfo()->constructors();
836 PythonQtSlotInfo* info = o->classInfo()->constructors();
836
837
837 while (info) {
838 while (info) {
838 results << info->fullSignature();
839 results << info->fullSignature();
839 info = info->nextInfo();
840 info = info->nextInfo();
840 }
841 }
841 } else {
842 } else {
842 QString signature = _p->getSignature(object);
843 QString signature = _p->getSignature(object);
843 if (!signature.isEmpty()) {
844 if (!signature.isEmpty()) {
844 results << signature;
845 results << signature;
845 } else {
846 } else {
846 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
847 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
847 if (doc) {
848 if (doc) {
848 results << PyString_AsString(doc);
849 results << PyString_AsString(doc);
849 Py_DECREF(doc);
850 Py_DECREF(doc);
850 }
851 }
851 }
852 }
852 }
853 }
853 } else {
854 } else {
854 PyObject* keys = NULL;
855 PyObject* keys = NULL;
855 bool isDict = false;
856 bool isDict = false;
856 if (PyDict_Check(object)) {
857 if (PyDict_Check(object)) {
857 keys = PyDict_Keys(object);
858 keys = PyDict_Keys(object);
858 isDict = true;
859 isDict = true;
859 } else {
860 } else {
860 keys = PyObject_Dir(object);
861 keys = PyObject_Dir(object);
861 }
862 }
862 if (keys) {
863 if (keys) {
863 int count = PyList_Size(keys);
864 int count = PyList_Size(keys);
864 PyObject* key;
865 PyObject* key;
865 PyObject* value;
866 PyObject* value;
866 QString keystr;
867 QString keystr;
867 for (int i = 0;i<count;i++) {
868 for (int i = 0;i<count;i++) {
868 key = PyList_GetItem(keys,i);
869 key = PyList_GetItem(keys,i);
869 if (isDict) {
870 if (isDict) {
870 value = PyDict_GetItem(object, key);
871 value = PyDict_GetItem(object, key);
871 Py_INCREF(value);
872 Py_INCREF(value);
872 } else {
873 } else {
873 value = PyObject_GetAttr(object, key);
874 value = PyObject_GetAttr(object, key);
874 }
875 }
875 if (!value) continue;
876 if (!value) continue;
876 keystr = PyString_AsString(key);
877 keystr = PyString_AsString(key);
877 static const QString underscoreStr("__tmp");
878 static const QString underscoreStr("__tmp");
878 if (!keystr.startsWith(underscoreStr)) {
879 if (!keystr.startsWith(underscoreStr)) {
879 switch (type) {
880 switch (type) {
880 case Anything:
881 case Anything:
881 results << keystr;
882 results << keystr;
882 break;
883 break;
883 case Class:
884 case Class:
884 if (value->ob_type == &PyClass_Type || value->ob_type == &PyType_Type) {
885 if (value->ob_type == &PyClass_Type || value->ob_type == &PyType_Type) {
885 results << keystr;
886 results << keystr;
886 }
887 }
887 break;
888 break;
888 case Variable:
889 case Variable:
889 if (value->ob_type != &PyClass_Type
890 if (value->ob_type != &PyClass_Type
890 && value->ob_type != &PyCFunction_Type
891 && value->ob_type != &PyCFunction_Type
891 && value->ob_type != &PyFunction_Type
892 && value->ob_type != &PyFunction_Type
892 && value->ob_type != &PyMethod_Type
893 && value->ob_type != &PyMethod_Type
893 && value->ob_type != &PyModule_Type
894 && value->ob_type != &PyModule_Type
894 && value->ob_type != &PyType_Type
895 && value->ob_type != &PyType_Type
895 && value->ob_type != &PythonQtSlotFunction_Type
896 && value->ob_type != &PythonQtSlotFunction_Type
896 ) {
897 ) {
897 results << keystr;
898 results << keystr;
898 }
899 }
899 break;
900 break;
900 case Function:
901 case Function:
901 if (value->ob_type == &PyCFunction_Type ||
902 if (value->ob_type == &PyCFunction_Type ||
902 value->ob_type == &PyFunction_Type ||
903 value->ob_type == &PyFunction_Type ||
903 value->ob_type == &PyMethod_Type ||
904 value->ob_type == &PyMethod_Type ||
904 value->ob_type == &PythonQtSlotFunction_Type
905 value->ob_type == &PythonQtSlotFunction_Type
905 ) {
906 ) {
906 results << keystr;
907 results << keystr;
907 }
908 }
908 break;
909 break;
909 case Module:
910 case Module:
910 if (value->ob_type == &PyModule_Type) {
911 if (value->ob_type == &PyModule_Type) {
911 results << keystr;
912 results << keystr;
912 }
913 }
913 break;
914 break;
914 default:
915 default:
915 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
916 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
916 }
917 }
917 }
918 }
918 Py_DECREF(value);
919 Py_DECREF(value);
919 }
920 }
920 Py_DECREF(keys);
921 Py_DECREF(keys);
921 }
922 }
923 if ((type == Anything) || (type == Variable)) {
924 if (object->ob_type == &PythonQtClassWrapper_Type) {
925 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
926 PythonQtClassInfo* info = o->classInfo();
927 results += info->propertyList();
928 }
929 }
922 }
930 }
923 return results;
931 return results;
924 }
932 }
925
933
926 PyObject* PythonQt::getObjectByType(const QString& typeName)
934 PyObject* PythonQt::getObjectByType(const QString& typeName)
927 {
935 {
928 PythonQtObjectPtr sys;
936 PythonQtObjectPtr sys;
929 sys.setNewRef(PyImport_ImportModule("sys"));
937 sys.setNewRef(PyImport_ImportModule("sys"));
930 PythonQtObjectPtr modules = lookupObject(sys, "modules");
938 PythonQtObjectPtr modules = lookupObject(sys, "modules");
931 Q_ASSERT(PyDict_Check(modules));
939 Q_ASSERT(PyDict_Check(modules));
932
940
933 QStringList tmp = typeName.split(".");
941 QStringList tmp = typeName.split(".");
934 QString simpleTypeName = tmp.takeLast();
942 QString simpleTypeName = tmp.takeLast();
935 QString moduleName = tmp.join(".");
943 QString moduleName = tmp.join(".");
936
944
937 PyObject* object = NULL;
945 PyObject* object = NULL;
938 PyObject* moduleObject = PyDict_GetItemString(modules, moduleName.toLatin1().constData());
946 PyObject* moduleObject = PyDict_GetItemString(modules, moduleName.toLatin1().constData());
939 if (moduleObject) {
947 if (moduleObject) {
940 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
948 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
941 }
949 }
942
950
943 if (!object) {
951 if (!object) {
944 moduleObject = PyDict_GetItemString(modules, "__builtin__");
952 moduleObject = PyDict_GetItemString(modules, "__builtin__");
945 if (moduleObject) {
953 if (moduleObject) {
946 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
954 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
947 }
955 }
948 }
956 }
949
957
950 return object;
958 return object;
951 }
959 }
952
960
953 QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
961 QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
954 {
962 {
955 QStringList results;
963 QStringList results;
956 PyObject* object = getObjectByType(typeName);
964 PyObject* object = getObjectByType(typeName);
957 if (!object) {
965 if (!object) {
958 // the last item may be a member, split it away and try again
966 // the last item may be a member, split it away and try again
959 QStringList tmp = typeName.split(".");
967 QStringList tmp = typeName.split(".");
960 QString memberName = tmp.takeLast();
968 QString memberName = tmp.takeLast();
961 QString typeName = tmp.takeLast();
969 QString typeName;
970 if (tmp.isEmpty()) {
971 typeName = memberName;
972 memberName.clear();
973 } else {
974 typeName = tmp.takeLast();
975 }
962 PyObject* typeObject = getObjectByType(typeName);
976 PyObject* typeObject = getObjectByType(typeName);
963 if (typeObject) {
977 if (typeObject) {
964 object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData());
978 object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData());
965 }
979 }
966 }
980 }
967 if (object) {
981 if (object) {
968 results = introspectObject(object, type);
982 results = introspectObject(object, type);
969 Py_DECREF(object);
983 Py_DECREF(object);
970 }
984 }
971 return results;
985 return results;
972 }
986 }
973
987
974 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
988 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
975 {
989 {
976 PythonQtObjectPtr callable = lookupCallable(object, name);
990 PythonQtObjectPtr callable = lookupCallable(object, name);
977 if (callable) {
991 if (callable) {
978 return call(callable, args);
992 return call(callable, args);
979 } else {
993 } else {
980 return QVariant();
994 return QVariant();
981 }
995 }
982 }
996 }
983
997
984 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
998 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
985 {
999 {
986 QVariant r;
1000 QVariant r;
987 PythonQtObjectPtr result;
1001 PythonQtObjectPtr result;
988 result.setNewRef(callAndReturnPyObject(callable, args));
1002 result.setNewRef(callAndReturnPyObject(callable, args));
989 if (result) {
1003 if (result) {
990 r = PythonQtConv::PyObjToQVariant(result);
1004 r = PythonQtConv::PyObjToQVariant(result);
991 } else {
1005 } else {
992 PythonQt::self()->handleError();
1006 PythonQt::self()->handleError();
993 }
1007 }
994 return r;
1008 return r;
995 }
1009 }
996
1010
997 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
1011 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
998 {
1012 {
999 PyObject* result = NULL;
1013 PyObject* result = NULL;
1000 if (callable) {
1014 if (callable) {
1001 PythonQtObjectPtr pargs;
1015 PythonQtObjectPtr pargs;
1002 int count = args.size();
1016 int count = args.size();
1003 if (count>0) {
1017 if (count>0) {
1004 pargs.setNewRef(PyTuple_New(count));
1018 pargs.setNewRef(PyTuple_New(count));
1005 }
1019 }
1006 bool err = false;
1020 bool err = false;
1007 // transform QVariants to Python
1021 // transform QVariants to Python
1008 for (int i = 0; i < count; i++) {
1022 for (int i = 0; i < count; i++) {
1009 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
1023 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
1010 if (arg) {
1024 if (arg) {
1011 // steals reference, no unref
1025 // steals reference, no unref
1012 PyTuple_SetItem(pargs, i,arg);
1026 PyTuple_SetItem(pargs, i,arg);
1013 } else {
1027 } else {
1014 err = true;
1028 err = true;
1015 break;
1029 break;
1016 }
1030 }
1017 }
1031 }
1018
1032
1019 if (!err) {
1033 if (!err) {
1020 PyErr_Clear();
1034 PyErr_Clear();
1021 result = PyObject_CallObject(callable, pargs);
1035 result = PyObject_CallObject(callable, pargs);
1022 }
1036 }
1023 }
1037 }
1024 return result;
1038 return result;
1025 }
1039 }
1026
1040
1027 void PythonQt::addInstanceDecorators(QObject* o)
1041 void PythonQt::addInstanceDecorators(QObject* o)
1028 {
1042 {
1029 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
1043 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
1030 }
1044 }
1031
1045
1032 void PythonQt::addClassDecorators(QObject* o)
1046 void PythonQt::addClassDecorators(QObject* o)
1033 {
1047 {
1034 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
1048 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
1035 }
1049 }
1036
1050
1037 void PythonQt::addDecorators(QObject* o)
1051 void PythonQt::addDecorators(QObject* o)
1038 {
1052 {
1039 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
1053 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
1040 }
1054 }
1041
1055
1042 void PythonQt::registerQObjectClassNames(const QStringList& names)
1056 void PythonQt::registerQObjectClassNames(const QStringList& names)
1043 {
1057 {
1044 _p->registerQObjectClassNames(names);
1058 _p->registerQObjectClassNames(names);
1045 }
1059 }
1046
1060
1047 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
1061 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
1048 {
1062 {
1049 _p->_importInterface = importInterface;
1063 _p->_importInterface = importInterface;
1050 PythonQtImport::init();
1064 PythonQtImport::init();
1051 }
1065 }
1052
1066
1053 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
1067 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
1054 {
1068 {
1055 _p->_importIgnorePaths = paths;
1069 _p->_importIgnorePaths = paths;
1056 }
1070 }
1057
1071
1058 const QStringList& PythonQt::getImporterIgnorePaths()
1072 const QStringList& PythonQt::getImporterIgnorePaths()
1059 {
1073 {
1060 return _p->_importIgnorePaths;
1074 return _p->_importIgnorePaths;
1061 }
1075 }
1062
1076
1063 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
1077 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
1064 {
1078 {
1065 _p->_cppWrapperFactories.append(factory);
1079 _p->_cppWrapperFactories.append(factory);
1066 }
1080 }
1067
1081
1068 void PythonQt::addWrapperFactory( PythonQtForeignWrapperFactory* factory )
1082 void PythonQt::addWrapperFactory( PythonQtForeignWrapperFactory* factory )
1069 {
1083 {
1070 _p->_foreignWrapperFactories.append(factory);
1084 _p->_foreignWrapperFactories.append(factory);
1071 }
1085 }
1072
1086
1073 //---------------------------------------------------------------------------------------------------
1087 //---------------------------------------------------------------------------------------------------
1074 PythonQtPrivate::PythonQtPrivate()
1088 PythonQtPrivate::PythonQtPrivate()
1075 {
1089 {
1076 _importInterface = NULL;
1090 _importInterface = NULL;
1077 _defaultImporter = new PythonQtQFileImporter;
1091 _defaultImporter = new PythonQtQFileImporter;
1078 _noLongerWrappedCB = NULL;
1092 _noLongerWrappedCB = NULL;
1079 _wrappedCB = NULL;
1093 _wrappedCB = NULL;
1080 _currentClassInfoForClassWrapperCreation = NULL;
1094 _currentClassInfoForClassWrapperCreation = NULL;
1081 _profilingCB = NULL;
1095 _profilingCB = NULL;
1082 }
1096 }
1083
1097
1084 void PythonQtPrivate::setupSharedLibrarySuffixes()
1098 void PythonQtPrivate::setupSharedLibrarySuffixes()
1085 {
1099 {
1086 _sharedLibrarySuffixes.clear();
1100 _sharedLibrarySuffixes.clear();
1087 PythonQtObjectPtr imp;
1101 PythonQtObjectPtr imp;
1088 imp.setNewRef(PyImport_ImportModule("imp"));
1102 imp.setNewRef(PyImport_ImportModule("imp"));
1089 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
1103 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
1090 QVariant result = imp.call("get_suffixes");
1104 QVariant result = imp.call("get_suffixes");
1091 #ifdef __linux
1105 #ifdef __linux
1092 #ifdef _DEBUG
1106 #ifdef _DEBUG
1093 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
1107 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
1094 // This is a workaround, because python does not append the '_d' suffix on Linux
1108 // This is a workaround, because python does not append the '_d' suffix on Linux
1095 // and would always load the release library otherwise.
1109 // and would always load the release library otherwise.
1096 _sharedLibrarySuffixes << "_d.so";
1110 _sharedLibrarySuffixes << "_d.so";
1097 #endif
1111 #endif
1098 #endif
1112 #endif
1099 foreach (QVariant entry, result.toList()) {
1113 foreach (QVariant entry, result.toList()) {
1100 QVariantList suffixEntry = entry.toList();
1114 QVariantList suffixEntry = entry.toList();
1101 if (suffixEntry.count()==3) {
1115 if (suffixEntry.count()==3) {
1102 int code = suffixEntry.at(2).toInt();
1116 int code = suffixEntry.at(2).toInt();
1103 if (code == cExtensionCode) {
1117 if (code == cExtensionCode) {
1104 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
1118 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
1105 }
1119 }
1106 }
1120 }
1107 }
1121 }
1108 }
1122 }
1109
1123
1110 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1124 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1111 {
1125 {
1112 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1126 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1113 _currentClassInfoForClassWrapperCreation = NULL;
1127 _currentClassInfoForClassWrapperCreation = NULL;
1114 return info;
1128 return info;
1115 }
1129 }
1116
1130
1117 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1131 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1118 {
1132 {
1119 o->setParent(this);
1133 o->setParent(this);
1120 int numMethods = o->metaObject()->methodCount();
1134 int numMethods = o->metaObject()->methodCount();
1121 for (int i = 0; i < numMethods; i++) {
1135 for (int i = 0; i < numMethods; i++) {
1122 QMetaMethod m = o->metaObject()->method(i);
1136 QMetaMethod m = o->metaObject()->method(i);
1123 if ((m.methodType() == QMetaMethod::Method ||
1137 if ((m.methodType() == QMetaMethod::Method ||
1124 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1138 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1125 if (qstrncmp(m.signature(), "new_", 4)==0) {
1139 if (qstrncmp(m.signature(), "new_", 4)==0) {
1126 if ((decoTypes & ConstructorDecorator) == 0) continue;
1140 if ((decoTypes & ConstructorDecorator) == 0) continue;
1127 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1141 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1128 if (info->parameters().at(0).pointerCount == 1) {
1142 if (info->parameters().at(0).pointerCount == 1) {
1129 QByteArray signature = m.signature();
1143 QByteArray signature = m.signature();
1130 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1144 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1131 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1145 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1132 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1146 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1133 classInfo->addConstructor(newSlot);
1147 classInfo->addConstructor(newSlot);
1134 }
1148 }
1135 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
1149 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
1136 if ((decoTypes & DestructorDecorator) == 0) continue;
1150 if ((decoTypes & DestructorDecorator) == 0) continue;
1137 QByteArray signature = m.signature();
1151 QByteArray signature = m.signature();
1138 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1152 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1139 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1153 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1140 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1154 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1141 classInfo->setDestructor(newSlot);
1155 classInfo->setDestructor(newSlot);
1142 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
1156 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
1143 if ((decoTypes & StaticDecorator) == 0) continue;
1157 if ((decoTypes & StaticDecorator) == 0) continue;
1144 QByteArray signature = m.signature();
1158 QByteArray signature = m.signature();
1145 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
1159 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
1146 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1160 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1147 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1161 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1148 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1162 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1149 classInfo->addDecoratorSlot(newSlot);
1163 classInfo->addDecoratorSlot(newSlot);
1150 } else {
1164 } else {
1151 if ((decoTypes & InstanceDecorator) == 0) continue;
1165 if ((decoTypes & InstanceDecorator) == 0) continue;
1152 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1166 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1153 if (info->parameters().count()>1) {
1167 if (info->parameters().count()>1) {
1154 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1168 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1155 if (p.pointerCount==1) {
1169 if (p.pointerCount==1) {
1156 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1170 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1157 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1171 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1158 classInfo->addDecoratorSlot(newSlot);
1172 classInfo->addDecoratorSlot(newSlot);
1159 }
1173 }
1160 }
1174 }
1161 }
1175 }
1162 }
1176 }
1163 }
1177 }
1164 }
1178 }
1165
1179
1166 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1180 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1167 {
1181 {
1168 foreach(QString name, names) {
1182 foreach(QString name, names) {
1169 _knownQObjectClassNames.insert(name.toLatin1(), true);
1183 _knownQObjectClassNames.insert(name.toLatin1(), true);
1170 }
1184 }
1171 }
1185 }
1172
1186
1173 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1187 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1174 {
1188 {
1175 _signalReceivers.remove(obj);
1189 _signalReceivers.remove(obj);
1176 }
1190 }
1177
1191
1178 bool PythonQt::handleError()
1192 bool PythonQt::handleError()
1179 {
1193 {
1180 bool flag = false;
1194 bool flag = false;
1181 if (PyErr_Occurred()) {
1195 if (PyErr_Occurred()) {
1182
1196
1183 // currently we just print the error and the stderr handler parses the errors
1197 // currently we just print the error and the stderr handler parses the errors
1184 PyErr_Print();
1198 PyErr_Print();
1185
1199
1186 /*
1200 /*
1187 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1201 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1188 PyObject *ptype;
1202 PyObject *ptype;
1189 PyObject *pvalue;
1203 PyObject *pvalue;
1190 PyObject *ptraceback;
1204 PyObject *ptraceback;
1191 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1205 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1192
1206
1193 Py_XDECREF(ptype);
1207 Py_XDECREF(ptype);
1194 Py_XDECREF(pvalue);
1208 Py_XDECREF(pvalue);
1195 Py_XDECREF(ptraceback);
1209 Py_XDECREF(ptraceback);
1196 */
1210 */
1197 PyErr_Clear();
1211 PyErr_Clear();
1198 flag = true;
1212 flag = true;
1199 }
1213 }
1200 return flag;
1214 return flag;
1201 }
1215 }
1202
1216
1203 void PythonQt::addSysPath(const QString& path)
1217 void PythonQt::addSysPath(const QString& path)
1204 {
1218 {
1205 PythonQtObjectPtr sys;
1219 PythonQtObjectPtr sys;
1206 sys.setNewRef(PyImport_ImportModule("sys"));
1220 sys.setNewRef(PyImport_ImportModule("sys"));
1207 PythonQtObjectPtr obj = lookupObject(sys, "path");
1221 PythonQtObjectPtr obj = lookupObject(sys, "path");
1208 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1222 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1209 }
1223 }
1210
1224
1211 void PythonQt::overwriteSysPath(const QStringList& paths)
1225 void PythonQt::overwriteSysPath(const QStringList& paths)
1212 {
1226 {
1213 PythonQtObjectPtr sys;
1227 PythonQtObjectPtr sys;
1214 sys.setNewRef(PyImport_ImportModule("sys"));
1228 sys.setNewRef(PyImport_ImportModule("sys"));
1215 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1229 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1216 }
1230 }
1217
1231
1218 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1232 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1219 {
1233 {
1220 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1234 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1221 }
1235 }
1222
1236
1223 void PythonQt::stdOutRedirectCB(const QString& str)
1237 void PythonQt::stdOutRedirectCB(const QString& str)
1224 {
1238 {
1225 if (!PythonQt::self()) {
1239 if (!PythonQt::self()) {
1226 std::cout << str.toLatin1().data() << std::endl;
1240 std::cout << str.toLatin1().data() << std::endl;
1227 return;
1241 return;
1228 }
1242 }
1229 emit PythonQt::self()->pythonStdOut(str);
1243 emit PythonQt::self()->pythonStdOut(str);
1230 }
1244 }
1231
1245
1232 void PythonQt::stdErrRedirectCB(const QString& str)
1246 void PythonQt::stdErrRedirectCB(const QString& str)
1233 {
1247 {
1234 if (!PythonQt::self()) {
1248 if (!PythonQt::self()) {
1235 std::cerr << str.toLatin1().data() << std::endl;
1249 std::cerr << str.toLatin1().data() << std::endl;
1236 return;
1250 return;
1237 }
1251 }
1238 emit PythonQt::self()->pythonStdErr(str);
1252 emit PythonQt::self()->pythonStdErr(str);
1239 }
1253 }
1240
1254
1241 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1255 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1242 {
1256 {
1243 _p->_wrappedCB = cb;
1257 _p->_wrappedCB = cb;
1244 }
1258 }
1245
1259
1246 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1260 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1247 {
1261 {
1248 _p->_noLongerWrappedCB = cb;
1262 _p->_noLongerWrappedCB = cb;
1249 }
1263 }
1250
1264
1251 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1265 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1252 {
1266 {
1253 _p->_profilingCB = cb;
1267 _p->_profilingCB = cb;
1254 }
1268 }
1255
1269
1256
1270
1257 static PyMethodDef PythonQtMethods[] = {
1271 static PyMethodDef PythonQtMethods[] = {
1258 {NULL, NULL, 0, NULL}
1272 {NULL, NULL, 0, NULL}
1259 };
1273 };
1260
1274
1261 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1275 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1262 {
1276 {
1263 QByteArray name = "PythonQt";
1277 QByteArray name = "PythonQt";
1264 if (!pythonQtModuleName.isEmpty()) {
1278 if (!pythonQtModuleName.isEmpty()) {
1265 name = pythonQtModuleName;
1279 name = pythonQtModuleName;
1266 }
1280 }
1267 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1281 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1268 _p->_pythonQtModuleName = name;
1282 _p->_pythonQtModuleName = name;
1269
1283
1270 if (redirectStdOut) {
1284 if (redirectStdOut) {
1271 PythonQtObjectPtr sys;
1285 PythonQtObjectPtr sys;
1272 PythonQtObjectPtr out;
1286 PythonQtObjectPtr out;
1273 PythonQtObjectPtr err;
1287 PythonQtObjectPtr err;
1274 sys.setNewRef(PyImport_ImportModule("sys"));
1288 sys.setNewRef(PyImport_ImportModule("sys"));
1275 // create a redirection object for stdout and stderr
1289 // create a redirection object for stdout and stderr
1276 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1290 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1277 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1291 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1278 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1292 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1279 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1293 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1280 // replace the built in file objects with our own objects
1294 // replace the built in file objects with our own objects
1281 PyModule_AddObject(sys, "stdout", out);
1295 PyModule_AddObject(sys, "stdout", out);
1282 PyModule_AddObject(sys, "stderr", err);
1296 PyModule_AddObject(sys, "stderr", err);
1283 }
1297 }
1284 }
1298 }
1285
1299
1286 QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString& name)
1300 QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString& name)
1287 {
1301 {
1288 QStringList tmp = name.split(".");
1302 QStringList tmp = name.split(".");
1289 QString methodName = tmp.takeLast();
1303 QString methodName = tmp.takeLast();
1290 QString variableName = tmp.join(".");
1304 QString variableName = tmp.join(".");
1291 // TODO: the variableName may be a type name, this needs to be handled differently,
1305 // TODO: the variableName may be a type name, this needs to be handled differently,
1292 // because it is not necessarily known in the module context
1306 // because it is not necessarily known in the module context
1293 PythonQtObjectPtr variableObject = lookupObject(module, variableName);
1307 PythonQtObjectPtr variableObject = lookupObject(module, variableName);
1294 if (variableObject.isNull()) {
1308 if (variableObject.isNull()) {
1295 return "";
1309 return "";
1296 }
1310 }
1297
1311
1298 return getReturnTypeOfWrappedMethodHelper(variableObject, methodName, name);
1312 return getReturnTypeOfWrappedMethodHelper(variableObject, methodName, name);
1299 }
1313 }
1300
1314
1301 QString PythonQt::getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName)
1315 QString PythonQt::getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName)
1302 {
1316 {
1303 PythonQtObjectPtr typeObject = getObjectByType(typeName);
1317 PythonQtObjectPtr typeObject = getObjectByType(typeName);
1304 if (typeObject.isNull()) {
1318 if (typeObject.isNull()) {
1305 return "";
1319 return "";
1306 }
1320 }
1307 return getReturnTypeOfWrappedMethodHelper(typeObject, methodName, typeName + "." + methodName);
1321 return getReturnTypeOfWrappedMethodHelper(typeObject, methodName, typeName + "." + methodName);
1308 }
1322 }
1309
1323
1310 QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context)
1324 QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context)
1311 {
1325 {
1312 PythonQtObjectPtr methodObject;
1326 PythonQtObjectPtr methodObject;
1313 if (PyDict_Check(variableObject)) {
1327 if (PyDict_Check(variableObject)) {
1314 methodObject = PyDict_GetItemString(variableObject, methodName.toLatin1().constData());
1328 methodObject = PyDict_GetItemString(variableObject, methodName.toLatin1().constData());
1315 } else {
1329 } else {
1316 methodObject.setNewRef(PyObject_GetAttrString(variableObject, methodName.toLatin1().constData()));
1330 methodObject.setNewRef(PyObject_GetAttrString(variableObject, methodName.toLatin1().constData()));
1317 }
1331 }
1318 if (methodObject.isNull()) {
1332 if (methodObject.isNull()) {
1319 return "";
1333 return "";
1320 }
1334 }
1321
1335
1322 QString type;
1336 QString type;
1323
1337
1324 if (methodObject->ob_type == &PyClass_Type || methodObject->ob_type == &PyType_Type) {
1338 if (methodObject->ob_type == &PyClass_Type || methodObject->ob_type == &PyType_Type) {
1325 // the methodObject is not a method, but the name of a type/class. This means
1339 // the methodObject is not a method, but the name of a type/class. This means
1326 // a constructor is called. Return the context.
1340 // a constructor is called. Return the context.
1327 type = context;
1341 type = context;
1328 } else if (methodObject->ob_type == &PythonQtSlotFunction_Type) {
1342 } else if (methodObject->ob_type == &PythonQtSlotFunction_Type) {
1329 QString className;
1343 QString className;
1330
1344
1331 if (PyObject_TypeCheck(variableObject, &PythonQtInstanceWrapper_Type)) {
1345 if (PyObject_TypeCheck(variableObject, &PythonQtInstanceWrapper_Type)) {
1332 // the type name of wrapped instance is the class name
1346 // the type name of wrapped instance is the class name
1333 className = variableObject->ob_type->tp_name;
1347 className = variableObject->ob_type->tp_name;
1334 } else {
1348 } else {
1335 PyObject* classNameObject = PyObject_GetAttrString(variableObject, "__name__");
1349 PyObject* classNameObject = PyObject_GetAttrString(variableObject, "__name__");
1336 if (classNameObject) {
1350 if (classNameObject) {
1337 Q_ASSERT(PyString_Check(classNameObject));
1351 Q_ASSERT(PyString_Check(classNameObject));
1338 className = PyString_AsString(classNameObject);
1352 className = PyString_AsString(classNameObject);
1339 Py_DECREF(classNameObject);
1353 Py_DECREF(classNameObject);
1340 }
1354 }
1341 }
1355 }
1342
1356
1343 if (!className.isEmpty()) {
1357 if (!className.isEmpty()) {
1344 PythonQtClassInfo* info = _p->_knownClassInfos.value(className.toLatin1().constData());
1358 PythonQtClassInfo* info = _p->_knownClassInfos.value(className.toLatin1().constData());
1345 if (info) {
1359 if (info) {
1346 PythonQtSlotInfo* slotInfo = info->member(methodName.toLatin1().constData())._slot;
1360 PythonQtSlotInfo* slotInfo = info->member(methodName.toLatin1().constData())._slot;
1347 if (slotInfo) {
1361 if (slotInfo) {
1348 if (slotInfo->metaMethod()) {
1362 if (slotInfo->metaMethod()) {
1349 type = slotInfo->metaMethod()->typeName();
1363 type = slotInfo->metaMethod()->typeName();
1350 if (!type.isEmpty()) {
1364 if (!type.isEmpty()) {
1351 QChar c = type.at(type.length()-1);
1365 QChar c = type.at(type.length()-1);
1352 while (c == '*' || c == '&') {
1366 while (c == '*' || c == '&') {
1353 type.truncate(type.length()-1);
1367 type.truncate(type.length()-1);
1354 if (!type.isEmpty()) {
1368 if (!type.isEmpty()) {
1355 c = type.at(type.length()-1);
1369 c = type.at(type.length()-1);
1356 } else {
1370 } else {
1357 break;
1371 break;
1358 }
1372 }
1359 }
1373 }
1360 // split away template arguments
1374 // split away template arguments
1361 type = type.split("<").first();
1375 type = type.split("<").first();
1362 // split away const
1376 // split away const
1363 type = type.split(" ").last().trimmed();
1377 type = type.split(" ").last().trimmed();
1364
1378
1365 // if the type is a known class info, then create the full type name, i.e. include the
1379 // if the type is a known class info, then create the full type name, i.e. include the
1366 // module name. For example, the slot may return a QDate, then this looks up the
1380 // module name. For example, the slot may return a QDate, then this looks up the
1367 // name _PythonQt.QtCore.QDate.
1381 // name _PythonQt.QtCore.QDate.
1368 PythonQtClassInfo* typeInfo = _p->_knownClassInfos.value(type.toLatin1().constData());
1382 PythonQtClassInfo* typeInfo = _p->_knownClassInfos.value(type.toLatin1().constData());
1369 if (typeInfo && typeInfo->pythonQtClassWrapper()) {
1383 if (typeInfo && typeInfo->pythonQtClassWrapper()) {
1370 PyObject* s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__module__");
1384 PyObject* s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__module__");
1371 Q_ASSERT(PyString_Check(s));
1385 Q_ASSERT(PyString_Check(s));
1372 type = QString(PyString_AsString(s)) + "." + type;
1386 type = QString(PyString_AsString(s)) + "." + type;
1373 Py_DECREF(s);
1387 Py_DECREF(s);
1374 s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__name__");
1388 s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__name__");
1375 Q_ASSERT(PyString_Check(s));
1389 Q_ASSERT(PyString_Check(s));
1376 Py_DECREF(s);
1390 Py_DECREF(s);
1377 }
1391 }
1378 }
1392 }
1379 }
1393 }
1380 }
1394 }
1381 }
1395 }
1382 }
1396 }
1383 }
1397 }
1384 return type;
1398 return type;
1385 }
1399 }
1386
1400
1387 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1401 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1388 {
1402 {
1389 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1403 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1390 }
1404 }
1391
1405
1392
1406
1393 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1407 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1394 {
1408 {
1395 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1409 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1396 if (!info) {
1410 if (!info) {
1397 info = new PythonQtClassInfo();
1411 info = new PythonQtClassInfo();
1398 info->setupCPPObject(typeName);
1412 info->setupCPPObject(typeName);
1399 _knownClassInfos.insert(typeName, info);
1413 _knownClassInfos.insert(typeName, info);
1400 }
1414 }
1401 return info;
1415 return info;
1402 }
1416 }
1403
1417
1404 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1418 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1405 {
1419 {
1406 _p->addPolymorphicHandler(typeName, cb);
1420 _p->addPolymorphicHandler(typeName, cb);
1407 }
1421 }
1408
1422
1409 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1423 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1410 {
1424 {
1411 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1425 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1412 info->addPolymorphicHandler(cb);
1426 info->addPolymorphicHandler(cb);
1413 }
1427 }
1414
1428
1415 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1429 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1416 {
1430 {
1417 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1431 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1418 }
1432 }
1419
1433
1420 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1434 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1421 {
1435 {
1422 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1436 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1423 if (info) {
1437 if (info) {
1424 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1438 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1425 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1439 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1426 return true;
1440 return true;
1427 } else {
1441 } else {
1428 return false;
1442 return false;
1429 }
1443 }
1430 }
1444 }
1431
1445
1432 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1446 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1433 {
1447 {
1434 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1448 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1435 if (!info->pythonQtClassWrapper()) {
1449 if (!info->pythonQtClassWrapper()) {
1436 info->setTypeSlots(typeSlots);
1450 info->setTypeSlots(typeSlots);
1437 info->setupCPPObject(typeName);
1451 info->setupCPPObject(typeName);
1438 createPythonQtClassWrapper(info, package, module);
1452 createPythonQtClassWrapper(info, package, module);
1439 }
1453 }
1440 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1454 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1441 addParentClass(typeName, parentTypeName, 0);
1455 addParentClass(typeName, parentTypeName, 0);
1442 }
1456 }
1443 if (wrapperCreator) {
1457 if (wrapperCreator) {
1444 info->setDecoratorProvider(wrapperCreator);
1458 info->setDecoratorProvider(wrapperCreator);
1445 }
1459 }
1446 if (shell) {
1460 if (shell) {
1447 info->setShellSetInstanceWrapperCB(shell);
1461 info->setShellSetInstanceWrapperCB(shell);
1448 }
1462 }
1449 }
1463 }
1450
1464
1451 PyObject* PythonQtPrivate::packageByName(const char* name)
1465 PyObject* PythonQtPrivate::packageByName(const char* name)
1452 {
1466 {
1453 if (name==NULL || name[0]==0) {
1467 if (name==NULL || name[0]==0) {
1454 name = "private";
1468 name = "private";
1455 }
1469 }
1456 PyObject* v = _packages.value(name);
1470 PyObject* v = _packages.value(name);
1457 if (!v) {
1471 if (!v) {
1458 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1472 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1459 _packages.insert(name, v);
1473 _packages.insert(name, v);
1460 // AddObject steals the reference, so increment it!
1474 // AddObject steals the reference, so increment it!
1461 Py_INCREF(v);
1475 Py_INCREF(v);
1462 PyModule_AddObject(_pythonQtModule, name, v);
1476 PyModule_AddObject(_pythonQtModule, name, v);
1463 }
1477 }
1464 return v;
1478 return v;
1465 }
1479 }
1466
1480
1467 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1481 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1468 {
1482 {
1469 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1483 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1470 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1484 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1471 PythonQt::self()->handleError();
1485 PythonQt::self()->handleError();
1472 }
1486 }
1473
1487
1474 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1488 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1475 {
1489 {
1476 if (_p->_initFlags & ExternalHelp) {
1490 if (_p->_initFlags & ExternalHelp) {
1477 emit pythonHelpRequest(QByteArray(info->className()));
1491 emit pythonHelpRequest(QByteArray(info->className()));
1478 return Py_BuildValue("");
1492 return Py_BuildValue("");
1479 } else {
1493 } else {
1480 return PyString_FromString(info->help().toLatin1().data());
1494 return PyString_FromString(info->help().toLatin1().data());
1481 }
1495 }
1482 }
1496 }
1483
1497
1484 void PythonQt::clearNotFoundCachedMembers()
1498 void PythonQt::clearNotFoundCachedMembers()
1485 {
1499 {
1486 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1500 foreach(PythonQtClassInfo* info, _p->_knownClassInfos) {
1487 info->clearNotFoundCachedMembers();
1501 info->clearNotFoundCachedMembers();
1488 }
1502 }
1489 }
1503 }
1490
1504
1491 void PythonQt::removeWrapperFactory( PythonQtCppWrapperFactory* factory )
1505 void PythonQt::removeWrapperFactory( PythonQtCppWrapperFactory* factory )
1492 {
1506 {
1493 _p->_cppWrapperFactories.removeAll(factory);
1507 _p->_cppWrapperFactories.removeAll(factory);
1494 }
1508 }
1495
1509
1496 void PythonQt::removeWrapperFactory( PythonQtForeignWrapperFactory* factory )
1510 void PythonQt::removeWrapperFactory( PythonQtForeignWrapperFactory* factory )
1497 {
1511 {
1498 _p->_foreignWrapperFactories.removeAll(factory);
1512 _p->_foreignWrapperFactories.removeAll(factory);
1499 }
1513 }
1500
1514
1501 void PythonQtPrivate::removeWrapperPointer(void* obj)
1515 void PythonQtPrivate::removeWrapperPointer(void* obj)
1502 {
1516 {
1503 _wrappedObjects.remove(obj);
1517 _wrappedObjects.remove(obj);
1504 }
1518 }
1505
1519
1506 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1520 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1507 {
1521 {
1508 _wrappedObjects.insert(obj, wrapper);
1522 _wrappedObjects.insert(obj, wrapper);
1509 }
1523 }
1510
1524
1511 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1525 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1512 {
1526 {
1513 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1527 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1514 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1528 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1515 // this is a wrapper whose QObject was already removed due to destruction
1529 // this is a wrapper whose QObject was already removed due to destruction
1516 // so the obj pointer has to be a new QObject with the same address...
1530 // so the obj pointer has to be a new QObject with the same address...
1517 // we remove the old one and set the copy to NULL
1531 // we remove the old one and set the copy to NULL
1518 wrap->_objPointerCopy = NULL;
1532 wrap->_objPointerCopy = NULL;
1519 removeWrapperPointer(obj);
1533 removeWrapperPointer(obj);
1520 wrap = NULL;
1534 wrap = NULL;
1521 }
1535 }
1522 return wrap;
1536 return wrap;
1523 }
1537 }
1524
1538
1525 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1539 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1526 {
1540 {
1527 PythonQtObjectPtr result;
1541 PythonQtObjectPtr result;
1528 if (pycode) {
1542 if (pycode) {
1529 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1543 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1530 } else {
1544 } else {
1531 PythonQt::self()->handleError();
1545 PythonQt::self()->handleError();
1532 }
1546 }
1533 return result;
1547 return result;
1534 }
1548 }
1535
1549
1536 void* PythonQtPrivate::unwrapForeignWrapper( const QByteArray& classname, PyObject* obj )
1550 void* PythonQtPrivate::unwrapForeignWrapper( const QByteArray& classname, PyObject* obj )
1537 {
1551 {
1538 void* foreignObject = NULL;
1552 void* foreignObject = NULL;
1539 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
1553 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
1540 foreignObject = _foreignWrapperFactories.at(i)->unwrap(classname, obj);
1554 foreignObject = _foreignWrapperFactories.at(i)->unwrap(classname, obj);
1541 if (foreignObject) {
1555 if (foreignObject) {
1542 return foreignObject;
1556 return foreignObject;
1543 }
1557 }
1544 }
1558 }
1545 return NULL;
1559 return NULL;
1546 }
1560 }
1547
1561
1548 bool PythonQtPrivate::isMethodDescriptor(PyObject* object) const
1562 bool PythonQtPrivate::isMethodDescriptor(PyObject* object) const
1549 {
1563 {
1550 // This implementation is the same as in inspect.ismethoddescriptor(), inspect.py.
1564 // This implementation is the same as in inspect.ismethoddescriptor(), inspect.py.
1551 if (PyObject_HasAttrString(object, "__get__") &&
1565 if (PyObject_HasAttrString(object, "__get__") &&
1552 !PyObject_HasAttrString(object, "__set__") &&
1566 !PyObject_HasAttrString(object, "__set__") &&
1553 !PyMethod_Check(object) &&
1567 !PyMethod_Check(object) &&
1554 !PyFunction_Check(object) &&
1568 !PyFunction_Check(object) &&
1555 !PyClass_Check(object)) {
1569 !PyClass_Check(object)) {
1556 return true;
1570 return true;
1557 }
1571 }
1558 return false;
1572 return false;
1559 }
1573 }
1560
1574
1561 QString PythonQtPrivate::getSignature(PyObject* object)
1575 QString PythonQtPrivate::getSignature(PyObject* object)
1562 {
1576 {
1563 QString signature;
1577 QString signature;
1564
1578
1565 if (object) {
1579 if (object) {
1566 PyMethodObject* method = NULL;
1580 PyMethodObject* method = NULL;
1567 PyFunctionObject* func = NULL;
1581 PyFunctionObject* func = NULL;
1568
1582
1569 bool decrefMethod = false;
1583 bool decrefMethod = false;
1570
1584
1571 if (object->ob_type == &PyClass_Type || object->ob_type == &PyType_Type) {
1585 if (object->ob_type == &PyClass_Type || object->ob_type == &PyType_Type) {
1572 method = (PyMethodObject*)PyObject_GetAttrString(object, "__init__");
1586 method = (PyMethodObject*)PyObject_GetAttrString(object, "__init__");
1573 decrefMethod = true;
1587 decrefMethod = true;
1574 } else if (object->ob_type == &PyFunction_Type) {
1588 } else if (object->ob_type == &PyFunction_Type) {
1575 func = (PyFunctionObject*)object;
1589 func = (PyFunctionObject*)object;
1576 } else if (object->ob_type == &PyMethod_Type) {
1590 } else if (object->ob_type == &PyMethod_Type) {
1577 method = (PyMethodObject*)object;
1591 method = (PyMethodObject*)object;
1578 }
1592 }
1579 if (method) {
1593 if (method) {
1580 if (PyFunction_Check(method->im_func)) {
1594 if (PyFunction_Check(method->im_func)) {
1581 func = (PyFunctionObject*)method->im_func;
1595 func = (PyFunctionObject*)method->im_func;
1582 } else if (isMethodDescriptor((PyObject*)method)) {
1596 } else if (isMethodDescriptor((PyObject*)method)) {
1583 QString docstr;
1597 QString docstr;
1584 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
1598 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
1585 if (doc) {
1599 if (doc) {
1586 docstr = PyString_AsString(doc);
1600 docstr = PyString_AsString(doc);
1587 Py_DECREF(doc);
1601 Py_DECREF(doc);
1588 }
1602 }
1589
1603
1590 PyObject* s = PyObject_GetAttrString(object, "__name__");
1604 PyObject* s = PyObject_GetAttrString(object, "__name__");
1591 if (s) {
1605 if (s) {
1592 Q_ASSERT(PyString_Check(s));
1606 Q_ASSERT(PyString_Check(s));
1593 signature = PyString_AsString(s);
1607 signature = PyString_AsString(s);
1594 if (docstr.startsWith(signature + "(")) {
1608 if (docstr.startsWith(signature + "(")) {
1595 signature = docstr;
1609 signature = docstr;
1596 } else {
1610 } else {
1597 signature += "(...)";
1611 signature += "(...)";
1598 if (!docstr.isEmpty()) {
1612 if (!docstr.isEmpty()) {
1599 signature += "\n\n" + docstr;
1613 signature += "\n\n" + docstr;
1600 }
1614 }
1601 }
1615 }
1602 Py_DECREF(s);
1616 Py_DECREF(s);
1603 }
1617 }
1604 }
1618 }
1605 }
1619 }
1606
1620
1607 if (func) {
1621 if (func) {
1608 QString funcName;
1622 QString funcName;
1609 PyObject* s = PyObject_GetAttrString((PyObject*)func, "__name__");
1623 PyObject* s = PyObject_GetAttrString((PyObject*)func, "__name__");
1610 if (s) {
1624 if (s) {
1611 Q_ASSERT(PyString_Check(s));
1625 Q_ASSERT(PyString_Check(s));
1612 funcName = PyString_AsString(s);
1626 funcName = PyString_AsString(s);
1613 Py_DECREF(s);
1627 Py_DECREF(s);
1614 }
1628 }
1615 if (method && funcName == "__init__") {
1629 if (method && funcName == "__init__") {
1616 PyObject* s = PyObject_GetAttrString(object, "__name__");
1630 PyObject* s = PyObject_GetAttrString(object, "__name__");
1617 if (s) {
1631 if (s) {
1618 Q_ASSERT(PyString_Check(s));
1632 Q_ASSERT(PyString_Check(s));
1619 funcName = PyString_AsString(s);
1633 funcName = PyString_AsString(s);
1620 Py_DECREF(s);
1634 Py_DECREF(s);
1621 }
1635 }
1622 }
1636 }
1623
1637
1624 QStringList arguments;
1638 QStringList arguments;
1625 QStringList defaults;
1639 QStringList defaults;
1626 QString varargs;
1640 QString varargs;
1627 QString varkeywords;
1641 QString varkeywords;
1628 // NOTE: This implementation is based on function getargs() in inspect.py.
1642 // NOTE: This implementation is based on function getargs() in inspect.py.
1629 // inspect.getargs() can handle anonymous (tuple) arguments, while this code does not.
1643 // inspect.getargs() can handle anonymous (tuple) arguments, while this code does not.
1630 // It can be implemented, but it may be rarely needed and not necessary.
1644 // It can be implemented, but it may be rarely needed and not necessary.
1631 PyCodeObject* code = (PyCodeObject*)func->func_code;
1645 PyCodeObject* code = (PyCodeObject*)func->func_code;
1632 if (code->co_varnames) {
1646 if (code->co_varnames) {
1633 int nargs = code->co_argcount;
1647 int nargs = code->co_argcount;
1634 Q_ASSERT(PyTuple_Check(code->co_varnames));
1648 Q_ASSERT(PyTuple_Check(code->co_varnames));
1635 for (int i=0; i<nargs; i++) {
1649 for (int i=0; i<nargs; i++) {
1636 PyObject* name = PyTuple_GetItem(code->co_varnames, i);
1650 PyObject* name = PyTuple_GetItem(code->co_varnames, i);
1637 Q_ASSERT(PyString_Check(name));
1651 Q_ASSERT(PyString_Check(name));
1638 arguments << PyString_AsString(name);
1652 arguments << PyString_AsString(name);
1639 }
1653 }
1640 if (code->co_flags & CO_VARARGS) {
1654 if (code->co_flags & CO_VARARGS) {
1641 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1655 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1642 Q_ASSERT(PyString_Check(s));
1656 Q_ASSERT(PyString_Check(s));
1643 varargs = PyString_AsString(s);
1657 varargs = PyString_AsString(s);
1644 nargs += 1;
1658 nargs += 1;
1645 }
1659 }
1646 if (code->co_flags & CO_VARKEYWORDS) {
1660 if (code->co_flags & CO_VARKEYWORDS) {
1647 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1661 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1648 Q_ASSERT(PyString_Check(s));
1662 Q_ASSERT(PyString_Check(s));
1649 varkeywords = PyString_AsString(s);
1663 varkeywords = PyString_AsString(s);
1650 }
1664 }
1651 }
1665 }
1652
1666
1653 PyObject* defaultsTuple = func->func_defaults;
1667 PyObject* defaultsTuple = func->func_defaults;
1654 if (defaultsTuple) {
1668 if (defaultsTuple) {
1655 Q_ASSERT(PyTuple_Check(defaultsTuple));
1669 Q_ASSERT(PyTuple_Check(defaultsTuple));
1656 for (Py_ssize_t i=0; i<PyTuple_Size(defaultsTuple); i++) {
1670 for (Py_ssize_t i=0; i<PyTuple_Size(defaultsTuple); i++) {
1657 PyObject* d = PyTuple_GetItem(defaultsTuple, i);
1671 PyObject* d = PyTuple_GetItem(defaultsTuple, i);
1658 PyObject* s = PyObject_Repr(d);
1672 PyObject* s = PyObject_Repr(d);
1659 Q_ASSERT(PyString_Check(s));
1673 Q_ASSERT(PyString_Check(s));
1660 defaults << PyString_AsString(s);
1674 defaults << PyString_AsString(s);
1661 Py_DECREF(s);
1675 Py_DECREF(s);
1662 }
1676 }
1663 }
1677 }
1664
1678
1665 int firstdefault = arguments.size() - defaults.size();
1679 int firstdefault = arguments.size() - defaults.size();
1666 for (int i=0; i<arguments.size(); i++) {
1680 for (int i=0; i<arguments.size(); i++) {
1667 if (!signature.isEmpty()) { signature += ", "; }
1681 if (!signature.isEmpty()) { signature += ", "; }
1668 if (!method || i>0 || arguments[i] != "self") {
1682 if (!method || i>0 || arguments[i] != "self") {
1669 signature += arguments[i];
1683 signature += arguments[i];
1670 if (i >= firstdefault) {
1684 if (i >= firstdefault) {
1671 signature += "=" + defaults[i-firstdefault];
1685 signature += "=" + defaults[i-firstdefault];
1672 }
1686 }
1673 }
1687 }
1674 }
1688 }
1675 if (!varargs.isEmpty()) {
1689 if (!varargs.isEmpty()) {
1676 if (!signature.isEmpty()) { signature += ", "; }
1690 if (!signature.isEmpty()) { signature += ", "; }
1677 signature += "*" + varargs;
1691 signature += "*" + varargs;
1678 }
1692 }
1679 if (!varkeywords.isEmpty()) {
1693 if (!varkeywords.isEmpty()) {
1680 if (!signature.isEmpty()) { signature += ", "; }
1694 if (!signature.isEmpty()) { signature += ", "; }
1681 signature += "**" + varkeywords;
1695 signature += "**" + varkeywords;
1682 }
1696 }
1683 signature = funcName + "(" + signature + ")";
1697 signature = funcName + "(" + signature + ")";
1684 }
1698 }
1685
1699
1686 if (method && decrefMethod) {
1700 if (method && decrefMethod) {
1687 Py_DECREF(method);
1701 Py_DECREF(method);
1688 }
1702 }
1689 }
1703 }
1690
1704
1691 return signature;
1705 return signature;
1692 }
1706 }
1707
1708 void PythonQtPrivate::shellClassDeleted( void* shellClass )
1709 {
1710 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(shellClass);
1711 if (wrap && wrap->_wrappedPtr) {
1712 // this is a pure C++ wrapper and the shell has gone, so we need
1713 // to set the _wrappedPtr to NULL on the wrapper
1714 wrap->_wrappedPtr = NULL;
1715 // and then we remove the wrapper, since the wrapped class is gone
1716 _wrappedObjects.remove(shellClass);
1717 }
1718 // if the wrapper is a QObject, we do not handle this here,
1719 // it will be handled by the QPointer<> to the QObject, which becomes NULL
1720 // via the QObject destructor.
1721 } No newline at end of file
@@ -1,711 +1,714
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) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, 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 "PythonQtInstanceWrapper.h"
46 #include "PythonQtInstanceWrapper.h"
47 #include "PythonQtClassWrapper.h"
47 #include "PythonQtClassWrapper.h"
48 #include "PythonQtSlot.h"
48 #include "PythonQtSlot.h"
49 #include "PythonQtObjectPtr.h"
49 #include "PythonQtObjectPtr.h"
50 #include "PythonQtStdIn.h"
50 #include "PythonQtStdIn.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 PythonQtForeignWrapperFactory;
67 class PythonQtForeignWrapperFactory;
68 class PythonQtQFileImporter;
68 class PythonQtQFileImporter;
69
69
70 typedef void PythonQtQObjectWrappedCB(QObject* object);
70 typedef void PythonQtQObjectWrappedCB(QObject* object);
71 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
71 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
72 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name);
72 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name);
73
73
74 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
74 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
75
75
76 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
76 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
77 (reinterpret_cast<T*>(object))->_wrapper = wrapper;
77 (reinterpret_cast<T*>(object))->_wrapper = wrapper;
78 }
78 }
79
79
80 //! returns the offset that needs to be added to upcast an object of type T1 to T2
80 //! returns the offset that needs to be added to upcast an object of type T1 to T2
81 template<class T1, class T2> int PythonQtUpcastingOffset() {
81 template<class T1, class T2> int PythonQtUpcastingOffset() {
82 return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
82 return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
83 - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
83 - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
84 }
84 }
85
85
86 //! callback to create a QObject lazily
86 //! callback to create a QObject lazily
87 typedef QObject* PythonQtQObjectCreatorFunctionCB();
87 typedef QObject* PythonQtQObjectCreatorFunctionCB();
88
88
89 //! helper template to create a derived QObject class
89 //! helper template to create a derived QObject class
90 template<class T> QObject* PythonQtCreateObject() { return new T(); };
90 template<class T> QObject* PythonQtCreateObject() { return new T(); };
91
91
92 //! The main interface to the Python Qt binding, realized as a singleton
92 //! The main interface to the Python Qt binding, realized as a singleton
93 /*!
93 /*!
94 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
94 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
95 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
95 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
96 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
96 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
97 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
97 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
98 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
98 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
99 code in the scope of a dict.
99 code in the scope of a dict.
100 */
100 */
101 class PYTHONQT_EXPORT PythonQt : public QObject {
101 class PYTHONQT_EXPORT PythonQt : public QObject {
102
102
103 Q_OBJECT
103 Q_OBJECT
104
104
105 public:
105 public:
106
106
107 //! flags that can be passed to PythonQt::init()
107 //! flags that can be passed to PythonQt::init()
108 enum InitFlags {
108 enum InitFlags {
109 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
109 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
110 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
110 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
111 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
111 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
112 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
112 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
113 };
113 };
114
114
115 //! flags that tell PythonQt which operators to expect on the registered type
115 //! flags that tell PythonQt which operators to expect on the registered type
116 enum TypeSlots {
116 enum TypeSlots {
117 Type_Add = 1,
117 Type_Add = 1,
118 Type_Subtract = 1 << 1,
118 Type_Subtract = 1 << 1,
119 Type_Multiply = 1 << 2,
119 Type_Multiply = 1 << 2,
120 Type_Divide = 1 << 3,
120 Type_Divide = 1 << 3,
121 Type_Mod = 1 << 4,
121 Type_Mod = 1 << 4,
122 Type_And = 1 << 5,
122 Type_And = 1 << 5,
123 Type_Or = 1 << 6,
123 Type_Or = 1 << 6,
124 Type_Xor = 1 << 7,
124 Type_Xor = 1 << 7,
125 Type_LShift = 1 << 8,
125 Type_LShift = 1 << 8,
126 Type_RShift = 1 << 9,
126 Type_RShift = 1 << 9,
127
127
128 Type_InplaceAdd = 1 << 10,
128 Type_InplaceAdd = 1 << 10,
129 Type_InplaceSubtract = 1 << 11,
129 Type_InplaceSubtract = 1 << 11,
130 Type_InplaceMultiply = 1 << 12,
130 Type_InplaceMultiply = 1 << 12,
131 Type_InplaceDivide = 1 << 13,
131 Type_InplaceDivide = 1 << 13,
132 Type_InplaceMod = 1 << 14,
132 Type_InplaceMod = 1 << 14,
133 Type_InplaceAnd = 1 << 15,
133 Type_InplaceAnd = 1 << 15,
134 Type_InplaceOr = 1 << 16,
134 Type_InplaceOr = 1 << 16,
135 Type_InplaceXor = 1 << 17,
135 Type_InplaceXor = 1 << 17,
136 Type_InplaceLShift = 1 << 18,
136 Type_InplaceLShift = 1 << 18,
137 Type_InplaceRShift = 1 << 19,
137 Type_InplaceRShift = 1 << 19,
138
138
139 // Not yet needed/nicely mappable/generated...
139 // Not yet needed/nicely mappable/generated...
140 //Type_Positive = 1 << 29,
140 //Type_Positive = 1 << 29,
141 //Type_Negative = 1 << 29,
141 //Type_Negative = 1 << 29,
142 //Type_Abs = 1 << 29,
142 //Type_Abs = 1 << 29,
143 //Type_Hash = 1 << 29,
143 //Type_Hash = 1 << 29,
144
144
145 Type_Invert = 1 << 29,
145 Type_Invert = 1 << 29,
146 Type_RichCompare = 1 << 30,
146 Type_RichCompare = 1 << 30,
147 Type_NonZero = 1 << 31,
147 Type_NonZero = 1 << 31,
148
148
149 };
149 };
150
150
151 //! enum for profiling callback
151 //! enum for profiling callback
152 enum ProfilingCallbackState {
152 enum ProfilingCallbackState {
153 Enter = 1,
153 Enter = 1,
154 Leave = 2
154 Leave = 2
155 };
155 };
156
156
157 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
157 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
158 //! they are NULL.
158 //! they are NULL.
159 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
159 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
160
160
161 //---------------------------------------------------------------------------
161 //---------------------------------------------------------------------------
162 //! \name Singleton Initialization
162 //! \name Singleton Initialization
163 //@{
163 //@{
164
164
165 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
165 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
166 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
166 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
167 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
167 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
168 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
168 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
169
169
170 //! cleanup of the singleton
170 //! cleanup of the singleton
171 static void cleanup();
171 static void cleanup();
172
172
173 //! get the singleton instance
173 //! get the singleton instance
174 static PythonQt* self();
174 static PythonQt* self();
175
175
176 //@}
176 //@}
177
177
178 //! defines the object types for introspection
178 //! defines the object types for introspection
179 enum ObjectType {
179 enum ObjectType {
180 Class,
180 Class,
181 Function,
181 Function,
182 Variable,
182 Variable,
183 Module,
183 Module,
184 Anything,
184 Anything,
185 CallOverloads
185 CallOverloads
186 };
186 };
187
187
188
188
189 //---------------------------------------------------------------------------
189 //---------------------------------------------------------------------------
190 //! \name Standard input handling
190 //! \name Standard input handling
191 //@{
191 //@{
192
192
193 //! Overwrite default handling of stdin using a custom callback. It internally backup
193 //! Overwrite default handling of stdin using a custom callback. It internally backup
194 //! the original 'sys.stdin' into 'sys.pythonqt_original_stdin'
194 //! the original 'sys.stdin' into 'sys.pythonqt_original_stdin'
195 void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
195 void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
196
196
197 //! Enable or disable stdin custom callback. It resets 'sys.stdin' using either 'sys.pythonqt_stdin'
197 //! Enable or disable stdin custom callback. It resets 'sys.stdin' using either 'sys.pythonqt_stdin'
198 //! or 'sys.pythonqt_original_stdin'
198 //! or 'sys.pythonqt_original_stdin'
199 void setRedirectStdInCallbackEnabled(bool enabled);
199 void setRedirectStdInCallbackEnabled(bool enabled);
200
200
201 //@}
201 //@}
202
202
203 //---------------------------------------------------------------------------
203 //---------------------------------------------------------------------------
204 //! \name Modules
204 //! \name Modules
205 //@{
205 //@{
206
206
207 //! get the __main__ module of python
207 //! get the __main__ module of python
208 PythonQtObjectPtr getMainModule();
208 PythonQtObjectPtr getMainModule();
209
209
210 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
210 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
211 //! If a module is already imported, this returns the already imported module.
211 //! If a module is already imported, this returns the already imported module.
212 PythonQtObjectPtr importModule(const QString& name);
212 PythonQtObjectPtr importModule(const QString& name);
213
213
214 //! creates the new module \c name and evaluates the given file in the context of that module
214 //! creates the new module \c name and evaluates the given file in the context of that module
215 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
215 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
216 //! to a module later on.
216 //! to a module later on.
217 //! The user needs to make sure that the \c name is unique in the python module dictionary.
217 //! The user needs to make sure that the \c name is unique in the python module dictionary.
218 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
218 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
219
219
220 //! creates the new module \c name and evaluates the given script in the context of that module.
220 //! creates the new module \c name and evaluates the given script in the context of that module.
221 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
221 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
222 //! to a module later on.
222 //! to a module later on.
223 //! The user needs to make sure that the \c name is unique in the python module dictionary.
223 //! The user needs to make sure that the \c name is unique in the python module dictionary.
224 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
224 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
225
225
226 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
226 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
227 //! script code
227 //! script code
228 PythonQtObjectPtr createUniqueModule();
228 PythonQtObjectPtr createUniqueModule();
229
229
230 //@}
230 //@}
231
231
232 //---------------------------------------------------------------------------
232 //---------------------------------------------------------------------------
233 //! \name Importing/Paths
233 //! \name Importing/Paths
234 //@{
234 //@{
235
235
236 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
236 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
237 void overwriteSysPath(const QStringList& paths);
237 void overwriteSysPath(const QStringList& paths);
238
238
239 //! prepend a path to sys.path to allow importing from it
239 //! prepend a path to sys.path to allow importing from it
240 void addSysPath(const QString& path);
240 void addSysPath(const QString& path);
241
241
242 //! sets the __path__ list of a module to the given list (important for local imports)
242 //! sets the __path__ list of a module to the given list (important for local imports)
243 void setModuleImportPath(PyObject* module, const QStringList& paths);
243 void setModuleImportPath(PyObject* module, const QStringList& paths);
244
244
245 //@}
245 //@}
246
246
247 //---------------------------------------------------------------------------
247 //---------------------------------------------------------------------------
248 //! \name Registering Classes
248 //! \name Registering Classes
249 //@{
249 //@{
250
250
251 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
251 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
252 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
252 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
253 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
253 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
254 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
254 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
255
255
256 //! 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
257 //! (ownership of wrapper is passed to PythonQt)
257 //! (ownership of wrapper is passed to PythonQt)
258 /*! 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!
259
259
260 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.
261 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
262 a variant object that contains such a type.
262 a variant object that contains such a type.
263 */
263 */
264 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
264 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
265
265
266 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
266 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
267 //! and it will register the classes when it first sees a pointer to such a derived class
267 //! and it will register the classes when it first sees a pointer to such a derived class
268 void registerQObjectClassNames(const QStringList& names);
268 void registerQObjectClassNames(const QStringList& names);
269
269
270 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
270 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
271 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
271 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
272 //! type is really derived from parentType.
272 //! type is really derived from parentType.
273 //! Returns false if the typeName was not yet registered.
273 //! Returns false if the typeName was not yet registered.
274 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
274 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
275
275
276 //! add a handler for polymorphic downcasting
276 //! add a handler for polymorphic downcasting
277 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
277 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
278
278
279 //@}
279 //@}
280
280
281 //---------------------------------------------------------------------------
281 //---------------------------------------------------------------------------
282 //! \name Script Parsing and Evaluation
282 //! \name Script Parsing and Evaluation
283 //@{
283 //@{
284
284
285 //! parses the given file and returns the python code object, this can then be used to call evalCode()
285 //! parses the given file and returns the python code object, this can then be used to call evalCode()
286 PythonQtObjectPtr parseFile(const QString& filename);
286 PythonQtObjectPtr parseFile(const QString& filename);
287
287
288 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
288 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
289 //! If pycode is NULL, a python error is printed.
289 //! If pycode is NULL, a python error is printed.
290 QVariant evalCode(PyObject* object, PyObject* pycode);
290 QVariant evalCode(PyObject* object, PyObject* pycode);
291
291
292 //! evaluates the given script code and returns the result value
292 //! evaluates the given script code and returns the result value
293 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
293 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
294
294
295 //! evaluates the given script code from file
295 //! evaluates the given script code from file
296 void evalFile(PyObject* object, const QString& filename);
296 void evalFile(PyObject* object, const QString& filename);
297
297
298 //@}
298 //@}
299
299
300 //---------------------------------------------------------------------------
300 //---------------------------------------------------------------------------
301 //! \name Signal Handlers
301 //! \name Signal Handlers
302 //@{
302 //@{
303
303
304 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
304 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
305 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
305 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
306
306
307 //! remove a signal handler from the given \c signal of \c obj
307 //! remove a signal handler from the given \c signal of \c obj
308 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
308 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
309
309
310 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
310 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
311 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
311 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
312
312
313 //! remove a signal handler from the given \c signal of \c obj
313 //! remove a signal handler from the given \c signal of \c obj
314 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
314 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
315
315
316 //@}
316 //@}
317
317
318 //---------------------------------------------------------------------------
318 //---------------------------------------------------------------------------
319 //! \name Variable access
319 //! \name Variable access
320 //@{
320 //@{
321
321
322 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
322 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
323 void addObject(PyObject* object, const QString& name, QObject* qObject);
323 void addObject(PyObject* object, const QString& name, QObject* qObject);
324
324
325 //! add the given variable to the object
325 //! add the given variable to the object
326 void addVariable(PyObject* object, const QString& name, const QVariant& v);
326 void addVariable(PyObject* object, const QString& name, const QVariant& v);
327
327
328 //! remove the given variable
328 //! remove the given variable
329 void removeVariable(PyObject* module, const QString& name);
329 void removeVariable(PyObject* module, const QString& name);
330
330
331 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
331 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
332 QVariant getVariable(PyObject* object, const QString& name);
332 QVariant getVariable(PyObject* object, const QString& name);
333
333
334 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
334 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
335 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
335 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
336 //! read vars etc. in scope of the given \c object
336 //! read vars etc. in scope of the given \c object
337 QStringList introspectObject(PyObject* object, ObjectType type);
337 QStringList introspectObject(PyObject* object, ObjectType type);
338 //! read vars etc. in scope of the type object called \c typename. First the typename
338 //! read vars etc. in scope of the type object called \c typename. First the typename
339 //! of the form module.type is split into module and type. Then the module is looked up
339 //! of the form module.type is split into module and type. Then the module is looked up
340 //! in sys.modules. If the module or type is not found there, then the type is looked up in
340 //! in sys.modules. If the module or type is not found there, then the type is looked up in
341 //! the __builtin__ module.
341 //! the __builtin__ module.
342 QStringList introspectType(const QString& typeName, ObjectType type);
342 QStringList introspectType(const QString& typeName, ObjectType type);
343
343
344 //! returns the found callable object or NULL
344 //! returns the found callable object or NULL
345 //! @return new reference
345 //! @return new reference
346 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
346 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
347
347
348 //! returns the return type of the method of a wrapped c++ object referenced by \c objectname
348 //! returns the return type of the method of a wrapped c++ object referenced by \c objectname
349 QString getReturnTypeOfWrappedMethod(PyObject* module, const QString& objectname);
349 QString getReturnTypeOfWrappedMethod(PyObject* module, const QString& objectname);
350 //! returns the return type of the method \c methodName of a wrapped c++ type referenced by \c typeName
350 //! returns the return type of the method \c methodName of a wrapped c++ type referenced by \c typeName
351 QString getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName);
351 QString getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName);
352 //@}
352 //@}
353
353
354 //---------------------------------------------------------------------------
354 //---------------------------------------------------------------------------
355 //! \name Calling Python Objects
355 //! \name Calling Python Objects
356 //@{
356 //@{
357
357
358 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
358 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
359 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
359 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
360
360
361 //! call the given python object, returns the result converted to a QVariant
361 //! call the given python object, returns the result converted to a QVariant
362 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
362 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
363
363
364 //! call the given python object, returns the result as new PyObject
364 //! call the given python object, returns the result as new PyObject
365 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
365 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
366
366
367 //@}
367 //@}
368
368
369 //---------------------------------------------------------------------------
369 //---------------------------------------------------------------------------
370 //! \name Decorations, Constructors, Wrappers...
370 //! \name Decorations, Constructors, Wrappers...
371 //@{
371 //@{
372
372
373 //! add an object whose slots will be used as decorator slots for
373 //! add an object whose slots will be used as decorator slots for
374 //! other QObjects or CPP classes. The slots need to follow the
374 //! other QObjects or CPP classes. The slots need to follow the
375 //! convention that the first argument is a pointer to the wrapped object.
375 //! convention that the first argument is a pointer to the wrapped object.
376 //! (ownership is passed to PythonQt)
376 //! (ownership is passed to PythonQt)
377 /*!
377 /*!
378 Example:
378 Example:
379
379
380 A slot with the signature
380 A slot with the signature
381
381
382 \code
382 \code
383 bool doSomething(QWidget* w, int a)
383 bool doSomething(QWidget* w, int a)
384 \endcode
384 \endcode
385
385
386 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
386 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
387 that will be called with the concrete instance as first argument.
387 that will be called with the concrete instance as first argument.
388 So in Python you can now e.g. call
388 So in Python you can now e.g. call
389
389
390 \code
390 \code
391 someWidget.doSomething(12)
391 someWidget.doSomething(12)
392 \endcode
392 \endcode
393
393
394 without QWidget really having this method. This allows to easily make normal methods
394 without QWidget really having this method. This allows to easily make normal methods
395 of Qt classes callable by forwarding them with such decorator slots
395 of Qt classes callable by forwarding them with such decorator slots
396 or to make CPP classes (which are not derived from QObject) callable from Python.
396 or to make CPP classes (which are not derived from QObject) callable from Python.
397 */
397 */
398 void addInstanceDecorators(QObject* o);
398 void addInstanceDecorators(QObject* o);
399
399
400 //! add an object whose slots will be used as decorator slots for
400 //! add an object whose slots will be used as decorator slots for
401 //! class objects (ownership is passed to PythonQt)
401 //! class objects (ownership is passed to PythonQt)
402 /*!
402 /*!
403 The slots need to follow the following convention:
403 The slots need to follow the following convention:
404 - SomeClass* new_SomeClass(...)
404 - SomeClass* new_SomeClass(...)
405 - QVariant new_SomeClass(...)
405 - QVariant new_SomeClass(...)
406 - void delete_SomeClass(SomeClass*)
406 - void delete_SomeClass(SomeClass*)
407 - ... static_SomeClass_someName(...)
407 - ... static_SomeClass_someName(...)
408
408
409 This will add:
409 This will add:
410 - a constructor
410 - a constructor
411 - a constructor which generates a QVariant
411 - a constructor which generates a QVariant
412 - a destructor (only useful for CPP objects)
412 - a destructor (only useful for CPP objects)
413 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
413 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
414
414
415 */
415 */
416 void addClassDecorators(QObject* o);
416 void addClassDecorators(QObject* o);
417
417
418 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
418 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
419 void addDecorators(QObject* o);
419 void addDecorators(QObject* o);
420
420
421 //! add the given factory to PythonQt (ownership stays with caller)
421 //! add the given factory to PythonQt (ownership stays with caller)
422 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
422 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
423
423
424 //! add the given factory to PythonQt (ownership stays with caller)
424 //! add the given factory to PythonQt (ownership stays with caller)
425 void addWrapperFactory(PythonQtForeignWrapperFactory* factory);
425 void addWrapperFactory(PythonQtForeignWrapperFactory* factory);
426
426
427 //! remove the wrapper factory
427 //! remove the wrapper factory
428 void removeWrapperFactory(PythonQtCppWrapperFactory* factory);
428 void removeWrapperFactory(PythonQtCppWrapperFactory* factory);
429
429
430 //! remove the wrapper factory
430 //! remove the wrapper factory
431 void removeWrapperFactory(PythonQtForeignWrapperFactory* factory);
431 void removeWrapperFactory(PythonQtForeignWrapperFactory* factory);
432
432
433 //@}
433 //@}
434
434
435 //---------------------------------------------------------------------------
435 //---------------------------------------------------------------------------
436 //! \name Custom Importer
436 //! \name Custom Importer
437 //@{
437 //@{
438
438
439 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
439 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
440 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
440 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
441 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
441 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
442 //! This is not reversible, so even setting setImporter(NULL) afterwards will
442 //! This is not reversible, so even setting setImporter(NULL) afterwards will
443 //! keep the custom PythonQt importer with a QFile default import interface.
443 //! keep the custom PythonQt importer with a QFile default import interface.
444 //! Subsequent python import calls will make use of the passed importInterface
444 //! Subsequent python import calls will make use of the passed importInterface
445 //! which forwards all import calls to the given \c importInterface.
445 //! which forwards all import calls to the given \c importInterface.
446 //! Passing NULL will install a default QFile importer.
446 //! Passing NULL will install a default QFile importer.
447 //! (\c importInterface ownership stays with caller)
447 //! (\c importInterface ownership stays with caller)
448 void setImporter(PythonQtImportFileInterface* importInterface);
448 void setImporter(PythonQtImportFileInterface* importInterface);
449
449
450 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
450 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
451 //! (without calling setImporter or installDefaultImporter at least once, the default python import
451 //! (without calling setImporter or installDefaultImporter at least once, the default python import
452 //! mechanism is in place)
452 //! mechanism is in place)
453 //! the default importer allows to import files from anywhere QFile can read from,
453 //! the default importer allows to import files from anywhere QFile can read from,
454 //! including the Qt resource system using ":". Keep in mind that you need to extend
454 //! including the Qt resource system using ":". Keep in mind that you need to extend
455 //! "sys.path" with ":" to be able to import from the Qt resources.
455 //! "sys.path" with ":" to be able to import from the Qt resources.
456 void installDefaultImporter() { setImporter(NULL); }
456 void installDefaultImporter() { setImporter(NULL); }
457
457
458 //! set paths that the importer should ignore
458 //! set paths that the importer should ignore
459 void setImporterIgnorePaths(const QStringList& paths);
459 void setImporterIgnorePaths(const QStringList& paths);
460
460
461 //! get paths that the importer should ignore
461 //! get paths that the importer should ignore
462 const QStringList& getImporterIgnorePaths();
462 const QStringList& getImporterIgnorePaths();
463
463
464 //! get access to the file importer (if set)
464 //! get access to the file importer (if set)
465 static PythonQtImportFileInterface* importInterface();
465 static PythonQtImportFileInterface* importInterface();
466
466
467 //@}
467 //@}
468
468
469 //---------------------------------------------------------------------------
469 //---------------------------------------------------------------------------
470 //! \name Other Stuff
470 //! \name Other Stuff
471 //@{
471 //@{
472
472
473 //! get access to internal data (should not be used on the public API, but is used by some C functions)
473 //! get access to internal data (should not be used on the public API, but is used by some C functions)
474 static PythonQtPrivate* priv() { return _self->_p; }
474 static PythonQtPrivate* priv() { return _self->_p; }
475
475
476 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
476 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
477 //! The error is currently just output to the python stderr, future version might implement better trace printing
477 //! The error is currently just output to the python stderr, future version might implement better trace printing
478 bool handleError();
478 bool handleError();
479
479
480 //! clear all NotFound entries on all class infos, to ensure that
480 //! clear all NotFound entries on all class infos, to ensure that
481 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
481 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
482 void clearNotFoundCachedMembers();
482 void clearNotFoundCachedMembers();
483
483
484 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
484 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
485 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
485 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
486 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
486 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
487 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
487 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
488
488
489 //! call the callback if it is set
489 //! call the callback if it is set
490 static void qObjectNoLongerWrappedCB(QObject* o);
490 static void qObjectNoLongerWrappedCB(QObject* o);
491
491
492 //! called by internal help methods
492 //! called by internal help methods
493 PyObject* helpCalled(PythonQtClassInfo* info);
493 PyObject* helpCalled(PythonQtClassInfo* info);
494
494
495 //! returns the found object or NULL
495 //! returns the found object or NULL
496 //! @return new reference
496 //! @return new reference
497 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
497 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
498
498
499 //! sets a callback that is called before and after function calls for profiling
499 //! sets a callback that is called before and after function calls for profiling
500 void setProfilingCallback(ProfilingCB* cb);
500 void setProfilingCallback(ProfilingCB* cb);
501
501
502 //@}
502 //@}
503
503
504 signals:
504 signals:
505 //! emitted when python outputs something to stdout (and redirection is turned on)
505 //! emitted when python outputs something to stdout (and redirection is turned on)
506 void pythonStdOut(const QString& str);
506 void pythonStdOut(const QString& str);
507 //! emitted when python outputs something to stderr (and redirection is turned on)
507 //! emitted when python outputs something to stderr (and redirection is turned on)
508 void pythonStdErr(const QString& str);
508 void pythonStdErr(const QString& str);
509
509
510 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
510 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
511 void pythonHelpRequest(const QByteArray& cppClassName);
511 void pythonHelpRequest(const QByteArray& cppClassName);
512
512
513 private:
513 private:
514 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
514 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
515
515
516 QString getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context);
516 QString getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context);
517
517
518 PyObject* getObjectByType(const QString& typeName);
518 PyObject* getObjectByType(const QString& typeName);
519
519
520 //! callback for stdout redirection, emits pythonStdOut signal
520 //! callback for stdout redirection, emits pythonStdOut signal
521 static void stdOutRedirectCB(const QString& str);
521 static void stdOutRedirectCB(const QString& str);
522 //! callback for stderr redirection, emits pythonStdErr signal
522 //! callback for stderr redirection, emits pythonStdErr signal
523 static void stdErrRedirectCB(const QString& str);
523 static void stdErrRedirectCB(const QString& str);
524
524
525 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
525 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
526 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
526 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
527
527
528 PythonQt(int flags, const QByteArray& pythonQtModuleName);
528 PythonQt(int flags, const QByteArray& pythonQtModuleName);
529 ~PythonQt();
529 ~PythonQt();
530
530
531 static PythonQt* _self;
531 static PythonQt* _self;
532 static int _uniqueModuleCount;
532 static int _uniqueModuleCount;
533
533
534 PythonQtPrivate* _p;
534 PythonQtPrivate* _p;
535
535
536 };
536 };
537
537
538 //! internal PythonQt details
538 //! internal PythonQt details
539 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
539 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
540
540
541 Q_OBJECT
541 Q_OBJECT
542
542
543 public:
543 public:
544 PythonQtPrivate();
544 PythonQtPrivate();
545 ~PythonQtPrivate();
545 ~PythonQtPrivate();
546
546
547 enum DecoratorTypes {
547 enum DecoratorTypes {
548 StaticDecorator = 1,
548 StaticDecorator = 1,
549 ConstructorDecorator = 2,
549 ConstructorDecorator = 2,
550 DestructorDecorator = 4,
550 DestructorDecorator = 4,
551 InstanceDecorator = 8,
551 InstanceDecorator = 8,
552 AllDecorators = 0xffff
552 AllDecorators = 0xffff
553 };
553 };
554
554
555 //! get the suffixes that are used for shared libraries
555 //! get the suffixes that are used for shared libraries
556 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
556 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
557
557
558 //! returns if the id is the id for PythonQtObjectPtr
558 //! returns if the id is the id for PythonQtObjectPtr
559 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
559 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
560
560
561 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
561 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
562 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
562 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
563 //! remove the wrapper ptr again
563 //! remove the wrapper ptr again
564 void removeWrapperPointer(void* obj);
564 void removeWrapperPointer(void* obj);
565
565
566 //! called by destructor of shells to allow invalidation of the Python wrapper
567 void shellClassDeleted(void* shellClass);
568
566 //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories
569 //! try to unwrap the given object to a C++ pointer using the foreign wrapper factories
567 void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
570 void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj);
568
571
569 //! add parent class relation
572 //! add parent class relation
570 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
573 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
571
574
572 //! add a handler for polymorphic downcasting
575 //! add a handler for polymorphic downcasting
573 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
576 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
574
577
575 //! lookup existing classinfo and return new if not yet present
578 //! lookup existing classinfo and return new if not yet present
576 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
579 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
577
580
578 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
581 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
579 void removeSignalEmitter(QObject* obj);
582 void removeSignalEmitter(QObject* obj);
580
583
581 //! wrap the given QObject into a Python object (or return existing wrapper!)
584 //! wrap the given QObject into a Python object (or return existing wrapper!)
582 PyObject* wrapQObject(QObject* obj);
585 PyObject* wrapQObject(QObject* obj);
583
586
584 //! 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
587 //! 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
585 PyObject* wrapPtr(void* ptr, const QByteArray& name);
588 PyObject* wrapPtr(void* ptr, const QByteArray& name);
586
589
587 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
590 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
588 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
591 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
589 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
592 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
590 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
593 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
591
594
592 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
595 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
593 //! (ownership of wrapper is passed to PythonQt)
596 //! (ownership of wrapper is passed to PythonQt)
594 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
597 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
595
598
596 This will add a wrapper object that is used to make calls to the given classname \c typeName.
599 This will add a wrapper object that is used to make calls to the given classname \c typeName.
597 All slots that take a pointer to typeName as the first argument will be callable from Python on
600 All slots that take a pointer to typeName as the first argument will be callable from Python on
598 a variant object that contains such a type.
601 a variant object that contains such a type.
599 */
602 */
600 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
603 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
601
604
602 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
605 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
603 //! and it will register the classes when it first sees a pointer to such a derived class
606 //! and it will register the classes when it first sees a pointer to such a derived class
604 void registerQObjectClassNames(const QStringList& names);
607 void registerQObjectClassNames(const QStringList& names);
605
608
606 //! add a decorator object
609 //! add a decorator object
607 void addDecorators(QObject* o, int decoTypes);
610 void addDecorators(QObject* o, int decoTypes);
608
611
609 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
612 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
610 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
613 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
611
614
612 //! create a new instance of the given enum type with given value (returns a new reference)
615 //! create a new instance of the given enum type with given value (returns a new reference)
613 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
616 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
614
617
615 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
618 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
616 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
619 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
617
620
618 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
621 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
619 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
622 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
620
623
621 //! get the class info for a meta object (if available)
624 //! get the class info for a meta object (if available)
622 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
625 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
623
626
624 //! get the class info for a meta object (if available)
627 //! get the class info for a meta object (if available)
625 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
628 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
626
629
627 //! creates the new module from the given pycode
630 //! creates the new module from the given pycode
628 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
631 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
629
632
630 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
633 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
631 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
634 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
632
635
633 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
636 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
634 static PyObject* dummyTuple();
637 static PyObject* dummyTuple();
635
638
636 //! called by virtual overloads when a python return value can not be converted to the required Qt type
639 //! called by virtual overloads when a python return value can not be converted to the required Qt type
637 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
640 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
638
641
639 //! get access to the PythonQt module
642 //! get access to the PythonQt module
640 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
643 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
641
644
642 //! returns the profiling callback, which may be NULL
645 //! returns the profiling callback, which may be NULL
643 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
646 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
644
647
645 //! determines the signature of the given callable object (similar as pydoc)
648 //! determines the signature of the given callable object (similar as pydoc)
646 QString getSignature(PyObject* object);
649 QString getSignature(PyObject* object);
647
650
648 //! returns true if the object is a method descriptor (same as inspect.ismethoddescriptor() in inspect.py)
651 //! returns true if the object is a method descriptor (same as inspect.ismethoddescriptor() in inspect.py)
649 bool isMethodDescriptor(PyObject* object) const;
652 bool isMethodDescriptor(PyObject* object) const;
650
653
651 private:
654 private:
652 //! Setup the shared library suffixes by getting them from the "imp" module.
655 //! Setup the shared library suffixes by getting them from the "imp" module.
653 void setupSharedLibrarySuffixes();
656 void setupSharedLibrarySuffixes();
654
657
655 //! create a new pythonqt class wrapper and place it in the pythonqt module
658 //! create a new pythonqt class wrapper and place it in the pythonqt module
656 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
659 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
657
660
658 //! get/create new package module (the returned object is a borrowed reference)
661 //! get/create new package module (the returned object is a borrowed reference)
659 PyObject* packageByName(const char* name);
662 PyObject* packageByName(const char* name);
660
663
661 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
664 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
662 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
665 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
663
666
664 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
667 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
665 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
668 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
666
669
667 //! stores the meta info of known Qt classes
670 //! stores the meta info of known Qt classes
668 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
671 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
669
672
670 //! names of qobject derived classes that can be casted to qobject savely
673 //! names of qobject derived classes that can be casted to qobject savely
671 QHash<QByteArray, bool> _knownQObjectClassNames;
674 QHash<QByteArray, bool> _knownQObjectClassNames;
672
675
673 //! stores signal receivers for QObjects
676 //! stores signal receivers for QObjects
674 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
677 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
675
678
676 //! the PythonQt python module
679 //! the PythonQt python module
677 PythonQtObjectPtr _pythonQtModule;
680 PythonQtObjectPtr _pythonQtModule;
678
681
679 //! the name of the PythonQt python module
682 //! the name of the PythonQt python module
680 QByteArray _pythonQtModuleName;
683 QByteArray _pythonQtModuleName;
681
684
682 //! the importer interface (if set)
685 //! the importer interface (if set)
683 PythonQtImportFileInterface* _importInterface;
686 PythonQtImportFileInterface* _importInterface;
684
687
685 //! the default importer
688 //! the default importer
686 PythonQtQFileImporter* _defaultImporter;
689 PythonQtQFileImporter* _defaultImporter;
687
690
688 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
691 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
689 PythonQtQObjectWrappedCB* _wrappedCB;
692 PythonQtQObjectWrappedCB* _wrappedCB;
690
693
691 QStringList _importIgnorePaths;
694 QStringList _importIgnorePaths;
692 QStringList _sharedLibrarySuffixes;
695 QStringList _sharedLibrarySuffixes;
693
696
694 //! the cpp object wrapper factories
697 //! the cpp object wrapper factories
695 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
698 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
696
699
697 QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories;
700 QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories;
698
701
699 QHash<QByteArray, PyObject*> _packages;
702 QHash<QByteArray, PyObject*> _packages;
700
703
701 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
704 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
702
705
703 PythonQt::ProfilingCB* _profilingCB;
706 PythonQt::ProfilingCB* _profilingCB;
704
707
705 int _initFlags;
708 int _initFlags;
706 int _PythonQtObjectPtr_metaId;
709 int _PythonQtObjectPtr_metaId;
707
710
708 friend class PythonQt;
711 friend class PythonQt;
709 };
712 };
710
713
711 #endif
714 #endif
@@ -1,894 +1,885
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtClassInfo.h"
42 #include "PythonQtClassInfo.h"
43 #include "PythonQtMethodInfo.h"
43 #include "PythonQtMethodInfo.h"
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include <QMetaMethod>
45 #include <QMetaMethod>
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaEnum>
47 #include <QMetaEnum>
48
48
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
50
50
51 PythonQtClassInfo::PythonQtClassInfo() {
51 PythonQtClassInfo::PythonQtClassInfo() {
52 _meta = NULL;
52 _meta = NULL;
53 _constructors = NULL;
53 _constructors = NULL;
54 _destructor = NULL;
54 _destructor = NULL;
55 _decoratorProvider = NULL;
55 _decoratorProvider = NULL;
56 _decoratorProviderCB = NULL;
56 _decoratorProviderCB = NULL;
57 _pythonQtClassWrapper = NULL;
57 _pythonQtClassWrapper = NULL;
58 _shellSetInstanceWrapperCB = NULL;
58 _shellSetInstanceWrapperCB = NULL;
59 _metaTypeId = -1;
59 _metaTypeId = -1;
60 _typeSlots = 0;
60 _typeSlots = 0;
61 _isQObject = false;
61 _isQObject = false;
62 _enumsCreated = false;
62 _enumsCreated = false;
63 }
63 }
64
64
65 PythonQtClassInfo::~PythonQtClassInfo()
65 PythonQtClassInfo::~PythonQtClassInfo()
66 {
66 {
67 clearCachedMembers();
67 clearCachedMembers();
68
68
69 if (_constructors) {
69 if (_constructors) {
70 _constructors->deleteOverloadsAndThis();
70 _constructors->deleteOverloadsAndThis();
71 }
71 }
72 if (_destructor) {
72 if (_destructor) {
73 _destructor->deleteOverloadsAndThis();
73 _destructor->deleteOverloadsAndThis();
74 }
74 }
75 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
76 info->deleteOverloadsAndThis();
76 info->deleteOverloadsAndThis();
77 }
77 }
78 }
78 }
79
79
80 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
81 {
81 {
82 // _wrappedClassName is already set earlier in the class setup
82 // _wrappedClassName is already set earlier in the class setup
83 _isQObject = true;
83 _isQObject = true;
84 _meta = meta;
84 _meta = meta;
85 }
85 }
86
86
87 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
88 {
88 {
89 _isQObject = false;
89 _isQObject = false;
90 _wrappedClassName = classname;
90 _wrappedClassName = classname;
91 _metaTypeId = QMetaType::type(classname);
91 _metaTypeId = QMetaType::type(classname);
92 }
92 }
93
93
94 void PythonQtClassInfo::clearCachedMembers()
94 void PythonQtClassInfo::clearCachedMembers()
95 {
95 {
96 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
97 while (i.hasNext()) {
97 while (i.hasNext()) {
98 PythonQtMemberInfo member = i.next().value();
98 PythonQtMemberInfo member = i.next().value();
99 if (member._type== PythonQtMemberInfo::Slot || member._type== PythonQtMemberInfo::Signal) {
99 if (member._type== PythonQtMemberInfo::Slot || member._type== PythonQtMemberInfo::Signal) {
100 PythonQtSlotInfo* info = member._slot;
100 PythonQtSlotInfo* info = member._slot;
101 while (info) {
101 while (info) {
102 PythonQtSlotInfo* next = info->nextInfo();
102 PythonQtSlotInfo* next = info->nextInfo();
103 delete info;
103 delete info;
104 info = next;
104 info = next;
105 }
105 }
106 }
106 }
107 }
107 }
108 }
108 }
109
109
110 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
111 {
111 {
112 const char* sigEnd = sigStart;
112 const char* sigEnd = sigStart;
113 char c;
113 char c;
114 do {
114 do {
115 c = *sigEnd++;
115 c = *sigEnd++;
116 } while (c!=someChar && c!=0);
116 } while (c!=someChar && c!=0);
117 return sigEnd-sigStart-1;
117 return sigEnd-sigStart-1;
118 }
118 }
119
119
120 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
121 {
121 {
122 if (!_meta) return false;
122 if (!_meta) return false;
123
123
124 bool found = false;
124 bool found = false;
125 bool nameMapped = false;
125 bool nameMapped = false;
126 const char* attributeName = memberName;
126 const char* attributeName = memberName;
127 // look for properties
127 // look for properties
128 int i = _meta->indexOfProperty(attributeName);
128 int i = _meta->indexOfProperty(attributeName);
129 if (i==-1) {
129 if (i==-1) {
130 // try to map name to objectName
130 // try to map name to objectName
131 if (qstrcmp(attributeName, "name")==0) {
131 if (qstrcmp(attributeName, "name")==0) {
132 attributeName = "objectName";
132 attributeName = "objectName";
133 nameMapped = true;
133 nameMapped = true;
134 i = _meta->indexOfProperty(attributeName);
134 i = _meta->indexOfProperty(attributeName);
135 }
135 }
136 }
136 }
137 if (i!=-1) {
137 if (i!=-1) {
138 PythonQtMemberInfo newInfo(_meta->property(i));
138 PythonQtMemberInfo newInfo(_meta->property(i));
139 _cachedMembers.insert(attributeName, newInfo);
139 _cachedMembers.insert(attributeName, newInfo);
140 if (nameMapped) {
140 if (nameMapped) {
141 _cachedMembers.insert(memberName, newInfo);
141 _cachedMembers.insert(memberName, newInfo);
142 }
142 }
143 #ifdef PYTHONQT_DEBUG
143 #ifdef PYTHONQT_DEBUG
144 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
144 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
145 #endif
145 #endif
146 found = true;
146 found = true;
147 }
147 }
148 return found;
148 return found;
149 }
149 }
150
150
151 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
151 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
152 {
152 {
153 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
153 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
154 foreach(const ParentClassInfo& info, _parentClasses) {
154 foreach(const ParentClassInfo& info, _parentClasses) {
155 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
155 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
156 }
156 }
157 return inputInfo;
157 return inputInfo;
158 }
158 }
159
159
160 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
160 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
161 QObject* decoratorProvider = decorator();
161 QObject* decoratorProvider = decorator();
162 int memberNameLen = static_cast<int>(strlen(memberName));
162 int memberNameLen = static_cast<int>(strlen(memberName));
163 if (decoratorProvider) {
163 if (decoratorProvider) {
164 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
164 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
165 const QMetaObject* meta = decoratorProvider->metaObject();
165 const QMetaObject* meta = decoratorProvider->metaObject();
166 int numMethods = meta->methodCount();
166 int numMethods = meta->methodCount();
167 int startFrom = QObject::staticMetaObject.methodCount();
167 int startFrom = QObject::staticMetaObject.methodCount();
168 for (int i = startFrom; i < numMethods; i++) {
168 for (int i = startFrom; i < numMethods; i++) {
169 QMetaMethod m = meta->method(i);
169 QMetaMethod m = meta->method(i);
170 if ((m.methodType() == QMetaMethod::Method ||
170 if ((m.methodType() == QMetaMethod::Method ||
171 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
171 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
172
172
173 const char* sigStart = m.signature();
173 const char* sigStart = m.signature();
174 bool isClassDeco = false;
174 bool isClassDeco = false;
175 if (qstrncmp(sigStart, "static_", 7)==0) {
175 if (qstrncmp(sigStart, "static_", 7)==0) {
176 // skip the static_classname_ part of the string
176 // skip the static_classname_ part of the string
177 sigStart += 7 + 1 + strlen(className());
177 sigStart += 7 + 1 + strlen(className());
178 isClassDeco = true;
178 isClassDeco = true;
179 } else if (qstrncmp(sigStart, "new_", 4)==0) {
179 } else if (qstrncmp(sigStart, "new_", 4)==0) {
180 isClassDeco = true;
180 isClassDeco = true;
181 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
181 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
182 isClassDeco = true;
182 isClassDeco = true;
183 }
183 }
184 // find the first '('
184 // find the first '('
185 int offset = findCharOffset(sigStart, '(');
185 int offset = findCharOffset(sigStart, '(');
186
186
187 // XXX no checking is currently done if the slots have correct first argument or not...
187 // XXX no checking is currently done if the slots have correct first argument or not...
188
188
189 // check if same length and same name
189 // check if same length and same name
190 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
190 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
191 found = true;
191 found = true;
192 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
192 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
193 info->setUpcastingOffset(upcastingOffset);
193 info->setUpcastingOffset(upcastingOffset);
194 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
194 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
195 if (tail) {
195 if (tail) {
196 tail->setNextInfo(info);
196 tail->setNextInfo(info);
197 } else {
197 } else {
198 PythonQtMemberInfo newInfo(info);
198 PythonQtMemberInfo newInfo(info);
199 memberCache.insert(memberName, newInfo);
199 memberCache.insert(memberName, newInfo);
200 }
200 }
201 tail = info;
201 tail = info;
202 }
202 }
203 }
203 }
204 }
204 }
205 }
205 }
206
206
207 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
207 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
208
208
209 return tail;
209 // now look for slots/signals/methods on this level of the meta object
210 }
211
212 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
213 {
214 bool found = false;
215 int memberNameLen = static_cast<int>(strlen(memberName));
216 PythonQtSlotInfo* tail = NULL;
217 if (_meta) {
210 if (_meta) {
218 int numMethods = _meta->methodCount();
211 int numMethods = _meta->methodCount();
219 for (int i = 0; i < numMethods; i++) {
212 // start from methodOffset, to only add slots which are located in this class,
213 // and not in the parent class, which is traversed recursively later on.
214 // (if the class in not a QObject, we are working with a script wrapper QObject
215 // and need to read all slots/signals starting from 0).
216 int methodOffset = _isQObject?_meta->methodOffset():0;
217 for (int i = methodOffset; i < numMethods; i++) {
220 QMetaMethod m = _meta->method(i);
218 QMetaMethod m = _meta->method(i);
221 if (((m.methodType() == QMetaMethod::Method ||
219 if (((m.methodType() == QMetaMethod::Method ||
222 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
220 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
223 || m.methodType()==QMetaMethod::Signal) {
221 || m.methodType()==QMetaMethod::Signal) {
224
222
225 const char* sigStart = m.signature();
223 const char* sigStart = m.signature();
226 // find the first '('
224 // find the first '('
227 int offset = findCharOffset(sigStart, '(');
225 int offset = findCharOffset(sigStart, '(');
228
226
229 // check if same length and same name
227 // check if same length and same name
230 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
228 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
231 found = true;
229 found = true;
232 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
230 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
233 if (tail) {
231 if (tail) {
234 tail->setNextInfo(info);
232 tail->setNextInfo(info);
235 } else {
233 } else {
236 PythonQtMemberInfo newInfo(info);
234 PythonQtMemberInfo newInfo(info);
237 _cachedMembers.insert(memberName, newInfo);
235 memberCache.insert(memberName, newInfo);
238 }
236 }
239 tail = info;
237 tail = info;
240 }
238 }
241 }
239 }
242 }
240 }
243 }
241 }
242 return tail;
243 }
244
245 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
246 {
247 bool found = false;
248 PythonQtSlotInfo* tail = NULL;
244
249
245 // look for dynamic decorators in this class and in derived classes
250 // look for dynamic decorators in this class and in derived classes
251 // (do this first to allow overloading of existing slots with generated wrappers,
252 // e.g. QDialog::accept is overloaded with PythonQtWrapper_QDialog::accept decorator)
246 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
253 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
247
254
248 return found;
255 return found;
249 }
256 }
250
257
251 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
258 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
252 {
259 {
253 bool found = false;
260 bool found = false;
254 // look for enum values
261 // look for enum values
255 int enumCount = meta->enumeratorCount();
262 int enumCount = meta->enumeratorCount();
256 for (int i=0;i<enumCount; i++) {
263 for (int i=0;i<enumCount; i++) {
257 QMetaEnum e = meta->enumerator(i);
264 QMetaEnum e = meta->enumerator(i);
258 // we do not want flags, they will cause our values to appear two times
265 // we do not want flags, they will cause our values to appear two times
259 if (e.isFlag()) continue;
266 if (e.isFlag()) continue;
260
267
261 for (int j=0; j < e.keyCount(); j++) {
268 for (int j=0; j < e.keyCount(); j++) {
262 if (qstrcmp(e.key(j), memberName)==0) {
269 if (qstrcmp(e.key(j), memberName)==0) {
263 PyObject* enumType = findEnumWrapper(e.name());
270 PyObject* enumType = findEnumWrapper(e.name());
264 if (enumType) {
271 if (enumType) {
265 PythonQtObjectPtr enumValuePtr;
272 PythonQtObjectPtr enumValuePtr;
266 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
273 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
267 PythonQtMemberInfo newInfo(enumValuePtr);
274 PythonQtMemberInfo newInfo(enumValuePtr);
268 _cachedMembers.insert(memberName, newInfo);
275 _cachedMembers.insert(memberName, newInfo);
269 #ifdef PYTHONQT_DEBUG
276 #ifdef PYTHONQT_DEBUG
270 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
277 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
271 #endif
278 #endif
272 found = true;
279 found = true;
273 break;
280 break;
274 } else {
281 } else {
275 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
282 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
276 }
283 }
277 }
284 }
278 }
285 }
279 }
286 }
280 return found;
287 return found;
281 }
288 }
282
289
283 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
290 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
284 {
291 {
285 PythonQtMemberInfo info = _cachedMembers.value(memberName);
292 PythonQtMemberInfo info = _cachedMembers.value(memberName);
286 if (info._type != PythonQtMemberInfo::Invalid) {
293 if (info._type != PythonQtMemberInfo::Invalid) {
287 return info;
294 return info;
288 } else {
295 } else {
289 bool found = false;
296 bool found = false;
290
297
291 found = lookForPropertyAndCache(memberName);
298 found = lookForPropertyAndCache(memberName);
292 if (!found) {
299 if (!found) {
293 found = lookForMethodAndCache(memberName);
300 found = lookForMethodAndCache(memberName);
294 }
301 }
295 if (!found) {
302 if (!found) {
296 if (_meta) {
303 if (_meta) {
297 // check enums in our meta object directly
304 // check enums in our meta object directly
298 found = lookForEnumAndCache(_meta, memberName);
305 found = lookForEnumAndCache(_meta, memberName);
299 }
306 }
300 if (!found) {
307 if (!found) {
301 // check enums in the class hierachy of CPP classes
308 // check enums in the class hierachy of CPP classes
302 // look for dynamic decorators in this class and in derived classes
309 // look for dynamic decorators in this class and in derived classes
303 QList<QObject*> decoObjects;
310 QList<QObject*> decoObjects;
304 recursiveCollectDecoratorObjects(decoObjects);
311 recursiveCollectDecoratorObjects(decoObjects);
305 foreach(QObject* deco, decoObjects) {
312 foreach(QObject* deco, decoObjects) {
306 // call on ourself for caching, but with different metaObject():
313 // call on ourself for caching, but with different metaObject():
307 found = lookForEnumAndCache(deco->metaObject(), memberName);
314 found = lookForEnumAndCache(deco->metaObject(), memberName);
308 if (found) {
315 if (found) {
309 break;
316 break;
310 }
317 }
311 }
318 }
312 }
319 }
313 }
320 }
314 if (!found) {
321 if (!found) {
315 // maybe it is an enum wrapper?
322 // maybe it is an enum wrapper?
316 PyObject* p = findEnumWrapper(memberName);
323 PyObject* p = findEnumWrapper(memberName);
317 if (p) {
324 if (p) {
318 info._type = PythonQtMemberInfo::EnumWrapper;
325 info._type = PythonQtMemberInfo::EnumWrapper;
319 info._enumWrapper = p;
326 info._enumWrapper = p;
320 _cachedMembers.insert(memberName, info);
327 _cachedMembers.insert(memberName, info);
321 found = true;
328 found = true;
322 }
329 }
323 }
330 }
324 if (!found) {
331 if (!found) {
325 // since python keywords can not be looked up, we check if the name contains a single trailing _
332 // since python keywords can not be looked up, we check if the name contains a single trailing _
326 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
333 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
327 QByteArray mbrName(memberName);
334 QByteArray mbrName(memberName);
328 if ((mbrName.length()>2) &&
335 if ((mbrName.length()>2) &&
329 (mbrName.at(mbrName.length()-1) == '_') &&
336 (mbrName.at(mbrName.length()-1) == '_') &&
330 (mbrName.at(mbrName.length()-2) != '_')) {
337 (mbrName.at(mbrName.length()-2) != '_')) {
331 mbrName = mbrName.mid(0,mbrName.length()-1);
338 mbrName = mbrName.mid(0,mbrName.length()-1);
332 found = lookForMethodAndCache(mbrName.constData());
339 found = lookForMethodAndCache(mbrName.constData());
333 if (found) {
340 if (found) {
334 return _cachedMembers.value(mbrName);
341 return _cachedMembers.value(mbrName);
335 }
342 }
336 }
343 }
337 }
344 }
338 if (!found) {
345 if (!found) {
339 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
346 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
340 info._type = PythonQtMemberInfo::NotFound;
347 info._type = PythonQtMemberInfo::NotFound;
341 _cachedMembers.insert(memberName, info);
348 _cachedMembers.insert(memberName, info);
342 }
349 }
343 }
350 }
344
351
345 return _cachedMembers.value(memberName);
352 return _cachedMembers.value(memberName);
346 }
353 }
347
354
348 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
355 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
349 QObject* deco = decorator();
356 QObject* deco = decorator();
350 if (deco) {
357 if (deco) {
351 decoratorObjects.append(deco);
358 decoratorObjects.append(deco);
352 }
359 }
353 foreach(const ParentClassInfo& info, _parentClasses) {
360 foreach(const ParentClassInfo& info, _parentClasses) {
354 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
361 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
355 }
362 }
356 }
363 }
357
364
358 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
365 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
359 classInfoObjects.append(this);
366 classInfoObjects.append(this);
360 foreach(const ParentClassInfo& info, _parentClasses) {
367 foreach(const ParentClassInfo& info, _parentClasses) {
361 info._parent->recursiveCollectClassInfos(classInfoObjects);
368 info._parent->recursiveCollectClassInfos(classInfoObjects);
362 }
369 }
363 }
370 }
364
371
365 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
372 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
366 {
373 {
367 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
374 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
368 while (it.hasNext()) {
375 while (it.hasNext()) {
369
376
370 PythonQtSlotInfo* infoOrig = it.next();
377 PythonQtSlotInfo* infoOrig = it.next();
371
378
372 const char* sigStart = infoOrig->metaMethod()->signature();
379 const char* sigStart = infoOrig->metaMethod()->signature();
373 if (qstrncmp("static_", sigStart, 7)==0) {
380 if (qstrncmp("static_", sigStart, 7)==0) {
374 sigStart += 7;
381 sigStart += 7;
375 sigStart += findCharOffset(sigStart, '_')+1;
382 sigStart += findCharOffset(sigStart, '_')+1;
376 }
383 }
377 int offset = findCharOffset(sigStart, '(');
384 int offset = findCharOffset(sigStart, '(');
378 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
385 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
379 //make a copy, otherwise we will have trouble on overloads!
386 //make a copy, otherwise we will have trouble on overloads!
380 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
387 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
381 info->setUpcastingOffset(upcastingOffset);
388 info->setUpcastingOffset(upcastingOffset);
382 found = true;
389 found = true;
383 if (tail) {
390 if (tail) {
384 tail->setNextInfo(info);
391 tail->setNextInfo(info);
385 } else {
392 } else {
386 PythonQtMemberInfo newInfo(info);
393 PythonQtMemberInfo newInfo(info);
387 memberCache.insert(memberName, newInfo);
394 memberCache.insert(memberName, newInfo);
388 }
395 }
389 tail = info;
396 tail = info;
390 }
397 }
391 }
398 }
392 return tail;
399 return tail;
393 }
400 }
394
401
395 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
402 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
396 QObject* decoratorProvider = decorator();
403 QObject* decoratorProvider = decorator();
397 if (decoratorProvider) {
404 if (decoratorProvider) {
398 const QMetaObject* meta = decoratorProvider->metaObject();
405 const QMetaObject* meta = decoratorProvider->metaObject();
399 int numMethods = meta->methodCount();
406 int numMethods = meta->methodCount();
400 int startFrom = QObject::staticMetaObject.methodCount();
407 int startFrom = QObject::staticMetaObject.methodCount();
401 for (int i = startFrom; i < numMethods; i++) {
408 for (int i = startFrom; i < numMethods; i++) {
402 QMetaMethod m = meta->method(i);
409 QMetaMethod m = meta->method(i);
403 if ((m.methodType() == QMetaMethod::Method ||
410 if ((m.methodType() == QMetaMethod::Method ||
404 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
411 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
405
412
406 const char* sigStart = m.signature();
413 const char* sigStart = m.signature();
407 bool isClassDeco = false;
414 bool isClassDeco = false;
408 if (qstrncmp(sigStart, "static_", 7)==0) {
415 if (qstrncmp(sigStart, "static_", 7)==0) {
409 // skip the static_classname_ part of the string
416 // skip the static_classname_ part of the string
410 sigStart += 7 + 1 + strlen(className());
417 sigStart += 7 + 1 + strlen(className());
411 isClassDeco = true;
418 isClassDeco = true;
412 } else if (qstrncmp(sigStart, "new_", 4)==0) {
419 } else if (qstrncmp(sigStart, "new_", 4)==0) {
413 continue;
420 continue;
414 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
421 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
415 continue;
422 continue;
416 } else if (qstrncmp(sigStart, "py_", 3)==0) {
423 } else if (qstrncmp(sigStart, "py_", 3)==0) {
417 // hide everything that starts with py_
424 // hide everything that starts with py_
418 continue;
425 continue;
419 }
426 }
420 // find the first '('
427 // find the first '('
421 int offset = findCharOffset(sigStart, '(');
428 int offset = findCharOffset(sigStart, '(');
422
429
423 // XXX no checking is currently done if the slots have correct first argument or not...
430 // XXX no checking is currently done if the slots have correct first argument or not...
424 if (!metaOnly || isClassDeco) {
431 if (!metaOnly || isClassDeco) {
425 list << QString::fromLatin1(sigStart, offset);
432 list << QString::fromLatin1(sigStart, offset);
426 }
433 }
427 }
434 }
428 }
435 }
429 }
436 }
430
437
431 // look for global decorator slots
438 // look for global decorator slots
432 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
439 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
433 while (it.hasNext()) {
440 while (it.hasNext()) {
434 PythonQtSlotInfo* slot = it.next();
441 PythonQtSlotInfo* slot = it.next();
435 if (metaOnly) {
442 if (metaOnly) {
436 if (slot->isClassDecorator()) {
443 if (slot->isClassDecorator()) {
437 QByteArray first = slot->slotName();
444 QByteArray first = slot->slotName();
438 if (first.startsWith("static_")) {
445 if (first.startsWith("static_")) {
439 int idx = first.indexOf('_');
446 int idx = first.indexOf('_');
440 idx = first.indexOf('_', idx+1);
447 idx = first.indexOf('_', idx+1);
441 first = first.mid(idx+1);
448 first = first.mid(idx+1);
442 }
449 }
443 list << first;
450 list << first;
444 }
451 }
445 } else {
452 } else {
446 list << slot->slotName();
453 list << slot->slotName();
447 }
454 }
448 }
455 }
449 }
456 }
450
457
451 QStringList PythonQtClassInfo::propertyList()
458 QStringList PythonQtClassInfo::propertyList()
452 {
459 {
453 QStringList l;
460 QStringList l;
454 if (_isQObject && _meta) {
461 if (_isQObject && _meta) {
455 int i;
462 int i;
456 int numProperties = _meta->propertyCount();
463 int numProperties = _meta->propertyCount();
457 for (i = 0; i < numProperties; i++) {
464 for (i = 0; i < numProperties; i++) {
458 QMetaProperty p = _meta->property(i);
465 QMetaProperty p = _meta->property(i);
459 l << QString(p.name());
466 l << QString(p.name());
460 }
467 }
461 }
468 }
462 return l;
469 return l;
463 }
470 }
464
471
465 QStringList PythonQtClassInfo::memberList()
472 QStringList PythonQtClassInfo::memberList()
466 {
473 {
467 decorator();
474 decorator();
468
475
469 QStringList l;
476 QStringList l;
470 QString h;
477 QString h;
471 // normal slots of QObject (or wrapper QObject)
478 // normal slots of QObject (or wrapper QObject)
472 if (_meta) {
479 if (_meta) {
473 int numMethods = _meta->methodCount();
480 int numMethods = _meta->methodCount();
474 bool skipQObj = !_isQObject;
481 bool skipQObj = !_isQObject;
475 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
482 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
476 QMetaMethod m = _meta->method(i);
483 QMetaMethod m = _meta->method(i);
477 if (((m.methodType() == QMetaMethod::Method ||
484 if (((m.methodType() == QMetaMethod::Method ||
478 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
485 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
479 || m.methodType()==QMetaMethod::Signal) {
486 || m.methodType()==QMetaMethod::Signal) {
480 QByteArray signa(m.signature());
487 QByteArray signa(m.signature());
481 signa = signa.left(signa.indexOf('('));
488 signa = signa.left(signa.indexOf('('));
482 l << signa;
489 l << signa;
483 }
490 }
484 }
491 }
485 }
492 }
486
493
487 {
494 {
488 // look for dynamic decorators in this class and in derived classes
495 // look for dynamic decorators in this class and in derived classes
489 QList<PythonQtClassInfo*> infos;
496 QList<PythonQtClassInfo*> infos;
490 recursiveCollectClassInfos(infos);
497 recursiveCollectClassInfos(infos);
491 foreach(PythonQtClassInfo* info, infos) {
498 foreach(PythonQtClassInfo* info, infos) {
492 info->listDecoratorSlotsFromDecoratorProvider(l, false);
499 info->listDecoratorSlotsFromDecoratorProvider(l, false);
493 }
500 }
494 }
501 }
495
502
496 // List enumerator keys...
503 // List enumerator keys...
497 QList<const QMetaObject*> enumMetaObjects;
504 QList<const QMetaObject*> enumMetaObjects;
498 if (_meta) {
505 if (_meta) {
499 enumMetaObjects << _meta;
506 enumMetaObjects << _meta;
500 }
507 }
501 // check enums in the class hierachy of CPP classes
508 // check enums in the class hierachy of CPP classes
502 QList<QObject*> decoObjects;
509 QList<QObject*> decoObjects;
503 recursiveCollectDecoratorObjects(decoObjects);
510 recursiveCollectDecoratorObjects(decoObjects);
504 foreach(QObject* deco, decoObjects) {
511 foreach(QObject* deco, decoObjects) {
505 enumMetaObjects << deco->metaObject();
512 enumMetaObjects << deco->metaObject();
506 }
513 }
507
514
508 foreach(const QMetaObject* meta, enumMetaObjects) {
515 foreach(const QMetaObject* meta, enumMetaObjects) {
509 for (int i = 0; i<meta->enumeratorCount(); i++) {
516 for (int i = 0; i<meta->enumeratorCount(); i++) {
510 QMetaEnum e = meta->enumerator(i);
517 QMetaEnum e = meta->enumerator(i);
511 l << e.name();
518 l << e.name();
512 // we do not want flags, they will cause our values to appear two times
519 // we do not want flags, they will cause our values to appear two times
513 if (e.isFlag()) continue;
520 if (e.isFlag()) continue;
514
521
515 for (int j=0; j < e.keyCount(); j++) {
522 for (int j=0; j < e.keyCount(); j++) {
516 l << QString(e.key(j));
523 l << QString(e.key(j));
517 }
524 }
518 }
525 }
519 }
526 }
520
527
521 return QSet<QString>::fromList(l).toList();
528 return QSet<QString>::fromList(l).toList();
522 }
529 }
523
530
524 const char* PythonQtClassInfo::className()
531 const char* PythonQtClassInfo::className()
525 {
532 {
526 return _wrappedClassName.constData();
533 return _wrappedClassName.constData();
527 }
534 }
528
535
529 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
536 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
530 {
537 {
531 if (ptr==NULL) {
538 if (ptr==NULL) {
532 return NULL;
539 return NULL;
533 }
540 }
534 if (_wrappedClassName == classname) {
541 if (_wrappedClassName == classname) {
535 return ptr;
542 return ptr;
536 }
543 }
537 foreach(const ParentClassInfo& info, _parentClasses) {
544 foreach(const ParentClassInfo& info, _parentClasses) {
538 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
545 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
539 if (result) {
546 if (result) {
540 return result;
547 return result;
541 }
548 }
542 }
549 }
543 return NULL;
550 return NULL;
544 }
551 }
545
552
546 bool PythonQtClassInfo::inherits(const char* name)
553 bool PythonQtClassInfo::inherits(const char* name)
547 {
554 {
548 if (_wrappedClassName == name) {
555 if (_wrappedClassName == name) {
549 return true;
556 return true;
550 }
557 }
551 foreach(const ParentClassInfo& info, _parentClasses) {
558 foreach(const ParentClassInfo& info, _parentClasses) {
552 if (info._parent->inherits(name)) {
559 if (info._parent->inherits(name)) {
553 return true;
560 return true;
554 }
561 }
555 }
562 }
556 return false;
563 return false;
557 }
564 }
558
565
559 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
566 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
560 {
567 {
561 if (classInfo == this) {
568 if (classInfo == this) {
562 return true;
569 return true;
563 }
570 }
564 foreach(const ParentClassInfo& info, _parentClasses) {
571 foreach(const ParentClassInfo& info, _parentClasses) {
565 if (info._parent->inherits(classInfo)) {
572 if (info._parent->inherits(classInfo)) {
566 return true;
573 return true;
567 }
574 }
568 }
575 }
569 return false;
576 return false;
570 }
577 }
571
578
572 QString PythonQtClassInfo::help()
579 QString PythonQtClassInfo::help()
573 {
580 {
574 decorator();
581 decorator();
575 QString h;
582 QString h;
576 h += QString("--- ") + QString(className()) + QString(" ---\n");
583 h += QString("--- ") + QString(className()) + QString(" ---\n");
577
584
578 if (_isQObject) {
585 if (_isQObject) {
579 h += "Properties:\n";
586 h += "Properties:\n";
580
587
581 int i;
588 int i;
582 int numProperties = _meta->propertyCount();
589 int numProperties = _meta->propertyCount();
583 for (i = 0; i < numProperties; i++) {
590 for (i = 0; i < numProperties; i++) {
584 QMetaProperty p = _meta->property(i);
591 QMetaProperty p = _meta->property(i);
585 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
592 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
586 }
593 }
587 }
594 }
588
595
589 if (constructors()) {
596 if (constructors()) {
590 h += "Constructors:\n";
597 h += "Constructors:\n";
591 PythonQtSlotInfo* constr = constructors();
598 PythonQtSlotInfo* constr = constructors();
592 while (constr) {
599 while (constr) {
593 h += constr->fullSignature() + "\n";
600 h += constr->fullSignature() + "\n";
594 constr = constr->nextInfo();
601 constr = constr->nextInfo();
595 }
602 }
596 }
603 }
597
604
598 h += "Slots:\n";
605 h += "Slots:\n";
599 h += "QString help()\n";
606 h += "QString help()\n";
600 h += "QString className()\n";
607 h += "QString className()\n";
601
608
602 if (_meta) {
609 if (_meta) {
603 int numMethods = _meta->methodCount();
610 int numMethods = _meta->methodCount();
604 for (int i = 0; i < numMethods; i++) {
611 for (int i = 0; i < numMethods; i++) {
605 QMetaMethod m = _meta->method(i);
612 QMetaMethod m = _meta->method(i);
606 if ((m.methodType() == QMetaMethod::Method ||
613 if ((m.methodType() == QMetaMethod::Method ||
607 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
614 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
608 PythonQtSlotInfo slot(this, m, i);
615 PythonQtSlotInfo slot(this, m, i);
609 h += slot.fullSignature()+ "\n";
616 h += slot.fullSignature()+ "\n";
610 }
617 }
611 }
618 }
612 }
619 }
613
620
614 // TODO xxx : decorators and enums from decorator() are missing...
621 // TODO xxx : decorators and enums from decorator() are missing...
615 // maybe we can reuse memberlist()?
622 // maybe we can reuse memberlist()?
616
623
617 if (_meta && _meta->enumeratorCount()) {
624 if (_meta && _meta->enumeratorCount()) {
618 h += "Enums:\n";
625 h += "Enums:\n";
619 for (int i = 0; i<_meta->enumeratorCount(); i++) {
626 for (int i = 0; i<_meta->enumeratorCount(); i++) {
620 QMetaEnum e = _meta->enumerator(i);
627 QMetaEnum e = _meta->enumerator(i);
621 h += QString(e.name()) + " {";
628 h += QString(e.name()) + " {";
622 for (int j=0; j < e.keyCount(); j++) {
629 for (int j=0; j < e.keyCount(); j++) {
623 if (j) { h+= ", "; }
630 if (j) { h+= ", "; }
624 h += e.key(j);
631 h += e.key(j);
625 }
632 }
626 h += " }\n";
633 h += " }\n";
627 }
634 }
628 }
635 }
629
636
630 if (_isQObject && _meta) {
637 if (_isQObject && _meta) {
631 int numMethods = _meta->methodCount();
638 int numMethods = _meta->methodCount();
632 if (numMethods>0) {
639 if (numMethods>0) {
633 h += "Signals:\n";
640 h += "Signals:\n";
634 for (int i = 0; i < numMethods; i++) {
641 for (int i = 0; i < numMethods; i++) {
635 QMetaMethod m = _meta->method(i);
642 QMetaMethod m = _meta->method(i);
636 if (m.methodType() == QMetaMethod::Signal) {
643 if (m.methodType() == QMetaMethod::Signal) {
637 h += QString(m.signature()) + "\n";
644 h += QString(m.signature()) + "\n";
638 }
645 }
639 }
646 }
640 }
647 }
641 }
648 }
642 return h;
649 return h;
643 }
650 }
644
651
645 PythonQtSlotInfo* PythonQtClassInfo::constructors()
652 PythonQtSlotInfo* PythonQtClassInfo::constructors()
646 {
653 {
647 if (!_constructors) {
654 if (!_constructors) {
648 // force creation of lazy decorator, which will register the decorators
655 // force creation of lazy decorator, which will register the decorators
649 decorator();
656 decorator();
650 }
657 }
651 return _constructors;
658 return _constructors;
652 }
659 }
653
660
654 PythonQtSlotInfo* PythonQtClassInfo::destructor()
661 PythonQtSlotInfo* PythonQtClassInfo::destructor()
655 {
662 {
656 if (!_destructor) {
663 if (!_destructor) {
657 // force creation of lazy decorator, which will register the decorators
664 // force creation of lazy decorator, which will register the decorators
658 decorator();
665 decorator();
659 }
666 }
660 return _destructor;
667 return _destructor;
661 }
668 }
662
669
663 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
670 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
664 {
671 {
665 PythonQtSlotInfo* prev = constructors();
672 PythonQtSlotInfo* prev = constructors();
666 if (prev) {
673 if (prev) {
667 info->setNextInfo(prev->nextInfo());
674 info->setNextInfo(prev->nextInfo());
668 prev->setNextInfo(info);
675 prev->setNextInfo(info);
669 } else {
676 } else {
670 _constructors = info;
677 _constructors = info;
671 }
678 }
672 }
679 }
673
680
674 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
681 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
675 {
682 {
676 _decoratorSlots.append(info);
683 _decoratorSlots.append(info);
677 }
684 }
678
685
679 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
686 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
680 {
687 {
681 if (_destructor) {
688 if (_destructor) {
682 _destructor->deleteOverloadsAndThis();
689 _destructor->deleteOverloadsAndThis();
683 }
690 }
684 _destructor = info;
691 _destructor = info;
685 }
692 }
686
693
687 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
694 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
688 {
695 {
689 _meta = meta;
696 _meta = meta;
690 clearCachedMembers();
697 clearCachedMembers();
691 }
698 }
692
699
693 QObject* PythonQtClassInfo::decorator()
700 QObject* PythonQtClassInfo::decorator()
694 {
701 {
695 if (!_decoratorProvider && _decoratorProviderCB) {
702 if (!_decoratorProvider && _decoratorProviderCB) {
696 _decoratorProvider = (*_decoratorProviderCB)();
703 _decoratorProvider = (*_decoratorProviderCB)();
697 if (_decoratorProvider) {
704 if (_decoratorProvider) {
698 _decoratorProvider->setParent(PythonQt::priv());
705 _decoratorProvider->setParent(PythonQt::priv());
699 // setup enums early, since they might be needed by the constructor decorators:
706 // setup enums early, since they might be needed by the constructor decorators:
700 if (!_enumsCreated) {
707 if (!_enumsCreated) {
701 createEnumWrappers();
708 createEnumWrappers();
702 }
709 }
703 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
710 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
704 }
711 }
705 }
712 }
706 // check if enums need to be created and create them if they are not yet created
713 // check if enums need to be created and create them if they are not yet created
707 if (!_enumsCreated) {
714 if (!_enumsCreated) {
708 createEnumWrappers();
715 createEnumWrappers();
709 }
716 }
710 return _decoratorProvider;
717 return _decoratorProvider;
711 }
718 }
712
719
713 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
714 {
715 PythonQtMemberInfo info = member("py_hasOwner");
716 if (info._type == PythonQtMemberInfo::Slot) {
717 void* obj = object;
718 bool result = false;
719 void* args[2];
720 args[0] = &result;
721 args[1] = &obj;
722 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
723 return !result;
724 } else {
725 return false;
726 }
727 }
728
729 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, const char** resultClassName)
720 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, const char** resultClassName)
730 {
721 {
731 if (!_polymorphicHandlers.isEmpty()) {
722 if (!_polymorphicHandlers.isEmpty()) {
732 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
723 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
733 void* resultPtr = (*cb)(ptr, resultClassName);
724 void* resultPtr = (*cb)(ptr, resultClassName);
734 if (resultPtr) {
725 if (resultPtr) {
735 return resultPtr;
726 return resultPtr;
736 }
727 }
737 }
728 }
738 }
729 }
739 foreach(const ParentClassInfo& info, _parentClasses) {
730 foreach(const ParentClassInfo& info, _parentClasses) {
740 if (!info._parent->isQObject()) {
731 if (!info._parent->isQObject()) {
741 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
732 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
742 if (resultPtr) {
733 if (resultPtr) {
743 return resultPtr;
734 return resultPtr;
744 }
735 }
745 }
736 }
746 }
737 }
747 return NULL;
738 return NULL;
748 }
739 }
749
740
750 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
741 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
751 {
742 {
752 const char* className;
743 const char* className;
753 // this would do downcasting recursively...
744 // this would do downcasting recursively...
754 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
745 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
755
746
756 // we only do downcasting on the base object, not on the whole inheritance tree...
747 // we only do downcasting on the base object, not on the whole inheritance tree...
757 void* resultPtr = NULL;
748 void* resultPtr = NULL;
758 if (!_polymorphicHandlers.isEmpty()) {
749 if (!_polymorphicHandlers.isEmpty()) {
759 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
750 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
760 resultPtr = (*cb)(ptr, &className);
751 resultPtr = (*cb)(ptr, &className);
761 if (resultPtr) {
752 if (resultPtr) {
762 break;
753 break;
763 }
754 }
764 }
755 }
765 }
756 }
766 if (resultPtr) {
757 if (resultPtr) {
767 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
758 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
768 } else {
759 } else {
769 *resultClassInfo = this;
760 *resultClassInfo = this;
770 resultPtr = ptr;
761 resultPtr = ptr;
771 }
762 }
772 return resultPtr;
763 return resultPtr;
773 }
764 }
774
765
775 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
766 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
776 {
767 {
777 if (isLocalEnum) {
768 if (isLocalEnum) {
778 *isLocalEnum = true;
769 *isLocalEnum = true;
779 }
770 }
780 int scopePos = name.lastIndexOf("::");
771 int scopePos = name.lastIndexOf("::");
781 if (scopePos != -1) {
772 if (scopePos != -1) {
782 if (isLocalEnum) {
773 if (isLocalEnum) {
783 *isLocalEnum = false;
774 *isLocalEnum = false;
784 }
775 }
785 // split into scope and enum name
776 // split into scope and enum name
786 QByteArray enumScope = name.mid(0,scopePos);
777 QByteArray enumScope = name.mid(0,scopePos);
787 QByteArray enumName = name.mid(scopePos+2);
778 QByteArray enumName = name.mid(scopePos+2);
788 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
779 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
789 if (info) {
780 if (info) {
790 return info->findEnumWrapper(enumName);
781 return info->findEnumWrapper(enumName);
791 } else{
782 } else{
792 return NULL;
783 return NULL;
793 }
784 }
794 }
785 }
795 if (localScope) {
786 if (localScope) {
796 return localScope->findEnumWrapper(name);
787 return localScope->findEnumWrapper(name);
797 } else {
788 } else {
798 return NULL;
789 return NULL;
799 }
790 }
800 }
791 }
801
792
802 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
793 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
803 {
794 {
804 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
795 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
805 QMetaEnum e = meta->enumerator(i);
796 QMetaEnum e = meta->enumerator(i);
806 PythonQtObjectPtr p;
797 PythonQtObjectPtr p;
807 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
798 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
808 _enumWrappers.append(p);
799 _enumWrappers.append(p);
809 }
800 }
810 }
801 }
811
802
812 void PythonQtClassInfo::createEnumWrappers()
803 void PythonQtClassInfo::createEnumWrappers()
813 {
804 {
814 if (!_enumsCreated) {
805 if (!_enumsCreated) {
815 _enumsCreated = true;
806 _enumsCreated = true;
816 if (_meta) {
807 if (_meta) {
817 createEnumWrappers(_meta);
808 createEnumWrappers(_meta);
818 }
809 }
819 if (decorator()) {
810 if (decorator()) {
820 createEnumWrappers(decorator()->metaObject());
811 createEnumWrappers(decorator()->metaObject());
821 }
812 }
822 foreach(const ParentClassInfo& info, _parentClasses) {
813 foreach(const ParentClassInfo& info, _parentClasses) {
823 info._parent->createEnumWrappers();
814 info._parent->createEnumWrappers();
824 }
815 }
825 }
816 }
826 }
817 }
827
818
828 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
819 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
829 // force enum creation
820 // force enum creation
830 if (!_enumsCreated) {
821 if (!_enumsCreated) {
831 createEnumWrappers();
822 createEnumWrappers();
832 }
823 }
833 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
824 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
834 const char* className = ((PyTypeObject*)p.object())->tp_name;
825 const char* className = ((PyTypeObject*)p.object())->tp_name;
835 if (qstrcmp(className, name)==0) {
826 if (qstrcmp(className, name)==0) {
836 return p.object();
827 return p.object();
837 }
828 }
838 }
829 }
839 foreach(const ParentClassInfo& info, _parentClasses) {
830 foreach(const ParentClassInfo& info, _parentClasses) {
840 PyObject* p = info._parent->findEnumWrapper(name);
831 PyObject* p = info._parent->findEnumWrapper(name);
841 if (p) return p;
832 if (p) return p;
842 }
833 }
843 return NULL;
834 return NULL;
844 }
835 }
845
836
846 void PythonQtClassInfo::setDecoratorProvider( PythonQtQObjectCreatorFunctionCB* cb )
837 void PythonQtClassInfo::setDecoratorProvider( PythonQtQObjectCreatorFunctionCB* cb )
847 {
838 {
848 _decoratorProviderCB = cb;
839 _decoratorProviderCB = cb;
849 _decoratorProvider = NULL;
840 _decoratorProvider = NULL;
850 _enumsCreated = false;
841 _enumsCreated = false;
851 }
842 }
852
843
853 void PythonQtClassInfo::clearNotFoundCachedMembers()
844 void PythonQtClassInfo::clearNotFoundCachedMembers()
854 {
845 {
855 // remove all not found entries, since a new decorator means new slots,
846 // remove all not found entries, since a new decorator means new slots,
856 // which might have been cached as "NotFound" already.
847 // which might have been cached as "NotFound" already.
857 QMutableHashIterator<QByteArray, PythonQtMemberInfo> it(_cachedMembers);
848 QMutableHashIterator<QByteArray, PythonQtMemberInfo> it(_cachedMembers);
858 while (it.hasNext()) {
849 while (it.hasNext()) {
859 it.next();
850 it.next();
860 if (it.value()._type == PythonQtMemberInfo::NotFound) {
851 if (it.value()._type == PythonQtMemberInfo::NotFound) {
861 it.remove();
852 it.remove();
862 }
853 }
863 }
854 }
864 }
855 }
865
856
866 //-------------------------------------------------------------------------
857 //-------------------------------------------------------------------------
867
858
868 PythonQtMemberInfo::PythonQtMemberInfo( PythonQtSlotInfo* info )
859 PythonQtMemberInfo::PythonQtMemberInfo( PythonQtSlotInfo* info )
869 {
860 {
870 if (info->metaMethod()->methodType() == QMetaMethod::Signal) {
861 if (info->metaMethod()->methodType() == QMetaMethod::Signal) {
871 _type = Signal;
862 _type = Signal;
872 } else {
863 } else {
873 _type = Slot;
864 _type = Slot;
874 }
865 }
875 _slot = info;
866 _slot = info;
876 _enumValue = NULL;
867 _enumValue = NULL;
877 }
868 }
878
869
879 PythonQtMemberInfo::PythonQtMemberInfo( const PythonQtObjectPtr& enumValue )
870 PythonQtMemberInfo::PythonQtMemberInfo( const PythonQtObjectPtr& enumValue )
880 {
871 {
881 _type = EnumValue;
872 _type = EnumValue;
882 _slot = NULL;
873 _slot = NULL;
883 _enumValue = enumValue;
874 _enumValue = enumValue;
884 _enumWrapper = NULL;
875 _enumWrapper = NULL;
885 }
876 }
886
877
887 PythonQtMemberInfo::PythonQtMemberInfo( const QMetaProperty& prop )
878 PythonQtMemberInfo::PythonQtMemberInfo( const QMetaProperty& prop )
888 {
879 {
889 _type = Property;
880 _type = Property;
890 _slot = NULL;
881 _slot = NULL;
891 _enumValue = NULL;
882 _enumValue = NULL;
892 _property = prop;
883 _property = prop;
893 _enumWrapper = NULL;
884 _enumWrapper = NULL;
894 } No newline at end of file
885 }
@@ -1,250 +1,247
1 #ifndef _PYTHONQTCLASSINFO_H
1 #ifndef _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 #include <QMetaObject>
36 #include <QMetaObject>
37 #include <QMetaMethod>
37 #include <QMetaMethod>
38 #include <QHash>
38 #include <QHash>
39 #include <QByteArray>
39 #include <QByteArray>
40 #include <QList>
40 #include <QList>
41 #include "PythonQt.h"
41 #include "PythonQt.h"
42
42
43 class PythonQtSlotInfo;
43 class PythonQtSlotInfo;
44
44
45 struct PythonQtMemberInfo {
45 struct PythonQtMemberInfo {
46 enum Type {
46 enum Type {
47 Invalid, Slot, Signal, EnumValue, EnumWrapper, Property, NotFound
47 Invalid, Slot, Signal, EnumValue, EnumWrapper, Property, NotFound
48 };
48 };
49
49
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
51
51
52 PythonQtMemberInfo(PythonQtSlotInfo* info);
52 PythonQtMemberInfo(PythonQtSlotInfo* info);
53
53
54 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue);
54 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue);
55
55
56 PythonQtMemberInfo(const QMetaProperty& prop);
56 PythonQtMemberInfo(const QMetaProperty& prop);
57
57
58 Type _type;
58 Type _type;
59
59
60 // TODO: this could be a union...
60 // TODO: this could be a union...
61 PythonQtSlotInfo* _slot;
61 PythonQtSlotInfo* _slot;
62 PyObject* _enumWrapper;
62 PyObject* _enumWrapper;
63 PythonQtObjectPtr _enumValue;
63 PythonQtObjectPtr _enumValue;
64 QMetaProperty _property;
64 QMetaProperty _property;
65 };
65 };
66
66
67 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
67 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
68 /*! for fast lookup of slots when calling the object from Python
68 /*! for fast lookup of slots when calling the object from Python
69 */
69 */
70 class PYTHONQT_EXPORT PythonQtClassInfo {
70 class PYTHONQT_EXPORT PythonQtClassInfo {
71
71
72 public:
72 public:
73 PythonQtClassInfo();
73 PythonQtClassInfo();
74 ~PythonQtClassInfo();
74 ~PythonQtClassInfo();
75
75
76 //! store information about parent classes
76 //! store information about parent classes
77 struct ParentClassInfo {
77 struct ParentClassInfo {
78 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
78 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
79 {};
79 {};
80
80
81 PythonQtClassInfo* _parent;
81 PythonQtClassInfo* _parent;
82 int _upcastingOffset;
82 int _upcastingOffset;
83 };
83 };
84
84
85
85
86 //! setup as a QObject, taking the meta object as meta information about the QObject
86 //! setup as a QObject, taking the meta object as meta information about the QObject
87 void setupQObject(const QMetaObject* meta);
87 void setupQObject(const QMetaObject* meta);
88
88
89 //! setup as a CPP (non-QObject), taking the classname
89 //! setup as a CPP (non-QObject), taking the classname
90 void setupCPPObject(const QByteArray& classname);
90 void setupCPPObject(const QByteArray& classname);
91
91
92 //! set the type capabilities
92 //! set the type capabilities
93 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
93 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
94 //! get the type capabilities
94 //! get the type capabilities
95 int typeSlots() const { return _typeSlots; }
95 int typeSlots() const { return _typeSlots; }
96
96
97 //! get the Python method definition for a given slot name (without return type and signature)
97 //! get the Python method definition for a given slot name (without return type and signature)
98 PythonQtMemberInfo member(const char* member);
98 PythonQtMemberInfo member(const char* member);
99
99
100 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
100 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
101 PythonQtSlotInfo* constructors();
101 PythonQtSlotInfo* constructors();
102
102
103 //! get access to the destructor slot
103 //! get access to the destructor slot
104 PythonQtSlotInfo* destructor();
104 PythonQtSlotInfo* destructor();
105
105
106 //! add a constructor, ownership is passed to classinfo
106 //! add a constructor, ownership is passed to classinfo
107 void addConstructor(PythonQtSlotInfo* info);
107 void addConstructor(PythonQtSlotInfo* info);
108
108
109 //! set a destructor, ownership is passed to classinfo
109 //! set a destructor, ownership is passed to classinfo
110 void setDestructor(PythonQtSlotInfo* info);
110 void setDestructor(PythonQtSlotInfo* info);
111
111
112 //! add a decorator slot, ownership is passed to classinfo
112 //! add a decorator slot, ownership is passed to classinfo
113 void addDecoratorSlot(PythonQtSlotInfo* info);
113 void addDecoratorSlot(PythonQtSlotInfo* info);
114
114
115 //! get the classname (either of the QObject or of the wrapped CPP object)
115 //! get the classname (either of the QObject or of the wrapped CPP object)
116 const char* className();
116 const char* className();
117
117
118 //! returns if the QObject
118 //! returns if the QObject
119 bool isQObject() { return _isQObject; }
119 bool isQObject() { return _isQObject; }
120
120
121 //! returns if the class is a CPP wrapper
121 //! returns if the class is a CPP wrapper
122 bool isCPPWrapper() { return !_isQObject; }
122 bool isCPPWrapper() { return !_isQObject; }
123
123
124 //! get the meta object
124 //! get the meta object
125 const QMetaObject* metaObject() { return _meta; }
125 const QMetaObject* metaObject() { return _meta; }
126
126
127 //! set the meta object, this will reset the caching
127 //! set the meta object, this will reset the caching
128 void setMetaObject(const QMetaObject* meta);
128 void setMetaObject(const QMetaObject* meta);
129
129
130 //! returns if this class inherits from the given classname
130 //! returns if this class inherits from the given classname
131 bool inherits(const char* classname);
131 bool inherits(const char* classname);
132
132
133 //! returns if this class inherits from the given classinfo
133 //! returns if this class inherits from the given classinfo
134 bool inherits(PythonQtClassInfo* info);
134 bool inherits(PythonQtClassInfo* info);
135
135
136 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
136 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
137 //! which might be different to \c ptr due to C++ multiple inheritance
137 //! which might be different to \c ptr due to C++ multiple inheritance
138 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
138 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
139 void* castTo(void* ptr, const char* classname);
139 void* castTo(void* ptr, const char* classname);
140
140
141 //! get help string for the metaobject
141 //! get help string for the metaobject
142 QString help();
142 QString help();
143
143
144 //! get list of all properties (on QObjects only, otherwise the list is empty)
144 //! get list of all properties (on QObjects only, otherwise the list is empty)
145 QStringList propertyList();
145 QStringList propertyList();
146
146
147 //! get list of all members (excluding properties, which can be listed with propertyList())
147 //! get list of all members (excluding properties, which can be listed with propertyList())
148 QStringList memberList();
148 QStringList memberList();
149
149
150 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
150 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
151 int metaTypeId() { return _metaTypeId; }
151 int metaTypeId() { return _metaTypeId; }
152
152
153 //! set an additional decorator provider that offers additional decorator slots for this class
153 //! set an additional decorator provider that offers additional decorator slots for this class
154 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb);
154 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb);
155
155
156 //! get the decorator qobject instance
156 //! get the decorator qobject instance
157 QObject* decorator();
157 QObject* decorator();
158
158
159 //! add the parent class info of a CPP object
159 //! add the parent class info of a CPP object
160 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
160 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
161
161
162 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
163 bool hasOwnerMethodButNoOwner(void* object);
164
165 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
162 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
166 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
163 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
167
164
168 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
165 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
169 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
166 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
170
167
171 //! set the shell set instance wrapper cb
168 //! set the shell set instance wrapper cb
172 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
169 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
173 _shellSetInstanceWrapperCB = cb;
170 _shellSetInstanceWrapperCB = cb;
174 }
171 }
175
172
176 //! get the shell set instance wrapper cb
173 //! get the shell set instance wrapper cb
177 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
174 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
178 return _shellSetInstanceWrapperCB;
175 return _shellSetInstanceWrapperCB;
179 }
176 }
180
177
181 //! add a handler for polymorphic downcasting
178 //! add a handler for polymorphic downcasting
182 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
179 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
183
180
184 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
181 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
185 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
182 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
186
183
187 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
184 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
188 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
185 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
189
186
190 //! clear all members that where cached as "NotFound"
187 //! clear all members that where cached as "NotFound"
191 void clearNotFoundCachedMembers();
188 void clearNotFoundCachedMembers();
192
189
193 private:
190 private:
194 void createEnumWrappers();
191 void createEnumWrappers();
195 void createEnumWrappers(const QMetaObject* meta);
192 void createEnumWrappers(const QMetaObject* meta);
196 PyObject* findEnumWrapper(const char* name);
193 PyObject* findEnumWrapper(const char* name);
197
194
198 //! clear all cached members
195 //! clear all cached members
199 void clearCachedMembers();
196 void clearCachedMembers();
200
197
201 void* recursiveCastDownIfPossible(void* ptr, const char** resultClassName);
198 void* recursiveCastDownIfPossible(void* ptr, const char** resultClassName);
202
199
203 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
200 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
204 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
201 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
205 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
202 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
206
203
207 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
204 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
208 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
205 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
209
206
210 bool lookForPropertyAndCache(const char* memberName);
207 bool lookForPropertyAndCache(const char* memberName);
211 bool lookForMethodAndCache(const char* memberName);
208 bool lookForMethodAndCache(const char* memberName);
212 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
209 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
213
210
214 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
211 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
215 int findCharOffset(const char* sigStart, char someChar);
212 int findCharOffset(const char* sigStart, char someChar);
216
213
217 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
214 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
218
215
219 PythonQtSlotInfo* _constructors;
216 PythonQtSlotInfo* _constructors;
220 PythonQtSlotInfo* _destructor;
217 PythonQtSlotInfo* _destructor;
221 QList<PythonQtSlotInfo*> _decoratorSlots;
218 QList<PythonQtSlotInfo*> _decoratorSlots;
222
219
223 QList<PythonQtObjectPtr> _enumWrappers;
220 QList<PythonQtObjectPtr> _enumWrappers;
224
221
225 const QMetaObject* _meta;
222 const QMetaObject* _meta;
226
223
227 QByteArray _wrappedClassName;
224 QByteArray _wrappedClassName;
228 QList<ParentClassInfo> _parentClasses;
225 QList<ParentClassInfo> _parentClasses;
229
226
230 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
227 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
231
228
232 QObject* _decoratorProvider;
229 QObject* _decoratorProvider;
233 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
230 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
234
231
235 PyObject* _pythonQtClassWrapper;
232 PyObject* _pythonQtClassWrapper;
236
233
237 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
234 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
238
235
239 int _metaTypeId;
236 int _metaTypeId;
240 int _typeSlots;
237 int _typeSlots;
241
238
242 bool _isQObject;
239 bool _isQObject;
243 bool _enumsCreated;
240 bool _enumsCreated;
244
241
245 };
242 };
246
243
247 //---------------------------------------------------------------
244 //---------------------------------------------------------------
248
245
249
246
250 #endif
247 #endif
@@ -1,1232 +1,1277
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtConversion.cpp
35 // \file PythonQtConversion.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtConversion.h"
42 #include "PythonQtConversion.h"
43 #include "PythonQtVariants.h"
43 #include "PythonQtVariants.h"
44 #include <QDateTime>
44 #include <QDateTime>
45 #include <QTime>
45 #include <QTime>
46 #include <QDate>
46 #include <QDate>
47
47
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 PythonQtValueStorageWithCleanup<QVariant, 128> PythonQtConv::global_variantStorage;
50 PythonQtValueStorageWithCleanup<QVariant, 128> PythonQtConv::global_variantStorage;
51
51
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
54
54
55 PyObject* PythonQtConv::GetPyBool(bool val)
55 PyObject* PythonQtConv::GetPyBool(bool val)
56 {
56 {
57 PyObject* r = val?Py_True:Py_False;
57 PyObject* r = val?Py_True:Py_False;
58 Py_INCREF(r);
58 Py_INCREF(r);
59 return r;
59 return r;
60 }
60 }
61
61
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
63 // is it an enum value?
63 // is it an enum value?
64 if (info.enumWrapper) {
64 if (info.enumWrapper) {
65 if (info.pointerCount==0) {
65 if (info.pointerCount==0) {
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
67 } else {
67 } else {
68 // we do not support pointers to enums (who needs them?)
68 // we do not support pointers to enums (who needs them?)
69 Py_INCREF(Py_None);
69 Py_INCREF(Py_None);
70 return Py_None;
70 return Py_None;
71 }
71 }
72 }
72 }
73
73
74 if (info.typeId == QMetaType::Void) {
74 if (info.typeId == QMetaType::Void) {
75 Py_INCREF(Py_None);
75 Py_INCREF(Py_None);
76 return Py_None;
76 return Py_None;
77 } else if ((info.pointerCount == 1) && (info.typeId == QMetaType::Char)) {
77 } else if ((info.pointerCount == 1) && (info.typeId == QMetaType::Char)) {
78 // a char ptr will probably be a null terminated string, so we support that:
78 // a char ptr will probably be a null terminated string, so we support that:
79 return PyString_FromString(*((char**)data));
79 return PyString_FromString(*((char**)data));
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
81 info.name.startsWith("QList<")) {
81 info.name.startsWith("QList<")) {
82 // it is a QList template:
82 // it is a QList template:
83 QByteArray innerType = info.name.mid(6,info.name.length()-7);
83 QByteArray innerType = info.name.mid(6,info.name.length()-7);
84 if (innerType.endsWith("*")) {
84 if (innerType.endsWith("*")) {
85 innerType.truncate(innerType.length()-1);
85 innerType.truncate(innerType.length()-1);
86 QList<void*>* listPtr = NULL;
86 QList<void*>* listPtr = NULL;
87 if (info.pointerCount == 1) {
87 if (info.pointerCount == 1) {
88 listPtr = *((QList<void*>**)data);
88 listPtr = *((QList<void*>**)data);
89 } else if (info.pointerCount == 0) {
89 } else if (info.pointerCount == 0) {
90 listPtr = (QList<void*>*)data;
90 listPtr = (QList<void*>*)data;
91 }
91 }
92 if (listPtr) {
92 if (listPtr) {
93 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
93 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
94 } else {
94 } else {
95 return NULL;
95 return NULL;
96 }
96 }
97 }
97 }
98 }
98 }
99
99
100 if (info.typeId >= QMetaType::User) {
100 if (info.typeId >= QMetaType::User) {
101 // if a converter is registered, we use is:
101 // if a converter is registered, we use is:
102 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
102 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
103 if (converter) {
103 if (converter) {
104 return (*converter)(data, info.typeId);
104 return (*converter)(data, info.typeId);
105 }
105 }
106 }
106 }
107
107
108 // special handling did not match, so we convert the usual way (either pointer or value version):
108 // special handling did not match, so we convert the usual way (either pointer or value version):
109 if (info.pointerCount == 1) {
109 if (info.pointerCount == 1) {
110 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
110 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
111 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
111 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
112 } else if (info.pointerCount == 0) {
112 } else if (info.pointerCount == 0) {
113 // handle values that are not yet handled and not pointers
113 // handle values that are not yet handled and not pointers
114 return ConvertQtValueToPythonInternal(info.typeId, data);
114 return ConvertQtValueToPythonInternal(info.typeId, data);
115 } else {
115 } else {
116 return NULL;
116 return NULL;
117 }
117 }
118 }
118 }
119
119
120 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
120 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
121 switch (type) {
121 switch (type) {
122 case QMetaType::Void:
122 case QMetaType::Void:
123 Py_INCREF(Py_None);
123 Py_INCREF(Py_None);
124 return Py_None;
124 return Py_None;
125 case QMetaType::Char:
125 case QMetaType::Char:
126 return PyInt_FromLong(*((char*)data));
126 return PyInt_FromLong(*((char*)data));
127 case QMetaType::UChar:
127 case QMetaType::UChar:
128 return PyInt_FromLong(*((unsigned char*)data));
128 return PyInt_FromLong(*((unsigned char*)data));
129 case QMetaType::Short:
129 case QMetaType::Short:
130 return PyInt_FromLong(*((short*)data));
130 return PyInt_FromLong(*((short*)data));
131 case QMetaType::UShort:
131 case QMetaType::UShort:
132 return PyInt_FromLong(*((unsigned short*)data));
132 return PyInt_FromLong(*((unsigned short*)data));
133 case QMetaType::Long:
133 case QMetaType::Long:
134 return PyInt_FromLong(*((long*)data));
134 return PyInt_FromLong(*((long*)data));
135 case QMetaType::ULong:
135 case QMetaType::ULong:
136 // does not fit into simple int of python
136 // does not fit into simple int of python
137 return PyLong_FromUnsignedLong(*((unsigned long*)data));
137 return PyLong_FromUnsignedLong(*((unsigned long*)data));
138 case QMetaType::Bool:
138 case QMetaType::Bool:
139 return PythonQtConv::GetPyBool(*((bool*)data));
139 return PythonQtConv::GetPyBool(*((bool*)data));
140 case QMetaType::Int:
140 case QMetaType::Int:
141 return PyInt_FromLong(*((int*)data));
141 return PyInt_FromLong(*((int*)data));
142 case QMetaType::UInt:
142 case QMetaType::UInt:
143 // does not fit into simple int of python
143 // does not fit into simple int of python
144 return PyLong_FromUnsignedLong(*((unsigned int*)data));
144 return PyLong_FromUnsignedLong(*((unsigned int*)data));
145 case QMetaType::QChar:
145 case QMetaType::QChar:
146 return PyInt_FromLong(*((short*)data));
146 return PyInt_FromLong(*((short*)data));
147 case QMetaType::Float:
147 case QMetaType::Float:
148 return PyFloat_FromDouble(*((float*)data));
148 return PyFloat_FromDouble(*((float*)data));
149 case QMetaType::Double:
149 case QMetaType::Double:
150 return PyFloat_FromDouble(*((double*)data));
150 return PyFloat_FromDouble(*((double*)data));
151 case QMetaType::LongLong:
151 case QMetaType::LongLong:
152 return PyLong_FromLongLong(*((qint64*)data));
152 return PyLong_FromLongLong(*((qint64*)data));
153 case QMetaType::ULongLong:
153 case QMetaType::ULongLong:
154 return PyLong_FromUnsignedLongLong(*((quint64*)data));
154 return PyLong_FromUnsignedLongLong(*((quint64*)data));
155 // implicit conversion from QByteArray to str has been removed:
155 // implicit conversion from QByteArray to str has been removed:
156 //case QMetaType::QByteArray: {
156 //case QMetaType::QByteArray: {
157 // QByteArray* v = (QByteArray*) data;
157 // QByteArray* v = (QByteArray*) data;
158 // return PyString_FromStringAndSize(*v, v->size());
158 // return PyString_FromStringAndSize(*v, v->size());
159 // }
159 // }
160 case QMetaType::QVariantMap:
160 case QMetaType::QVariantMap:
161 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
161 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
162 case QMetaType::QVariantList:
162 case QMetaType::QVariantList:
163 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
163 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
164 case QMetaType::QString:
164 case QMetaType::QString:
165 return PythonQtConv::QStringToPyObject(*((QString*)data));
165 return PythonQtConv::QStringToPyObject(*((QString*)data));
166 case QMetaType::QStringList:
166 case QMetaType::QStringList:
167 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
167 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
168
168
169 case PythonQtMethodInfo::Variant:
169 case PythonQtMethodInfo::Variant:
170 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
170 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
171 case QMetaType::QObjectStar:
171 case QMetaType::QObjectStar:
172 case QMetaType::QWidgetStar:
172 case QMetaType::QWidgetStar:
173 return PythonQt::priv()->wrapQObject(*((QObject**)data));
173 return PythonQt::priv()->wrapQObject(*((QObject**)data));
174
174
175 default:
175 default:
176 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
176 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
177 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
177 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
178 PyObject* o = ((PythonQtObjectPtr*)data)->object();
178 PyObject* o = ((PythonQtObjectPtr*)data)->object();
179 Py_INCREF(o);
179 Py_INCREF(o);
180 return o;
180 return o;
181 } else {
181 } else {
182 if (type > 0) {
182 if (type > 0) {
183 // if the type is known, we can construct it via QMetaType::construct
183 // if the type is known, we can construct it via QMetaType::construct
184 void* newCPPObject = QMetaType::construct(type, data);
184 void* newCPPObject = QMetaType::construct(type, data);
185 // XXX this could be optimized by using metatypeid directly
185 // XXX this could be optimized by using metatypeid directly
186 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
186 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
187 wrap->_ownedByPythonQt = true;
187 wrap->_ownedByPythonQt = true;
188 wrap->_useQMetaTypeDestroy = true;
188 wrap->_useQMetaTypeDestroy = true;
189 return (PyObject*)wrap;
189 return (PyObject*)wrap;
190 }
190 }
191 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
191 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
192 }
192 }
193 }
193 }
194 Py_INCREF(Py_None);
194 Py_INCREF(Py_None);
195 return Py_None;
195 return Py_None;
196 }
196 }
197
197
198 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
198 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
199 void* ptr = NULL;
199 void* ptr = NULL;
200 if (info.pointerCount>1) {
200 if (info.pointerCount>1) {
201 return NULL;
201 return NULL;
202 } else if (info.pointerCount==1) {
202 } else if (info.pointerCount==1) {
203 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
203 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
204 } else if (info.enumWrapper) {
204 } else if (info.enumWrapper) {
205 // create enum return value
205 // create enum return value
206 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
206 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
207 } else {
207 } else {
208 switch (info.typeId) {
208 switch (info.typeId) {
209 case QMetaType::Char:
209 case QMetaType::Char:
210 case QMetaType::UChar:
210 case QMetaType::UChar:
211 case QMetaType::Short:
211 case QMetaType::Short:
212 case QMetaType::UShort:
212 case QMetaType::UShort:
213 case QMetaType::Long:
213 case QMetaType::Long:
214 case QMetaType::ULong:
214 case QMetaType::ULong:
215 case QMetaType::Bool:
215 case QMetaType::Bool:
216 case QMetaType::Int:
216 case QMetaType::Int:
217 case QMetaType::UInt:
217 case QMetaType::UInt:
218 case QMetaType::QChar:
218 case QMetaType::QChar:
219 case QMetaType::Float:
219 case QMetaType::Float:
220 case QMetaType::Double:
220 case QMetaType::Double:
221 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
221 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
222 break;
222 break;
223 case PythonQtMethodInfo::Variant:
223 case PythonQtMethodInfo::Variant:
224 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
224 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
225 // return the ptr to the variant
225 // return the ptr to the variant
226 break;
226 break;
227 default:
227 default:
228 if (info.typeId == PythonQtMethodInfo::Unknown) {
228 if (info.typeId == PythonQtMethodInfo::Unknown) {
229 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
229 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
230 if (info.name.startsWith("QList<")) {
230 if (info.name.startsWith("QList<")) {
231 QByteArray innerType = info.name.mid(6,info.name.length()-7);
231 QByteArray innerType = info.name.mid(6,info.name.length()-7);
232 if (innerType.endsWith("*")) {
232 if (innerType.endsWith("*")) {
233 static int id = QMetaType::type("QList<void*>");
233 static int id = QMetaType::type("QList<void*>");
234 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
234 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
235 // return the constData pointer that will be filled with the result value later on
235 // return the constData pointer that will be filled with the result value later on
236 ptr = (void*)((QVariant*)ptr)->constData();
236 ptr = (void*)((QVariant*)ptr)->constData();
237 }
237 }
238 }
238 }
239 }
239 }
240
240
241 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
241 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
242 // everything else is stored in a QVariant, if we know the meta type...
242 // everything else is stored in a QVariant, if we know the meta type...
243 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
243 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
244 // return the constData pointer that will be filled with the result value later on
244 // return the constData pointer that will be filled with the result value later on
245 ptr = (void*)((QVariant*)ptr)->constData();
245 ptr = (void*)((QVariant*)ptr)->constData();
246 }
246 }
247 }
247 }
248 }
248 }
249 return ptr;
249 return ptr;
250 }
250 }
251
251
252 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
252 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
253 {
253 {
254 void* object;
254 void* object;
255 if (wrapper->classInfo()->isCPPWrapper()) {
255 if (wrapper->classInfo()->isCPPWrapper()) {
256 object = wrapper->_wrappedPtr;
256 object = wrapper->_wrappedPtr;
257 } else {
257 } else {
258 QObject* tmp = wrapper->_obj;
258 QObject* tmp = wrapper->_obj;
259 object = tmp;
259 object = tmp;
260 }
260 }
261 if (object) {
261 if (object) {
262 // if we can be upcasted to the given name, we pass the casted pointer in:
262 // if we can be upcasted to the given name, we pass the casted pointer in:
263 object = wrapper->classInfo()->castTo(object, className);
263 object = wrapper->classInfo()->castTo(object, className);
264 ok = object!=NULL;
264 ok = object!=NULL;
265 } else {
265 } else {
266 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
266 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
267 ok = wrapper->classInfo()->inherits(className);
267 ok = wrapper->classInfo()->inherits(className);
268 }
268 }
269 return object;
269 return object;
270 }
270 }
271
271
272 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
272 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
273 {
273 {
274 void* ptr = alreadyAllocatedCPPObject;
274 void* ptr = alreadyAllocatedCPPObject;
275
275
276 static int penId = QMetaType::type("QPen");
276 static int penId = QMetaType::type("QPen");
277 static int brushId = QMetaType::type("QBrush");
277 static int brushId = QMetaType::type("QBrush");
278 static int cursorId = QMetaType::type("QCursor");
278 static int cursorId = QMetaType::type("QCursor");
279 static int colorId = QMetaType::type("QColor");
279 static int colorId = QMetaType::type("QColor");
280 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
280 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
281 if (typeId == cursorId) {
281 if (typeId == cursorId) {
282 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
282 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
283 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
283 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
284 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
284 Qt::CursorShape val = (Qt::CursorShape)PyInt_AS_LONG(obj);
285 if (!ptr) {
285 if (!ptr) {
286 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
286 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
287 ptr = (void*)((QVariant*)ptr)->constData();
287 ptr = (void*)((QVariant*)ptr)->constData();
288 }
288 }
289 *((QCursor*)ptr) = QCursor(val);
289 *((QCursor*)ptr) = QCursor(val);
290 return ptr;
290 return ptr;
291 }
291 }
292 } else if (typeId == penId) {
292 } else if (typeId == penId) {
293 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
293 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
294 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
294 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
295 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
295 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
296 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
296 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
297 if (!ptr) {
297 if (!ptr) {
298 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
298 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
299 ptr = (void*)((QVariant*)ptr)->constData();
299 ptr = (void*)((QVariant*)ptr)->constData();
300 }
300 }
301 *((QPen*)ptr) = QPen(QColor(val));
301 *((QPen*)ptr) = QPen(QColor(val));
302 return ptr;
302 return ptr;
303 } else if ((PyObject*)obj->ob_type == qtColorClass) {
303 } else if ((PyObject*)obj->ob_type == qtColorClass) {
304 if (!ptr) {
304 if (!ptr) {
305 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
305 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
306 ptr = (void*)((QVariant*)ptr)->constData();
306 ptr = (void*)((QVariant*)ptr)->constData();
307 }
307 }
308 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
308 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
309 return ptr;
309 return ptr;
310 }
310 }
311 } else if (typeId == brushId) {
311 } else if (typeId == brushId) {
312 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
312 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
313 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
313 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
314 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
314 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
315 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
315 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
316 if (!ptr) {
316 if (!ptr) {
317 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
317 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
318 ptr = (void*)((QVariant*)ptr)->constData();
318 ptr = (void*)((QVariant*)ptr)->constData();
319 }
319 }
320 *((QBrush*)ptr) = QBrush(QColor(val));
320 *((QBrush*)ptr) = QBrush(QColor(val));
321 return ptr;
321 return ptr;
322 } else if ((PyObject*)obj->ob_type == qtColorClass) {
322 } else if ((PyObject*)obj->ob_type == qtColorClass) {
323 if (!ptr) {
323 if (!ptr) {
324 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
324 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
325 ptr = (void*)((QVariant*)ptr)->constData();
325 ptr = (void*)((QVariant*)ptr)->constData();
326 }
326 }
327 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
327 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
328 return ptr;
328 return ptr;
329 }
329 }
330 } else if (typeId == colorId) {
330 } else if (typeId == colorId) {
331 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
331 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
332 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
332 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
333 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
333 Qt::GlobalColor val = (Qt::GlobalColor)PyInt_AS_LONG(obj);
334 if (!ptr) {
334 if (!ptr) {
335 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
335 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
336 ptr = (void*)((QVariant*)ptr)->constData();
336 ptr = (void*)((QVariant*)ptr)->constData();
337 }
337 }
338 *((QColor*)ptr) = QColor(val);
338 *((QColor*)ptr) = QColor(val);
339 return ptr;
339 return ptr;
340 }
340 }
341 }
341 }
342 return NULL;
342 return NULL;
343 }
343 }
344
344
345 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
345 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
346 {
346 {
347 bool ok = false;
347 bool ok = false;
348 void* ptr = NULL;
348 void* ptr = NULL;
349
349
350 // autoconversion of QPen/QBrush/QCursor/QColor from different type
350 // autoconversion of QPen/QBrush/QCursor/QColor from different type
351 if (info.pointerCount==0 && !strict) {
351 if (info.pointerCount==0 && !strict) {
352 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
352 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
353 if (ptr) {
353 if (ptr) {
354 return ptr;
354 return ptr;
355 }
355 }
356 }
356 }
357
357
358 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
358 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
359 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
359 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
360 // (the Variant case is handled below in a switch)
360 // (the Variant case is handled below in a switch)
361
361
362 // a C++ wrapper (can be passed as pointer or reference)
362 // a C++ wrapper (can be passed as pointer or reference)
363 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
363 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
364 void* object = castWrapperTo(wrap, info.name, ok);
364 void* object = castWrapperTo(wrap, info.name, ok);
365 if (ok) {
365 if (ok) {
366 if (info.pointerCount==1) {
366 if (info.pointerCount==1) {
367 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
367 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
368 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
368 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
369 } else if (info.pointerCount==0) {
369 } else if (info.pointerCount==0) {
370 // store the wrapped pointer directly, since we are a reference
370 // store the wrapped pointer directly, since we are a reference
371 ptr = object;
371 ptr = object;
372 }
372 }
373 } else {
373 } else {
374 // not matching
374 // not matching
375 }
375 }
376 } else if (info.pointerCount == 1) {
376 } else if (info.pointerCount == 1) {
377 // a pointer
377 // a pointer
378 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
378 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
379 {
379 {
380 if (obj->ob_type == &PyString_Type) {
381 // take direct reference to string data
382 const char* data = PyString_AS_STRING(obj);
383 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)data, ptr);
384 } else {
385 // convert to string
380 QString str = PyObjGetString(obj, strict, ok);
386 QString str = PyObjGetString(obj, strict, ok);
381 if (ok) {
387 if (ok) {
388 QByteArray bytes;
389 bytes = str.toUtf8();
390 if (ok) {
382 void* ptr2 = NULL;
391 void* ptr2 = NULL;
383 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
392 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(bytes), ptr2);
384 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
393 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
385 }
394 }
395 }
396 }
397 } else if (info.typeId == QMetaType::QString) {
398 // TODO: this is a special case for bad Qt APIs which take a QString*, like QtGui.QFileDialog.getSaveFileName
399 // In general we would need to decide to either support * args for all basic types (ignoring the fact that the
400 // result value is not useable in Python), or if all these APIs need to be wrapped manually/differently, like PyQt/PySide do.
401 QString str = PyObjGetString(obj, strict, ok);
402 if (ok) {
403 void* ptr2 = NULL;
404 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(str), ptr2);
405 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)((QVariant*)ptr2)->constData(), ptr);
406 }
386 } else if (info.name == "PyObject") {
407 } else if (info.name == "PyObject") {
387 // handle low level PyObject directly
408 // handle low level PyObject directly
388 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
409 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
389 } else if (obj == Py_None) {
410 } else if (obj == Py_None) {
390 // None is treated as a NULL ptr
411 // None is treated as a NULL ptr
391 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
412 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
392 } else {
413 } else {
393 void* foreignWrapper = PythonQt::priv()->unwrapForeignWrapper(info.name, obj);
414 void* foreignWrapper = PythonQt::priv()->unwrapForeignWrapper(info.name, obj);
394 if (foreignWrapper) {
415 if (foreignWrapper) {
395 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, foreignWrapper, ptr);
416 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, foreignWrapper, ptr);
396 } else {
417 } else {
397 // if we are not strict, we try if we are passed a 0 integer
418 // if we are not strict, we try if we are passed a 0 integer
398 if (!strict) {
419 if (!strict) {
399 bool ok;
420 bool ok;
400 int value = PyObjGetInt(obj, true, ok);
421 int value = PyObjGetInt(obj, true, ok);
401 if (ok && value==0) {
422 if (ok && value==0) {
402 // TODOXXX is this wise? or should it be expected from the programmer to use None?
423 // TODOXXX is this wise? or should it be expected from the programmer to use None?
403 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
424 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
404 }
425 }
405 }
426 }
406 }
427 }
407 }
428 }
408 } else if (info.pointerCount == 0) {
429 } else if (info.pointerCount == 0) {
409 // not a pointer
430 // not a pointer
410 switch (info.typeId) {
431 switch (info.typeId) {
411 case QMetaType::Char:
432 case QMetaType::Char:
412 {
433 {
413 int val = PyObjGetInt(obj, strict, ok);
434 int val = PyObjGetInt(obj, strict, ok);
414 if (ok) {
435 if (ok) {
415 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
436 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
416 }
437 }
417 }
438 }
418 break;
439 break;
419 case QMetaType::UChar:
440 case QMetaType::UChar:
420 {
441 {
421 int val = PyObjGetInt(obj, strict, ok);
442 int val = PyObjGetInt(obj, strict, ok);
422 if (ok) {
443 if (ok) {
423 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
444 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
424 }
445 }
425 }
446 }
426 break;
447 break;
427 case QMetaType::Short:
448 case QMetaType::Short:
428 {
449 {
429 int val = PyObjGetInt(obj, strict, ok);
450 int val = PyObjGetInt(obj, strict, ok);
430 if (ok) {
451 if (ok) {
431 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
452 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
432 }
453 }
433 }
454 }
434 break;
455 break;
435 case QMetaType::UShort:
456 case QMetaType::UShort:
436 {
457 {
437 int val = PyObjGetInt(obj, strict, ok);
458 int val = PyObjGetInt(obj, strict, ok);
438 if (ok) {
459 if (ok) {
439 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
460 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
440 }
461 }
441 }
462 }
442 break;
463 break;
443 case QMetaType::Long:
464 case QMetaType::Long:
444 {
465 {
445 long val = (long)PyObjGetLongLong(obj, strict, ok);
466 long val = (long)PyObjGetLongLong(obj, strict, ok);
446 if (ok) {
467 if (ok) {
447 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
468 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
448 }
469 }
449 }
470 }
450 break;
471 break;
451 case QMetaType::ULong:
472 case QMetaType::ULong:
452 {
473 {
453 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
474 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
454 if (ok) {
475 if (ok) {
455 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
476 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
456 }
477 }
457 }
478 }
458 break;
479 break;
459 case QMetaType::Bool:
480 case QMetaType::Bool:
460 {
481 {
461 bool val = PyObjGetBool(obj, strict, ok);
482 bool val = PyObjGetBool(obj, strict, ok);
462 if (ok) {
483 if (ok) {
463 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
484 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
464 }
485 }
465 }
486 }
466 break;
487 break;
467 case QMetaType::Int:
488 case QMetaType::Int:
468 {
489 {
469 int val = PyObjGetInt(obj, strict, ok);
490 int val = PyObjGetInt(obj, strict, ok);
470 if (ok) {
491 if (ok) {
471 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
492 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
472 }
493 }
473 }
494 }
474 break;
495 break;
475 case QMetaType::UInt:
496 case QMetaType::UInt:
476 {
497 {
477 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
498 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
478 if (ok) {
499 if (ok) {
479 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
500 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
480 }
501 }
481 }
502 }
482 break;
503 break;
483 case QMetaType::QChar:
504 case QMetaType::QChar:
484 {
505 {
485 int val = PyObjGetInt(obj, strict, ok);
506 int val = PyObjGetInt(obj, strict, ok);
486 if (ok) {
507 if (ok) {
487 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
508 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
488 }
509 }
489 }
510 }
490 break;
511 break;
491 case QMetaType::Float:
512 case QMetaType::Float:
492 {
513 {
493 float val = (float)PyObjGetDouble(obj, strict, ok);
514 float val = (float)PyObjGetDouble(obj, strict, ok);
494 if (ok) {
515 if (ok) {
495 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
516 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
496 }
517 }
497 }
518 }
498 break;
519 break;
499 case QMetaType::Double:
520 case QMetaType::Double:
500 {
521 {
501 double val = (double)PyObjGetDouble(obj, strict, ok);
522 double val = (double)PyObjGetDouble(obj, strict, ok);
502 if (ok) {
523 if (ok) {
503 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
524 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
504 }
525 }
505 }
526 }
506 break;
527 break;
507 case QMetaType::LongLong:
528 case QMetaType::LongLong:
508 {
529 {
509 qint64 val = PyObjGetLongLong(obj, strict, ok);
530 qint64 val = PyObjGetLongLong(obj, strict, ok);
510 if (ok) {
531 if (ok) {
511 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
532 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
512 }
533 }
513 }
534 }
514 break;
535 break;
515 case QMetaType::ULongLong:
536 case QMetaType::ULongLong:
516 {
537 {
517 quint64 val = PyObjGetULongLong(obj, strict, ok);
538 quint64 val = PyObjGetULongLong(obj, strict, ok);
518 if (ok) {
539 if (ok) {
519 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
540 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
520 }
541 }
521 }
542 }
522 break;
543 break;
523 case QMetaType::QByteArray:
544 case QMetaType::QByteArray:
524 {
545 {
525 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
546 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
526 if (ok) {
547 if (ok) {
527 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
548 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
528 ptr = (void*)((QVariant*)ptr)->constData();
549 ptr = (void*)((QVariant*)ptr)->constData();
529 }
550 }
530 }
551 }
531 break;
552 break;
532 case QMetaType::QString:
553 case QMetaType::QString:
533 {
554 {
534 QString str = PyObjGetString(obj, strict, ok);
555 QString str = PyObjGetString(obj, strict, ok);
535 if (ok) {
556 if (ok) {
536 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
557 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
537 ptr = (void*)((QVariant*)ptr)->constData();
558 ptr = (void*)((QVariant*)ptr)->constData();
538 }
559 }
539 }
560 }
540 break;
561 break;
541 case QMetaType::QStringList:
562 case QMetaType::QStringList:
542 {
563 {
543 QStringList l = PyObjToStringList(obj, strict, ok);
564 QStringList l = PyObjToStringList(obj, strict, ok);
544 if (ok) {
565 if (ok) {
545 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
566 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
546 ptr = (void*)((QVariant*)ptr)->constData();
567 ptr = (void*)((QVariant*)ptr)->constData();
547 }
568 }
548 }
569 }
549 break;
570 break;
550
571
551 case PythonQtMethodInfo::Variant:
572 case PythonQtMethodInfo::Variant:
552 {
573 {
553 QVariant v = PyObjToQVariant(obj);
574 QVariant v = PyObjToQVariant(obj);
554 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
575 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
555 // so we do not check v.isValid() here
576 // so we do not check v.isValid() here
556 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
577 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
557 }
578 }
558 break;
579 break;
559 default:
580 default:
560 {
581 {
561 // check for enum case
582 // check for enum case
562 if (info.enumWrapper) {
583 if (info.enumWrapper) {
563 unsigned int val;
584 unsigned int val;
564 ok = false;
585 ok = false;
565 if ((PyObject*)obj->ob_type == info.enumWrapper) {
586 if ((PyObject*)obj->ob_type == info.enumWrapper) {
566 // we have a exact enum type match:
587 // we have a exact enum type match:
567 val = PyInt_AS_LONG(obj);
588 val = PyInt_AS_LONG(obj);
568 ok = true;
589 ok = true;
569 } else if (!strict) {
590 } else if (!strict) {
570 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
591 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
571 // we want an integer overload to be taken first!
592 // we want an integer overload to be taken first!
572 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
593 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
573 }
594 }
574 if (ok) {
595 if (ok) {
575 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
596 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
576 return ptr;
597 return ptr;
577 } else {
598 } else {
578 return NULL;
599 return NULL;
579 }
600 }
580 }
601 }
581
602
582 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
603 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
583 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
604 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
584 if (info.name.startsWith("QList<")) {
605 if (info.name.startsWith("QList<")) {
585 QByteArray innerType = info.name.mid(6,info.name.length()-7);
606 QByteArray innerType = info.name.mid(6,info.name.length()-7);
586 if (innerType.endsWith("*")) {
607 if (innerType.endsWith("*")) {
587 innerType.truncate(innerType.length()-1);
608 innerType.truncate(innerType.length()-1);
588 static int id = QMetaType::type("QList<void*>");
609 static int id = QMetaType::type("QList<void*>");
589 if (!alreadyAllocatedCPPObject) {
610 if (!alreadyAllocatedCPPObject) {
590 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
611 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
591 ptr = (void*)((QVariant*)ptr)->constData();
612 ptr = (void*)((QVariant*)ptr)->constData();
592 } else {
613 } else {
593 ptr = alreadyAllocatedCPPObject;
614 ptr = alreadyAllocatedCPPObject;
594 }
615 }
595 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
616 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
596 if (ok) {
617 if (ok) {
597 return ptr;
618 return ptr;
598 } else {
619 } else {
599 return NULL;
620 return NULL;
600 }
621 }
601 }
622 }
602 }
623 }
603 }
624 }
604
625
605 // We only do this for registered type > QMetaType::User for performance reasons.
626 // We only do this for registered type > QMetaType::User for performance reasons.
606 if (info.typeId >= QMetaType::User) {
627 if (info.typeId >= QMetaType::User) {
607 // Maybe we have a special converter that is registered for that type:
628 // Maybe we have a special converter that is registered for that type:
608 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
629 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
609 if (converter) {
630 if (converter) {
610 if (!alreadyAllocatedCPPObject) {
631 if (!alreadyAllocatedCPPObject) {
611 // create a new empty variant of concrete type:
632 // create a new empty variant of concrete type:
612 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
633 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
613 ptr = (void*)((QVariant*)ptr)->constData();
634 ptr = (void*)((QVariant*)ptr)->constData();
614 } else {
635 } else {
615 ptr = alreadyAllocatedCPPObject;
636 ptr = alreadyAllocatedCPPObject;
616 }
637 }
617 // now call the converter, passing the internal object of the variant
638 // now call the converter, passing the internal object of the variant
618 ok = (*converter)(obj, ptr, info.typeId, strict);
639 ok = (*converter)(obj, ptr, info.typeId, strict);
619 if (ok) {
640 if (ok) {
620 return ptr;
641 return ptr;
621 } else {
642 } else {
622 return NULL;
643 return NULL;
623 }
644 }
624 }
645 }
625 }
646 }
626 // if no type id is available, conversion to a QVariant makes no sense/is not possible
647 // if no type id is available, conversion to a QVariant makes no sense/is not possible
627 if (info.typeId != PythonQtMethodInfo::Unknown) {
648 if (info.typeId != PythonQtMethodInfo::Unknown) {
628 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
649 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
629 QVariant v = PyObjToQVariant(obj, info.typeId);
650 QVariant v = PyObjToQVariant(obj, info.typeId);
630 if (v.isValid()) {
651 if (v.isValid()) {
631 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
652 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
632 ptr = (void*)((QVariant*)ptr)->constData();
653 ptr = (void*)((QVariant*)ptr)->constData();
633 }
654 }
634 }
655 }
635 }
656 }
636 }
657 }
637 }
658 }
638 return ptr;
659 return ptr;
639 }
660 }
640
661
641
662
642 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
663 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
643 QStringList v;
664 QStringList v;
644 ok = false;
665 ok = false;
645 // if we are strict, we do not want to convert a string to a stringlist
666 // if we are strict, we do not want to convert a string to a stringlist
646 // (strings in python are detected to be sequences)
667 // (strings in python are detected to be sequences)
647 if (strict &&
668 if (strict &&
648 (val->ob_type == &PyString_Type ||
669 (val->ob_type == &PyString_Type ||
649 PyUnicode_Check(val))) {
670 PyUnicode_Check(val))) {
650 ok = false;
671 ok = false;
651 return v;
672 return v;
652 }
673 }
653 if (PySequence_Check(val)) {
674 if (PySequence_Check(val)) {
654 int count = PySequence_Size(val);
675 int count = PySequence_Size(val);
655 for (int i = 0;i<count;i++) {
676 for (int i = 0;i<count;i++) {
656 PyObject* value = PySequence_GetItem(val,i);
677 PyObject* value = PySequence_GetItem(val,i);
657 v.append(PyObjGetString(value,false,ok));
678 v.append(PyObjGetString(value,false,ok));
658 }
679 }
659 ok = true;
680 ok = true;
660 }
681 }
661 return v;
682 return v;
662 }
683 }
663
684
664 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
685 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
665 {
686 {
666 QString r;
687 QString r;
667 PyObject* str = PyObject_Repr(val);
688 PyObject* str = PyObject_Repr(val);
668 if (str) {
689 if (str) {
669 r = QString(PyString_AS_STRING(str));
690 r = QString(PyString_AS_STRING(str));
670 Py_DECREF(str);
691 Py_DECREF(str);
671 }
692 }
672 return r;
693 return r;
673 }
694 }
674
695
675 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
696 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
676 QString r;
697 QString r;
677 ok = true;
698 ok = true;
678 if (val->ob_type == &PyString_Type) {
699 if (val->ob_type == &PyString_Type) {
679 r = QString(PyString_AS_STRING(val));
700 r = QString(PyString_AS_STRING(val));
680 } else if (PyUnicode_Check(val)) {
701 } else if (PyUnicode_Check(val)) {
681 PyObject *ptmp = PyUnicode_AsUTF8String(val);
702 PyObject *ptmp = PyUnicode_AsUTF8String(val);
682 if(ptmp) {
703 if(ptmp) {
683 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
704 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
684 Py_DECREF(ptmp);
705 Py_DECREF(ptmp);
685 }
706 }
686 } else if (!strict) {
707 } else if (!strict) {
687 // EXTRA: could also use _Unicode, but why should we?
708 // EXTRA: could also use _Unicode, but why should we?
688 PyObject* str = PyObject_Str(val);
709 PyObject* str = PyObject_Str(val);
689 if (str) {
710 if (str) {
690 r = QString(PyString_AS_STRING(str));
711 r = QString(PyString_AS_STRING(str));
691 Py_DECREF(str);
712 Py_DECREF(str);
692 } else {
713 } else {
693 ok = false;
714 ok = false;
694 }
715 }
695 } else {
716 } else {
696 ok = false;
717 ok = false;
697 }
718 }
698 return r;
719 return r;
699 }
720 }
700
721
701 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
722 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
702 // TODO: support buffer objects in general
723 // TODO: support buffer objects in general
703 QByteArray r;
724 QByteArray r;
704 ok = true;
725 ok = true;
705 if (val->ob_type == &PyString_Type) {
726 if (val->ob_type == &PyString_Type) {
706 long size = PyString_GET_SIZE(val);
727 long size = PyString_GET_SIZE(val);
707 r = QByteArray(PyString_AS_STRING(val), size);
728 r = QByteArray(PyString_AS_STRING(val), size);
708 } else {
729 } else {
709 ok = false;
730 ok = false;
710 }
731 }
711 return r;
732 return r;
712 }
733 }
713
734
714 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
735 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
715 bool d = false;
736 bool d = false;
716 ok = false;
737 ok = false;
717 if (val == Py_False) {
738 if (val == Py_False) {
718 d = false;
739 d = false;
719 ok = true;
740 ok = true;
720 } else if (val == Py_True) {
741 } else if (val == Py_True) {
721 d = true;
742 d = true;
722 ok = true;
743 ok = true;
723 } else if (!strict) {
744 } else if (!strict) {
724 d = PyObjGetInt(val, false, ok)!=0;
745 d = PyObjGetInt(val, false, ok)!=0;
725 ok = true;
746 ok = true;
726 }
747 }
727 return d;
748 return d;
728 }
749 }
729
750
730 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
751 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
731 int d = 0;
752 int d = 0;
732 ok = true;
753 ok = true;
733 if (val->ob_type == &PyInt_Type) {
754 if (val->ob_type == &PyInt_Type) {
734 d = PyInt_AS_LONG(val);
755 d = PyInt_AS_LONG(val);
735 } else if (!strict) {
756 } else if (!strict) {
736 if (PyObject_TypeCheck(val, &PyInt_Type)) {
757 if (PyObject_TypeCheck(val, &PyInt_Type)) {
737 // support for derived int classes, e.g. for our enums
758 // support for derived int classes, e.g. for our enums
738 d = PyInt_AS_LONG(val);
759 d = PyInt_AS_LONG(val);
739 } else if (val->ob_type == &PyFloat_Type) {
760 } else if (val->ob_type == &PyFloat_Type) {
740 d = floor(PyFloat_AS_DOUBLE(val));
761 d = floor(PyFloat_AS_DOUBLE(val));
741 } else if (val->ob_type == &PyLong_Type) {
762 } else if (val->ob_type == &PyLong_Type) {
742 // handle error on overflow!
763 // handle error on overflow!
743 d = PyLong_AsLong(val);
764 d = PyLong_AsLong(val);
744 } else if (val == Py_False) {
765 } else if (val == Py_False) {
745 d = 0;
766 d = 0;
746 } else if (val == Py_True) {
767 } else if (val == Py_True) {
747 d = 1;
768 d = 1;
748 } else {
769 } else {
770 PyErr_Clear();
771 // PyInt_AsLong will try conversion to an int if the object is not an int:
772 d = PyInt_AsLong(val);
773 if (PyErr_Occurred()) {
749 ok = false;
774 ok = false;
775 PyErr_Clear();
776 }
750 }
777 }
751 } else {
778 } else {
752 ok = false;
779 ok = false;
753 }
780 }
754 return d;
781 return d;
755 }
782 }
756
783
757 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
784 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
758 qint64 d = 0;
785 qint64 d = 0;
759 ok = true;
786 ok = true;
760 if (val->ob_type == &PyInt_Type) {
787 if (val->ob_type == &PyInt_Type) {
761 d = PyInt_AS_LONG(val);
788 d = PyInt_AS_LONG(val);
762 } else if (val->ob_type == &PyLong_Type) {
789 } else if (val->ob_type == &PyLong_Type) {
763 d = PyLong_AsLongLong(val);
790 d = PyLong_AsLongLong(val);
764 } else if (!strict) {
791 } else if (!strict) {
765 if (PyObject_TypeCheck(val, &PyInt_Type)) {
792 if (PyObject_TypeCheck(val, &PyInt_Type)) {
766 // support for derived int classes, e.g. for our enums
793 // support for derived int classes, e.g. for our enums
767 d = PyInt_AS_LONG(val);
794 d = PyInt_AS_LONG(val);
768 } else if (val->ob_type == &PyFloat_Type) {
795 } else if (val->ob_type == &PyFloat_Type) {
769 d = floor(PyFloat_AS_DOUBLE(val));
796 d = floor(PyFloat_AS_DOUBLE(val));
770 } else if (val == Py_False) {
797 } else if (val == Py_False) {
771 d = 0;
798 d = 0;
772 } else if (val == Py_True) {
799 } else if (val == Py_True) {
773 d = 1;
800 d = 1;
774 } else {
801 } else {
802 PyErr_Clear();
803 // PyLong_AsLongLong will try conversion to an int if the object is not an int:
804 d = PyLong_AsLongLong(val);
805 if (PyErr_Occurred()) {
775 ok = false;
806 ok = false;
807 PyErr_Clear();
808 }
776 }
809 }
777 } else {
810 } else {
778 ok = false;
811 ok = false;
779 }
812 }
780 return d;
813 return d;
781 }
814 }
782
815
783 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
816 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
784 quint64 d = 0;
817 quint64 d = 0;
785 ok = true;
818 ok = true;
786 if (PyObject_TypeCheck(val, &PyInt_Type)) {
819 if (PyObject_TypeCheck(val, &PyInt_Type)) {
787 d = PyInt_AS_LONG(val);
820 d = PyInt_AS_LONG(val);
788 } else if (val->ob_type == &PyLong_Type) {
821 } else if (val->ob_type == &PyLong_Type) {
789 d = PyLong_AsLongLong(val);
822 d = PyLong_AsLongLong(val);
790 } else if (!strict) {
823 } else if (!strict) {
791 if (PyObject_TypeCheck(val, &PyInt_Type)) {
824 if (PyObject_TypeCheck(val, &PyInt_Type)) {
792 // support for derived int classes, e.g. for our enums
825 // support for derived int classes, e.g. for our enums
793 d = PyInt_AS_LONG(val);
826 d = PyInt_AS_LONG(val);
794 } else if (val->ob_type == &PyFloat_Type) {
827 } else if (val->ob_type == &PyFloat_Type) {
795 d = floor(PyFloat_AS_DOUBLE(val));
828 d = floor(PyFloat_AS_DOUBLE(val));
796 } else if (val == Py_False) {
829 } else if (val == Py_False) {
797 d = 0;
830 d = 0;
798 } else if (val == Py_True) {
831 } else if (val == Py_True) {
799 d = 1;
832 d = 1;
800 } else {
833 } else {
834 PyErr_Clear();
835 // PyLong_AsLongLong will try conversion to an int if the object is not an int:
836 d = PyLong_AsLongLong(val);
837 if (PyErr_Occurred()) {
838 PyErr_Clear();
801 ok = false;
839 ok = false;
802 }
840 }
841 }
803 } else {
842 } else {
804 ok = false;
843 ok = false;
805 }
844 }
806 return d;
845 return d;
807 }
846 }
808
847
809 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
848 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
810 double d = 0;
849 double d = 0;
811 ok = true;
850 ok = true;
812 if (val->ob_type == &PyFloat_Type) {
851 if (val->ob_type == &PyFloat_Type) {
813 d = PyFloat_AS_DOUBLE(val);
852 d = PyFloat_AS_DOUBLE(val);
814 } else if (!strict) {
853 } else if (!strict) {
815 if (PyObject_TypeCheck(val, &PyInt_Type)) {
854 if (PyObject_TypeCheck(val, &PyInt_Type)) {
816 d = PyInt_AS_LONG(val);
855 d = PyInt_AS_LONG(val);
817 } else if (val->ob_type == &PyLong_Type) {
856 } else if (val->ob_type == &PyLong_Type) {
818 d = PyLong_AsLong(val);
857 d = PyLong_AsLong(val);
819 } else if (val == Py_False) {
858 } else if (val == Py_False) {
820 d = 0;
859 d = 0;
821 } else if (val == Py_True) {
860 } else if (val == Py_True) {
822 d = 1;
861 d = 1;
823 } else {
862 } else {
863 PyErr_Clear();
864 // PyFloat_AsDouble will try conversion to a double if the object is not a float:
865 d = PyFloat_AsDouble(val);
866 if (PyErr_Occurred()) {
867 PyErr_Clear();
824 ok = false;
868 ok = false;
825 }
869 }
870 }
826 } else {
871 } else {
827 ok = false;
872 ok = false;
828 }
873 }
829 return d;
874 return d;
830 }
875 }
831
876
832 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
877 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
833 {
878 {
834 QVariant v;
879 QVariant v;
835 bool ok = true;
880 bool ok = true;
836
881
837 if (type==-1) {
882 if (type==-1) {
838 // no special type requested
883 // no special type requested
839 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
884 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
840 type = QVariant::String;
885 type = QVariant::String;
841 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
886 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
842 type = QVariant::Int;
887 type = QVariant::Int;
843 } else if (val->ob_type==&PyLong_Type) {
888 } else if (val->ob_type==&PyLong_Type) {
844 type = QVariant::LongLong;
889 type = QVariant::LongLong;
845 } else if (val->ob_type==&PyFloat_Type) {
890 } else if (val->ob_type==&PyFloat_Type) {
846 type = QVariant::Double;
891 type = QVariant::Double;
847 } else if (val == Py_False || val == Py_True) {
892 } else if (val == Py_False || val == Py_True) {
848 type = QVariant::Bool;
893 type = QVariant::Bool;
849 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
894 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
850 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
895 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
851 // c++ wrapper, check if the class names of the c++ objects match
896 // c++ wrapper, check if the class names of the c++ objects match
852 if (wrap->classInfo()->isCPPWrapper()) {
897 if (wrap->classInfo()->isCPPWrapper()) {
853 if (wrap->classInfo()->metaTypeId()>0) {
898 if (wrap->classInfo()->metaTypeId()>0) {
854 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
899 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
855 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
900 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
856 } else {
901 } else {
857 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
902 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
858 // the pointer here...
903 // the pointer here...
859 // is this worth anything? we loose the knowledge of the cpp object type
904 // is this worth anything? we loose the knowledge of the cpp object type
860 v = qVariantFromValue(wrap->_wrappedPtr);
905 v = qVariantFromValue(wrap->_wrappedPtr);
861 }
906 }
862 } else {
907 } else {
863 // this gives us a QObject pointer
908 // this gives us a QObject pointer
864 QObject* myObject = wrap->_obj;
909 QObject* myObject = wrap->_obj;
865 v = qVariantFromValue(myObject);
910 v = qVariantFromValue(myObject);
866 }
911 }
867 return v;
912 return v;
868 } else if (val->ob_type==&PyDict_Type) {
913 } else if (val->ob_type==&PyDict_Type) {
869 type = QVariant::Map;
914 type = QVariant::Map;
870 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
915 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
871 type = QVariant::List;
916 type = QVariant::List;
872 } else if (val == Py_None) {
917 } else if (val == Py_None) {
873 // none is invalid
918 // none is invalid
874 type = QVariant::Invalid;
919 type = QVariant::Invalid;
875 } else {
920 } else {
876 // this used to be:
921 // this used to be:
877 // type = QVariant::String;
922 // type = QVariant::String;
878 // but now we want to transport the Python Objects directly:
923 // but now we want to transport the Python Objects directly:
879 PythonQtObjectPtr o(val);
924 PythonQtObjectPtr o(val);
880 v = qVariantFromValue(o);
925 v = qVariantFromValue(o);
881 return v;
926 return v;
882 }
927 }
883 }
928 }
884 // special type request:
929 // special type request:
885 switch (type) {
930 switch (type) {
886 case QVariant::Invalid:
931 case QVariant::Invalid:
887 return v;
932 return v;
888 break;
933 break;
889 case QVariant::Int:
934 case QVariant::Int:
890 {
935 {
891 int d = PyObjGetInt(val, false, ok);
936 int d = PyObjGetInt(val, false, ok);
892 if (ok) return QVariant(d);
937 if (ok) return QVariant(d);
893 }
938 }
894 break;
939 break;
895 case QVariant::UInt:
940 case QVariant::UInt:
896 {
941 {
897 int d = PyObjGetInt(val, false,ok);
942 int d = PyObjGetInt(val, false,ok);
898 if (ok) v = QVariant((unsigned int)d);
943 if (ok) v = QVariant((unsigned int)d);
899 }
944 }
900 break;
945 break;
901 case QVariant::Bool:
946 case QVariant::Bool:
902 {
947 {
903 int d = PyObjGetBool(val,false,ok);
948 int d = PyObjGetBool(val,false,ok);
904 if (ok) v = QVariant((bool)(d!=0));
949 if (ok) v = QVariant((bool)(d!=0));
905 }
950 }
906 break;
951 break;
907 case QVariant::Double:
952 case QVariant::Double:
908 {
953 {
909 double d = PyObjGetDouble(val,false,ok);
954 double d = PyObjGetDouble(val,false,ok);
910 if (ok) v = QVariant(d);
955 if (ok) v = QVariant(d);
911 break;
956 break;
912 }
957 }
913 case QMetaType::Float:
958 case QMetaType::Float:
914 {
959 {
915 float d = (float) PyObjGetDouble(val,false,ok);
960 float d = (float) PyObjGetDouble(val,false,ok);
916 if (ok) v = qVariantFromValue(d);
961 if (ok) v = qVariantFromValue(d);
917 break;
962 break;
918 }
963 }
919 case QMetaType::Long:
964 case QMetaType::Long:
920 {
965 {
921 long d = (long) PyObjGetLongLong(val,false,ok);
966 long d = (long) PyObjGetLongLong(val,false,ok);
922 if (ok) v = qVariantFromValue(d);
967 if (ok) v = qVariantFromValue(d);
923 break;
968 break;
924 }
969 }
925 case QMetaType::ULong:
970 case QMetaType::ULong:
926 {
971 {
927 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
972 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
928 if (ok) v = qVariantFromValue(d);
973 if (ok) v = qVariantFromValue(d);
929 break;
974 break;
930 }
975 }
931 case QMetaType::LongLong:
976 case QMetaType::LongLong:
932 {
977 {
933 qint64 d = PyObjGetLongLong(val, false, ok);
978 qint64 d = PyObjGetLongLong(val, false, ok);
934 if (ok) v = qVariantFromValue(d);
979 if (ok) v = qVariantFromValue(d);
935 }
980 }
936 break;
981 break;
937 case QMetaType::ULongLong:
982 case QMetaType::ULongLong:
938 {
983 {
939 quint64 d = PyObjGetULongLong(val, false, ok);
984 quint64 d = PyObjGetULongLong(val, false, ok);
940 if (ok) v = qVariantFromValue(d);
985 if (ok) v = qVariantFromValue(d);
941 }
986 }
942 break;
987 break;
943 case QMetaType::Short:
988 case QMetaType::Short:
944 {
989 {
945 short d = (short) PyObjGetInt(val,false,ok);
990 short d = (short) PyObjGetInt(val,false,ok);
946 if (ok) v = qVariantFromValue(d);
991 if (ok) v = qVariantFromValue(d);
947 break;
992 break;
948 }
993 }
949 case QMetaType::UShort:
994 case QMetaType::UShort:
950 {
995 {
951 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
996 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
952 if (ok) v = qVariantFromValue(d);
997 if (ok) v = qVariantFromValue(d);
953 break;
998 break;
954 }
999 }
955 case QMetaType::Char:
1000 case QMetaType::Char:
956 {
1001 {
957 char d = (char) PyObjGetInt(val,false,ok);
1002 char d = (char) PyObjGetInt(val,false,ok);
958 if (ok) v = qVariantFromValue(d);
1003 if (ok) v = qVariantFromValue(d);
959 break;
1004 break;
960 }
1005 }
961 case QMetaType::UChar:
1006 case QMetaType::UChar:
962 {
1007 {
963 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
1008 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
964 if (ok) v = qVariantFromValue(d);
1009 if (ok) v = qVariantFromValue(d);
965 break;
1010 break;
966 }
1011 }
967
1012
968 case QVariant::ByteArray:
1013 case QVariant::ByteArray:
969 case QVariant::String:
1014 case QVariant::String:
970 {
1015 {
971 bool ok;
1016 bool ok;
972 v = QVariant(PyObjGetString(val, false, ok));
1017 v = QVariant(PyObjGetString(val, false, ok));
973 }
1018 }
974 break;
1019 break;
975
1020
976 // these are important for MeVisLab
1021 // these are important for MeVisLab
977 case QVariant::Map:
1022 case QVariant::Map:
978 {
1023 {
979 if (PyMapping_Check(val)) {
1024 if (PyMapping_Check(val)) {
980 QMap<QString,QVariant> map;
1025 QMap<QString,QVariant> map;
981 PyObject* items = PyMapping_Items(val);
1026 PyObject* items = PyMapping_Items(val);
982 if (items) {
1027 if (items) {
983 int count = PyList_Size(items);
1028 int count = PyList_Size(items);
984 PyObject* value;
1029 PyObject* value;
985 PyObject* key;
1030 PyObject* key;
986 PyObject* tuple;
1031 PyObject* tuple;
987 for (int i = 0;i<count;i++) {
1032 for (int i = 0;i<count;i++) {
988 tuple = PyList_GetItem(items,i);
1033 tuple = PyList_GetItem(items,i);
989 key = PyTuple_GetItem(tuple, 0);
1034 key = PyTuple_GetItem(tuple, 0);
990 value = PyTuple_GetItem(tuple, 1);
1035 value = PyTuple_GetItem(tuple, 1);
991 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
1036 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
992 }
1037 }
993 Py_DECREF(items);
1038 Py_DECREF(items);
994 v = map;
1039 v = map;
995 }
1040 }
996 }
1041 }
997 }
1042 }
998 break;
1043 break;
999 case QVariant::List:
1044 case QVariant::List:
1000 if (PySequence_Check(val)) {
1045 if (PySequence_Check(val)) {
1001 QVariantList list;
1046 QVariantList list;
1002 int count = PySequence_Size(val);
1047 int count = PySequence_Size(val);
1003 PyObject* value;
1048 PyObject* value;
1004 for (int i = 0;i<count;i++) {
1049 for (int i = 0;i<count;i++) {
1005 value = PySequence_GetItem(val,i);
1050 value = PySequence_GetItem(val,i);
1006 list.append(PyObjToQVariant(value, -1));
1051 list.append(PyObjToQVariant(value, -1));
1007 }
1052 }
1008 v = list;
1053 v = list;
1009 }
1054 }
1010 break;
1055 break;
1011 case QVariant::StringList:
1056 case QVariant::StringList:
1012 {
1057 {
1013 bool ok;
1058 bool ok;
1014 QStringList l = PyObjToStringList(val, false, ok);
1059 QStringList l = PyObjToStringList(val, false, ok);
1015 if (ok) {
1060 if (ok) {
1016 v = l;
1061 v = l;
1017 }
1062 }
1018 }
1063 }
1019 break;
1064 break;
1020
1065
1021 default:
1066 default:
1022 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1067 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1023 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1068 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1024 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1069 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1025 // construct a new variant from the C++ object if it has the same meta type
1070 // construct a new variant from the C++ object if it has the same meta type
1026 v = QVariant(type, wrap->_wrappedPtr);
1071 v = QVariant(type, wrap->_wrappedPtr);
1027 } else {
1072 } else {
1028 v = QVariant();
1073 v = QVariant();
1029 }
1074 }
1030 } else {
1075 } else {
1031 v = QVariant();
1076 v = QVariant();
1032 }
1077 }
1033 }
1078 }
1034 return v;
1079 return v;
1035 }
1080 }
1036
1081
1037 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1082 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1038 {
1083 {
1039 if (str.isNull()) {
1084 if (str.isNull()) {
1040 return PyString_FromString("");
1085 return PyString_FromString("");
1041 } else {
1086 } else {
1042 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1087 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1043 }
1088 }
1044 }
1089 }
1045
1090
1046 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1091 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1047 {
1092 {
1048 PyObject* result = PyTuple_New(list.count());
1093 PyObject* result = PyTuple_New(list.count());
1049 int i = 0;
1094 int i = 0;
1050 QString str;
1095 QString str;
1051 foreach (str, list) {
1096 foreach (str, list) {
1052 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1097 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1053 i++;
1098 i++;
1054 }
1099 }
1055 // why is the error state bad after this?
1100 // why is the error state bad after this?
1056 PyErr_Clear();
1101 PyErr_Clear();
1057 return result;
1102 return result;
1058 }
1103 }
1059
1104
1060 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1105 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1061 {
1106 {
1062 PyObject* result = PyList_New(list.count());
1107 PyObject* result = PyList_New(list.count());
1063 int i = 0;
1108 int i = 0;
1064 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1109 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1065 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1110 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1066 i++;
1111 i++;
1067 }
1112 }
1068 return result;
1113 return result;
1069 }
1114 }
1070
1115
1071 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1116 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1072 {
1117 {
1073 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1118 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1074 }
1119 }
1075
1120
1076 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1121 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1077 PyObject* result = PyDict_New();
1122 PyObject* result = PyDict_New();
1078 QVariantMap::const_iterator t = m.constBegin();
1123 QVariantMap::const_iterator t = m.constBegin();
1079 PyObject* key;
1124 PyObject* key;
1080 PyObject* val;
1125 PyObject* val;
1081 for (;t!=m.end();t++) {
1126 for (;t!=m.end();t++) {
1082 key = QStringToPyObject(t.key());
1127 key = QStringToPyObject(t.key());
1083 val = QVariantToPyObject(t.value());
1128 val = QVariantToPyObject(t.value());
1084 PyDict_SetItem(result, key, val);
1129 PyDict_SetItem(result, key, val);
1085 Py_DECREF(key);
1130 Py_DECREF(key);
1086 Py_DECREF(val);
1131 Py_DECREF(val);
1087 }
1132 }
1088 return result;
1133 return result;
1089 }
1134 }
1090
1135
1091 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1136 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1092 PyObject* result = PyTuple_New(l.count());
1137 PyObject* result = PyTuple_New(l.count());
1093 int i = 0;
1138 int i = 0;
1094 QVariant v;
1139 QVariant v;
1095 foreach (v, l) {
1140 foreach (v, l) {
1096 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1141 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1097 i++;
1142 i++;
1098 }
1143 }
1099 // why is the error state bad after this?
1144 // why is the error state bad after this?
1100 PyErr_Clear();
1145 PyErr_Clear();
1101 return result;
1146 return result;
1102 }
1147 }
1103
1148
1104 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1149 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1105 {
1150 {
1106 PyObject* result = PyTuple_New(list->count());
1151 PyObject* result = PyTuple_New(list->count());
1107 int i = 0;
1152 int i = 0;
1108 foreach (void* value, *list) {
1153 foreach (void* value, *list) {
1109 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1154 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1110 i++;
1155 i++;
1111 }
1156 }
1112 return result;
1157 return result;
1113 }
1158 }
1114
1159
1115 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1160 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1116 {
1161 {
1117 bool result = false;
1162 bool result = false;
1118 if (PySequence_Check(obj)) {
1163 if (PySequence_Check(obj)) {
1119 result = true;
1164 result = true;
1120 int count = PySequence_Size(obj);
1165 int count = PySequence_Size(obj);
1121 PyObject* value;
1166 PyObject* value;
1122 for (int i = 0;i<count;i++) {
1167 for (int i = 0;i<count;i++) {
1123 value = PySequence_GetItem(obj,i);
1168 value = PySequence_GetItem(obj,i);
1124 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1169 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1125 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1170 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1126 bool ok;
1171 bool ok;
1127 void* object = castWrapperTo(wrap, type, ok);
1172 void* object = castWrapperTo(wrap, type, ok);
1128 if (ok) {
1173 if (ok) {
1129 list->append(object);
1174 list->append(object);
1130 } else {
1175 } else {
1131 result = false;
1176 result = false;
1132 break;
1177 break;
1133 }
1178 }
1134 }
1179 }
1135 }
1180 }
1136 }
1181 }
1137 return result;
1182 return result;
1138 }
1183 }
1139
1184
1140 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1185 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1141 {
1186 {
1142 int idx = typeName.indexOf("<");
1187 int idx = typeName.indexOf("<");
1143 if (idx>0) {
1188 if (idx>0) {
1144 int idx2 = typeName.indexOf(">");
1189 int idx2 = typeName.indexOf(">");
1145 if (idx2>0) {
1190 if (idx2>0) {
1146 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1191 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1147 return QMetaType::type(innerType.constData());
1192 return QMetaType::type(innerType.constData());
1148 }
1193 }
1149 }
1194 }
1150 return QMetaType::Void;
1195 return QMetaType::Void;
1151 }
1196 }
1152
1197
1153
1198
1154 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1199 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1155 QString r;
1200 QString r;
1156 switch (type) {
1201 switch (type) {
1157 case QVariant::Size: {
1202 case QVariant::Size: {
1158 const QSize* s = static_cast<const QSize*>(data);
1203 const QSize* s = static_cast<const QSize*>(data);
1159 r = QString::number(s->width()) + ", " + QString::number(s->height());
1204 r = QString::number(s->width()) + ", " + QString::number(s->height());
1160 }
1205 }
1161 break;
1206 break;
1162 case QVariant::SizeF: {
1207 case QVariant::SizeF: {
1163 const QSizeF* s = static_cast<const QSizeF*>(data);
1208 const QSizeF* s = static_cast<const QSizeF*>(data);
1164 r = QString::number(s->width()) + ", " + QString::number(s->height());
1209 r = QString::number(s->width()) + ", " + QString::number(s->height());
1165 }
1210 }
1166 break;
1211 break;
1167 case QVariant::Point: {
1212 case QVariant::Point: {
1168 const QPoint* s = static_cast<const QPoint*>(data);
1213 const QPoint* s = static_cast<const QPoint*>(data);
1169 r = QString::number(s->x()) + ", " + QString::number(s->y());
1214 r = QString::number(s->x()) + ", " + QString::number(s->y());
1170 }
1215 }
1171 break;
1216 break;
1172 case QVariant::PointF: {
1217 case QVariant::PointF: {
1173 const QPointF* s = static_cast<const QPointF*>(data);
1218 const QPointF* s = static_cast<const QPointF*>(data);
1174 r = QString::number(s->x()) + ", " + QString::number(s->y());
1219 r = QString::number(s->x()) + ", " + QString::number(s->y());
1175 }
1220 }
1176 break;
1221 break;
1177 case QVariant::Rect: {
1222 case QVariant::Rect: {
1178 const QRect* s = static_cast<const QRect*>(data);
1223 const QRect* s = static_cast<const QRect*>(data);
1179 r = QString::number(s->x()) + ", " + QString::number(s->y());
1224 r = QString::number(s->x()) + ", " + QString::number(s->y());
1180 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1225 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1181 }
1226 }
1182 break;
1227 break;
1183 case QVariant::RectF: {
1228 case QVariant::RectF: {
1184 const QRectF* s = static_cast<const QRectF*>(data);
1229 const QRectF* s = static_cast<const QRectF*>(data);
1185 r = QString::number(s->x()) + ", " + QString::number(s->y());
1230 r = QString::number(s->x()) + ", " + QString::number(s->y());
1186 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1231 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1187 }
1232 }
1188 break;
1233 break;
1189 case QVariant::Date: {
1234 case QVariant::Date: {
1190 const QDate* s = static_cast<const QDate*>(data);
1235 const QDate* s = static_cast<const QDate*>(data);
1191 r = s->toString(Qt::ISODate);
1236 r = s->toString(Qt::ISODate);
1192 }
1237 }
1193 break;
1238 break;
1194 case QVariant::DateTime: {
1239 case QVariant::DateTime: {
1195 const QDateTime* s = static_cast<const QDateTime*>(data);
1240 const QDateTime* s = static_cast<const QDateTime*>(data);
1196 r = s->toString(Qt::ISODate);
1241 r = s->toString(Qt::ISODate);
1197 }
1242 }
1198 break;
1243 break;
1199 case QVariant::Time: {
1244 case QVariant::Time: {
1200 const QTime* s = static_cast<const QTime*>(data);
1245 const QTime* s = static_cast<const QTime*>(data);
1201 r = s->toString(Qt::ISODate);
1246 r = s->toString(Qt::ISODate);
1202 }
1247 }
1203 break;
1248 break;
1204 case QVariant::Pixmap:
1249 case QVariant::Pixmap:
1205 {
1250 {
1206 const QPixmap* s = static_cast<const QPixmap*>(data);
1251 const QPixmap* s = static_cast<const QPixmap*>(data);
1207 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1252 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1208 }
1253 }
1209 break;
1254 break;
1210 case QVariant::Image:
1255 case QVariant::Image:
1211 {
1256 {
1212 const QImage* s = static_cast<const QImage*>(data);
1257 const QImage* s = static_cast<const QImage*>(data);
1213 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1258 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1214 }
1259 }
1215 break;
1260 break;
1216 case QVariant::Url:
1261 case QVariant::Url:
1217 {
1262 {
1218 const QUrl* s = static_cast<const QUrl*>(data);
1263 const QUrl* s = static_cast<const QUrl*>(data);
1219 r = s->toString();
1264 r = s->toString();
1220 }
1265 }
1221 break;
1266 break;
1222 //TODO: add more printing for other variant types
1267 //TODO: add more printing for other variant types
1223 default:
1268 default:
1224 // this creates a copy, but that should not be expensive for typical simple variants
1269 // this creates a copy, but that should not be expensive for typical simple variants
1225 // (but we do not want to do this for our won user types!
1270 // (but we do not want to do this for our won user types!
1226 if (type>0 && type < (int)QVariant::UserType) {
1271 if (type>0 && type < (int)QVariant::UserType) {
1227 QVariant v(type, data);
1272 QVariant v(type, data);
1228 r = v.toString();
1273 r = v.toString();
1229 }
1274 }
1230 }
1275 }
1231 return r;
1276 return r;
1232 }
1277 }
@@ -1,774 +1,774
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtInstanceWrapper.cpp
35 // \file PythonQtInstanceWrapper.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtInstanceWrapper.h"
42 #include "PythonQtInstanceWrapper.h"
43 #include <QObject>
43 #include <QObject>
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include "PythonQtSlot.h"
45 #include "PythonQtSlot.h"
46 #include "PythonQtSignal.h"
46 #include "PythonQtSignal.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49 #include "PythonQtClassWrapper.h"
49 #include "PythonQtClassWrapper.h"
50
50
51 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
51 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
52 {
52 {
53 // take the class info from our type object
53 // take the class info from our type object
54 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
54 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
55 }
55 }
56
56
57 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
57 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
58
58
59 // is this a C++ wrapper?
59 // is this a C++ wrapper?
60 if (self->_wrappedPtr) {
60 if (self->_wrappedPtr) {
61 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
61 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
62
62
63 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
63 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
64 // we own our qobject, so we delete it now:
64 // we own our qobject, so we delete it now:
65 delete self->_obj;
65 delete self->_obj;
66 self->_obj = NULL;
66 self->_obj = NULL;
67 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
67 if (force || self->_ownedByPythonQt) {
68 int type = self->classInfo()->metaTypeId();
68 int type = self->classInfo()->metaTypeId();
69 if (self->_useQMetaTypeDestroy && type>=0) {
69 if (self->_useQMetaTypeDestroy && type>=0) {
70 // use QMetaType to destroy the object
70 // use QMetaType to destroy the object
71 QMetaType::destroy(type, self->_wrappedPtr);
71 QMetaType::destroy(type, self->_wrappedPtr);
72 } else {
72 } else {
73 PythonQtSlotInfo* slot = self->classInfo()->destructor();
73 PythonQtSlotInfo* slot = self->classInfo()->destructor();
74 if (slot) {
74 if (slot) {
75 void* args[2];
75 void* args[2];
76 args[0] = NULL;
76 args[0] = NULL;
77 args[1] = &self->_wrappedPtr;
77 args[1] = &self->_wrappedPtr;
78 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
78 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
79 self->_wrappedPtr = NULL;
79 self->_wrappedPtr = NULL;
80 } else {
80 } else {
81 if (type>=0) {
81 if (type>=0) {
82 // use QMetaType to destroy the object
82 // use QMetaType to destroy the object
83 QMetaType::destroy(type, self->_wrappedPtr);
83 QMetaType::destroy(type, self->_wrappedPtr);
84 } else {
84 } else {
85 // TODO: warn about not being able to destroy the object?
85 // TODO: warn about not being able to destroy the object?
86 }
86 }
87 }
87 }
88 }
88 }
89 }
89 }
90 } else {
90 } else {
91 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
91 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
92 if (self->_objPointerCopy) {
92 if (self->_objPointerCopy) {
93 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
93 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
94 }
94 }
95 if (self->_obj) {
95 if (self->_obj) {
96 if (force || self->_ownedByPythonQt) {
96 if (force || self->_ownedByPythonQt) {
97 if (force || !self->_obj->parent()) {
97 if (force || !self->_obj->parent()) {
98 delete self->_obj;
98 delete self->_obj;
99 }
99 }
100 } else {
100 } else {
101 if (self->_obj->parent()==NULL) {
101 if (self->_obj->parent()==NULL) {
102 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
102 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
103 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
103 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
104 }
104 }
105 }
105 }
106 }
106 }
107 }
107 }
108 self->_obj = NULL;
108 self->_obj = NULL;
109 }
109 }
110
110
111 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
111 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
112 {
112 {
113 PythonQtInstanceWrapper_deleteObject(self);
113 PythonQtInstanceWrapper_deleteObject(self);
114 self->_obj.~QPointer<QObject>();
114 self->_obj.~QPointer<QObject>();
115 self->ob_type->tp_free((PyObject*)self);
115 self->ob_type->tp_free((PyObject*)self);
116 }
116 }
117
117
118 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
118 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
119 {
119 {
120 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
120 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
121 PythonQtInstanceWrapper *self;
121 PythonQtInstanceWrapper *self;
122 static PyObject* emptyTuple = NULL;
122 static PyObject* emptyTuple = NULL;
123 if (emptyTuple==NULL) {
123 if (emptyTuple==NULL) {
124 emptyTuple = PyTuple_New(0);
124 emptyTuple = PyTuple_New(0);
125 }
125 }
126
126
127 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
127 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
128
128
129 if (self != NULL) {
129 if (self != NULL) {
130 new (&self->_obj) QPointer<QObject>();
130 new (&self->_obj) QPointer<QObject>();
131 self->_wrappedPtr = NULL;
131 self->_wrappedPtr = NULL;
132 self->_ownedByPythonQt = false;
132 self->_ownedByPythonQt = false;
133 self->_useQMetaTypeDestroy = false;
133 self->_useQMetaTypeDestroy = false;
134 self->_isShellInstance = false;
134 self->_isShellInstance = false;
135 }
135 }
136 return (PyObject *)self;
136 return (PyObject *)self;
137 }
137 }
138
138
139 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
139 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
140 {
140 {
141 if (args == PythonQtPrivate::dummyTuple()) {
141 if (args == PythonQtPrivate::dummyTuple()) {
142 // we are called from the internal PythonQt API, so our data will be filled later on...
142 // we are called from the internal PythonQt API, so our data will be filled later on...
143 return 0;
143 return 0;
144 }
144 }
145
145
146 // we are called from python, try to construct our object
146 // we are called from python, try to construct our object
147 if (self->classInfo()->constructors()) {
147 if (self->classInfo()->constructors()) {
148 void* directCPPPointer = NULL;
148 void* directCPPPointer = NULL;
149 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
149 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
150 if (PyErr_Occurred()) {
150 if (PyErr_Occurred()) {
151 return -1;
151 return -1;
152 }
152 }
153 if (directCPPPointer) {
153 if (directCPPPointer) {
154 // change ownershipflag to be owned by PythonQt
154 // change ownershipflag to be owned by PythonQt
155 self->_ownedByPythonQt = true;
155 self->_ownedByPythonQt = true;
156 self->_useQMetaTypeDestroy = false;
156 self->_useQMetaTypeDestroy = false;
157 if (self->classInfo()->isCPPWrapper()) {
157 if (self->classInfo()->isCPPWrapper()) {
158 self->_wrappedPtr = directCPPPointer;
158 self->_wrappedPtr = directCPPPointer;
159 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
159 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
160 } else {
160 } else {
161 self->setQObject((QObject*)directCPPPointer);
161 self->setQObject((QObject*)directCPPPointer);
162 }
162 }
163 // register with PythonQt
163 // register with PythonQt
164 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
164 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
165
165
166 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
166 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
167 if (cb) {
167 if (cb) {
168 // if we are a derived python class, we set the wrapper
168 // if we are a derived python class, we set the wrapper
169 // to activate the shell class, otherwise we just ignore that it is a shell...
169 // to activate the shell class, otherwise we just ignore that it is a shell...
170 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
170 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
171 // which is the case for all non-python derived types
171 // which is the case for all non-python derived types
172 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
172 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
173 // set the wrapper and remember that we have a shell instance!
173 // set the wrapper and remember that we have a shell instance!
174 (*cb)(directCPPPointer, self);
174 (*cb)(directCPPPointer, self);
175 self->_isShellInstance = true;
175 self->_isShellInstance = true;
176 }
176 }
177 }
177 }
178 }
178 }
179 } else {
179 } else {
180 QString error = QString("No constructors available for ") + self->classInfo()->className();
180 QString error = QString("No constructors available for ") + self->classInfo()->className();
181 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
181 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
182 return -1;
182 return -1;
183 }
183 }
184 return 0;
184 return 0;
185 }
185 }
186
186
187 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
187 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
188 {
188 {
189 bool validPtrs = false;
189 bool validPtrs = false;
190 bool areSamePtrs = false;
190 bool areSamePtrs = false;
191 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
191 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
192 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
192 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
193 validPtrs = true;
193 validPtrs = true;
194 PythonQtInstanceWrapper* w1 = wrapper;
194 PythonQtInstanceWrapper* w1 = wrapper;
195 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
195 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
196 // check pointers directly
196 // check pointers directly
197 if (w1->_wrappedPtr != NULL) {
197 if (w1->_wrappedPtr != NULL) {
198 if (w1->_wrappedPtr == w2->_wrappedPtr) {
198 if (w1->_wrappedPtr == w2->_wrappedPtr) {
199 areSamePtrs = true;
199 areSamePtrs = true;
200 }
200 }
201 } else if (w1->_obj == w2->_obj) {
201 } else if (w1->_obj == w2->_obj) {
202 areSamePtrs = true;
202 areSamePtrs = true;
203 }
203 }
204 } else if (other == Py_None) {
204 } else if (other == Py_None) {
205 validPtrs = true;
205 validPtrs = true;
206 if (wrapper->_obj || wrapper->_wrappedPtr) {
206 if (wrapper->_obj || wrapper->_wrappedPtr) {
207 areSamePtrs = false;
207 areSamePtrs = false;
208 } else {
208 } else {
209 areSamePtrs = true;
209 areSamePtrs = true;
210 }
210 }
211 }
211 }
212 }
212 }
213
213
214 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
214 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
215 // shortcut if richcompare is not supported:
215 // shortcut if richcompare is not supported:
216 if (validPtrs && code == Py_EQ) {
216 if (validPtrs && code == Py_EQ) {
217 return PythonQtConv::GetPyBool(areSamePtrs);
217 return PythonQtConv::GetPyBool(areSamePtrs);
218 } else if (validPtrs && code == Py_NE) {
218 } else if (validPtrs && code == Py_NE) {
219 return PythonQtConv::GetPyBool(!areSamePtrs);
219 return PythonQtConv::GetPyBool(!areSamePtrs);
220 }
220 }
221 Py_INCREF(Py_NotImplemented);
221 Py_INCREF(Py_NotImplemented);
222 return Py_NotImplemented;
222 return Py_NotImplemented;
223 }
223 }
224
224
225 QByteArray memberName;
225 QByteArray memberName;
226 switch (code) {
226 switch (code) {
227 case Py_LT:
227 case Py_LT:
228 {
228 {
229 static QByteArray name = "__lt__";
229 static QByteArray name = "__lt__";
230 memberName = name;
230 memberName = name;
231 }
231 }
232 break;
232 break;
233
233
234 case Py_LE:
234 case Py_LE:
235 {
235 {
236 static QByteArray name = "__le__";
236 static QByteArray name = "__le__";
237 memberName = name;
237 memberName = name;
238 }
238 }
239 break;
239 break;
240
240
241 case Py_EQ:
241 case Py_EQ:
242 {
242 {
243 static QByteArray name = "__eq__";
243 static QByteArray name = "__eq__";
244 memberName = name;
244 memberName = name;
245 }
245 }
246 break;
246 break;
247
247
248 case Py_NE:
248 case Py_NE:
249 {
249 {
250 static QByteArray name = "__ne__";
250 static QByteArray name = "__ne__";
251 memberName = name;
251 memberName = name;
252 }
252 }
253 break;
253 break;
254
254
255 case Py_GT:
255 case Py_GT:
256 {
256 {
257 static QByteArray name = "__gt__";
257 static QByteArray name = "__gt__";
258 memberName = name;
258 memberName = name;
259 }
259 }
260 break;
260 break;
261
261
262 case Py_GE:
262 case Py_GE:
263 {
263 {
264 static QByteArray name = "__ge__";
264 static QByteArray name = "__ge__";
265 memberName = name;
265 memberName = name;
266 }
266 }
267 break;
267 break;
268 }
268 }
269
269
270 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
270 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
271 if (opSlot._type == PythonQtMemberInfo::Slot) {
271 if (opSlot._type == PythonQtMemberInfo::Slot) {
272 // TODO get rid of tuple
272 // TODO get rid of tuple
273 PyObject* args = PyTuple_New(1);
273 PyObject* args = PyTuple_New(1);
274 Py_INCREF(other);
274 Py_INCREF(other);
275 PyTuple_SET_ITEM(args, 0, other);
275 PyTuple_SET_ITEM(args, 0, other);
276 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
276 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
277 Py_DECREF(args);
277 Py_DECREF(args);
278 return result;
278 return result;
279 } else {
279 } else {
280 // not implemented, let python try something else!
280 // not implemented, let python try something else!
281 Py_INCREF(Py_NotImplemented);
281 Py_INCREF(Py_NotImplemented);
282 return Py_NotImplemented;
282 return Py_NotImplemented;
283 }
283 }
284 }
284 }
285
285
286
286
287 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
287 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
288 {
288 {
289 return PyString_FromString(obj->ob_type->tp_name);
289 return PyString_FromString(obj->ob_type->tp_name);
290 }
290 }
291
291
292 PyObject *PythonQtInstanceWrapper_inherits(PythonQtInstanceWrapper* obj, PyObject *args)
292 PyObject *PythonQtInstanceWrapper_inherits(PythonQtInstanceWrapper* obj, PyObject *args)
293 {
293 {
294 char *name = NULL;
294 char *name = NULL;
295 if (!PyArg_ParseTuple(args, "s:PythonQtInstanceWrapper.inherits",&name)) {
295 if (!PyArg_ParseTuple(args, "s:PythonQtInstanceWrapper.inherits",&name)) {
296 return NULL;
296 return NULL;
297 }
297 }
298 return PythonQtConv::GetPyBool(obj->classInfo()->inherits(name));
298 return PythonQtConv::GetPyBool(obj->classInfo()->inherits(name));
299 }
299 }
300
300
301 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
301 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
302 {
302 {
303 return PythonQt::self()->helpCalled(obj->classInfo());
303 return PythonQt::self()->helpCalled(obj->classInfo());
304 }
304 }
305
305
306 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
306 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
307 {
307 {
308 PythonQtInstanceWrapper_deleteObject(self, true);
308 PythonQtInstanceWrapper_deleteObject(self, true);
309 Py_INCREF(Py_None);
309 Py_INCREF(Py_None);
310 return Py_None;
310 return Py_None;
311 }
311 }
312
312
313
313
314 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
314 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
315 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
315 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
316 "Return the classname of the object"
316 "Return the classname of the object"
317 },
317 },
318 {"inherits", (PyCFunction)PythonQtInstanceWrapper_inherits, METH_VARARGS,
318 {"inherits", (PyCFunction)PythonQtInstanceWrapper_inherits, METH_VARARGS,
319 "Returns if the class inherits or is of given type name"
319 "Returns if the class inherits or is of given type name"
320 },
320 },
321 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
321 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
322 "Shows the help of available methods for this class"
322 "Shows the help of available methods for this class"
323 },
323 },
324 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
324 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
325 "Deletes the C++ object (at your own risk, my friend!)"
325 "Deletes the C++ object (at your own risk, my friend!)"
326 },
326 },
327 {NULL, NULL, 0, NULL} /* Sentinel */
327 {NULL, NULL, 0, NULL} /* Sentinel */
328 };
328 };
329
329
330
330
331 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
331 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
332 {
332 {
333 const char *attributeName;
333 const char *attributeName;
334 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
334 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
335
335
336 if ((attributeName = PyString_AsString(name)) == NULL) {
336 if ((attributeName = PyString_AsString(name)) == NULL) {
337 return NULL;
337 return NULL;
338 }
338 }
339
339
340 if (qstrcmp(attributeName, "__dict__")==0) {
340 if (qstrcmp(attributeName, "__dict__")==0) {
341 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
341 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
342 dict = PyDict_Copy(dict);
342 dict = PyDict_Copy(dict);
343
343
344 if (wrapper->_obj) {
344 if (wrapper->_obj) {
345 // only the properties are missing, the rest is already available from
345 // only the properties are missing, the rest is already available from
346 // PythonQtClassWrapper...
346 // PythonQtClassWrapper...
347 QStringList l = wrapper->classInfo()->propertyList();
347 QStringList l = wrapper->classInfo()->propertyList();
348 foreach (QString name, l) {
348 foreach (QString name, l) {
349 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
349 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
350 if (o) {
350 if (o) {
351 PyDict_SetItemString(dict, name.toLatin1().data(), o);
351 PyDict_SetItemString(dict, name.toLatin1().data(), o);
352 Py_DECREF(o);
352 Py_DECREF(o);
353 } else {
353 } else {
354 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
354 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
355 }
355 }
356 }
356 }
357
357
358 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
358 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
359 foreach (QByteArray name, dynamicProps) {
359 foreach (QByteArray name, dynamicProps) {
360 PyObject* o = PyObject_GetAttrString(obj, name.data());
360 PyObject* o = PyObject_GetAttrString(obj, name.data());
361 if (o) {
361 if (o) {
362 PyDict_SetItemString(dict, name.data(), o);
362 PyDict_SetItemString(dict, name.data(), o);
363 Py_DECREF(o);
363 Py_DECREF(o);
364 } else {
364 } else {
365 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
365 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
366 }
366 }
367 }
367 }
368 }
368 }
369 // Note: we do not put children into the dict, is would look confusing?!
369 // Note: we do not put children into the dict, is would look confusing?!
370 return dict;
370 return dict;
371 }
371 }
372
372
373 // first look in super, to return derived methods from base object first
373 // first look in super, to return derived methods from base object first
374 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
374 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
375 if (superAttr) {
375 if (superAttr) {
376 return superAttr;
376 return superAttr;
377 }
377 }
378 PyErr_Clear();
378 PyErr_Clear();
379
379
380 // mlabDebugConst("Python","get " << attributeName);
380 // mlabDebugConst("Python","get " << attributeName);
381
381
382 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
382 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
383 switch (member._type) {
383 switch (member._type) {
384 case PythonQtMemberInfo::Property:
384 case PythonQtMemberInfo::Property:
385 if (wrapper->_obj) {
385 if (wrapper->_obj) {
386 if (member._property.userType() != QVariant::Invalid) {
386 if (member._property.userType() != QVariant::Invalid) {
387
387
388 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
388 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
389 if (profilingCB) {
389 if (profilingCB) {
390 QString methodName = "getProperty(";
390 QString methodName = "getProperty(";
391 methodName += attributeName;
391 methodName += attributeName;
392 methodName += ")";
392 methodName += ")";
393 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
393 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
394 }
394 }
395
395
396 PyObject* value = PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
396 PyObject* value = PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
397
397
398 if (profilingCB) {
398 if (profilingCB) {
399 profilingCB(PythonQt::Leave, NULL, NULL);
399 profilingCB(PythonQt::Leave, NULL, NULL);
400 }
400 }
401
401
402 return value;
402 return value;
403
403
404 } else {
404 } else {
405 Py_INCREF(Py_None);
405 Py_INCREF(Py_None);
406 return Py_None;
406 return Py_None;
407 }
407 }
408 } else {
408 } else {
409 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
409 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
410 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
410 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
411 return NULL;
411 return NULL;
412 }
412 }
413 break;
413 break;
414 case PythonQtMemberInfo::Slot:
414 case PythonQtMemberInfo::Slot:
415 return PythonQtSlotFunction_New(member._slot, obj, NULL);
415 return PythonQtSlotFunction_New(member._slot, obj, NULL);
416 break;
416 break;
417 case PythonQtMemberInfo::Signal:
417 case PythonQtMemberInfo::Signal:
418 return PythonQtSignalFunction_New(member._slot, obj, NULL);
418 return PythonQtSignalFunction_New(member._slot, obj, NULL);
419 break;
419 break;
420 case PythonQtMemberInfo::EnumValue:
420 case PythonQtMemberInfo::EnumValue:
421 {
421 {
422 PyObject* enumValue = member._enumValue;
422 PyObject* enumValue = member._enumValue;
423 Py_INCREF(enumValue);
423 Py_INCREF(enumValue);
424 return enumValue;
424 return enumValue;
425 }
425 }
426 break;
426 break;
427 case PythonQtMemberInfo::EnumWrapper:
427 case PythonQtMemberInfo::EnumWrapper:
428 {
428 {
429 PyObject* enumWrapper = member._enumWrapper;
429 PyObject* enumWrapper = member._enumWrapper;
430 Py_INCREF(enumWrapper);
430 Py_INCREF(enumWrapper);
431 return enumWrapper;
431 return enumWrapper;
432 }
432 }
433 break;
433 break;
434 case PythonQtMemberInfo::NotFound:
434 case PythonQtMemberInfo::NotFound:
435 {
435 {
436 static const QByteArray getterString("py_get_");
436 static const QByteArray getterString("py_get_");
437 // check for a getter slot
437 // check for a getter slot
438 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
438 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
439 if (member._type == PythonQtMemberInfo::Slot) {
439 if (member._type == PythonQtMemberInfo::Slot) {
440 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
440 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
441 }
441 }
442
442
443 // handle dynamic properties
443 // handle dynamic properties
444 if (wrapper->_obj) {
444 if (wrapper->_obj) {
445 QVariant v = wrapper->_obj->property(attributeName);
445 QVariant v = wrapper->_obj->property(attributeName);
446 if (v.isValid()) {
446 if (v.isValid()) {
447 return PythonQtConv::QVariantToPyObject(v);
447 return PythonQtConv::QVariantToPyObject(v);
448 }
448 }
449 }
449 }
450 }
450 }
451 break;
451 break;
452 default:
452 default:
453 // is an invalid type, go on
453 // is an invalid type, go on
454 break;
454 break;
455 }
455 }
456
456
457 // look for the internal methods (className(), help())
457 // look for the internal methods (className(), help())
458 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
458 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
459 if (internalMethod) {
459 if (internalMethod) {
460 return internalMethod;
460 return internalMethod;
461 }
461 }
462 PyErr_Clear();
462 PyErr_Clear();
463
463
464 if (wrapper->_obj) {
464 if (wrapper->_obj) {
465 // look for a child
465 // look for a child
466 QObjectList children = wrapper->_obj->children();
466 QObjectList children = wrapper->_obj->children();
467 for (int i = 0; i < children.count(); i++) {
467 for (int i = 0; i < children.count(); i++) {
468 QObject *child = children.at(i);
468 QObject *child = children.at(i);
469 if (child->objectName() == attributeName) {
469 if (child->objectName() == attributeName) {
470 return PythonQt::priv()->wrapQObject(child);
470 return PythonQt::priv()->wrapQObject(child);
471 }
471 }
472 }
472 }
473 }
473 }
474
474
475 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
475 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
476 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
476 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
477 return NULL;
477 return NULL;
478 }
478 }
479
479
480 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
480 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
481 {
481 {
482 QString error;
482 QString error;
483 const char *attributeName;
483 const char *attributeName;
484 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
484 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
485
485
486 if ((attributeName = PyString_AsString(name)) == NULL)
486 if ((attributeName = PyString_AsString(name)) == NULL)
487 return -1;
487 return -1;
488
488
489 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
489 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
490 if (member._type == PythonQtMemberInfo::Property) {
490 if (member._type == PythonQtMemberInfo::Property) {
491
491
492 if (!wrapper->_obj) {
492 if (!wrapper->_obj) {
493 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
493 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
494 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
494 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
495 return -1;
495 return -1;
496 }
496 }
497
497
498 QMetaProperty prop = member._property;
498 QMetaProperty prop = member._property;
499 if (prop.isWritable()) {
499 if (prop.isWritable()) {
500 QVariant v;
500 QVariant v;
501 if (prop.isEnumType()) {
501 if (prop.isEnumType()) {
502 // this will give us either a string or an int, everything else will probably be an error
502 // this will give us either a string or an int, everything else will probably be an error
503 v = PythonQtConv::PyObjToQVariant(value);
503 v = PythonQtConv::PyObjToQVariant(value);
504 } else {
504 } else {
505 int t = prop.userType();
505 int t = prop.userType();
506 v = PythonQtConv::PyObjToQVariant(value, t);
506 v = PythonQtConv::PyObjToQVariant(value, t);
507 }
507 }
508 bool success = false;
508 bool success = false;
509 if (v.isValid()) {
509 if (v.isValid()) {
510 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
510 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
511 if (profilingCB) {
511 if (profilingCB) {
512 QString methodName = "setProperty(";
512 QString methodName = "setProperty(";
513 methodName += attributeName;
513 methodName += attributeName;
514 methodName += ")";
514 methodName += ")";
515 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
515 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
516 }
516 }
517
517
518 success = prop.write(wrapper->_obj, v);
518 success = prop.write(wrapper->_obj, v);
519
519
520 if (profilingCB) {
520 if (profilingCB) {
521 profilingCB(PythonQt::Leave, NULL, NULL);
521 profilingCB(PythonQt::Leave, NULL, NULL);
522 }
522 }
523 }
523 }
524 if (success) {
524 if (success) {
525 return 0;
525 return 0;
526 } else {
526 } else {
527 error = QString("Property '") + attributeName + "' of type '" +
527 error = QString("Property '") + attributeName + "' of type '" +
528 prop.typeName() + "' does not accept an object of type "
528 prop.typeName() + "' does not accept an object of type "
529 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
529 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
530 }
530 }
531 } else {
531 } else {
532 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
532 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
533 }
533 }
534 } else if (member._type == PythonQtMemberInfo::Slot) {
534 } else if (member._type == PythonQtMemberInfo::Slot) {
535 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
535 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
536 } else if (member._type == PythonQtMemberInfo::Signal) {
536 } else if (member._type == PythonQtMemberInfo::Signal) {
537 error = QString("Signal '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
537 error = QString("Signal '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
538 } else if (member._type == PythonQtMemberInfo::EnumValue) {
538 } else if (member._type == PythonQtMemberInfo::EnumValue) {
539 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
539 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
540 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
540 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
541 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
541 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
542 } else if (member._type == PythonQtMemberInfo::NotFound) {
542 } else if (member._type == PythonQtMemberInfo::NotFound) {
543 // check for a setter slot
543 // check for a setter slot
544 static const QByteArray setterString("py_set_");
544 static const QByteArray setterString("py_set_");
545 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
545 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
546 if (setter._type == PythonQtMemberInfo::Slot) {
546 if (setter._type == PythonQtMemberInfo::Slot) {
547 // call the setter and ignore the result value
547 // call the setter and ignore the result value
548 void* result;
548 void* result;
549 PyObject* args = PyTuple_New(1);
549 PyObject* args = PyTuple_New(1);
550 Py_INCREF(value);
550 Py_INCREF(value);
551 PyTuple_SET_ITEM(args, 0, value);
551 PyTuple_SET_ITEM(args, 0, value);
552 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
552 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
553 Py_DECREF(args);
553 Py_DECREF(args);
554 return 0;
554 return 0;
555 }
555 }
556
556
557 // handle dynamic properties
557 // handle dynamic properties
558 if (wrapper->_obj) {
558 if (wrapper->_obj) {
559 QVariant prop = wrapper->_obj->property(attributeName);
559 QVariant prop = wrapper->_obj->property(attributeName);
560 if (prop.isValid()) {
560 if (prop.isValid()) {
561 QVariant v = PythonQtConv::PyObjToQVariant(value);
561 QVariant v = PythonQtConv::PyObjToQVariant(value);
562 if (v.isValid()) {
562 if (v.isValid()) {
563 wrapper->_obj->setProperty(attributeName, v);
563 wrapper->_obj->setProperty(attributeName, v);
564 return 0;
564 return 0;
565 } else {
565 } else {
566 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
566 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
567 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
567 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
568 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
568 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
569 return -1;
569 return -1;
570 }
570 }
571 }
571 }
572 }
572 }
573
573
574 // if we are a derived python class, we allow setting attributes.
574 // if we are a derived python class, we allow setting attributes.
575 // if we are a direct CPP wrapper, we do NOT allow it, since
575 // if we are a direct CPP wrapper, we do NOT allow it, since
576 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
576 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
577 // and when it is recreated from a CPP pointer the attributes are gone...
577 // and when it is recreated from a CPP pointer the attributes are gone...
578 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
578 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
579 return PyBaseObject_Type.tp_setattro(obj,name,value);
579 return PyBaseObject_Type.tp_setattro(obj,name,value);
580 } else {
580 } else {
581 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
581 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
582 }
582 }
583 }
583 }
584
584
585 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
585 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
586 return -1;
586 return -1;
587 }
587 }
588
588
589 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
589 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
590 QString result;
590 QString result;
591 if (wrapper->_wrappedPtr) {
591 if (wrapper->_wrappedPtr) {
592 // first try some manually string conversions for some variants
592 // first try some manually string conversions for some variants
593 int metaid = wrapper->classInfo()->metaTypeId();
593 int metaid = wrapper->classInfo()->metaTypeId();
594 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
594 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
595 if (!result.isEmpty()) {
595 if (!result.isEmpty()) {
596 return result;
596 return result;
597 }
597 }
598 }
598 }
599 if (wrapper->_wrappedPtr || wrapper->_obj) {
599 if (wrapper->_wrappedPtr || wrapper->_obj) {
600 // next, try to call py_toString
600 // next, try to call py_toString
601 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
601 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
602 if (info._type == PythonQtMemberInfo::Slot) {
602 if (info._type == PythonQtMemberInfo::Slot) {
603 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
603 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
604 if (resultObj) {
604 if (resultObj) {
605 // TODO this is one conversion too much, would be nicer to call the slot directly...
605 // TODO this is one conversion too much, would be nicer to call the slot directly...
606 result = PythonQtConv::PyObjGetString(resultObj);
606 result = PythonQtConv::PyObjGetString(resultObj);
607 Py_DECREF(resultObj);
607 Py_DECREF(resultObj);
608 }
608 }
609 }
609 }
610 }
610 }
611 return result;
611 return result;
612 }
612 }
613
613
614 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
614 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
615 {
615 {
616 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
616 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
617
617
618 // QByteArray should be directly returned as a str
618 // QByteArray should be directly returned as a str
619 if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) {
619 if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) {
620 QByteArray* b = (QByteArray*) wrapper->_wrappedPtr;
620 QByteArray* b = (QByteArray*) wrapper->_wrappedPtr;
621 if (b->data()) {
621 if (b->data()) {
622 return PyString_FromStringAndSize(b->data(), b->size());
622 return PyString_FromStringAndSize(b->data(), b->size());
623 } else {
623 } else {
624 return PyString_FromString("");
624 return PyString_FromString("");
625 }
625 }
626 }
626 }
627
627
628 const char* typeName = obj->ob_type->tp_name;
628 const char* typeName = obj->ob_type->tp_name;
629 QObject *qobj = wrapper->_obj;
629 QObject *qobj = wrapper->_obj;
630 QString str = getStringFromObject(wrapper);
630 QString str = getStringFromObject(wrapper);
631 if (!str.isEmpty()) {
631 if (!str.isEmpty()) {
632 return PyString_FromFormat("%s", str.toLatin1().constData());
632 return PyString_FromFormat("%s", str.toLatin1().constData());
633 }
633 }
634 if (wrapper->_wrappedPtr) {
634 if (wrapper->_wrappedPtr) {
635 if (wrapper->_obj) {
635 if (wrapper->_obj) {
636 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
636 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
637 } else {
637 } else {
638 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
638 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
639 }
639 }
640 } else {
640 } else {
641 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
641 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
642 }
642 }
643 }
643 }
644
644
645 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
645 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
646 {
646 {
647 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
647 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
648 const char* typeName = obj->ob_type->tp_name;
648 const char* typeName = obj->ob_type->tp_name;
649
649
650 QObject *qobj = wrapper->_obj;
650 QObject *qobj = wrapper->_obj;
651 QString str = getStringFromObject(wrapper);
651 QString str = getStringFromObject(wrapper);
652 if (!str.isEmpty()) {
652 if (!str.isEmpty()) {
653 if (str.startsWith(typeName)) {
653 if (str.startsWith(typeName)) {
654 return PyString_FromFormat("%s", str.toLatin1().constData());
654 return PyString_FromFormat("%s", str.toLatin1().constData());
655 } else {
655 } else {
656 return PyString_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj);
656 return PyString_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj);
657 }
657 }
658 }
658 }
659 if (wrapper->_wrappedPtr) {
659 if (wrapper->_wrappedPtr) {
660 if (wrapper->_obj) {
660 if (wrapper->_obj) {
661 return PyString_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
661 return PyString_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
662 } else {
662 } else {
663 return PyString_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr);
663 return PyString_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr);
664 }
664 }
665 } else {
665 } else {
666 return PyString_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj);
666 return PyString_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj);
667 }
667 }
668 }
668 }
669
669
670 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
670 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
671 {
671 {
672 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
672 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
673 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
673 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
674 }
674 }
675
675
676
676
677 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
677 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
678 {
678 {
679 if (obj->_wrappedPtr != NULL) {
679 if (obj->_wrappedPtr != NULL) {
680 return reinterpret_cast<long>(obj->_wrappedPtr);
680 return reinterpret_cast<long>(obj->_wrappedPtr);
681 } else {
681 } else {
682 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
682 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
683 return reinterpret_cast<long>(qobj);
683 return reinterpret_cast<long>(qobj);
684 }
684 }
685 }
685 }
686
686
687
687
688
688
689 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
689 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
690 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
690 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
691 0, /* nb_add */
691 0, /* nb_add */
692 0, /* nb_subtract */
692 0, /* nb_subtract */
693 0, /* nb_multiply */
693 0, /* nb_multiply */
694 0, /* nb_divide */
694 0, /* nb_divide */
695 0, /* nb_remainder */
695 0, /* nb_remainder */
696 0, /* nb_divmod */
696 0, /* nb_divmod */
697 0, /* nb_power */
697 0, /* nb_power */
698 0, /* nb_negative */
698 0, /* nb_negative */
699 0, /* nb_positive */
699 0, /* nb_positive */
700 0, /* nb_absolute */
700 0, /* nb_absolute */
701 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */
701 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */
702 0, /* nb_invert */
702 0, /* nb_invert */
703 0, /* nb_lshift */
703 0, /* nb_lshift */
704 0, /* nb_rshift */
704 0, /* nb_rshift */
705 0, /* nb_and */
705 0, /* nb_and */
706 0, /* nb_xor */
706 0, /* nb_xor */
707 0, /* nb_or */
707 0, /* nb_or */
708 0, /* nb_coerce */
708 0, /* nb_coerce */
709 0, /* nb_int */
709 0, /* nb_int */
710 0, /* nb_long */
710 0, /* nb_long */
711 0, /* nb_float */
711 0, /* nb_float */
712 0, /* nb_oct */
712 0, /* nb_oct */
713 0, /* nb_hex */
713 0, /* nb_hex */
714 0, /* nb_inplace_add */
714 0, /* nb_inplace_add */
715 0, /* nb_inplace_subtract */
715 0, /* nb_inplace_subtract */
716 0, /* nb_inplace_multiply */
716 0, /* nb_inplace_multiply */
717 0, /* nb_inplace_divide */
717 0, /* nb_inplace_divide */
718 0, /* nb_inplace_remainder */
718 0, /* nb_inplace_remainder */
719 0, /* nb_inplace_power */
719 0, /* nb_inplace_power */
720 0, /* nb_inplace_lshift */
720 0, /* nb_inplace_lshift */
721 0, /* nb_inplace_rshift */
721 0, /* nb_inplace_rshift */
722 0, /* nb_inplace_and */
722 0, /* nb_inplace_and */
723 0, /* nb_inplace_xor */
723 0, /* nb_inplace_xor */
724 0, /* nb_inplace_or */
724 0, /* nb_inplace_or */
725 0, /* nb_floor_divide */
725 0, /* nb_floor_divide */
726 0, /* nb_true_divide */
726 0, /* nb_true_divide */
727 0, /* nb_inplace_floor_divide */
727 0, /* nb_inplace_floor_divide */
728 0, /* nb_inplace_true_divide */
728 0, /* nb_inplace_true_divide */
729 };
729 };
730
730
731 PyTypeObject PythonQtInstanceWrapper_Type = {
731 PyTypeObject PythonQtInstanceWrapper_Type = {
732 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
732 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
733 0, /*ob_size*/
733 0, /*ob_size*/
734 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
734 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
735 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
735 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
736 0, /*tp_itemsize*/
736 0, /*tp_itemsize*/
737 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
737 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
738 0, /*tp_print*/
738 0, /*tp_print*/
739 0, /*tp_getattr*/
739 0, /*tp_getattr*/
740 0, /*tp_setattr*/
740 0, /*tp_setattr*/
741 0, /*tp_compare*/
741 0, /*tp_compare*/
742 PythonQtInstanceWrapper_repr, /*tp_repr*/
742 PythonQtInstanceWrapper_repr, /*tp_repr*/
743 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
743 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
744 0, /*tp_as_sequence*/
744 0, /*tp_as_sequence*/
745 0, /*tp_as_mapping*/
745 0, /*tp_as_mapping*/
746 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
746 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
747 0, /*tp_call*/
747 0, /*tp_call*/
748 PythonQtInstanceWrapper_str, /*tp_str*/
748 PythonQtInstanceWrapper_str, /*tp_str*/
749 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
749 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
750 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
750 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
751 0, /*tp_as_buffer*/
751 0, /*tp_as_buffer*/
752 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
752 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
753 "PythonQtInstanceWrapper object", /* tp_doc */
753 "PythonQtInstanceWrapper object", /* tp_doc */
754 0, /* tp_traverse */
754 0, /* tp_traverse */
755 0, /* tp_clear */
755 0, /* tp_clear */
756 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
756 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
757 0, /* tp_weaklistoffset */
757 0, /* tp_weaklistoffset */
758 0, /* tp_iter */
758 0, /* tp_iter */
759 0, /* tp_iternext */
759 0, /* tp_iternext */
760 0, /* tp_methods */
760 0, /* tp_methods */
761 0, /* tp_members */
761 0, /* tp_members */
762 0, /* tp_getset */
762 0, /* tp_getset */
763 0, /* tp_base */
763 0, /* tp_base */
764 0, /* tp_dict */
764 0, /* tp_dict */
765 0, /* tp_descr_get */
765 0, /* tp_descr_get */
766 0, /* tp_descr_set */
766 0, /* tp_descr_set */
767 0, /* tp_dictoffset */
767 0, /* tp_dictoffset */
768 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
768 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
769 0, /* tp_alloc */
769 0, /* tp_alloc */
770 PythonQtInstanceWrapper_new, /* tp_new */
770 PythonQtInstanceWrapper_new, /* tp_new */
771 };
771 };
772
772
773 //-------------------------------------------------------
773 //-------------------------------------------------------
774
774
@@ -1,352 +1,377
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtMethodInfo.cpp
35 // \file PythonQtMethodInfo.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtMethodInfo.h"
42 #include "PythonQtMethodInfo.h"
43 #include "PythonQtClassInfo.h"
43 #include "PythonQtClassInfo.h"
44 #include <iostream>
44 #include <iostream>
45
45
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
48
48
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
50 {
50 {
51 #ifdef PYTHONQT_DEBUG
51 #ifdef PYTHONQT_DEBUG
52 QByteArray sig(meta.signature());
52 QByteArray sig(meta.signature());
53 sig = sig.mid(sig.indexOf('('));
53 sig = sig.mid(sig.indexOf('('));
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
55 std::cout << "caching " << fullSig.data() << std::endl;
55 std::cout << "caching " << fullSig.data() << std::endl;
56 #endif
56 #endif
57
57
58 ParameterInfo type;
58 ParameterInfo type;
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
60 _parameters.append(type);
60 _parameters.append(type);
61 QList<QByteArray> names = meta.parameterTypes();
61 QList<QByteArray> names = meta.parameterTypes();
62 foreach (const QByteArray& name, names) {
62 foreach (const QByteArray& name, names) {
63 fillParameterInfo(type, name, classInfo);
63 fillParameterInfo(type, name, classInfo);
64 _parameters.append(type);
64 _parameters.append(type);
65 }
65 }
66 }
66 }
67
67
68 PythonQtMethodInfo::PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args)
68 PythonQtMethodInfo::PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args)
69 {
69 {
70 ParameterInfo type;
70 ParameterInfo type;
71 fillParameterInfo(type, typeName, NULL);
71 fillParameterInfo(type, typeName, NULL);
72 _parameters.append(type);
72 _parameters.append(type);
73 foreach (const QByteArray& name, args) {
73 foreach (const QByteArray& name, args) {
74 fillParameterInfo(type, name, NULL);
74 fillParameterInfo(type, name, NULL);
75 _parameters.append(type);
75 _parameters.append(type);
76 }
76 }
77 }
77 }
78
78
79 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
79 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
80 {
80 {
81 QByteArray sig(signal.signature());
81 QByteArray sig(signal.signature());
82 sig = sig.mid(sig.indexOf('('));
82 sig = sig.mid(sig.indexOf('('));
83 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
83 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
84 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
84 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
85 if (!result) {
85 if (!result) {
86 result = new PythonQtMethodInfo(signal, classInfo);
86 result = new PythonQtMethodInfo(signal, classInfo);
87 _cachedSignatures.insert(fullSig, result);
87 _cachedSignatures.insert(fullSig, result);
88 }
88 }
89 return result;
89 return result;
90 }
90 }
91
91
92 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(int numArgs, const char** args)
92 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(int numArgs, const char** args)
93 {
93 {
94 QByteArray typeName = args[0];
94 QByteArray typeName = args[0];
95 QList<QByteArray> arguments;
95 QList<QByteArray> arguments;
96 QByteArray fullSig = typeName;
96 QByteArray fullSig = typeName;
97 fullSig += "(";
97 fullSig += "(";
98 for (int i =1;i<numArgs; i++) {
98 for (int i =1;i<numArgs; i++) {
99 if (i>1) {
99 if (i>1) {
100 fullSig += ",";
100 fullSig += ",";
101 }
101 }
102 QByteArray arg(args[i]);
102 QByteArray arg(args[i]);
103 fullSig += arg;
103 fullSig += arg;
104 arguments << arg;
104 arguments << arg;
105 }
105 }
106 fullSig += ")";
106 fullSig += ")";
107 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
107 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
108 if (!result) {
108 if (!result) {
109 result = new PythonQtMethodInfo(typeName, arguments);
109 result = new PythonQtMethodInfo(typeName, arguments);
110 _cachedSignatures.insert(fullSig, result);
110 _cachedSignatures.insert(fullSig, result);
111 }
111 }
112 return result;
112 return result;
113 }
113 }
114
114
115 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
115 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
116 {
116 {
117 QByteArray name = orgName;
117 QByteArray name = orgName;
118
118
119 type.enumWrapper = NULL;
119 type.enumWrapper = NULL;
120
120
121 int len = name.length();
121 int len = name.length();
122 if (len>0) {
122 if (len>0) {
123 if (strncmp(name.constData(), "const ", 6)==0) {
123 if (strncmp(name.constData(), "const ", 6)==0) {
124 name = name.mid(6);
124 name = name.mid(6);
125 len -= 6;
125 len -= 6;
126 type.isConst = true;
126 type.isConst = true;
127 } else {
127 } else {
128 type.isConst = false;
128 type.isConst = false;
129 }
129 }
130 char pointerCount = 0;
130 char pointerCount = 0;
131 bool hadReference = false;
131 bool hadReference = false;
132 // remove * and & from the end of the string, handle & and * the same way
132 // remove * and & from the end of the string, handle & and * the same way
133 while (name.at(len-1) == '*') {
133 while (name.at(len-1) == '*') {
134 len--;
134 len--;
135 pointerCount++;
135 pointerCount++;
136 }
136 }
137 while (name.at(len-1) == '&') {
137 while (name.at(len-1) == '&') {
138 len--;
138 len--;
139 hadReference = true;
139 hadReference = true;
140 }
140 }
141 if (len!=name.length()) {
141 if (len!=name.length()) {
142 name = name.left(len);
142 name = name.left(len);
143 }
143 }
144 type.pointerCount = pointerCount;
144 type.pointerCount = pointerCount;
145
145
146 QByteArray alias = _parameterNameAliases.value(name);
146 QByteArray alias = _parameterNameAliases.value(name);
147 if (!alias.isEmpty()) {
147 if (!alias.isEmpty()) {
148 name = alias;
148 name = alias;
149 }
149 }
150
150
151 type.typeId = nameToType(name);
151 type.typeId = nameToType(name);
152 if ((type.pointerCount == 0) && type.typeId == Unknown) {
152 if ((type.pointerCount == 0) && type.typeId == Unknown) {
153 type.typeId = QMetaType::type(name.constData());
153 type.typeId = QMetaType::type(name.constData());
154 if (type.typeId == QMetaType::Void) {
154 if (type.typeId == QMetaType::Void) {
155 type.typeId = Unknown;
155 type.typeId = Unknown;
156 }
156 }
157 }
157 }
158 type.name = name;
158 type.name = name;
159
159
160 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
160 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
161 bool isLocalEnum;
161 bool isLocalEnum;
162 // TODOXXX: make use of this flag!
162 // TODOXXX: make use of this flag!
163 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
163 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
164 }
164 }
165 } else {
165 } else {
166 type.typeId = QMetaType::Void;
166 type.typeId = QMetaType::Void;
167 type.pointerCount = 0;
167 type.pointerCount = 0;
168 type.isConst = false;
168 type.isConst = false;
169 }
169 }
170 }
170 }
171
171
172 int PythonQtMethodInfo::nameToType(const char* name)
172 int PythonQtMethodInfo::nameToType(const char* name)
173 {
173 {
174 if (_parameterTypeDict.isEmpty()) {
174 if (_parameterTypeDict.isEmpty()) {
175 // we could also use QMetaType::nameToType, but that does a string compare search
175 // we could also use QMetaType::nameToType, but that does a string compare search
176 // and does not support QVariant
176 // and does not support QVariant
177
177
178 // QMetaType names
178 // QMetaType names
179 _parameterTypeDict.insert("long", QMetaType::Long);
179 _parameterTypeDict.insert("long", QMetaType::Long);
180 _parameterTypeDict.insert("int", QMetaType::Int);
180 _parameterTypeDict.insert("int", QMetaType::Int);
181 _parameterTypeDict.insert("short", QMetaType::Short);
181 _parameterTypeDict.insert("short", QMetaType::Short);
182 _parameterTypeDict.insert("char", QMetaType::Char);
182 _parameterTypeDict.insert("char", QMetaType::Char);
183 _parameterTypeDict.insert("ulong", QMetaType::ULong);
183 _parameterTypeDict.insert("ulong", QMetaType::ULong);
184 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
184 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
185 _parameterTypeDict.insert("uint", QMetaType::UInt);
185 _parameterTypeDict.insert("uint", QMetaType::UInt);
186 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
186 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
187 _parameterTypeDict.insert("ushort", QMetaType::UShort);
187 _parameterTypeDict.insert("ushort", QMetaType::UShort);
188 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
188 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
189 _parameterTypeDict.insert("uchar", QMetaType::UChar);
189 _parameterTypeDict.insert("uchar", QMetaType::UChar);
190 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
190 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
191 _parameterTypeDict.insert("bool", QMetaType::Bool);
191 _parameterTypeDict.insert("bool", QMetaType::Bool);
192 _parameterTypeDict.insert("float", QMetaType::Float);
192 _parameterTypeDict.insert("float", QMetaType::Float);
193 _parameterTypeDict.insert("double", QMetaType::Double);
193 _parameterTypeDict.insert("double", QMetaType::Double);
194 _parameterTypeDict.insert("qreal", QMetaType::Double);
194 _parameterTypeDict.insert("qreal", QMetaType::Double);
195 _parameterTypeDict.insert("QChar", QMetaType::QChar);
195 _parameterTypeDict.insert("QChar", QMetaType::QChar);
196 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
196 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
197 _parameterTypeDict.insert("QString", QMetaType::QString);
197 _parameterTypeDict.insert("QString", QMetaType::QString);
198 _parameterTypeDict.insert("", QMetaType::Void);
198 _parameterTypeDict.insert("", QMetaType::Void);
199 _parameterTypeDict.insert("void", QMetaType::Void);
199 _parameterTypeDict.insert("void", QMetaType::Void);
200
201 // GL types
202 _parameterTypeDict.insert("GLenum", QMetaType::UInt);
203 _parameterTypeDict.insert("GLboolean", QMetaType::UChar);
204 _parameterTypeDict.insert("GLbitfield", QMetaType::UInt);
205 _parameterTypeDict.insert("GLbyte", QMetaType::Char);
206 _parameterTypeDict.insert("GLubyte", QMetaType::UChar);
207 _parameterTypeDict.insert("GLshort", QMetaType::Short);
208 _parameterTypeDict.insert("GLushort", QMetaType::UShort);
209 _parameterTypeDict.insert("GLint", QMetaType::Int);
210 _parameterTypeDict.insert("GLuint", QMetaType::UInt);
211 _parameterTypeDict.insert("GLsizei", QMetaType::UInt);
212 _parameterTypeDict.insert("GLclampf", QMetaType::Float);
213 _parameterTypeDict.insert("GLfloat", QMetaType::Float);
214 _parameterTypeDict.insert("GLclampd", QMetaType::Double);
215 _parameterTypeDict.insert("GLdouble", QMetaType::Double);
216 _parameterTypeDict.insert("GLvoid", QMetaType::Void);
217 if (QT_POINTER_SIZE == 8) {
218 _parameterTypeDict.insert("qgl_GLintptr", QMetaType::LongLong);
219 _parameterTypeDict.insert("qgl_GLsizeiptr", QMetaType::LongLong);
220 } else {
221 _parameterTypeDict.insert("qgl_GLintptr", QMetaType::Int);
222 _parameterTypeDict.insert("qgl_GLsizeiptr", QMetaType::Int);
223 }
224
200 // QVariant names
225 // QVariant names
201 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
226 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
202 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
227 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
203 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
228 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
204 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
229 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
205 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
230 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
206 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
231 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
207 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
232 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
208 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
233 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
209 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
234 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
210 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
235 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
211 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
236 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
212 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
237 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
213 _parameterTypeDict.insert("QDate", QMetaType::QDate);
238 _parameterTypeDict.insert("QDate", QMetaType::QDate);
214 _parameterTypeDict.insert("QTime", QMetaType::QTime);
239 _parameterTypeDict.insert("QTime", QMetaType::QTime);
215 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
240 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
216 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
241 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
217 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
242 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
218 _parameterTypeDict.insert("QRect", QMetaType::QRect);
243 _parameterTypeDict.insert("QRect", QMetaType::QRect);
219 _parameterTypeDict.insert("QRectF", QMetaType::QRectF);
244 _parameterTypeDict.insert("QRectF", QMetaType::QRectF);
220 _parameterTypeDict.insert("QSize", QMetaType::QSize);
245 _parameterTypeDict.insert("QSize", QMetaType::QSize);
221 _parameterTypeDict.insert("QSizeF", QMetaType::QSizeF);
246 _parameterTypeDict.insert("QSizeF", QMetaType::QSizeF);
222 _parameterTypeDict.insert("QLine", QMetaType::QLine);
247 _parameterTypeDict.insert("QLine", QMetaType::QLine);
223 _parameterTypeDict.insert("QLineF", QMetaType::QLineF);
248 _parameterTypeDict.insert("QLineF", QMetaType::QLineF);
224 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
249 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
225 _parameterTypeDict.insert("QPointF", QMetaType::QPointF);
250 _parameterTypeDict.insert("QPointF", QMetaType::QPointF);
226 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
251 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
227 _parameterTypeDict.insert("QFont", QMetaType::QFont);
252 _parameterTypeDict.insert("QFont", QMetaType::QFont);
228 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
253 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
229 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
254 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
230 _parameterTypeDict.insert("QColor", QMetaType::QColor);
255 _parameterTypeDict.insert("QColor", QMetaType::QColor);
231 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
256 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
232 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
257 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
233 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
258 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
234 _parameterTypeDict.insert("QImage", QMetaType::QImage);
259 _parameterTypeDict.insert("QImage", QMetaType::QImage);
235 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
260 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
236 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
261 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
237 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
262 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
238 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
263 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
239 _parameterTypeDict.insert("QPen", QMetaType::QPen);
264 _parameterTypeDict.insert("QPen", QMetaType::QPen);
240 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
265 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
241 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
266 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
242 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
267 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
243 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
268 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
244 // own special types... (none so far, could be e.g. ObjectList
269 // own special types... (none so far, could be e.g. ObjectList
245 }
270 }
246 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
271 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
247 if (it!=_parameterTypeDict.end()) {
272 if (it!=_parameterTypeDict.end()) {
248 return it.value();
273 return it.value();
249 } else {
274 } else {
250 return PythonQtMethodInfo::Unknown;
275 return PythonQtMethodInfo::Unknown;
251 }
276 }
252 }
277 }
253
278
254 void PythonQtMethodInfo::cleanupCachedMethodInfos()
279 void PythonQtMethodInfo::cleanupCachedMethodInfos()
255 {
280 {
256 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
281 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
257 while (i.hasNext()) {
282 while (i.hasNext()) {
258 delete i.next().value();
283 delete i.next().value();
259 }
284 }
260 }
285 }
261
286
262 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
287 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
263 {
288 {
264 _parameterNameAliases.insert(alias, name);
289 _parameterNameAliases.insert(alias, name);
265 }
290 }
266
291
267 //-------------------------------------------------------------------------------------------------
292 //-------------------------------------------------------------------------------------------------
268
293
269 void PythonQtSlotInfo::deleteOverloadsAndThis()
294 void PythonQtSlotInfo::deleteOverloadsAndThis()
270 {
295 {
271 PythonQtSlotInfo* cur = this;
296 PythonQtSlotInfo* cur = this;
272 while(cur->nextInfo()) {
297 while(cur->nextInfo()) {
273 PythonQtSlotInfo* next = cur->nextInfo();
298 PythonQtSlotInfo* next = cur->nextInfo();
274 delete cur;
299 delete cur;
275 cur = next;
300 cur = next;
276 }
301 }
277 }
302 }
278
303
279
304
280 QString PythonQtSlotInfo::fullSignature()
305 QString PythonQtSlotInfo::fullSignature()
281 {
306 {
282 bool skipFirstArg = isInstanceDecorator();
307 bool skipFirstArg = isInstanceDecorator();
283 QString result = _meta.typeName();
308 QString result = _meta.typeName();
284 QByteArray sig = slotName();
309 QByteArray sig = slotName();
285 QList<QByteArray> names = _meta.parameterNames();
310 QList<QByteArray> names = _meta.parameterNames();
286
311
287 bool isStatic = false;
312 bool isStatic = false;
288 bool isConstructor = false;
313 bool isConstructor = false;
289 bool isDestructor = false;
314 bool isDestructor = false;
290
315
291 if (_type == ClassDecorator) {
316 if (_type == ClassDecorator) {
292 if (sig.startsWith("new_")) {
317 if (sig.startsWith("new_")) {
293 sig = sig.mid(4);
318 sig = sig.mid(4);
294 isConstructor = true;
319 isConstructor = true;
295 } else if (sig.startsWith("delete_")) {
320 } else if (sig.startsWith("delete_")) {
296 sig = sig.mid(7);
321 sig = sig.mid(7);
297 isDestructor = true;
322 isDestructor = true;
298 } else if(sig.startsWith("static_")) {
323 } else if(sig.startsWith("static_")) {
299 isStatic = true;
324 isStatic = true;
300 sig = sig.mid(7);
325 sig = sig.mid(7);
301 int idx = sig.indexOf("_");
326 int idx = sig.indexOf("_");
302 if (idx>=0) {
327 if (idx>=0) {
303 sig = sig.mid(idx+1);
328 sig = sig.mid(idx+1);
304 }
329 }
305 }
330 }
306 }
331 }
307
332
308 result += QByteArray(" ") + sig;
333 result += QByteArray(" ") + sig;
309 result += "(";
334 result += "(";
310
335
311 int lastEntry = _parameters.count()-1;
336 int lastEntry = _parameters.count()-1;
312 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
337 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
313 if (_parameters.at(i).isConst) {
338 if (_parameters.at(i).isConst) {
314 result += "const ";
339 result += "const ";
315 }
340 }
316 result += _parameters.at(i).name;
341 result += _parameters.at(i).name;
317 if (_parameters.at(i).pointerCount) {
342 if (_parameters.at(i).pointerCount) {
318 QByteArray stars;
343 QByteArray stars;
319 stars.fill('*', _parameters.at(i).pointerCount);
344 stars.fill('*', _parameters.at(i).pointerCount);
320 result += stars;
345 result += stars;
321 }
346 }
322 if (!names.at(i-1).isEmpty()) {
347 if (!names.at(i-1).isEmpty()) {
323 result += " ";
348 result += " ";
324 result += names.at(i-1);
349 result += names.at(i-1);
325 }
350 }
326 if (i!=lastEntry) {
351 if (i!=lastEntry) {
327 result += ", ";
352 result += ", ";
328 }
353 }
329 }
354 }
330 result += ")";
355 result += ")";
331
356
332 if (isStatic) {
357 if (isStatic) {
333 result = QString("static ") + result;
358 result = QString("static ") + result;
334 }
359 }
335 if (isConstructor) {
360 if (isConstructor) {
336 // result = QString("constructor ") + result;
361 // result = QString("constructor ") + result;
337 }
362 }
338 if (isDestructor) {
363 if (isDestructor) {
339 result = QString("~") + result;
364 result = QString("~") + result;
340 }
365 }
341 return result;
366 return result;
342 }
367 }
343
368
344
369
345 QByteArray PythonQtSlotInfo::slotName()
370 QByteArray PythonQtSlotInfo::slotName()
346 {
371 {
347 QByteArray sig(_meta.signature());
372 QByteArray sig(_meta.signature());
348 int idx = sig.indexOf('(');
373 int idx = sig.indexOf('(');
349 sig = sig.left(idx);
374 sig = sig.left(idx);
350 return sig;
375 return sig;
351 }
376 }
352
377
@@ -1,242 +1,273
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, 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 #include "funcobject.h"
49
49
50 // use -2 to signal that the variable is uninitialized
51 int PythonQtSignalReceiver::_destroyedSignal1Id = -2;
52 int PythonQtSignalReceiver::_destroyedSignal2Id = -2;
53
50 void PythonQtSignalTarget::call(void **arguments) const {
54 void PythonQtSignalTarget::call(void **arguments) const {
51 PyObject* result = call(_callable, methodInfo(), arguments);
55 PyObject* result = call(_callable, methodInfo(), arguments);
52 if (result) {
56 if (result) {
53 Py_DECREF(result);
57 Py_DECREF(result);
54 }
58 }
55 }
59 }
56
60
57 PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInfo* methodInfos, void **arguments, bool skipFirstArgumentOfMethodInfo)
61 PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInfo* methodInfos, void **arguments, bool skipFirstArgumentOfMethodInfo)
58 {
62 {
59 Q_UNUSED(skipFirstArgumentOfMethodInfo)
63 Q_UNUSED(skipFirstArgumentOfMethodInfo)
60
64
61 // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments
65 // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments
62 // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal
66 // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal
63
67
64 int numPythonArgs = -1;
68 int numPythonArgs = -1;
65 if (PyFunction_Check(callable)) {
69 if (PyFunction_Check(callable)) {
66 PyObject* o = callable;
70 PyObject* o = callable;
67 PyFunctionObject* func = (PyFunctionObject*)o;
71 PyFunctionObject* func = (PyFunctionObject*)o;
68 PyCodeObject* code = (PyCodeObject*)func->func_code;
72 PyCodeObject* code = (PyCodeObject*)func->func_code;
69 if (!(code->co_flags & CO_VARARGS)) {
73 if (!(code->co_flags & CO_VARARGS)) {
70 numPythonArgs = code->co_argcount;
74 numPythonArgs = code->co_argcount;
71 } else {
75 } else {
72 // variable numbers of arguments allowed
76 // variable numbers of arguments allowed
73 }
77 }
74 } else if (PyMethod_Check(callable)) {
78 } else if (PyMethod_Check(callable)) {
75 PyObject* o = callable;
79 PyObject* o = callable;
76 PyMethodObject* method = (PyMethodObject*)o;
80 PyMethodObject* method = (PyMethodObject*)o;
77 if (PyFunction_Check(method->im_func)) {
81 if (PyFunction_Check(method->im_func)) {
78 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
82 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
79 PyCodeObject* code = (PyCodeObject*)func->func_code;
83 PyCodeObject* code = (PyCodeObject*)func->func_code;
80 if (!(code->co_flags & CO_VARARGS)) {
84 if (!(code->co_flags & CO_VARARGS)) {
81 numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self"
85 numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self"
82 } else {
86 } else {
83 // variable numbers of arguments allowed
87 // variable numbers of arguments allowed
84 }
88 }
85 }
89 }
86 }
90 }
87
91
88 const PythonQtMethodInfo* m = methodInfos;
92 const PythonQtMethodInfo* m = methodInfos;
89 // parameterCount includes return value:
93 // parameterCount includes return value:
90 int count = m->parameterCount();
94 int count = m->parameterCount();
91 if (numPythonArgs!=-1) {
95 if (numPythonArgs!=-1) {
92 if (count>numPythonArgs+1) {
96 if (count>numPythonArgs+1) {
93 // take less arguments
97 // take less arguments
94 count = numPythonArgs+1;
98 count = numPythonArgs+1;
95 }
99 }
96 }
100 }
97
101
98 PyObject* pargs = NULL;
102 PyObject* pargs = NULL;
99 if (count>1) {
103 if (count>1) {
100 pargs = PyTuple_New(count-1);
104 pargs = PyTuple_New(count-1);
101 }
105 }
102 bool err = false;
106 bool err = false;
103 // transform Qt values to Python
107 // transform Qt values to Python
104 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
108 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
105 for (int i = 1; i < count; i++) {
109 for (int i = 1; i < count; i++) {
106 const PythonQtMethodInfo::ParameterInfo& param = params.at(i);
110 const PythonQtMethodInfo::ParameterInfo& param = params.at(i);
107 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
111 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
108 if (arg) {
112 if (arg) {
109 // steals reference, no unref
113 // steals reference, no unref
110 PyTuple_SetItem(pargs, i-1,arg);
114 PyTuple_SetItem(pargs, i-1,arg);
111 } else {
115 } else {
112 err = true;
116 err = true;
113 break;
117 break;
114 }
118 }
115 }
119 }
116
120
117 PyObject* result = NULL;
121 PyObject* result = NULL;
118 if (!err) {
122 if (!err) {
119 PyErr_Clear();
123 PyErr_Clear();
120 result = PyObject_CallObject(callable, pargs);
124 result = PyObject_CallObject(callable, pargs);
121 if (result) {
125 if (result) {
122 // ok
126 // ok
123 } else {
127 } else {
124 PythonQt::self()->handleError();
128 PythonQt::self()->handleError();
125 }
129 }
126 }
130 }
127 if (pargs) {
131 if (pargs) {
128 // free the arguments again
132 // free the arguments again
129 Py_DECREF(pargs);
133 Py_DECREF(pargs);
130 }
134 }
131
135
132 return result;
136 return result;
133 }
137 }
134
138
135 bool PythonQtSignalTarget::isSame( int signalId, PyObject* callable ) const
139 bool PythonQtSignalTarget::isSame( int signalId, PyObject* callable ) const
136 {
140 {
137 return PyObject_Compare(callable, _callable) == 0 && signalId==_signalId;
141 return PyObject_Compare(callable, _callable) == 0 && signalId==_signalId;
138 }
142 }
139
143
140 //------------------------------------------------------------------------------
144 //------------------------------------------------------------------------------
141
145
142 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
146 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
143 {
147 {
148 if (_destroyedSignal1Id == -2) {
149 // initialize these once
150 _destroyedSignal1Id = QObject::staticMetaObject.indexOfSignal("destroyed()");
151 _destroyedSignal2Id = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
152 if (_destroyedSignal1Id == -1 || _destroyedSignal2Id == -1) {
153 std::cerr << "PythonQt: could not find destroyed signal index, should never happen!" << std::endl;
154 }
155 }
156
157 _destroyedSignalCount = 0;
144 _obj = obj;
158 _obj = obj;
145
159
146 // fetch the class info for object, since we will need to for correct enum resolution in
160 // fetch the class info for object, since we will need to for correct enum resolution in
147 // signals
161 // signals
148 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
162 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
149 if (!_objClassInfo || !_objClassInfo->isQObject()) {
163 if (!_objClassInfo || !_objClassInfo->isQObject()) {
150 PythonQt::self()->registerClass(obj->metaObject());
164 PythonQt::self()->registerClass(obj->metaObject());
151 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
165 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
152 }
166 }
153 // force decorator/enum creation
167 // force decorator/enum creation
154 _objClassInfo->decorator();
168 _objClassInfo->decorator();
155
169
156 _slotCount = staticMetaObject.methodOffset();
170 _slotCount = staticMetaObject.methodOffset();
157 }
171 }
158
172
159 PythonQtSignalReceiver::~PythonQtSignalReceiver()
173 PythonQtSignalReceiver::~PythonQtSignalReceiver()
160 {
174 {
161 PythonQt::priv()->removeSignalEmitter(_obj);
175 PythonQt::priv()->removeSignalEmitter(_obj);
162 }
176 }
163
177
164
178
165 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
179 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
166 {
180 {
167 bool flag = false;
181 bool flag = false;
168 int sigId = getSignalIndex(signal);
182 int sigId = getSignalIndex(signal);
169 if (sigId>=0) {
183 if (sigId>=0) {
170 // create PythonQtMethodInfo from signal
184 // create PythonQtMethodInfo from signal
171 QMetaMethod meta = _obj->metaObject()->method(sigId);
185 QMetaMethod meta = _obj->metaObject()->method(sigId);
172 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo);
186 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo);
173 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
187 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
174 _targets.append(t);
188 _targets.append(t);
175 // now connect to ourselves with the new slot id
189 // now connect to ourselves with the new slot id
176 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
190 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
177
191
178 _slotCount++;
192 _slotCount++;
179 flag = true;
193 flag = true;
194
195 if (sigId == _destroyedSignal1Id || sigId == _destroyedSignal2Id) {
196 _destroyedSignalCount++;
197 if (_destroyedSignalCount==1) {
198 // make ourself parent of PythonQt, to not get deleted as a child of the QObject we are
199 // listening to, since we do that manually when we receive the destroyed signal
200 this->setParent(PythonQt::priv());
201 }
202 }
180 }
203 }
181 return flag;
204 return flag;
182 }
205 }
183
206
184 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
207 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
185 {
208 {
186 bool found = false;
209 int foundCount = 0;
187 int sigId = getSignalIndex(signal);
210 int sigId = getSignalIndex(signal);
188 if (sigId>=0) {
211 if (sigId>=0) {
189 QMutableListIterator<PythonQtSignalTarget> i(_targets);
212 QMutableListIterator<PythonQtSignalTarget> i(_targets);
190 if (callable) {
213 if (callable) {
191 while (i.hasNext()) {
214 while (i.hasNext()) {
192 if (i.next().isSame(sigId, callable)) {
215 if (i.next().isSame(sigId, callable)) {
193 i.remove();
216 i.remove();
194 found = true;
217 foundCount++;
195 break;
218 break;
196 }
219 }
197 }
220 }
198 } else {
221 } else {
199 while (i.hasNext()) {
222 while (i.hasNext()) {
200 if (i.next().signalId() == sigId) {
223 if (i.next().signalId() == sigId) {
201 i.remove();
224 i.remove();
202 found = true;
225 foundCount++;
203 }
226 }
204 }
227 }
205 }
228 }
206 }
229 }
207 return found;
230 if ((foundCount>0) && (sigId == _destroyedSignal1Id) || (sigId == _destroyedSignal2Id)) {
231 _destroyedSignalCount -= foundCount;
232 if (_destroyedSignalCount==0) {
233 // make ourself child of QObject again, to get deleted when the object gets deleted
234 this->setParent(_obj);
208 }
235 }
209
236 }
210 void PythonQtSignalReceiver::removeSignalHandlers()
237 return foundCount>0;
211 {
212 _targets.clear();
213 }
238 }
214
239
215 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
240 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
216 {
241 {
217 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
242 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
218 if (sigId<0) {
243 if (sigId<0) {
219 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
244 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
220 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
245 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
221 }
246 }
222 return sigId;
247 return sigId;
223 }
248 }
224
249
225 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
250 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
226 {
251 {
227 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
252 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
228 if (c != QMetaObject::InvokeMetaMethod) {
253 if (c != QMetaObject::InvokeMetaMethod) {
229 QObject::qt_metacall(c, id, arguments);
254 QObject::qt_metacall(c, id, arguments);
230 }
255 }
231
256
232 bool found = false;
233 foreach(const PythonQtSignalTarget& t, _targets) {
257 foreach(const PythonQtSignalTarget& t, _targets) {
234 if (t.slotId() == id) {
258 if (t.slotId() == id) {
235 found = true;
236 t.call(arguments);
259 t.call(arguments);
260 // if the signal is the last destroyed signal, we delete ourselves
261 int sigId = t.signalId();
262 if ((sigId == _destroyedSignal1Id) || (sigId == _destroyedSignal2Id)) {
263 _destroyedSignalCount--;
264 if (_destroyedSignalCount == 0) {
265 delete this;
266 }
267 }
237 break;
268 break;
238 }
269 }
239 }
270 }
240 return 0;
271 return 0;
241 }
272 }
242
273
@@ -1,143 +1,144
1 #ifndef _PYTHONQTSIGNALRECEIVER_H
1 #ifndef _PYTHONQTSIGNALRECEIVER_H
2 #define _PYTHONQTSIGNALRECEIVER_H
2 #define _PYTHONQTSIGNALRECEIVER_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, 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 PythonQtSignalReceiver.h
38 // \file PythonQtSignalReceiver.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 "PythonQtPythonInclude.h"
45 #include "PythonQtPythonInclude.h"
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48 #include "PythonQtObjectPtr.h"
48 #include "PythonQtObjectPtr.h"
49
49
50 class PythonQtMethodInfo;
50 class PythonQtMethodInfo;
51 class PythonQtClassInfo;
51 class PythonQtClassInfo;
52
52
53 //! stores information about a signal target
53 //! stores information about a signal target
54 /*! copy construction and assignment works fine with the C++ standard behavior and are thus not implemented
54 /*! copy construction and assignment works fine with the C++ standard behavior and are thus not implemented
55 */
55 */
56 class PYTHONQT_EXPORT PythonQtSignalTarget {
56 class PYTHONQT_EXPORT PythonQtSignalTarget {
57 public:
57 public:
58 PythonQtSignalTarget() {
58 PythonQtSignalTarget() {
59 _signalId = -1;
59 _signalId = -1;
60 _methodInfo = NULL;
60 _methodInfo = NULL;
61 _slotId = -1;
61 _slotId = -1;
62 }
62 }
63
63
64 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
64 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
65 {
65 {
66 _signalId = signalId;
66 _signalId = signalId;
67 _slotId = slotId;
67 _slotId = slotId;
68 _methodInfo = methodInfo;
68 _methodInfo = methodInfo;
69 _callable = callable;
69 _callable = callable;
70 };
70 };
71
71
72 ~PythonQtSignalTarget() {
72 ~PythonQtSignalTarget() {
73 };
73 };
74
74
75 //! get the id of the original signal
75 //! get the id of the original signal
76 int signalId() const { return _signalId; }
76 int signalId() const { return _signalId; }
77
77
78 //! get the id that was assigned to this simulated slot
78 //! get the id that was assigned to this simulated slot
79 int slotId() const { return _slotId; }
79 int slotId() const { return _slotId; }
80
80
81 //! get the signals parameter info
81 //! get the signals parameter info
82 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
82 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
83
83
84 //! call the python callable with the given arguments (as defined in methodInfo)
84 //! call the python callable with the given arguments (as defined in methodInfo)
85 void call(void **arguments) const;
85 void call(void **arguments) const;
86
86
87 //! check if it is the same signal target
87 //! check if it is the same signal target
88 bool isSame(int signalId, PyObject* callable) const;
88 bool isSame(int signalId, PyObject* callable) const;
89
89
90 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
90 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
91 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
91 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
92
92
93 private:
93 private:
94 int _signalId;
94 int _signalId;
95 int _slotId;
95 int _slotId;
96 const PythonQtMethodInfo* _methodInfo;
96 const PythonQtMethodInfo* _methodInfo;
97 PythonQtObjectPtr _callable;
97 PythonQtObjectPtr _callable;
98 };
98 };
99
99
100 //! base class for signal receivers
100 //! base class for signal receivers
101 /*!
101 /*!
102 */
102 */
103 class PythonQtSignalReceiverBase : public QObject {
103 class PythonQtSignalReceiverBase : public QObject {
104 Q_OBJECT
104 Q_OBJECT
105 public:
105 public:
106 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
106 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
107 };
107 };
108
108
109 //! receives all signals for one QObject
109 //! receives all signals for one QObject
110 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
110 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
111 */
111 */
112 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
112 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
113
113
114 public:
114 public:
115 PythonQtSignalReceiver(QObject* obj);
115 PythonQtSignalReceiver(QObject* obj);
116 ~PythonQtSignalReceiver();
116 ~PythonQtSignalReceiver();
117
117
118 //! add a signal handler
118 //! add a signal handler
119 bool addSignalHandler(const char* signal, PyObject* callable);
119 bool addSignalHandler(const char* signal, PyObject* callable);
120
120
121 //! remove a signal handler for given callable (or all callables on that signal if callable is NULL)
121 //! remove a signal handler for given callable (or all callables on that signal if callable is NULL)
122 bool removeSignalHandler(const char* signal, PyObject* callable = NULL);
122 bool removeSignalHandler(const char* signal, PyObject* callable = NULL);
123
123
124 //! remove all signal handlers
125 void removeSignalHandlers();
126
127 //! we implement this method to simulate a number of slots that match the ids in _targets
124 //! we implement this method to simulate a number of slots that match the ids in _targets
128 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
125 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
129
126
130 private:
127 private:
131 //! get the index of the signal
128 //! get the index of the signal
132 int getSignalIndex(const char* signal);
129 int getSignalIndex(const char* signal);
133
130
134 QObject* _obj;
131 QObject* _obj;
135 PythonQtClassInfo* _objClassInfo;
132 PythonQtClassInfo* _objClassInfo;
136 int _slotCount;
133 int _slotCount;
134 int _destroyedSignalCount;
137 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
135 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
138 QList<PythonQtSignalTarget> _targets;
136 QList<PythonQtSignalTarget> _targets;
137
138 static int _destroyedSignal1Id;
139 static int _destroyedSignal2Id;
139 };
140 };
140
141
141
142
142 #endif
143 #endif
143
144
@@ -1,318 +1,323
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtStdDecorators.cpp
35 // \file PythonQtStdDecorators.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2007-04
38 // \date 2007-04
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtStdDecorators.h"
42 #include "PythonQtStdDecorators.h"
43 #include "PythonQt.h"
43 #include "PythonQt.h"
44 #include "PythonQtClassInfo.h"
44 #include "PythonQtClassInfo.h"
45 #include <QCoreApplication>
45 #include <QCoreApplication>
46
46
47 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, PyObject* callable)
47 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, PyObject* callable)
48 {
48 {
49 bool result = false;
49 bool result = false;
50 QByteArray signalTmp;
50 QByteArray signalTmp;
51 char first = signal.at(0);
51 char first = signal.at(0);
52 if (first>='0' && first<='9') {
52 if (first>='0' && first<='9') {
53 signalTmp = signal;
53 signalTmp = signal;
54 } else {
54 } else {
55 signalTmp = "2" + signal;
55 signalTmp = "2" + signal;
56 }
56 }
57
57
58 if (sender) {
58 if (sender) {
59 result = PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
59 result = PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
60 if (!result) {
60 if (!result) {
61 if (sender->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(signalTmp.constData()+1)) == -1) {
61 if (sender->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(signalTmp.constData()+1)) == -1) {
62 qWarning("PythonQt: QObject::connect() signal '%s' does not exist on %s", signal.constData(), sender->metaObject()->className());
62 qWarning("PythonQt: QObject::connect() signal '%s' does not exist on %s", signal.constData(), sender->metaObject()->className());
63 }
63 }
64 }
64 }
65 }
65 }
66 return result;
66 return result;
67 }
67 }
68
68
69 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
69 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot, Qt::ConnectionType type)
70 {
70 {
71 bool r = false;
71 bool r = false;
72 if (sender && receiver) {
72 if (sender && receiver) {
73 QByteArray signalTmp;
73 QByteArray signalTmp;
74 char first = signal.at(0);
74 char first = signal.at(0);
75 if (first>='0' && first<='9') {
75 if (first>='0' && first<='9') {
76 signalTmp = signal;
76 signalTmp = signal;
77 } else {
77 } else {
78 signalTmp = "2" + signal;
78 signalTmp = "2" + signal;
79 }
79 }
80
80
81 QByteArray slotTmp;
81 QByteArray slotTmp;
82 first = slot.at(0);
82 first = slot.at(0);
83 if (first>='0' && first<='9') {
83 if (first>='0' && first<='9') {
84 slotTmp = slot;
84 slotTmp = slot;
85 } else {
85 } else {
86 slotTmp = "1" + slot;
86 slotTmp = "1" + slot;
87 }
87 }
88 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
88 r = QObject::connect(sender, signalTmp, receiver, slotTmp, type);
89 }
89 }
90 return r;
90 return r;
91 }
91 }
92
92
93 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
93 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
94 {
94 {
95 bool result = false;
95 bool result = false;
96 QByteArray signalTmp;
96 QByteArray signalTmp;
97 char first = signal.at(0);
97 char first = signal.at(0);
98 if (first>='0' && first<='9') {
98 if (first>='0' && first<='9') {
99 signalTmp = signal;
99 signalTmp = signal;
100 } else {
100 } else {
101 signalTmp = "2" + signal;
101 signalTmp = "2" + signal;
102 }
102 }
103 if (sender) {
103 if (sender) {
104 result = PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
104 result = PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
105 if (callable == NULL) {
105 if (callable == NULL) {
106 result |= QObject::disconnect(sender, signalTmp, NULL, NULL);
106 result |= QObject::disconnect(sender, signalTmp, NULL, NULL);
107 }
107 }
108 if (!result) {
108 if (!result) {
109 if (sender->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(signalTmp.constData()+1)) == -1) {
109 if (sender->metaObject()->indexOfSignal(QMetaObject::normalizedSignature(signalTmp.constData()+1)) == -1) {
110 qWarning("PythonQt: QObject::disconnect() signal '%s' does not exist on %s", signal.constData(), sender->metaObject()->className());
110 qWarning("PythonQt: QObject::disconnect() signal '%s' does not exist on %s", signal.constData(), sender->metaObject()->className());
111 }
111 }
112 }
112 }
113 }
113 }
114 return result;
114 return result;
115 }
115 }
116
116
117 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
117 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
118 {
118 {
119 bool r = false;
119 bool r = false;
120 if (sender && receiver) {
120 if (sender && receiver) {
121 QByteArray signalTmp;
121 QByteArray signalTmp;
122 char first = signal.at(0);
122 char first = signal.at(0);
123 if (first>='0' && first<='9') {
123 if (first>='0' && first<='9') {
124 signalTmp = signal;
124 signalTmp = signal;
125 } else {
125 } else {
126 signalTmp = "2" + signal;
126 signalTmp = "2" + signal;
127 }
127 }
128
128
129 QByteArray slotTmp;
129 QByteArray slotTmp;
130 first = slot.at(0);
130 first = slot.at(0);
131 if (first>='0' && first<='9') {
131 if (first>='0' && first<='9') {
132 slotTmp = slot;
132 slotTmp = slot;
133 } else {
133 } else {
134 slotTmp = "1" + slot;
134 slotTmp = "1" + slot;
135 }
135 }
136
136
137 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
137 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
138 }
138 }
139 return r;
139 return r;
140 }
140 }
141
141
142 QObject* PythonQtStdDecorators::parent(QObject* o) {
142 QObject* PythonQtStdDecorators::parent(QObject* o) {
143 return o->parent();
143 return o->parent();
144 }
144 }
145
145
146 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
146 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
147 {
147 {
148 o->setParent(parent);
148 o->setParent(parent);
149 }
149 }
150
150
151 const QObjectList* PythonQtStdDecorators::children(QObject* o)
151 const QObjectList* PythonQtStdDecorators::children(QObject* o)
152 {
152 {
153 return &o->children();
153 return &o->children();
154 }
154 }
155
155
156 bool PythonQtStdDecorators::setProperty(QObject* o, const char* name, const QVariant& value)
156 bool PythonQtStdDecorators::setProperty(QObject* o, const char* name, const QVariant& value)
157 {
157 {
158 return o->setProperty(name, value);
158 return o->setProperty(name, value);
159 }
159 }
160
160
161 QVariant PythonQtStdDecorators::property(QObject* o, const char* name)
161 QVariant PythonQtStdDecorators::property(QObject* o, const char* name)
162 {
162 {
163 return o->property(name);
163 return o->property(name);
164 }
164 }
165
165
166 QString PythonQtStdDecorators::tr(QObject* obj, const QByteArray& text, const QByteArray& ambig, int n)
166 QString PythonQtStdDecorators::tr(QObject* obj, const QByteArray& text, const QByteArray& ambig, int n)
167 {
167 {
168 return QCoreApplication::translate(obj->metaObject()->className(), text.constData(), ambig.constData(), QCoreApplication::CodecForTr, n);
168 return QCoreApplication::translate(obj->metaObject()->className(), text.constData(), ambig.constData(), QCoreApplication::CodecForTr, n);
169 }
169 }
170
170
171 QObject* PythonQtStdDecorators::findChild(QObject* parent, PyObject* type, const QString& name)
171 QObject* PythonQtStdDecorators::findChild(QObject* parent, PyObject* type, const QString& name)
172 {
172 {
173 const QMetaObject* meta = NULL;
173 const QMetaObject* meta = NULL;
174 const char* typeName = NULL;
174 const char* typeName = NULL;
175
175
176 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
176 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
177 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
177 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
178 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
178 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
179 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
179 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
180 } else if (PyString_Check(type)) {
180 } else if (PyString_Check(type)) {
181 typeName = PyString_AsString(type);
181 typeName = PyString_AsString(type);
182 }
182 }
183
183
184 if (!typeName && !meta)
184 if (!typeName && !meta)
185 return NULL;
185 return NULL;
186
186
187 return findChild(parent, typeName, meta, name);
187 return findChild(parent, typeName, meta, name);
188 }
188 }
189
189
190 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QString& name)
190 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QString& name)
191 {
191 {
192 const QMetaObject* meta = NULL;
192 const QMetaObject* meta = NULL;
193 const char* typeName = NULL;
193 const char* typeName = NULL;
194
194
195 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
195 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
196 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
196 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
197 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
197 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
198 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
198 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
199 } else if (PyString_Check(type)) {
199 } else if (PyString_Check(type)) {
200 typeName = PyString_AsString(type);
200 typeName = PyString_AsString(type);
201 }
201 }
202
202
203 QList<QObject*> list;
203 QList<QObject*> list;
204
204
205 if (!typeName && !meta)
205 if (!typeName && !meta)
206 return list;
206 return list;
207
207
208 findChildren(parent, typeName, meta, name, list);
208 findChildren(parent, typeName, meta, name, list);
209
209
210 return list;
210 return list;
211 }
211 }
212
212
213 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QRegExp& regExp)
213 QList<QObject*> PythonQtStdDecorators::findChildren(QObject* parent, PyObject* type, const QRegExp& regExp)
214 {
214 {
215 const QMetaObject* meta = NULL;
215 const QMetaObject* meta = NULL;
216 const char* typeName = NULL;
216 const char* typeName = NULL;
217
217
218 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
218 if (PyObject_TypeCheck(type, &PythonQtClassWrapper_Type)) {
219 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
219 meta = ((PythonQtClassWrapper*)type)->classInfo()->metaObject();
220 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
220 } else if (PyObject_TypeCheck(type, &PythonQtInstanceWrapper_Type)) {
221 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
221 meta = ((PythonQtInstanceWrapper*)type)->classInfo()->metaObject();
222 } else if (PyString_Check(type)) {
222 } else if (PyString_Check(type)) {
223 typeName = PyString_AsString(type);
223 typeName = PyString_AsString(type);
224 }
224 }
225
225
226 QList<QObject*> list;
226 QList<QObject*> list;
227
227
228 if (!typeName && !meta)
228 if (!typeName && !meta)
229 return list;
229 return list;
230
230
231 findChildren(parent, typeName, meta, regExp, list);
231 findChildren(parent, typeName, meta, regExp, list);
232
232
233 return list;
233 return list;
234 }
234 }
235
235
236 QObject* PythonQtStdDecorators::findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name)
236 QObject* PythonQtStdDecorators::findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name)
237 {
237 {
238 const QObjectList &children = parent->children();
238 const QObjectList &children = parent->children();
239
239
240 int i;
240 int i;
241 for (i = 0; i < children.size(); ++i) {
241 for (i = 0; i < children.size(); ++i) {
242 QObject* obj = children.at(i);
242 QObject* obj = children.at(i);
243
243
244 if (!obj)
244 if (!obj)
245 return NULL;
245 return NULL;
246
246
247 // Skip if the name doesn't match.
247 // Skip if the name doesn't match.
248 if (!name.isNull() && obj->objectName() != name)
248 if (!name.isNull() && obj->objectName() != name)
249 continue;
249 continue;
250
250
251 if ((typeName && obj->inherits(typeName)) ||
251 if ((typeName && obj->inherits(typeName)) ||
252 (meta && meta->cast(obj)))
252 (meta && meta->cast(obj)))
253 return obj;
253 return obj;
254 }
254 }
255
255
256 for (i = 0; i < children.size(); ++i) {
256 for (i = 0; i < children.size(); ++i) {
257 QObject* obj = findChild(children.at(i), typeName, meta, name);
257 QObject* obj = findChild(children.at(i), typeName, meta, name);
258
258
259 if (obj != NULL)
259 if (obj != NULL)
260 return obj;
260 return obj;
261 }
261 }
262
262
263 return NULL;
263 return NULL;
264 }
264 }
265
265
266 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list)
266 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list)
267 {
267 {
268 const QObjectList& children = parent->children();
268 const QObjectList& children = parent->children();
269 int i;
269 int i;
270
270
271 for (i = 0; i < children.size(); ++i) {
271 for (i = 0; i < children.size(); ++i) {
272 QObject* obj = children.at(i);
272 QObject* obj = children.at(i);
273
273
274 if (!obj)
274 if (!obj)
275 return -1;
275 return -1;
276
276
277 // Skip if the name doesn't match.
277 // Skip if the name doesn't match.
278 if (!name.isNull() && obj->objectName() != name)
278 if (!name.isNull() && obj->objectName() != name)
279 continue;
279 continue;
280
280
281 if ((typeName && obj->inherits(typeName)) ||
281 if ((typeName && obj->inherits(typeName)) ||
282 (meta && meta->cast(obj))) {
282 (meta && meta->cast(obj))) {
283 list += obj;
283 list += obj;
284 }
284 }
285
285
286 if (findChildren(obj, typeName, meta, name, list) < 0)
286 if (findChildren(obj, typeName, meta, name, list) < 0)
287 return -1;
287 return -1;
288 }
288 }
289
289
290 return 0;
290 return 0;
291 }
291 }
292
292
293 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list)
293 int PythonQtStdDecorators::findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list)
294 {
294 {
295 const QObjectList& children = parent->children();
295 const QObjectList& children = parent->children();
296 int i;
296 int i;
297
297
298 for (i = 0; i < children.size(); ++i) {
298 for (i = 0; i < children.size(); ++i) {
299 QObject* obj = children.at(i);
299 QObject* obj = children.at(i);
300
300
301 if (!obj)
301 if (!obj)
302 return -1;
302 return -1;
303
303
304 // Skip if the name doesn't match.
304 // Skip if the name doesn't match.
305 if (regExp.indexIn(obj->objectName()) == -1)
305 if (regExp.indexIn(obj->objectName()) == -1)
306 continue;
306 continue;
307
307
308 if ((typeName && obj->inherits(typeName)) ||
308 if ((typeName && obj->inherits(typeName)) ||
309 (meta && meta->cast(obj))) {
309 (meta && meta->cast(obj))) {
310 list += obj;
310 list += obj;
311 }
311 }
312
312
313 if (findChildren(obj, typeName, meta, regExp, list) < 0)
313 if (findChildren(obj, typeName, meta, regExp, list) < 0)
314 return -1;
314 return -1;
315 }
315 }
316
316
317 return 0;
317 return 0;
318 }
318 }
319
320 const QMetaObject* PythonQtStdDecorators::metaObject( QObject* obj )
321 {
322 return obj->metaObject();
323 } No newline at end of file
@@ -1,109 +1,159
1 #ifndef _PYTHONQTSTDDECORATORS_H
1 #ifndef _PYTHONQTSTDDECORATORS_H
2 #define _PYTHONQTSTDDECORATORS_H
2 #define _PYTHONQTSTDDECORATORS_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtStdDecorators.h
38 // \file PythonQtStdDecorators.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2007-04
41 // \date 2007-04
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtPythonInclude.h"
45 #include "PythonQtPythonInclude.h"
46
46
47 #include "PythonQtSystem.h"
47 #include "PythonQtSystem.h"
48
48
49 #include <QObject>
49 #include <QObject>
50 #include <QVariantList>
50 #include <QVariantList>
51 #include <QTextDocument>
51 #include <QTextDocument>
52 #include <QColor>
52 #include <QColor>
53 #include <QDateTime>
53 #include <QDateTime>
54 #include <QDate>
54 #include <QDate>
55 #include <QTime>
55 #include <QTime>
56 #include <QImage>
57 #include <QMetaMethod>
58 #include <QMetaEnum>
59 #include <QMetaProperty>
56
60
57 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
61 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
58 {
62 {
59 Q_OBJECT
63 Q_OBJECT
60
64
61 public slots:
65 public slots:
62 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
66 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
63 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
67 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot, Qt::ConnectionType type = Qt::AutoConnection);
68 bool connect(QObject* receiver, QObject* sender, const QByteArray& signal, const QByteArray& slot, Qt::ConnectionType type = Qt::AutoConnection) { return connect(sender, signal, receiver, slot, type); }
69 bool static_QObject_connect(QObject* sender, const QByteArray& signal, PyObject* callable) { return connect(sender, signal, callable); }
70 bool static_QObject_connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot, Qt::ConnectionType type = Qt::AutoConnection) { return connect(sender, signal, receiver, slot, type); }
64 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable = NULL);
71 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable = NULL);
65 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
72 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
73 bool static_QObject_disconnect(QObject* sender, const QByteArray& signal, PyObject* callable = NULL) { return disconnect(sender, signal, callable); }
74 bool static_QObject_disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot) { return connect(sender, signal, receiver, slot); }
75
76 const QMetaObject* metaObject( QObject* obj );
66
77
67 QObject* parent(QObject* o);
78 QObject* parent(QObject* o);
68 void setParent(QObject* o, QObject* parent);
79 void setParent(QObject* o, QObject* parent);
69
80
70 const QObjectList* children(QObject* o);
81 const QObjectList* children(QObject* o);
71 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
82 QObject* findChild(QObject* parent, PyObject* type, const QString& name = QString());
72 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
83 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QString& name= QString());
73 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
84 QList<QObject*> findChildren(QObject* parent, PyObject* type, const QRegExp& regExp);
74
85
75 bool setProperty(QObject* o, const char* name, const QVariant& value);
86 bool setProperty(QObject* o, const char* name, const QVariant& value);
76 QVariant property(QObject* o, const char* name);
87 QVariant property(QObject* o, const char* name);
77
88
78 double static_Qt_qAbs(double a) { return qAbs(a); }
89 double static_Qt_qAbs(double a) { return qAbs(a); }
79 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
90 double static_Qt_qBound(double a,double b,double c) { return qBound(a,b,c); }
80 void static_Qt_qDebug(const QByteArray& msg) { qDebug("%s", msg.constData()); }
91 void static_Qt_qDebug(const QByteArray& msg) { qDebug("%s", msg.constData()); }
81 // TODO: multi arg qDebug...
92 // TODO: multi arg qDebug...
82 void static_Qt_qWarning(const QByteArray& msg) { qWarning("%s", msg.constData()); }
93 void static_Qt_qWarning(const QByteArray& msg) { qWarning("%s", msg.constData()); }
83 // TODO: multi arg qWarning...
94 // TODO: multi arg qWarning...
84 void static_Qt_qCritical(const QByteArray& msg) { qCritical("%s", msg.constData()); }
95 void static_Qt_qCritical(const QByteArray& msg) { qCritical("%s", msg.constData()); }
85 // TODO: multi arg qCritical...
96 // TODO: multi arg qCritical...
86 void static_Qt_qFatal(const QByteArray& msg) { qFatal("%s", msg.constData()); }
97 void static_Qt_qFatal(const QByteArray& msg) { qFatal("%s", msg.constData()); }
87 // TODO: multi arg qFatal...
98 // TODO: multi arg qFatal...
88 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
99 bool static_Qt_qFuzzyCompare(double a, double b) { return qFuzzyCompare(a, b); }
89 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
100 double static_Qt_qMax(double a, double b) { return qMax(a, b); }
90 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
101 double static_Qt_qMin(double a, double b) { return qMin(a, b); }
91 int static_Qt_qRound(double a) { return qRound(a); }
102 int static_Qt_qRound(double a) { return qRound(a); }
92 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
103 qint64 static_Qt_qRound64(double a) { return qRound64(a); }
93 const char* static_Qt_qVersion() { return qVersion(); }
104 const char* static_Qt_qVersion() { return qVersion(); }
94 int static_Qt_qrand() { return qrand(); }
105 int static_Qt_qrand() { return qrand(); }
95 void static_Qt_qsrand(uint a) { qsrand(a); }
106 void static_Qt_qsrand(uint a) { qsrand(a); }
96
107
97 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
108 QString tr(QObject* obj, const QByteArray& text, const QByteArray& ambig = QByteArray(), int n = -1);
98
109
99 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
110 QByteArray static_Qt_SIGNAL(const QByteArray& s) { return QByteArray("2") + s; }
100 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
111 QByteArray static_Qt_SLOT(const QByteArray& s) { return QByteArray("1") + s; }
101
112
102 private:
113 private:
103 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
114 QObject* findChild(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name);
104 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
115 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QString& name, QList<QObject*>& list);
105 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
116 int findChildren(QObject* parent, const char* typeName, const QMetaObject* meta, const QRegExp& regExp, QList<QObject*>& list);
106 };
117 };
107
118
119 class PythonQtWrapper_QMetaObject : public QObject
120 {
121 Q_OBJECT
122
123 public slots:
124 const char *className(QMetaObject* obj) const { return obj->className(); }
125 const QMetaObject *superClass(QMetaObject* obj) const { return obj->superClass(); }
126
127 int methodOffset(QMetaObject* obj) const { return obj->methodOffset(); }
128 int enumeratorOffset(QMetaObject* obj) const { return obj->enumeratorOffset(); }
129 int propertyOffset(QMetaObject* obj) const { return obj->propertyOffset(); }
130 int classInfoOffset(QMetaObject* obj) const { return obj->classInfoOffset(); }
131
132 int constructorCount(QMetaObject* obj) const { return obj->constructorCount(); }
133 int methodCount(QMetaObject* obj) const { return obj->methodCount(); }
134 int enumeratorCount(QMetaObject* obj) const { return obj->enumeratorCount(); }
135 int propertyCount(QMetaObject* obj) const { return obj->propertyCount(); }
136 int classInfoCount(QMetaObject* obj) const { return obj->classInfoCount(); }
137
138 int indexOfConstructor(QMetaObject* obj, const char *constructor) const { return obj->indexOfConstructor(constructor); }
139 int indexOfMethod(QMetaObject* obj, const char *method) const { return obj->indexOfMethod(method); }
140 int indexOfSignal(QMetaObject* obj, const char *signal) const { return obj->indexOfSignal(signal); }
141 int indexOfSlot(QMetaObject* obj, const char *slot) const { return obj->indexOfSlot(slot); }
142 int indexOfEnumerator(QMetaObject* obj, const char *name) const { return obj->indexOfEnumerator(name); }
143 int indexOfProperty(QMetaObject* obj, const char *name) const { return obj->indexOfProperty(name); }
144 int indexOfClassInfo(QMetaObject* obj, const char *name) const { return obj->indexOfClassInfo(name); }
145
146 QMetaMethod constructor(QMetaObject* obj, int index) const { return obj->constructor(index); }
147 QMetaMethod method(QMetaObject* obj, int index) const { return obj->method(index); }
148 QMetaEnum enumerator(QMetaObject* obj, int index) const { return obj->enumerator(index); }
149 QMetaProperty property(QMetaObject* obj, int index) const { return obj->property(index); }
150 QMetaClassInfo classInfo(QMetaObject* obj, int index) const { return obj->classInfo(index); }
151 QMetaProperty userProperty(QMetaObject* obj) const { return obj->userProperty(); }
152
153 bool static_QMetaObject_checkConnectArgs(const char *signal, const char *method) { return QMetaObject::checkConnectArgs(signal, method); }
154 QByteArray static_QMetaObject_normalizedSignature(const char *method) { return QMetaObject::normalizedSignature(method); }
155 QByteArray static_QMetaObject_normalizedType(const char *type) { return QMetaObject::normalizedType(type); }
156
157 };
108
158
109 #endif
159 #endif
General Comments 0
You need to be logged in to leave comments. Login now