##// END OF EJS Templates
support enum values on signals as well, all tests should succeed now...
florianlink -
r56:607d4eb3cb2d
parent child
Show More
@@ -1,1185 +1,1193
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtImporter.h"
43 #include "PythonQtImporter.h"
44 #include "PythonQtClassInfo.h"
44 #include "PythonQtClassInfo.h"
45 #include "PythonQtMethodInfo.h"
45 #include "PythonQtMethodInfo.h"
46 #include "PythonQtSignalReceiver.h"
46 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtStdOut.h"
48 #include "PythonQtStdOut.h"
49 #include "PythonQtCppWrapperFactory.h"
49 #include "PythonQtCppWrapperFactory.h"
50 #include "PythonQtVariants.h"
50 #include "PythonQtVariants.h"
51 #include "PythonQtStdDecorators.h"
51 #include "PythonQtStdDecorators.h"
52 #include "PythonQtQFileImporter.h"
52 #include "PythonQtQFileImporter.h"
53 #include <pydebug.h>
53 #include <pydebug.h>
54 #include <vector>
54 #include <vector>
55
55
56 PythonQt* PythonQt::_self = NULL;
56 PythonQt* PythonQt::_self = NULL;
57 int PythonQt::_uniqueModuleCount = 0;
57 int PythonQt::_uniqueModuleCount = 0;
58
58
59 void PythonQt::init(int flags)
59 void PythonQt::init(int flags)
60 {
60 {
61 if (!_self) {
61 if (!_self) {
62 _self = new PythonQt(flags);
62 _self = new PythonQt(flags);
63 }
63 }
64
64
65 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
65 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
66 qRegisterMetaType<QList<QObject*> >("QList<void*>");
66 qRegisterMetaType<QList<QObject*> >("QList<void*>");
67
67
68 PythonQtRegisterToolClassesTemplateConverter(int);
68 PythonQtRegisterToolClassesTemplateConverter(int);
69 PythonQtRegisterToolClassesTemplateConverter(float);
69 PythonQtRegisterToolClassesTemplateConverter(float);
70 PythonQtRegisterToolClassesTemplateConverter(double);
70 PythonQtRegisterToolClassesTemplateConverter(double);
71 // TODO: which other POD types should be available for QList etc.
71 // TODO: which other POD types should be available for QList etc.
72
72
73 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
73 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
74
74
75 PythonQt::self()->registerCPPClass("Qt", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_Qt>);
75 PythonQt::self()->registerCPPClass("Qt", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_Qt>);
76 PythonQt::self()->registerCPPClass("QBitArray", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QBitArray>);
76 PythonQt::self()->registerCPPClass("QBitArray", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QBitArray>);
77 PythonQt::self()->registerCPPClass("QDate", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QDate>);
77 PythonQt::self()->registerCPPClass("QDate", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QDate>);
78 PythonQt::self()->registerCPPClass("QTime", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QTime>);
78 PythonQt::self()->registerCPPClass("QTime", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QTime>);
79 PythonQt::self()->registerCPPClass("QDateTime", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QDateTime>);
79 PythonQt::self()->registerCPPClass("QDateTime", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QDateTime>);
80 PythonQt::self()->registerCPPClass("QUrl", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QUrl>);
80 PythonQt::self()->registerCPPClass("QUrl", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QUrl>);
81 PythonQt::self()->registerCPPClass("QLocale", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLocale>);
81 PythonQt::self()->registerCPPClass("QLocale", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLocale>);
82 PythonQt::self()->registerCPPClass("QRect", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRect>);
82 PythonQt::self()->registerCPPClass("QRect", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRect>);
83 PythonQt::self()->registerCPPClass("QRectF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRectF>);
83 PythonQt::self()->registerCPPClass("QRectF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRectF>);
84 PythonQt::self()->registerCPPClass("QSize", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QSize>);
84 PythonQt::self()->registerCPPClass("QSize", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QSize>);
85 PythonQt::self()->registerCPPClass("QSizeF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QSizeF>);
85 PythonQt::self()->registerCPPClass("QSizeF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QSizeF>);
86 PythonQt::self()->registerCPPClass("QLine", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLine>);
86 PythonQt::self()->registerCPPClass("QLine", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLine>);
87 PythonQt::self()->registerCPPClass("QLineF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLineF>);
87 PythonQt::self()->registerCPPClass("QLineF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLineF>);
88 PythonQt::self()->registerCPPClass("QPoint", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QPoint>);
88 PythonQt::self()->registerCPPClass("QPoint", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QPoint>);
89 PythonQt::self()->registerCPPClass("QPointF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QPointF>);
89 PythonQt::self()->registerCPPClass("QPointF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QPointF>);
90 PythonQt::self()->registerCPPClass("QRegExp", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRegExp>);
90 PythonQt::self()->registerCPPClass("QRegExp", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRegExp>);
91
91
92 PythonQtRegisterToolClassesTemplateConverter(QDate);
92 PythonQtRegisterToolClassesTemplateConverter(QDate);
93 PythonQtRegisterToolClassesTemplateConverter(QTime);
93 PythonQtRegisterToolClassesTemplateConverter(QTime);
94 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
94 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
95 PythonQtRegisterToolClassesTemplateConverter(QUrl);
95 PythonQtRegisterToolClassesTemplateConverter(QUrl);
96 PythonQtRegisterToolClassesTemplateConverter(QLocale);
96 PythonQtRegisterToolClassesTemplateConverter(QLocale);
97 PythonQtRegisterToolClassesTemplateConverter(QRect);
97 PythonQtRegisterToolClassesTemplateConverter(QRect);
98 PythonQtRegisterToolClassesTemplateConverter(QRectF);
98 PythonQtRegisterToolClassesTemplateConverter(QRectF);
99 PythonQtRegisterToolClassesTemplateConverter(QSize);
99 PythonQtRegisterToolClassesTemplateConverter(QSize);
100 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
100 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
101 PythonQtRegisterToolClassesTemplateConverter(QLine);
101 PythonQtRegisterToolClassesTemplateConverter(QLine);
102 PythonQtRegisterToolClassesTemplateConverter(QLineF);
102 PythonQtRegisterToolClassesTemplateConverter(QLineF);
103 PythonQtRegisterToolClassesTemplateConverter(QPoint);
103 PythonQtRegisterToolClassesTemplateConverter(QPoint);
104 PythonQtRegisterToolClassesTemplateConverter(QPointF);
104 PythonQtRegisterToolClassesTemplateConverter(QPointF);
105 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
105 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
106
106
107 PythonQt::self()->registerCPPClass("QFont", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QFont>);
107 PythonQt::self()->registerCPPClass("QFont", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QFont>);
108 PythonQt::self()->registerCPPClass("QPixmap", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPixmap>);
108 PythonQt::self()->registerCPPClass("QPixmap", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPixmap>);
109 PythonQt::self()->registerCPPClass("QBrush", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QBrush>);
109 PythonQt::self()->registerCPPClass("QBrush", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QBrush>);
110 PythonQt::self()->registerCPPClass("QColor", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QColor>);
110 PythonQt::self()->registerCPPClass("QColor", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QColor>);
111 PythonQt::self()->registerCPPClass("QPalette", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPalette>);
111 PythonQt::self()->registerCPPClass("QPalette", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPalette>);
112 PythonQt::self()->registerCPPClass("QIcon", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QIcon>);
112 PythonQt::self()->registerCPPClass("QIcon", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QIcon>);
113 PythonQt::self()->registerCPPClass("QImage", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QImage>);
113 PythonQt::self()->registerCPPClass("QImage", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QImage>);
114 PythonQt::self()->registerCPPClass("QPolygon", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPolygon>);
114 PythonQt::self()->registerCPPClass("QPolygon", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPolygon>);
115 PythonQt::self()->registerCPPClass("QRegion", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QRegion>);
115 PythonQt::self()->registerCPPClass("QRegion", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QRegion>);
116 PythonQt::self()->registerCPPClass("QBitmap", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QBitmap>);
116 PythonQt::self()->registerCPPClass("QBitmap", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QBitmap>);
117 PythonQt::self()->registerCPPClass("QCursor", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QCursor>);
117 PythonQt::self()->registerCPPClass("QCursor", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QCursor>);
118 PythonQt::self()->registerCPPClass("QSizePolicy", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QSizePolicy>);
118 PythonQt::self()->registerCPPClass("QSizePolicy", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QSizePolicy>);
119 PythonQt::self()->registerCPPClass("QKeySequence", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QKeySequence>);
119 PythonQt::self()->registerCPPClass("QKeySequence", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QKeySequence>);
120 PythonQt::self()->registerCPPClass("QPen", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPen>);
120 PythonQt::self()->registerCPPClass("QPen", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPen>);
121 PythonQt::self()->registerCPPClass("QTextLength", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QTextLength>);
121 PythonQt::self()->registerCPPClass("QTextLength", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QTextLength>);
122 PythonQt::self()->registerCPPClass("QTextFormat", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QTextFormat>);
122 PythonQt::self()->registerCPPClass("QTextFormat", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QTextFormat>);
123 PythonQt::self()->registerCPPClass("QMatrix", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QMatrix>);
123 PythonQt::self()->registerCPPClass("QMatrix", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QMatrix>);
124
124
125 PythonQtRegisterToolClassesTemplateConverter(QFont);
125 PythonQtRegisterToolClassesTemplateConverter(QFont);
126 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
126 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
127 PythonQtRegisterToolClassesTemplateConverter(QBrush);
127 PythonQtRegisterToolClassesTemplateConverter(QBrush);
128 PythonQtRegisterToolClassesTemplateConverter(QColor);
128 PythonQtRegisterToolClassesTemplateConverter(QColor);
129 PythonQtRegisterToolClassesTemplateConverter(QPalette);
129 PythonQtRegisterToolClassesTemplateConverter(QPalette);
130 PythonQtRegisterToolClassesTemplateConverter(QIcon);
130 PythonQtRegisterToolClassesTemplateConverter(QIcon);
131 PythonQtRegisterToolClassesTemplateConverter(QImage);
131 PythonQtRegisterToolClassesTemplateConverter(QImage);
132 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
132 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
133 PythonQtRegisterToolClassesTemplateConverter(QRegion);
133 PythonQtRegisterToolClassesTemplateConverter(QRegion);
134 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
134 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
135 PythonQtRegisterToolClassesTemplateConverter(QCursor);
135 PythonQtRegisterToolClassesTemplateConverter(QCursor);
136 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
136 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
137 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
137 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
138 PythonQtRegisterToolClassesTemplateConverter(QPen);
138 PythonQtRegisterToolClassesTemplateConverter(QPen);
139 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
139 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
140 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
140 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
141 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
141 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
142
142
143 }
143 }
144
144
145 void PythonQt::cleanup()
145 void PythonQt::cleanup()
146 {
146 {
147 if (_self) {
147 if (_self) {
148 delete _self;
148 delete _self;
149 _self = NULL;
149 _self = NULL;
150 }
150 }
151 }
151 }
152
152
153 PythonQt::PythonQt(int flags)
153 PythonQt::PythonQt(int flags)
154 {
154 {
155 _p = new PythonQtPrivate;
155 _p = new PythonQtPrivate;
156 _p->_initFlags = flags;
156 _p->_initFlags = flags;
157
157
158 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
158 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
159
159
160 Py_SetProgramName("PythonQt");
160 Py_SetProgramName("PythonQt");
161 if (flags & IgnoreSiteModule) {
161 if (flags & IgnoreSiteModule) {
162 // this prevents the automatic importing of Python site files
162 // this prevents the automatic importing of Python site files
163 Py_NoSiteFlag = 1;
163 Py_NoSiteFlag = 1;
164 }
164 }
165 Py_Initialize();
165 Py_Initialize();
166
166
167 // add our own python object types for qt object slots
167 // add our own python object types for qt object slots
168 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
168 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
169 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
169 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
170 }
170 }
171 Py_INCREF(&PythonQtSlotFunction_Type);
171 Py_INCREF(&PythonQtSlotFunction_Type);
172
172
173 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
173 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
174 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
174 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
175 // add our own python object types for classes
175 // add our own python object types for classes
176 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
176 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
177 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
177 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
178 }
178 }
179 Py_INCREF(&PythonQtClassWrapper_Type);
179 Py_INCREF(&PythonQtClassWrapper_Type);
180
180
181 // add our own python object types for CPP instances
181 // add our own python object types for CPP instances
182 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
182 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
183 PythonQt::handleError();
183 PythonQt::handleError();
184 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
184 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
185 }
185 }
186 Py_INCREF(&PythonQtInstanceWrapper_Type);
186 Py_INCREF(&PythonQtInstanceWrapper_Type);
187
187
188 // add our own python object types for redirection of stdout
188 // add our own python object types for redirection of stdout
189 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
189 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
190 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
190 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
191 }
191 }
192 Py_INCREF(&PythonQtStdOutRedirectType);
192 Py_INCREF(&PythonQtStdOutRedirectType);
193
193
194 initPythonQtModule(flags & RedirectStdOut);
194 initPythonQtModule(flags & RedirectStdOut);
195
195
196 }
196 }
197
197
198 PythonQt::~PythonQt() {
198 PythonQt::~PythonQt() {
199 delete _p;
199 delete _p;
200 _p = NULL;
200 _p = NULL;
201 }
201 }
202
202
203 PythonQtPrivate::~PythonQtPrivate() {
203 PythonQtPrivate::~PythonQtPrivate() {
204 delete _defaultImporter;
204 delete _defaultImporter;
205 _defaultImporter = NULL;
205 _defaultImporter = NULL;
206
206
207 {
207 {
208 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
208 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
209 while (i.hasNext()) {
209 while (i.hasNext()) {
210 delete i.next().value();
210 delete i.next().value();
211 }
211 }
212 }
212 }
213 PythonQtConv::global_valueStorage.clear();
213 PythonQtConv::global_valueStorage.clear();
214 PythonQtConv::global_ptrStorage.clear();
214 PythonQtConv::global_ptrStorage.clear();
215 PythonQtConv::global_variantStorage.clear();
215 PythonQtConv::global_variantStorage.clear();
216
216
217 PythonQtMethodInfo::cleanupCachedMethodInfos();
217 PythonQtMethodInfo::cleanupCachedMethodInfos();
218 }
218 }
219
219
220 PythonQtImportFileInterface* PythonQt::importInterface()
220 PythonQtImportFileInterface* PythonQt::importInterface()
221 {
221 {
222 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
222 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
223 }
223 }
224
224
225 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
225 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
226 {
226 {
227 if (_self->_p->_noLongerWrappedCB) {
227 if (_self->_p->_noLongerWrappedCB) {
228 (*_self->_p->_noLongerWrappedCB)(o);
228 (*_self->_p->_noLongerWrappedCB)(o);
229 };
229 };
230 }
230 }
231
231
232 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
232 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
233 {
233 {
234 _p->registerClass(metaobject, package, wrapperCreator, shell);
234 _p->registerClass(metaobject, package, wrapperCreator, shell);
235 }
235 }
236
236
237 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
237 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
238 {
238 {
239 // we register all classes in the hierarchy
239 // we register all classes in the hierarchy
240 const QMetaObject* m = metaobject;
240 const QMetaObject* m = metaobject;
241 bool first = true;
241 bool first = true;
242 while (m) {
242 while (m) {
243 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
243 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
244 if (!info->pythonQtClassWrapper()) {
244 if (!info->pythonQtClassWrapper()) {
245 info->setupQObject(m);
245 info->setupQObject(m);
246 createPythonQtClassWrapper(info, package);
246 createPythonQtClassWrapper(info, package);
247 if (m->superClass()) {
247 if (m->superClass()) {
248 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
248 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
249 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
249 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
250 }
250 }
251 }
251 }
252 if (first) {
252 if (first) {
253 first = false;
253 first = false;
254 if (wrapperCreator) {
254 if (wrapperCreator) {
255 info->setDecoratorProvider(wrapperCreator);
255 info->setDecoratorProvider(wrapperCreator);
256 }
256 }
257 if (shell) {
257 if (shell) {
258 info->setShellSetInstanceWrapperCB(shell);
258 info->setShellSetInstanceWrapperCB(shell);
259 }
259 }
260 }
260 }
261 m = m->superClass();
261 m = m->superClass();
262 }
262 }
263 }
263 }
264
264
265 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package)
265 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package)
266 {
266 {
267 PyObject* pack = packageByName(package);
267 PyObject* pack = packageByName(package);
268 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, package);
268 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, package);
269 PyModule_AddObject(pack, info->className(), pyobj);
269 PyModule_AddObject(pack, info->className(), pyobj);
270 if (package && strncmp(package,"Qt",2)==0) {
270 if (package && strncmp(package,"Qt",2)==0) {
271 // since PyModule_AddObject steals the reference, we need a incref once more...
271 // since PyModule_AddObject steals the reference, we need a incref once more...
272 Py_INCREF(pyobj);
272 Py_INCREF(pyobj);
273 // put all qt objects into Qt as well
273 // put all qt objects into Qt as well
274 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
274 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
275 }
275 }
276 info->setPythonQtClassWrapper(pyobj);
276 info->setPythonQtClassWrapper(pyobj);
277 }
277 }
278
278
279 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
279 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
280 {
280 {
281 if (!obj) {
281 if (!obj) {
282 Py_INCREF(Py_None);
282 Py_INCREF(Py_None);
283 return Py_None;
283 return Py_None;
284 }
284 }
285 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
285 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
286 if (!wrap) {
286 if (!wrap) {
287 // smuggling it in...
287 // smuggling it in...
288 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
288 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
289 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
289 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
290 registerClass(obj->metaObject());
290 registerClass(obj->metaObject());
291 classInfo = _knownClassInfos.value(obj->metaObject()->className());
291 classInfo = _knownClassInfos.value(obj->metaObject()->className());
292 }
292 }
293 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
293 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
294 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
294 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
295 } else {
295 } else {
296 Py_INCREF(wrap);
296 Py_INCREF(wrap);
297 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
297 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
298 }
298 }
299 return (PyObject*)wrap;
299 return (PyObject*)wrap;
300 }
300 }
301
301
302 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
302 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
303 {
303 {
304 if (!ptr) {
304 if (!ptr) {
305 Py_INCREF(Py_None);
305 Py_INCREF(Py_None);
306 return Py_None;
306 return Py_None;
307 }
307 }
308
308
309 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
309 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
310 if (!wrap) {
310 if (!wrap) {
311 PythonQtClassInfo* info = _knownClassInfos.value(name);
311 PythonQtClassInfo* info = _knownClassInfos.value(name);
312 if (!info) {
312 if (!info) {
313 // maybe it is a PyObject, which we can return directly
313 // maybe it is a PyObject, which we can return directly
314 if (name == "PyObject") {
314 if (name == "PyObject") {
315 PyObject* p = (PyObject*)ptr;
315 PyObject* p = (PyObject*)ptr;
316 Py_INCREF(p);
316 Py_INCREF(p);
317 return p;
317 return p;
318 }
318 }
319
319
320 // we do not know the metaobject yet, but we might know it by it's name:
320 // we do not know the metaobject yet, but we might know it by it's name:
321 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
321 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
322 // yes, we know it, so we can convert to QObject
322 // yes, we know it, so we can convert to QObject
323 QObject* qptr = (QObject*)ptr;
323 QObject* qptr = (QObject*)ptr;
324 registerClass(qptr->metaObject());
324 registerClass(qptr->metaObject());
325 info = _knownClassInfos.value(qptr->metaObject()->className());
325 info = _knownClassInfos.value(qptr->metaObject()->className());
326 }
326 }
327 }
327 }
328 if (info && info->isQObject()) {
328 if (info && info->isQObject()) {
329 QObject* qptr = (QObject*)ptr;
329 QObject* qptr = (QObject*)ptr;
330 // if the object is a derived object, we want to switch the class info to the one of the derived class:
330 // if the object is a derived object, we want to switch the class info to the one of the derived class:
331 if (name!=(qptr->metaObject()->className())) {
331 if (name!=(qptr->metaObject()->className())) {
332 registerClass(qptr->metaObject());
332 registerClass(qptr->metaObject());
333 info = _knownClassInfos.value(qptr->metaObject()->className());
333 info = _knownClassInfos.value(qptr->metaObject()->className());
334 }
334 }
335 wrap = createNewPythonQtInstanceWrapper(qptr, info);
335 wrap = createNewPythonQtInstanceWrapper(qptr, info);
336 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
336 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
337 return (PyObject*)wrap;
337 return (PyObject*)wrap;
338 }
338 }
339
339
340 // not a known QObject, so try our wrapper factory:
340 // not a known QObject, so try our wrapper factory:
341 QObject* wrapper = NULL;
341 QObject* wrapper = NULL;
342 for (int i=0; i<_cppWrapperFactories.size(); i++) {
342 for (int i=0; i<_cppWrapperFactories.size(); i++) {
343 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
343 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
344 if (wrapper) {
344 if (wrapper) {
345 break;
345 break;
346 }
346 }
347 }
347 }
348
348
349 if (info) {
349 if (info) {
350 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
350 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
351 ptr = info->castDownIfPossible(ptr, &info);
351 ptr = info->castDownIfPossible(ptr, &info);
352 }
352 }
353
353
354 if (!info || info->pythonQtClassWrapper()==NULL) {
354 if (!info || info->pythonQtClassWrapper()==NULL) {
355 // still unknown, register as CPP class
355 // still unknown, register as CPP class
356 registerCPPClass(name.constData());
356 registerCPPClass(name.constData());
357 info = _knownClassInfos.value(name);
357 info = _knownClassInfos.value(name);
358 }
358 }
359 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
359 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
360 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
360 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
361 info->setMetaObject(wrapper->metaObject());
361 info->setMetaObject(wrapper->metaObject());
362 }
362 }
363 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
363 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
364 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
364 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
365 } else {
365 } else {
366 Py_INCREF(wrap);
366 Py_INCREF(wrap);
367 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
367 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
368 }
368 }
369 return (PyObject*)wrap;
369 return (PyObject*)wrap;
370 }
370 }
371
371
372 PyObject* PythonQtPrivate::dummyTuple() {
372 PyObject* PythonQtPrivate::dummyTuple() {
373 static PyObject* dummyTuple = NULL;
373 static PyObject* dummyTuple = NULL;
374 if (dummyTuple==NULL) {
374 if (dummyTuple==NULL) {
375 dummyTuple = PyTuple_New(1);
375 dummyTuple = PyTuple_New(1);
376 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
376 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
377 }
377 }
378 return dummyTuple;
378 return dummyTuple;
379 }
379 }
380
380
381
381
382 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
382 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
383 // call the associated class type to create a new instance...
383 // call the associated class type to create a new instance...
384 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
384 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
385
385
386 result->setQObject(obj);
386 result->setQObject(obj);
387 result->_wrappedPtr = wrappedPtr;
387 result->_wrappedPtr = wrappedPtr;
388 result->_ownedByPythonQt = false;
388 result->_ownedByPythonQt = false;
389 result->_useQMetaTypeDestroy = false;
389 result->_useQMetaTypeDestroy = false;
390
390
391 if (wrappedPtr) {
391 if (wrappedPtr) {
392 _wrappedObjects.insert(wrappedPtr, result);
392 _wrappedObjects.insert(wrappedPtr, result);
393 } else {
393 } else {
394 _wrappedObjects.insert(obj, result);
394 _wrappedObjects.insert(obj, result);
395 if (obj->parent()== NULL && _wrappedCB) {
395 if (obj->parent()== NULL && _wrappedCB) {
396 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
396 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
397 (*_wrappedCB)(obj);
397 (*_wrappedCB)(obj);
398 }
398 }
399 }
399 }
400 return result;
400 return result;
401 }
401 }
402
402
403 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) {
403 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) {
404 PythonQtClassWrapper* result;
404 PythonQtClassWrapper* result;
405
405
406 PyObject* className = PyString_FromString(info->className());
406 PyObject* className = PyString_FromString(info->className());
407
407
408 PyObject* baseClasses = PyTuple_New(1);
408 PyObject* baseClasses = PyTuple_New(1);
409 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
409 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
410
410
411 PyObject* typeDict = PyDict_New();
411 PyObject* typeDict = PyDict_New();
412 QByteArray moduleName("PythonQt");
412 QByteArray moduleName("PythonQt");
413 if (package && strcmp(package, "")!=0) {
413 if (package && strcmp(package, "")!=0) {
414 moduleName += ".";
414 moduleName += ".";
415 moduleName += package;
415 moduleName += package;
416 }
416 }
417 PyDict_SetItemString(typeDict, "__module__", PyString_FromString(moduleName.constData()));
417 PyDict_SetItemString(typeDict, "__module__", PyString_FromString(moduleName.constData()));
418
418
419 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
419 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
420
420
421 // set the class info so that PythonQtClassWrapper_new can read it
421 // set the class info so that PythonQtClassWrapper_new can read it
422 _currentClassInfoForClassWrapperCreation = info;
422 _currentClassInfoForClassWrapperCreation = info;
423 // create the new type object by calling the type
423 // create the new type object by calling the type
424 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
424 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
425
425
426 Py_DECREF(baseClasses);
426 Py_DECREF(baseClasses);
427 Py_DECREF(typeDict);
427 Py_DECREF(typeDict);
428 Py_DECREF(args);
428 Py_DECREF(args);
429 Py_DECREF(className);
429 Py_DECREF(className);
430
430
431 return result;
431 return result;
432 }
432 }
433
433
434 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
435 {
436 PyObject* args = Py_BuildValue("(i)", enumValue);
437 PyObject* result = PyObject_Call(enumType, args, NULL);
438 Py_DECREF(args);
439 return result;
440 }
441
434 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
442 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
435 PyObject* result;
443 PyObject* result;
436
444
437 PyObject* className = PyString_FromString(enumName);
445 PyObject* className = PyString_FromString(enumName);
438
446
439 PyObject* baseClasses = PyTuple_New(1);
447 PyObject* baseClasses = PyTuple_New(1);
440 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
448 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
441
449
442 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
450 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
443 PyObject* typeDict = PyDict_New();
451 PyObject* typeDict = PyDict_New();
444 PyDict_SetItemString(typeDict, "__module__", module);
452 PyDict_SetItemString(typeDict, "__module__", module);
445
453
446 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
454 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
447
455
448 // create the new int derived type object by calling the core type
456 // create the new int derived type object by calling the core type
449 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
457 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
450
458
451 Py_DECREF(baseClasses);
459 Py_DECREF(baseClasses);
452 Py_DECREF(typeDict);
460 Py_DECREF(typeDict);
453 Py_DECREF(args);
461 Py_DECREF(args);
454 Py_DECREF(className);
462 Py_DECREF(className);
455
463
456 return result;
464 return result;
457 }
465 }
458
466
459 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
467 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
460 {
468 {
461 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
469 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
462 if (!r) {
470 if (!r) {
463 r = new PythonQtSignalReceiver(obj);
471 r = new PythonQtSignalReceiver(obj);
464 _p->_signalReceivers.insert(obj, r);
472 _p->_signalReceivers.insert(obj, r);
465 }
473 }
466 return r;
474 return r;
467 }
475 }
468
476
469 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
477 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
470 {
478 {
471 bool flag = false;
479 bool flag = false;
472 PythonQtObjectPtr callable = lookupCallable(module, objectname);
480 PythonQtObjectPtr callable = lookupCallable(module, objectname);
473 if (callable) {
481 if (callable) {
474 PythonQtSignalReceiver* r = getSignalReceiver(obj);
482 PythonQtSignalReceiver* r = getSignalReceiver(obj);
475 flag = r->addSignalHandler(signal, callable);
483 flag = r->addSignalHandler(signal, callable);
476 if (!flag) {
484 if (!flag) {
477 // signal not found
485 // signal not found
478 }
486 }
479 } else {
487 } else {
480 // callable not found
488 // callable not found
481 }
489 }
482 return flag;
490 return flag;
483 }
491 }
484
492
485 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
493 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
486 {
494 {
487 bool flag = false;
495 bool flag = false;
488 PythonQtSignalReceiver* r = getSignalReceiver(obj);
496 PythonQtSignalReceiver* r = getSignalReceiver(obj);
489 if (r) {
497 if (r) {
490 flag = r->addSignalHandler(signal, receiver);
498 flag = r->addSignalHandler(signal, receiver);
491 }
499 }
492 return flag;
500 return flag;
493 }
501 }
494
502
495 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
503 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
496 {
504 {
497 bool flag = false;
505 bool flag = false;
498 PythonQtObjectPtr callable = lookupCallable(module, objectname);
506 PythonQtObjectPtr callable = lookupCallable(module, objectname);
499 if (callable) {
507 if (callable) {
500 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
508 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
501 if (r) {
509 if (r) {
502 flag = r->removeSignalHandler(signal, callable);
510 flag = r->removeSignalHandler(signal, callable);
503 }
511 }
504 } else {
512 } else {
505 // callable not found
513 // callable not found
506 }
514 }
507 return flag;
515 return flag;
508 }
516 }
509
517
510 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
518 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
511 {
519 {
512 bool flag = false;
520 bool flag = false;
513 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
521 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
514 if (r) {
522 if (r) {
515 flag = r->removeSignalHandler(signal, receiver);
523 flag = r->removeSignalHandler(signal, receiver);
516 }
524 }
517 return flag;
525 return flag;
518 }
526 }
519
527
520 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
528 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
521 {
529 {
522 PythonQtObjectPtr p = lookupObject(module, name);
530 PythonQtObjectPtr p = lookupObject(module, name);
523 if (p) {
531 if (p) {
524 if (PyCallable_Check(p)) {
532 if (PyCallable_Check(p)) {
525 return p;
533 return p;
526 }
534 }
527 }
535 }
528 PyErr_Clear();
536 PyErr_Clear();
529 return NULL;
537 return NULL;
530 }
538 }
531
539
532 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
540 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
533 {
541 {
534 QStringList l = name.split('.');
542 QStringList l = name.split('.');
535 PythonQtObjectPtr p = module;
543 PythonQtObjectPtr p = module;
536 PythonQtObjectPtr prev;
544 PythonQtObjectPtr prev;
537 QString s;
545 QString s;
538 QByteArray b;
546 QByteArray b;
539 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
547 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
540 prev = p;
548 prev = p;
541 b = (*i).toLatin1();
549 b = (*i).toLatin1();
542 if (PyDict_Check(p)) {
550 if (PyDict_Check(p)) {
543 p = PyDict_GetItemString(p, b.data());
551 p = PyDict_GetItemString(p, b.data());
544 } else {
552 } else {
545 p.setNewRef(PyObject_GetAttrString(p, b.data()));
553 p.setNewRef(PyObject_GetAttrString(p, b.data()));
546 }
554 }
547 }
555 }
548 PyErr_Clear();
556 PyErr_Clear();
549 return p;
557 return p;
550 }
558 }
551
559
552 PythonQtObjectPtr PythonQt::getMainModule() {
560 PythonQtObjectPtr PythonQt::getMainModule() {
553 //both borrowed
561 //both borrowed
554 PythonQtObjectPtr dict = PyImport_GetModuleDict();
562 PythonQtObjectPtr dict = PyImport_GetModuleDict();
555 return PyDict_GetItemString(dict, "__main__");
563 return PyDict_GetItemString(dict, "__main__");
556 }
564 }
557
565
558 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
566 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
559 QVariant result;
567 QVariant result;
560 if (pycode) {
568 if (pycode) {
561 PyObject* dict = NULL;
569 PyObject* dict = NULL;
562 if (PyModule_Check(object)) {
570 if (PyModule_Check(object)) {
563 dict = PyModule_GetDict(object);
571 dict = PyModule_GetDict(object);
564 } else if (PyDict_Check(object)) {
572 } else if (PyDict_Check(object)) {
565 dict = object;
573 dict = object;
566 }
574 }
567 PyObject* r = NULL;
575 PyObject* r = NULL;
568 if (dict) {
576 if (dict) {
569 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
577 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
570 }
578 }
571 if (r) {
579 if (r) {
572 result = PythonQtConv::PyObjToQVariant(r);
580 result = PythonQtConv::PyObjToQVariant(r);
573 Py_DECREF(r);
581 Py_DECREF(r);
574 } else {
582 } else {
575 handleError();
583 handleError();
576 }
584 }
577 } else {
585 } else {
578 handleError();
586 handleError();
579 }
587 }
580 return result;
588 return result;
581 }
589 }
582
590
583 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
591 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
584 {
592 {
585 QVariant result;
593 QVariant result;
586 PythonQtObjectPtr p;
594 PythonQtObjectPtr p;
587 PyObject* dict = NULL;
595 PyObject* dict = NULL;
588 if (PyModule_Check(object)) {
596 if (PyModule_Check(object)) {
589 dict = PyModule_GetDict(object);
597 dict = PyModule_GetDict(object);
590 } else if (PyDict_Check(object)) {
598 } else if (PyDict_Check(object)) {
591 dict = object;
599 dict = object;
592 }
600 }
593 if (dict) {
601 if (dict) {
594 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
602 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
595 }
603 }
596 if (p) {
604 if (p) {
597 result = PythonQtConv::PyObjToQVariant(p);
605 result = PythonQtConv::PyObjToQVariant(p);
598 } else {
606 } else {
599 handleError();
607 handleError();
600 }
608 }
601 return result;
609 return result;
602 }
610 }
603
611
604 void PythonQt::evalFile(PyObject* module, const QString& filename)
612 void PythonQt::evalFile(PyObject* module, const QString& filename)
605 {
613 {
606 PythonQtObjectPtr code = parseFile(filename);
614 PythonQtObjectPtr code = parseFile(filename);
607 if (code) {
615 if (code) {
608 evalCode(module, code);
616 evalCode(module, code);
609 } else {
617 } else {
610 handleError();
618 handleError();
611 }
619 }
612 }
620 }
613
621
614 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
622 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
615 {
623 {
616 PythonQtObjectPtr p;
624 PythonQtObjectPtr p;
617 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
625 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
618 if (!p) {
626 if (!p) {
619 handleError();
627 handleError();
620 }
628 }
621 return p;
629 return p;
622 }
630 }
623
631
624 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
632 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
625 {
633 {
626 PythonQtObjectPtr code = parseFile(filename);
634 PythonQtObjectPtr code = parseFile(filename);
627 PythonQtObjectPtr module = _p->createModule(name, code);
635 PythonQtObjectPtr module = _p->createModule(name, code);
628 return module;
636 return module;
629 }
637 }
630
638
631 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
639 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
632 {
640 {
633 PyErr_Clear();
641 PyErr_Clear();
634 QString scriptCode = script;
642 QString scriptCode = script;
635 if (scriptCode.isEmpty()) {
643 if (scriptCode.isEmpty()) {
636 // we always need at least a linefeed
644 // we always need at least a linefeed
637 scriptCode = "\n";
645 scriptCode = "\n";
638 }
646 }
639 PythonQtObjectPtr pycode;
647 PythonQtObjectPtr pycode;
640 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
648 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
641 PythonQtObjectPtr module = _p->createModule(name, pycode);
649 PythonQtObjectPtr module = _p->createModule(name, pycode);
642 return module;
650 return module;
643 }
651 }
644
652
645 PythonQtObjectPtr PythonQt::createUniqueModule()
653 PythonQtObjectPtr PythonQt::createUniqueModule()
646 {
654 {
647 static QString pyQtStr("PythonQt_module");
655 static QString pyQtStr("PythonQt_module");
648 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
656 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
649 return createModuleFromScript(moduleName);
657 return createModuleFromScript(moduleName);
650 }
658 }
651
659
652 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
660 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
653 {
661 {
654 if (PyModule_Check(object)) {
662 if (PyModule_Check(object)) {
655 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
663 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
656 } else if (PyDict_Check(object)) {
664 } else if (PyDict_Check(object)) {
657 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
665 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
658 } else {
666 } else {
659 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
667 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
660 }
668 }
661 }
669 }
662
670
663 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
671 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
664 {
672 {
665 if (PyModule_Check(object)) {
673 if (PyModule_Check(object)) {
666 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
674 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
667 } else if (PyDict_Check(object)) {
675 } else if (PyDict_Check(object)) {
668 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
676 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
669 } else {
677 } else {
670 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
678 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
671 }
679 }
672 }
680 }
673
681
674 void PythonQt::removeVariable(PyObject* object, const QString& name)
682 void PythonQt::removeVariable(PyObject* object, const QString& name)
675 {
683 {
676 if (PyDict_Check(object)) {
684 if (PyDict_Check(object)) {
677 PyDict_DelItemString(object, name.toLatin1().data());
685 PyDict_DelItemString(object, name.toLatin1().data());
678 } else {
686 } else {
679 PyObject_DelAttrString(object, name.toLatin1().data());
687 PyObject_DelAttrString(object, name.toLatin1().data());
680 }
688 }
681 }
689 }
682
690
683 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
691 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
684 {
692 {
685 QVariant result;
693 QVariant result;
686 PythonQtObjectPtr obj = lookupObject(object, objectname);
694 PythonQtObjectPtr obj = lookupObject(object, objectname);
687 if (obj) {
695 if (obj) {
688 result = PythonQtConv::PyObjToQVariant(obj);
696 result = PythonQtConv::PyObjToQVariant(obj);
689 }
697 }
690 return result;
698 return result;
691 }
699 }
692
700
693 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
701 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
694 {
702 {
695 QStringList results;
703 QStringList results;
696
704
697 PythonQtObjectPtr object;
705 PythonQtObjectPtr object;
698 if (objectname.isEmpty()) {
706 if (objectname.isEmpty()) {
699 object = module;
707 object = module;
700 } else {
708 } else {
701 object = lookupObject(module, objectname);
709 object = lookupObject(module, objectname);
702 if (!object && type == CallOverloads) {
710 if (!object && type == CallOverloads) {
703 PyObject* dict = lookupObject(module, "__builtins__");
711 PyObject* dict = lookupObject(module, "__builtins__");
704 if (dict) {
712 if (dict) {
705 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
713 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
706 }
714 }
707 }
715 }
708 }
716 }
709
717
710 if (object) {
718 if (object) {
711 if (type == CallOverloads) {
719 if (type == CallOverloads) {
712 if (PythonQtSlotFunction_Check(object)) {
720 if (PythonQtSlotFunction_Check(object)) {
713 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
721 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
714 PythonQtSlotInfo* info = o->m_ml;
722 PythonQtSlotInfo* info = o->m_ml;
715
723
716 while (info) {
724 while (info) {
717 results << info->fullSignature();
725 results << info->fullSignature();
718 info = info->nextInfo();
726 info = info->nextInfo();
719 }
727 }
720 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
728 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
721 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
729 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
722 PythonQtSlotInfo* info = o->classInfo()->constructors();
730 PythonQtSlotInfo* info = o->classInfo()->constructors();
723
731
724 while (info) {
732 while (info) {
725 results << info->fullSignature();
733 results << info->fullSignature();
726 info = info->nextInfo();
734 info = info->nextInfo();
727 }
735 }
728 } else {
736 } else {
729 //TODO: use pydoc!
737 //TODO: use pydoc!
730 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
738 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
731 if (doc) {
739 if (doc) {
732 results << PyString_AsString(doc);
740 results << PyString_AsString(doc);
733 Py_DECREF(doc);
741 Py_DECREF(doc);
734 }
742 }
735 }
743 }
736 } else {
744 } else {
737 PyObject* keys = NULL;
745 PyObject* keys = NULL;
738 bool isDict = false;
746 bool isDict = false;
739 if (PyDict_Check(object)) {
747 if (PyDict_Check(object)) {
740 keys = PyDict_Keys(object);
748 keys = PyDict_Keys(object);
741 isDict = true;
749 isDict = true;
742 } else {
750 } else {
743 keys = PyObject_Dir(object);
751 keys = PyObject_Dir(object);
744 }
752 }
745 if (keys) {
753 if (keys) {
746 int count = PyList_Size(keys);
754 int count = PyList_Size(keys);
747 PyObject* key;
755 PyObject* key;
748 PyObject* value;
756 PyObject* value;
749 QString keystr;
757 QString keystr;
750 for (int i = 0;i<count;i++) {
758 for (int i = 0;i<count;i++) {
751 key = PyList_GetItem(keys,i);
759 key = PyList_GetItem(keys,i);
752 if (isDict) {
760 if (isDict) {
753 value = PyDict_GetItem(object, key);
761 value = PyDict_GetItem(object, key);
754 Py_INCREF(value);
762 Py_INCREF(value);
755 } else {
763 } else {
756 value = PyObject_GetAttr(object, key);
764 value = PyObject_GetAttr(object, key);
757 }
765 }
758 if (!value) continue;
766 if (!value) continue;
759 keystr = PyString_AsString(key);
767 keystr = PyString_AsString(key);
760 static const QString underscoreStr("__tmp");
768 static const QString underscoreStr("__tmp");
761 if (!keystr.startsWith(underscoreStr)) {
769 if (!keystr.startsWith(underscoreStr)) {
762 switch (type) {
770 switch (type) {
763 case Anything:
771 case Anything:
764 results << keystr;
772 results << keystr;
765 break;
773 break;
766 case Class:
774 case Class:
767 if (value->ob_type == &PyClass_Type) {
775 if (value->ob_type == &PyClass_Type) {
768 results << keystr;
776 results << keystr;
769 }
777 }
770 break;
778 break;
771 case Variable:
779 case Variable:
772 if (value->ob_type != &PyClass_Type
780 if (value->ob_type != &PyClass_Type
773 && value->ob_type != &PyCFunction_Type
781 && value->ob_type != &PyCFunction_Type
774 && value->ob_type != &PyFunction_Type
782 && value->ob_type != &PyFunction_Type
775 && value->ob_type != &PyModule_Type
783 && value->ob_type != &PyModule_Type
776 ) {
784 ) {
777 results << keystr;
785 results << keystr;
778 }
786 }
779 break;
787 break;
780 case Function:
788 case Function:
781 if (value->ob_type == &PyFunction_Type ||
789 if (value->ob_type == &PyFunction_Type ||
782 value->ob_type == &PyMethod_Type
790 value->ob_type == &PyMethod_Type
783 ) {
791 ) {
784 results << keystr;
792 results << keystr;
785 }
793 }
786 break;
794 break;
787 case Module:
795 case Module:
788 if (value->ob_type == &PyModule_Type) {
796 if (value->ob_type == &PyModule_Type) {
789 results << keystr;
797 results << keystr;
790 }
798 }
791 break;
799 break;
792 default:
800 default:
793 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
801 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
794 }
802 }
795 }
803 }
796 Py_DECREF(value);
804 Py_DECREF(value);
797 }
805 }
798 Py_DECREF(keys);
806 Py_DECREF(keys);
799 }
807 }
800 }
808 }
801 }
809 }
802 return results;
810 return results;
803 }
811 }
804
812
805 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
813 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
806 {
814 {
807 PythonQtObjectPtr callable = lookupCallable(object, name);
815 PythonQtObjectPtr callable = lookupCallable(object, name);
808 if (callable) {
816 if (callable) {
809 return call(callable, args);
817 return call(callable, args);
810 } else {
818 } else {
811 return QVariant();
819 return QVariant();
812 }
820 }
813 }
821 }
814
822
815 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
823 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
816 {
824 {
817 QVariant r;
825 QVariant r;
818 if (callable) {
826 if (callable) {
819 PythonQtObjectPtr pargs;
827 PythonQtObjectPtr pargs;
820 int count = args.size();
828 int count = args.size();
821 if (count>0) {
829 if (count>0) {
822 pargs.setNewRef(PyTuple_New(count));
830 pargs.setNewRef(PyTuple_New(count));
823 }
831 }
824 bool err = false;
832 bool err = false;
825 // transform QVariants to Python
833 // transform QVariants to Python
826 for (int i = 0; i < count; i++) {
834 for (int i = 0; i < count; i++) {
827 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
835 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
828 if (arg) {
836 if (arg) {
829 // steals reference, no unref
837 // steals reference, no unref
830 PyTuple_SetItem(pargs, i,arg);
838 PyTuple_SetItem(pargs, i,arg);
831 } else {
839 } else {
832 err = true;
840 err = true;
833 break;
841 break;
834 }
842 }
835 }
843 }
836
844
837 if (!err) {
845 if (!err) {
838 PyErr_Clear();
846 PyErr_Clear();
839 PythonQtObjectPtr result;
847 PythonQtObjectPtr result;
840 result.setNewRef(PyObject_CallObject(callable, pargs));
848 result.setNewRef(PyObject_CallObject(callable, pargs));
841 if (result) {
849 if (result) {
842 // ok
850 // ok
843 r = PythonQtConv::PyObjToQVariant(result);
851 r = PythonQtConv::PyObjToQVariant(result);
844 } else {
852 } else {
845 PythonQt::self()->handleError();
853 PythonQt::self()->handleError();
846 }
854 }
847 }
855 }
848 }
856 }
849 return r;
857 return r;
850 }
858 }
851
859
852 void PythonQt::addInstanceDecorators(QObject* o)
860 void PythonQt::addInstanceDecorators(QObject* o)
853 {
861 {
854 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
862 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
855 }
863 }
856
864
857 void PythonQt::addClassDecorators(QObject* o)
865 void PythonQt::addClassDecorators(QObject* o)
858 {
866 {
859 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
867 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
860 }
868 }
861
869
862 void PythonQt::addDecorators(QObject* o)
870 void PythonQt::addDecorators(QObject* o)
863 {
871 {
864 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
872 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
865 }
873 }
866
874
867 void PythonQt::registerQObjectClassNames(const QStringList& names)
875 void PythonQt::registerQObjectClassNames(const QStringList& names)
868 {
876 {
869 _p->registerQObjectClassNames(names);
877 _p->registerQObjectClassNames(names);
870 }
878 }
871
879
872 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
880 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
873 {
881 {
874 PythonQtImport::init();
882 PythonQtImport::init();
875 _p->_importInterface = importInterface;
883 _p->_importInterface = importInterface;
876 }
884 }
877
885
878 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
886 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
879 {
887 {
880 _p->_importIgnorePaths = paths;
888 _p->_importIgnorePaths = paths;
881 }
889 }
882
890
883 const QStringList& PythonQt::getImporterIgnorePaths()
891 const QStringList& PythonQt::getImporterIgnorePaths()
884 {
892 {
885 return _p->_importIgnorePaths;
893 return _p->_importIgnorePaths;
886 }
894 }
887
895
888 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
896 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
889 {
897 {
890 _p->_cppWrapperFactories.append(factory);
898 _p->_cppWrapperFactories.append(factory);
891 }
899 }
892
900
893 //---------------------------------------------------------------------------------------------------
901 //---------------------------------------------------------------------------------------------------
894 PythonQtPrivate::PythonQtPrivate()
902 PythonQtPrivate::PythonQtPrivate()
895 {
903 {
896 _importInterface = NULL;
904 _importInterface = NULL;
897 _defaultImporter = new PythonQtQFileImporter;
905 _defaultImporter = new PythonQtQFileImporter;
898 _noLongerWrappedCB = NULL;
906 _noLongerWrappedCB = NULL;
899 _wrappedCB = NULL;
907 _wrappedCB = NULL;
900 _currentClassInfoForClassWrapperCreation = NULL;
908 _currentClassInfoForClassWrapperCreation = NULL;
901 }
909 }
902
910
903 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
911 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
904 {
912 {
905 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
913 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
906 _currentClassInfoForClassWrapperCreation = NULL;
914 _currentClassInfoForClassWrapperCreation = NULL;
907 return info;
915 return info;
908 }
916 }
909
917
910 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
918 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
911 {
919 {
912 o->setParent(this);
920 o->setParent(this);
913 int numMethods = o->metaObject()->methodCount();
921 int numMethods = o->metaObject()->methodCount();
914 for (int i = 0; i < numMethods; i++) {
922 for (int i = 0; i < numMethods; i++) {
915 QMetaMethod m = o->metaObject()->method(i);
923 QMetaMethod m = o->metaObject()->method(i);
916 if ((m.methodType() == QMetaMethod::Method ||
924 if ((m.methodType() == QMetaMethod::Method ||
917 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
925 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
918 if (qstrncmp(m.signature(), "new_", 4)==0) {
926 if (qstrncmp(m.signature(), "new_", 4)==0) {
919 if ((decoTypes & ConstructorDecorator) == 0) continue;
927 if ((decoTypes & ConstructorDecorator) == 0) continue;
920 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
928 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
921 if (info->parameters().at(0).isPointer) {
929 if (info->parameters().at(0).isPointer) {
922 QByteArray signature = m.signature();
930 QByteArray signature = m.signature();
923 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
931 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
924 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
932 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
925 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
933 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
926 classInfo->addConstructor(newSlot);
934 classInfo->addConstructor(newSlot);
927 }
935 }
928 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
936 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
929 if ((decoTypes & DestructorDecorator) == 0) continue;
937 if ((decoTypes & DestructorDecorator) == 0) continue;
930 QByteArray signature = m.signature();
938 QByteArray signature = m.signature();
931 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
939 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
932 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
940 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
933 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
941 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
934 classInfo->setDestructor(newSlot);
942 classInfo->setDestructor(newSlot);
935 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
943 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
936 if ((decoTypes & StaticDecorator) == 0) continue;
944 if ((decoTypes & StaticDecorator) == 0) continue;
937 QByteArray signature = m.signature();
945 QByteArray signature = m.signature();
938 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
946 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
939 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
947 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
940 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
948 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
941 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
949 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
942 classInfo->addDecoratorSlot(newSlot);
950 classInfo->addDecoratorSlot(newSlot);
943 } else {
951 } else {
944 if ((decoTypes & InstanceDecorator) == 0) continue;
952 if ((decoTypes & InstanceDecorator) == 0) continue;
945 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
953 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
946 if (info->parameters().count()>1) {
954 if (info->parameters().count()>1) {
947 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
955 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
948 if (p.isPointer) {
956 if (p.isPointer) {
949 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
957 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
950 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
958 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
951 classInfo->addDecoratorSlot(newSlot);
959 classInfo->addDecoratorSlot(newSlot);
952 }
960 }
953 }
961 }
954 }
962 }
955 }
963 }
956 }
964 }
957 }
965 }
958
966
959 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
967 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
960 {
968 {
961 foreach(QString name, names) {
969 foreach(QString name, names) {
962 _knownQObjectClassNames.insert(name.toLatin1(), true);
970 _knownQObjectClassNames.insert(name.toLatin1(), true);
963 }
971 }
964 }
972 }
965
973
966 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
974 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
967 {
975 {
968 _signalReceivers.remove(obj);
976 _signalReceivers.remove(obj);
969 }
977 }
970
978
971 bool PythonQt::handleError()
979 bool PythonQt::handleError()
972 {
980 {
973 bool flag = false;
981 bool flag = false;
974 if (PyErr_Occurred()) {
982 if (PyErr_Occurred()) {
975
983
976 // currently we just print the error and the stderr handler parses the errors
984 // currently we just print the error and the stderr handler parses the errors
977 PyErr_Print();
985 PyErr_Print();
978
986
979 /*
987 /*
980 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
988 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
981 PyObject *ptype;
989 PyObject *ptype;
982 PyObject *pvalue;
990 PyObject *pvalue;
983 PyObject *ptraceback;
991 PyObject *ptraceback;
984 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
992 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
985
993
986 Py_XDECREF(ptype);
994 Py_XDECREF(ptype);
987 Py_XDECREF(pvalue);
995 Py_XDECREF(pvalue);
988 Py_XDECREF(ptraceback);
996 Py_XDECREF(ptraceback);
989 */
997 */
990 PyErr_Clear();
998 PyErr_Clear();
991 flag = true;
999 flag = true;
992 }
1000 }
993 return flag;
1001 return flag;
994 }
1002 }
995
1003
996 void PythonQt::addSysPath(const QString& path)
1004 void PythonQt::addSysPath(const QString& path)
997 {
1005 {
998 PythonQtObjectPtr sys;
1006 PythonQtObjectPtr sys;
999 sys.setNewRef(PyImport_ImportModule("sys"));
1007 sys.setNewRef(PyImport_ImportModule("sys"));
1000 PythonQtObjectPtr obj = lookupObject(sys, "path");
1008 PythonQtObjectPtr obj = lookupObject(sys, "path");
1001 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1009 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1002 }
1010 }
1003
1011
1004 void PythonQt::overwriteSysPath(const QStringList& paths)
1012 void PythonQt::overwriteSysPath(const QStringList& paths)
1005 {
1013 {
1006 PythonQtObjectPtr sys;
1014 PythonQtObjectPtr sys;
1007 sys.setNewRef(PyImport_ImportModule("sys"));
1015 sys.setNewRef(PyImport_ImportModule("sys"));
1008 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1016 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1009 }
1017 }
1010
1018
1011 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1019 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1012 {
1020 {
1013 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1021 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1014 }
1022 }
1015
1023
1016 void PythonQt::stdOutRedirectCB(const QString& str)
1024 void PythonQt::stdOutRedirectCB(const QString& str)
1017 {
1025 {
1018 emit PythonQt::self()->pythonStdOut(str);
1026 emit PythonQt::self()->pythonStdOut(str);
1019 }
1027 }
1020
1028
1021 void PythonQt::stdErrRedirectCB(const QString& str)
1029 void PythonQt::stdErrRedirectCB(const QString& str)
1022 {
1030 {
1023 emit PythonQt::self()->pythonStdErr(str);
1031 emit PythonQt::self()->pythonStdErr(str);
1024 }
1032 }
1025
1033
1026 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1034 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1027 {
1035 {
1028 _p->_wrappedCB = cb;
1036 _p->_wrappedCB = cb;
1029 }
1037 }
1030
1038
1031 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1039 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1032 {
1040 {
1033 _p->_noLongerWrappedCB = cb;
1041 _p->_noLongerWrappedCB = cb;
1034 }
1042 }
1035
1043
1036
1044
1037
1045
1038 static PyMethodDef PythonQtMethods[] = {
1046 static PyMethodDef PythonQtMethods[] = {
1039 {NULL, NULL, 0, NULL}
1047 {NULL, NULL, 0, NULL}
1040 };
1048 };
1041
1049
1042 void PythonQt::initPythonQtModule(bool redirectStdOut)
1050 void PythonQt::initPythonQtModule(bool redirectStdOut)
1043 {
1051 {
1044 _p->_pythonQtModule = Py_InitModule("PythonQt", PythonQtMethods);
1052 _p->_pythonQtModule = Py_InitModule("PythonQt", PythonQtMethods);
1045
1053
1046 if (redirectStdOut) {
1054 if (redirectStdOut) {
1047 PythonQtObjectPtr sys;
1055 PythonQtObjectPtr sys;
1048 PythonQtObjectPtr out;
1056 PythonQtObjectPtr out;
1049 PythonQtObjectPtr err;
1057 PythonQtObjectPtr err;
1050 sys.setNewRef(PyImport_ImportModule("sys"));
1058 sys.setNewRef(PyImport_ImportModule("sys"));
1051 // create a redirection object for stdout and stderr
1059 // create a redirection object for stdout and stderr
1052 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1060 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1053 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1061 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1054 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1062 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1055 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1063 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1056 // replace the built in file objects with our own objects
1064 // replace the built in file objects with our own objects
1057 PyModule_AddObject(sys, "stdout", out);
1065 PyModule_AddObject(sys, "stdout", out);
1058 PyModule_AddObject(sys, "stderr", err);
1066 PyModule_AddObject(sys, "stderr", err);
1059 }
1067 }
1060 }
1068 }
1061
1069
1062 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1070 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1063 {
1071 {
1064 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1072 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1065 }
1073 }
1066
1074
1067
1075
1068 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1076 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1069 {
1077 {
1070 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1078 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1071 if (!info) {
1079 if (!info) {
1072 info = new PythonQtClassInfo();
1080 info = new PythonQtClassInfo();
1073 info->setupCPPObject(typeName);
1081 info->setupCPPObject(typeName);
1074 _knownClassInfos.insert(typeName, info);
1082 _knownClassInfos.insert(typeName, info);
1075 }
1083 }
1076 return info;
1084 return info;
1077 }
1085 }
1078
1086
1079 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1087 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1080 {
1088 {
1081 _p->addPolymorphicHandler(typeName, cb);
1089 _p->addPolymorphicHandler(typeName, cb);
1082 }
1090 }
1083
1091
1084 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1092 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1085 {
1093 {
1086 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1094 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1087 info->addPolymorphicHandler(cb);
1095 info->addPolymorphicHandler(cb);
1088 }
1096 }
1089
1097
1090 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1098 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1091 {
1099 {
1092 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1100 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1093 }
1101 }
1094
1102
1095 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1103 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1096 {
1104 {
1097 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1105 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1098 if (info) {
1106 if (info) {
1099 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1107 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1100 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1108 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1101 return true;
1109 return true;
1102 } else {
1110 } else {
1103 return false;
1111 return false;
1104 }
1112 }
1105 }
1113 }
1106
1114
1107 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1115 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1108 {
1116 {
1109 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1117 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1110 if (!info->pythonQtClassWrapper()) {
1118 if (!info->pythonQtClassWrapper()) {
1111 info->setupCPPObject(typeName);
1119 info->setupCPPObject(typeName);
1112 createPythonQtClassWrapper(info, package);
1120 createPythonQtClassWrapper(info, package);
1113 }
1121 }
1114 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1122 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1115 addParentClass(typeName, parentTypeName, 0);
1123 addParentClass(typeName, parentTypeName, 0);
1116 }
1124 }
1117 if (wrapperCreator) {
1125 if (wrapperCreator) {
1118 info->setDecoratorProvider(wrapperCreator);
1126 info->setDecoratorProvider(wrapperCreator);
1119 }
1127 }
1120 if (shell) {
1128 if (shell) {
1121 info->setShellSetInstanceWrapperCB(shell);
1129 info->setShellSetInstanceWrapperCB(shell);
1122 }
1130 }
1123 }
1131 }
1124
1132
1125 PyObject* PythonQtPrivate::packageByName(const char* name)
1133 PyObject* PythonQtPrivate::packageByName(const char* name)
1126 {
1134 {
1127 if (name==NULL || name[0]==0) {
1135 if (name==NULL || name[0]==0) {
1128 return _pythonQtModule;
1136 return _pythonQtModule;
1129 }
1137 }
1130 PyObject* v = _packages.value(name);
1138 PyObject* v = _packages.value(name);
1131 if (!v) {
1139 if (!v) {
1132 v = PyImport_AddModule((QByteArray("PythonQt.") + name).constData());
1140 v = PyImport_AddModule((QByteArray("PythonQt.") + name).constData());
1133 _packages.insert(name, v);
1141 _packages.insert(name, v);
1134 // AddObject steals the reference, so increment it!
1142 // AddObject steals the reference, so increment it!
1135 Py_INCREF(v);
1143 Py_INCREF(v);
1136 PyModule_AddObject(_pythonQtModule, name, v);
1144 PyModule_AddObject(_pythonQtModule, name, v);
1137 }
1145 }
1138 return v;
1146 return v;
1139 }
1147 }
1140
1148
1141
1149
1142 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1150 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1143 {
1151 {
1144 if (_p->_initFlags & ExternalHelp) {
1152 if (_p->_initFlags & ExternalHelp) {
1145 emit pythonHelpRequest(QByteArray(info->className()));
1153 emit pythonHelpRequest(QByteArray(info->className()));
1146 return Py_BuildValue("");
1154 return Py_BuildValue("");
1147 } else {
1155 } else {
1148 return PyString_FromString(info->help().toLatin1().data());
1156 return PyString_FromString(info->help().toLatin1().data());
1149 }
1157 }
1150 }
1158 }
1151
1159
1152 void PythonQtPrivate::removeWrapperPointer(void* obj)
1160 void PythonQtPrivate::removeWrapperPointer(void* obj)
1153 {
1161 {
1154 _wrappedObjects.remove(obj);
1162 _wrappedObjects.remove(obj);
1155 }
1163 }
1156
1164
1157 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1165 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1158 {
1166 {
1159 _wrappedObjects.insert(obj, wrapper);
1167 _wrappedObjects.insert(obj, wrapper);
1160 }
1168 }
1161
1169
1162 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1170 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1163 {
1171 {
1164 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1172 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1165 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1173 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1166 // this is a wrapper whose QObject was already removed due to destruction
1174 // this is a wrapper whose QObject was already removed due to destruction
1167 // so the obj pointer has to be a new QObject with the same address...
1175 // so the obj pointer has to be a new QObject with the same address...
1168 // we remove the old one and set the copy to NULL
1176 // we remove the old one and set the copy to NULL
1169 wrap->_objPointerCopy = NULL;
1177 wrap->_objPointerCopy = NULL;
1170 removeWrapperPointer(obj);
1178 removeWrapperPointer(obj);
1171 wrap = NULL;
1179 wrap = NULL;
1172 }
1180 }
1173 return wrap;
1181 return wrap;
1174 }
1182 }
1175
1183
1176 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1184 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1177 {
1185 {
1178 PythonQtObjectPtr result;
1186 PythonQtObjectPtr result;
1179 if (pycode) {
1187 if (pycode) {
1180 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1188 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1181 } else {
1189 } else {
1182 PythonQt::self()->handleError();
1190 PythonQt::self()->handleError();
1183 }
1191 }
1184 return result;
1192 return result;
1185 }
1193 }
@@ -1,520 +1,523
1 #ifndef _PYTHONQT_H
1 #ifndef _PYTHONQT_H
2 #define _PYTHONQT_H
2 #define _PYTHONQT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQt.h
38 // \file PythonQt.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include "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 <QObject>
50 #include <QObject>
51 #include <QVariant>
51 #include <QVariant>
52 #include <QList>
52 #include <QList>
53 #include <QHash>
53 #include <QHash>
54 #include <QByteArray>
54 #include <QByteArray>
55 #include <QStringList>
55 #include <QStringList>
56 #include <QtDebug>
56 #include <QtDebug>
57 #include <iostream>
57 #include <iostream>
58
58
59
59
60 class PythonQtClassInfo;
60 class PythonQtClassInfo;
61 class PythonQtPrivate;
61 class PythonQtPrivate;
62 class PythonQtMethodInfo;
62 class PythonQtMethodInfo;
63 class PythonQtSignalReceiver;
63 class PythonQtSignalReceiver;
64 class PythonQtImportFileInterface;
64 class PythonQtImportFileInterface;
65 class PythonQtCppWrapperFactory;
65 class PythonQtCppWrapperFactory;
66 class PythonQtQFileImporter;
66 class PythonQtQFileImporter;
67
67
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
71
71
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
73
73
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
75
75
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
79 }
79 }
80
80
81 //! callback to create a QObject lazily
81 //! callback to create a QObject lazily
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
83
83
84 //! helper template to create a derived QObject class
84 //! helper template to create a derived QObject class
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
86
86
87 //! the main interface to the Python Qt binding, realized as a singleton
87 //! the main interface to the Python Qt binding, realized as a singleton
88 class PYTHONQT_EXPORT PythonQt : public QObject {
88 class PYTHONQT_EXPORT PythonQt : public QObject {
89
89
90 Q_OBJECT
90 Q_OBJECT
91
91
92 public:
92 public:
93 enum InitFlags {
93 enum InitFlags {
94 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
94 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
95 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
95 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
96 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
96 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
97 };
97 };
98
98
99 //! initialize the python qt binding (flags are a or combination of InitFlags)
99 //! initialize the python qt binding (flags are a or combination of InitFlags)
100 static void init(int flags = IgnoreSiteModule | RedirectStdOut);
100 static void init(int flags = IgnoreSiteModule | RedirectStdOut);
101
101
102 //! cleanup
102 //! cleanup
103 static void cleanup();
103 static void cleanup();
104
104
105 //! get the singleton instance
105 //! get the singleton instance
106 static PythonQt* self() { return _self; }
106 static PythonQt* self() { return _self; }
107
107
108 //-----------------------------------------------------------------------------
108 //-----------------------------------------------------------------------------
109 // Public API:
109 // Public API:
110
110
111 //! defines the object types for introspection
111 //! defines the object types for introspection
112 enum ObjectType {
112 enum ObjectType {
113 Class,
113 Class,
114 Function,
114 Function,
115 Variable,
115 Variable,
116 Module,
116 Module,
117 Anything,
117 Anything,
118 CallOverloads
118 CallOverloads
119 };
119 };
120
120
121 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
121 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
122 void overwriteSysPath(const QStringList& paths);
122 void overwriteSysPath(const QStringList& paths);
123
123
124 //! prepend a path to sys.path to allow importing from it
124 //! prepend a path to sys.path to allow importing from it
125 void addSysPath(const QString& path);
125 void addSysPath(const QString& path);
126
126
127 //! sets the __path__ list of a module to the given list (important for local imports)
127 //! sets the __path__ list of a module to the given list (important for local imports)
128 void setModuleImportPath(PyObject* module, const QStringList& paths);
128 void setModuleImportPath(PyObject* module, const QStringList& paths);
129
129
130 //! get the __main__ module of python
130 //! get the __main__ module of python
131 PythonQtObjectPtr getMainModule();
131 PythonQtObjectPtr getMainModule();
132
132
133 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
133 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
134 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
134 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
135 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
135 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
136 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
136 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
137
137
138 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
138 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
139 //! (ownership of wrapper is passed to PythonQt)
139 //! (ownership of wrapper is passed to PythonQt)
140 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
140 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
141
141
142 This will add a wrapper object that is used to make calls to the given classname \c typeName.
142 This will add a wrapper object that is used to make calls to the given classname \c typeName.
143 All slots that take a pointer to typeName as the first argument will be callable from Python on
143 All slots that take a pointer to typeName as the first argument will be callable from Python on
144 a variant object that contains such a type.
144 a variant object that contains such a type.
145 */
145 */
146 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
146 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
147
147
148 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
148 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
149 //! and it will register the classes when it first sees a pointer to such a derived class
149 //! and it will register the classes when it first sees a pointer to such a derived class
150 void registerQObjectClassNames(const QStringList& names);
150 void registerQObjectClassNames(const QStringList& names);
151
151
152 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
152 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
153 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
153 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
154 //! type is really derived from parentType.
154 //! type is really derived from parentType.
155 //! Returns false if the typeName was not yet registered.
155 //! Returns false if the typeName was not yet registered.
156 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
156 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
157
157
158 //! add a handler for polymorphic downcasting
158 //! add a handler for polymorphic downcasting
159 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
159 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
160
160
161 //! parses the given file and returns the python code object, this can then be used to call evalCode()
161 //! parses the given file and returns the python code object, this can then be used to call evalCode()
162 PythonQtObjectPtr parseFile(const QString& filename);
162 PythonQtObjectPtr parseFile(const QString& filename);
163
163
164 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
164 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
165 //! If pycode is NULL, a python error is printed.
165 //! If pycode is NULL, a python error is printed.
166 QVariant evalCode(PyObject* object, PyObject* pycode);
166 QVariant evalCode(PyObject* object, PyObject* pycode);
167
167
168 //! evaluates the given script code and returns the result value
168 //! evaluates the given script code and returns the result value
169 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
169 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
170
170
171 //! evaluates the given script code from file
171 //! evaluates the given script code from file
172 void evalFile(PyObject* object, const QString& filename);
172 void evalFile(PyObject* object, const QString& filename);
173
173
174 //! creates the new module \c name and evaluates the given file in the context of that module
174 //! creates the new module \c name and evaluates the given file in the context of that module
175 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
175 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
176 //! to a module later on.
176 //! to a module later on.
177 //! The user needs to make sure that the \c name is unique in the python module dictionary.
177 //! The user needs to make sure that the \c name is unique in the python module dictionary.
178 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
178 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
179
179
180 //! creates the new module \c name and evaluates the given script in the context of that module.
180 //! creates the new module \c name and evaluates the given script in the context of that module.
181 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
181 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
182 //! to a module later on.
182 //! to a module later on.
183 //! The user needs to make sure that the \c name is unique in the python module dictionary.
183 //! The user needs to make sure that the \c name is unique in the python module dictionary.
184 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
184 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
185
185
186 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
186 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
187 //! script code
187 //! script code
188 PythonQtObjectPtr createUniqueModule();
188 PythonQtObjectPtr createUniqueModule();
189
189
190 //@{ Signal handlers
190 //@{ Signal handlers
191
191
192 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
192 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
193 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
193 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
194
194
195 //! remove a signal handler from the given \c signal of \c obj
195 //! remove a signal handler from the given \c signal of \c obj
196 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
196 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
197
197
198 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
198 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
199 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
199 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
200
200
201 //! remove a signal handler from the given \c signal of \c obj
201 //! remove a signal handler from the given \c signal of \c obj
202 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
202 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
203
203
204 //@}
204 //@}
205
205
206 //@{ Variable access
206 //@{ Variable access
207
207
208 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
208 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
209 void addObject(PyObject* object, const QString& name, QObject* qObject);
209 void addObject(PyObject* object, const QString& name, QObject* qObject);
210
210
211 //! add the given variable to the object
211 //! add the given variable to the object
212 void addVariable(PyObject* object, const QString& name, const QVariant& v);
212 void addVariable(PyObject* object, const QString& name, const QVariant& v);
213
213
214 //! remove the given variable
214 //! remove the given variable
215 void removeVariable(PyObject* module, const QString& name);
215 void removeVariable(PyObject* module, const QString& name);
216
216
217 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
217 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
218 QVariant getVariable(PyObject* object, const QString& name);
218 QVariant getVariable(PyObject* object, const QString& name);
219
219
220 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
220 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
221 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
221 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
222
222
223 //! returns the found callable object or NULL
223 //! returns the found callable object or NULL
224 //! @return new reference
224 //! @return new reference
225 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
225 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
226
226
227 //@}
227 //@}
228
228
229 //@{ Calling of python callables
229 //@{ Calling of python callables
230
230
231 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
231 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
232 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
232 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
233
233
234 //! call the given python object, returns the result converted to a QVariant
234 //! call the given python object, returns the result converted to a QVariant
235 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
235 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
236
236
237 //@}
237 //@}
238
238
239 //@{ Decorations, constructors, wrappers...
239 //@{ Decorations, constructors, wrappers...
240
240
241
241
242 //! add an object whose slots will be used as decorator slots for
242 //! add an object whose slots will be used as decorator slots for
243 //! other QObjects or CPP classes. The slots need to follow the
243 //! other QObjects or CPP classes. The slots need to follow the
244 //! convention that the first argument is a pointer to the wrapped object.
244 //! convention that the first argument is a pointer to the wrapped object.
245 //! (ownership is passed to PythonQt)
245 //! (ownership is passed to PythonQt)
246 /*!
246 /*!
247 Example:
247 Example:
248
248
249 A slot with the signature
249 A slot with the signature
250
250
251 \code
251 \code
252 bool doSomething(QWidget* w, int a)
252 bool doSomething(QWidget* w, int a)
253 \endcode
253 \endcode
254
254
255 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
255 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
256 that will be called with the concrete instance as first argument.
256 that will be called with the concrete instance as first argument.
257 So in Python you can now e.g. call
257 So in Python you can now e.g. call
258
258
259 \code
259 \code
260 someWidget.doSomething(12)
260 someWidget.doSomething(12)
261 \endcode
261 \endcode
262
262
263 without QWidget really having this method. This allows to easily make normal methods
263 without QWidget really having this method. This allows to easily make normal methods
264 of Qt classes callable by forwarding them with such decorator slots
264 of Qt classes callable by forwarding them with such decorator slots
265 or to make CPP classes (which are not derived from QObject) callable from Python.
265 or to make CPP classes (which are not derived from QObject) callable from Python.
266 */
266 */
267 void addInstanceDecorators(QObject* o);
267 void addInstanceDecorators(QObject* o);
268
268
269 //! add an object whose slots will be used as decorator slots for
269 //! add an object whose slots will be used as decorator slots for
270 //! class objects (ownership is passed to PythonQt)
270 //! class objects (ownership is passed to PythonQt)
271 /*!
271 /*!
272 The slots need to follow the following convention:
272 The slots need to follow the following convention:
273 - SomeClass* new_SomeClass(...)
273 - SomeClass* new_SomeClass(...)
274 - QVariant new_SomeClass(...)
274 - QVariant new_SomeClass(...)
275 - void delete_SomeClass(SomeClass*)
275 - void delete_SomeClass(SomeClass*)
276 - ... static_SomeClass_someName(...)
276 - ... static_SomeClass_someName(...)
277
277
278 This will add:
278 This will add:
279 - a constructor
279 - a constructor
280 - a constructor which generates a QVariant
280 - a constructor which generates a QVariant
281 - a destructor (only useful for CPP objects)
281 - a destructor (only useful for CPP objects)
282 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
282 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
283
283
284 */
284 */
285 void addClassDecorators(QObject* o);
285 void addClassDecorators(QObject* o);
286
286
287 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
287 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
288 void addDecorators(QObject* o);
288 void addDecorators(QObject* o);
289
289
290 //! add the given factory to PythonQt (ownership stays with caller)
290 //! add the given factory to PythonQt (ownership stays with caller)
291 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
291 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
292
292
293 //@}
293 //@}
294
294
295 //@{ Custom importer (to replace internal import implementation of python)
295 //@{ Custom importer (to replace internal import implementation of python)
296
296
297 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
297 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
298 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
298 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
299 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
299 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
300 //! This is not reversible, so even setting setImporter(NULL) afterwards will
300 //! This is not reversible, so even setting setImporter(NULL) afterwards will
301 //! keep the custom PythonQt importer with a QFile default import interface.
301 //! keep the custom PythonQt importer with a QFile default import interface.
302 //! Subsequent python import calls will make use of the passed importInterface
302 //! Subsequent python import calls will make use of the passed importInterface
303 //! which forwards all import calls to the given \c importInterface.
303 //! which forwards all import calls to the given \c importInterface.
304 //! Passing NULL will install a default QFile importer.
304 //! Passing NULL will install a default QFile importer.
305 //! (\c importInterface ownership stays with caller)
305 //! (\c importInterface ownership stays with caller)
306 void setImporter(PythonQtImportFileInterface* importInterface);
306 void setImporter(PythonQtImportFileInterface* importInterface);
307
307
308 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
308 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
309 //! (without calling setImporter or installDefaultImporter at least once, the default python import
309 //! (without calling setImporter or installDefaultImporter at least once, the default python import
310 //! mechanism is in place)
310 //! mechanism is in place)
311 //! the default importer allows to import files from anywhere QFile can read from,
311 //! the default importer allows to import files from anywhere QFile can read from,
312 //! including the Qt resource system using ":". Keep in mind that you need to extend
312 //! including the Qt resource system using ":". Keep in mind that you need to extend
313 //! "sys.path" with ":" to be able to import from the Qt resources.
313 //! "sys.path" with ":" to be able to import from the Qt resources.
314 void installDefaultImporter() { setImporter(NULL); }
314 void installDefaultImporter() { setImporter(NULL); }
315
315
316 //! set paths that the importer should ignore
316 //! set paths that the importer should ignore
317 void setImporterIgnorePaths(const QStringList& paths);
317 void setImporterIgnorePaths(const QStringList& paths);
318
318
319 //! get paths that the importer should ignore
319 //! get paths that the importer should ignore
320 const QStringList& getImporterIgnorePaths();
320 const QStringList& getImporterIgnorePaths();
321
321
322 //@}
322 //@}
323
323
324 //! get access to internal data (should not be used on the public API, but is used by some C functions)
324 //! get access to internal data (should not be used on the public API, but is used by some C functions)
325 static PythonQtPrivate* priv() { return _self->_p; }
325 static PythonQtPrivate* priv() { return _self->_p; }
326
326
327 //! get access to the file importer (if set)
327 //! get access to the file importer (if set)
328 static PythonQtImportFileInterface* importInterface();
328 static PythonQtImportFileInterface* importInterface();
329
329
330 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
330 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
331 //! The error is currently just output to the python stderr, future version might implement better trace printing
331 //! The error is currently just output to the python stderr, future version might implement better trace printing
332 bool handleError();
332 bool handleError();
333
333
334 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
334 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
335 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
335 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
336 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
336 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
337 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
337 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
338
338
339 //! call the callback if it is set
339 //! call the callback if it is set
340 static void qObjectNoLongerWrappedCB(QObject* o);
340 static void qObjectNoLongerWrappedCB(QObject* o);
341
341
342 signals:
342 signals:
343 //! emitted when python outputs something to stdout (and redirection is turned on)
343 //! emitted when python outputs something to stdout (and redirection is turned on)
344 void pythonStdOut(const QString& str);
344 void pythonStdOut(const QString& str);
345 //! emitted when python outputs something to stderr (and redirection is turned on)
345 //! emitted when python outputs something to stderr (and redirection is turned on)
346 void pythonStdErr(const QString& str);
346 void pythonStdErr(const QString& str);
347
347
348 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
348 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
349 void pythonHelpRequest(const QByteArray& cppClassName);
349 void pythonHelpRequest(const QByteArray& cppClassName);
350
350
351
351
352 public:
352 public:
353 //! called by internal help methods
353 //! called by internal help methods
354 PyObject* helpCalled(PythonQtClassInfo* info);
354 PyObject* helpCalled(PythonQtClassInfo* info);
355
355
356 //! returns the found object or NULL
356 //! returns the found object or NULL
357 //! @return new reference
357 //! @return new reference
358 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
358 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
359
359
360 private:
360 private:
361 void initPythonQtModule(bool redirectStdOut);
361 void initPythonQtModule(bool redirectStdOut);
362
362
363 //! callback for stdout redirection, emits pythonStdOut signal
363 //! callback for stdout redirection, emits pythonStdOut signal
364 static void stdOutRedirectCB(const QString& str);
364 static void stdOutRedirectCB(const QString& str);
365 //! callback for stderr redirection, emits pythonStdErr signal
365 //! callback for stderr redirection, emits pythonStdErr signal
366 static void stdErrRedirectCB(const QString& str);
366 static void stdErrRedirectCB(const QString& str);
367
367
368 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
368 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
369 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
369 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
370
370
371 PythonQt(int flags);
371 PythonQt(int flags);
372 ~PythonQt();
372 ~PythonQt();
373
373
374 static PythonQt* _self;
374 static PythonQt* _self;
375 static int _uniqueModuleCount;
375 static int _uniqueModuleCount;
376
376
377 PythonQtPrivate* _p;
377 PythonQtPrivate* _p;
378
378
379 };
379 };
380
380
381 //! internal PythonQt details
381 //! internal PythonQt details
382 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
382 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
383
383
384 Q_OBJECT
384 Q_OBJECT
385
385
386 public:
386 public:
387 PythonQtPrivate();
387 PythonQtPrivate();
388 ~PythonQtPrivate();
388 ~PythonQtPrivate();
389
389
390 enum DecoratorTypes {
390 enum DecoratorTypes {
391 StaticDecorator = 1,
391 StaticDecorator = 1,
392 ConstructorDecorator = 2,
392 ConstructorDecorator = 2,
393 DestructorDecorator = 4,
393 DestructorDecorator = 4,
394 InstanceDecorator = 8,
394 InstanceDecorator = 8,
395 AllDecorators = 0xffff
395 AllDecorators = 0xffff
396 };
396 };
397
397
398 //! returns if the id is the id for PythonQtObjectPtr
398 //! returns if the id is the id for PythonQtObjectPtr
399 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
399 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
400
400
401 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
401 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
402 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
402 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
403 //! remove the wrapper ptr again
403 //! remove the wrapper ptr again
404 void removeWrapperPointer(void* obj);
404 void removeWrapperPointer(void* obj);
405
405
406 //! add parent class relation
406 //! add parent class relation
407 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
407 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
408
408
409 //! add a handler for polymorphic downcasting
409 //! add a handler for polymorphic downcasting
410 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
410 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
411
411
412 //! lookup existing classinfo and return new if not yet present
412 //! lookup existing classinfo and return new if not yet present
413 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
413 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
414
414
415 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
415 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
416 void removeSignalEmitter(QObject* obj);
416 void removeSignalEmitter(QObject* obj);
417
417
418 //! wrap the given QObject into a Python object (or return existing wrapper!)
418 //! wrap the given QObject into a Python object (or return existing wrapper!)
419 PyObject* wrapQObject(QObject* obj);
419 PyObject* wrapQObject(QObject* obj);
420
420
421 //! 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
421 //! 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
422 PyObject* wrapPtr(void* ptr, const QByteArray& name);
422 PyObject* wrapPtr(void* ptr, const QByteArray& name);
423
423
424 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
424 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
425 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
425 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
426 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
426 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
427 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
427 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
428
428
429 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
429 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
430 //! (ownership of wrapper is passed to PythonQt)
430 //! (ownership of wrapper is passed to PythonQt)
431 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
431 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
432
432
433 This will add a wrapper object that is used to make calls to the given classname \c typeName.
433 This will add a wrapper object that is used to make calls to the given classname \c typeName.
434 All slots that take a pointer to typeName as the first argument will be callable from Python on
434 All slots that take a pointer to typeName as the first argument will be callable from Python on
435 a variant object that contains such a type.
435 a variant object that contains such a type.
436 */
436 */
437 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
437 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
438
438
439 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
439 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
440 //! and it will register the classes when it first sees a pointer to such a derived class
440 //! and it will register the classes when it first sees a pointer to such a derived class
441 void registerQObjectClassNames(const QStringList& names);
441 void registerQObjectClassNames(const QStringList& names);
442
442
443 //! add a decorator object
443 //! add a decorator object
444 void addDecorators(QObject* o, int decoTypes);
444 void addDecorators(QObject* o, int decoTypes);
445
445
446 //! helper method that creates a PythonQtClassWrapper object
446 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
447 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package = NULL);
447 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package = NULL);
448
448
449 //! helper that creates a new int derived class that represents the enum of the given name
449 //! create a new instance of the given enum type with given value (returns a new reference)
450 PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
450 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
451
452 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
453 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
451
454
452 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
455 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
453 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
456 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
454
457
455 //! get the class info for a meta object (if available)
458 //! get the class info for a meta object (if available)
456 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
459 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
457
460
458 //! get the class info for a meta object (if available)
461 //! get the class info for a meta object (if available)
459 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
462 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
460
463
461 //! creates the new module from the given pycode
464 //! creates the new module from the given pycode
462 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
465 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
463
466
464 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
467 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
465 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
468 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
466
469
467 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
470 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
468 static PyObject* dummyTuple();
471 static PyObject* dummyTuple();
469
472
470 private:
473 private:
471
474
472 //! create a new pythonqt class wrapper and place it in the pythonqt module
475 //! create a new pythonqt class wrapper and place it in the pythonqt module
473 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package);
476 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package);
474
477
475 //! get/create new package module (the returned object is a borrowed reference)
478 //! get/create new package module (the returned object is a borrowed reference)
476 PyObject* packageByName(const char* name);
479 PyObject* packageByName(const char* name);
477
480
478 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
481 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
479 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
482 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
480
483
481 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
484 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
482 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
485 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
483
486
484 //! stores the meta info of known Qt classes
487 //! stores the meta info of known Qt classes
485 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
488 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
486
489
487 //! names of qobject derived classes that can be casted to qobject savely
490 //! names of qobject derived classes that can be casted to qobject savely
488 QHash<QByteArray, bool> _knownQObjectClassNames;
491 QHash<QByteArray, bool> _knownQObjectClassNames;
489
492
490 //! stores signal receivers for QObjects
493 //! stores signal receivers for QObjects
491 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
494 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
492
495
493 //! the PythonQt python module
496 //! the PythonQt python module
494 PythonQtObjectPtr _pythonQtModule;
497 PythonQtObjectPtr _pythonQtModule;
495
498
496 //! the importer interface (if set)
499 //! the importer interface (if set)
497 PythonQtImportFileInterface* _importInterface;
500 PythonQtImportFileInterface* _importInterface;
498
501
499 //! the default importer
502 //! the default importer
500 PythonQtQFileImporter* _defaultImporter;
503 PythonQtQFileImporter* _defaultImporter;
501
504
502 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
505 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
503 PythonQtQObjectWrappedCB* _wrappedCB;
506 PythonQtQObjectWrappedCB* _wrappedCB;
504
507
505 QStringList _importIgnorePaths;
508 QStringList _importIgnorePaths;
506
509
507 //! the cpp object wrapper factories
510 //! the cpp object wrapper factories
508 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
511 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
509
512
510 QHash<QByteArray, PyObject*> _packages;
513 QHash<QByteArray, PyObject*> _packages;
511
514
512 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
515 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
513
516
514 int _initFlags;
517 int _initFlags;
515 int _PythonQtObjectPtr_metaId;
518 int _PythonQtObjectPtr_metaId;
516
519
517 friend class PythonQt;
520 friend class PythonQt;
518 };
521 };
519
522
520 #endif
523 #endif
@@ -1,821 +1,822
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtClassInfo.h"
42 #include "PythonQtClassInfo.h"
43 #include "PythonQtMethodInfo.h"
43 #include "PythonQtMethodInfo.h"
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include <QMetaMethod>
45 #include <QMetaMethod>
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaEnum>
47 #include <QMetaEnum>
48
48
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
50
50
51 PythonQtClassInfo::PythonQtClassInfo() {
51 PythonQtClassInfo::PythonQtClassInfo() {
52 _meta = NULL;
52 _meta = NULL;
53 _constructors = NULL;
53 _constructors = NULL;
54 _destructor = NULL;
54 _destructor = NULL;
55 _decoratorProvider = NULL;
55 _decoratorProvider = NULL;
56 _decoratorProviderCB = NULL;
56 _decoratorProviderCB = NULL;
57 _pythonQtClassWrapper = NULL;
57 _pythonQtClassWrapper = NULL;
58 _shellSetInstanceWrapperCB = NULL;
58 _shellSetInstanceWrapperCB = NULL;
59 _metaTypeId = -1;
59 _metaTypeId = -1;
60 _isQObject = false;
60 _isQObject = false;
61 _enumsCreated = false;
61 _enumsCreated = false;
62 }
62 }
63
63
64 PythonQtClassInfo::~PythonQtClassInfo()
64 PythonQtClassInfo::~PythonQtClassInfo()
65 {
65 {
66 clearCachedMembers();
66 clearCachedMembers();
67
67
68 if (_constructors) {
68 if (_constructors) {
69 _constructors->deleteOverloadsAndThis();
69 _constructors->deleteOverloadsAndThis();
70 }
70 }
71 if (_destructor) {
71 if (_destructor) {
72 _destructor->deleteOverloadsAndThis();
72 _destructor->deleteOverloadsAndThis();
73 }
73 }
74 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
74 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 info->deleteOverloadsAndThis();
75 info->deleteOverloadsAndThis();
76 }
76 }
77 }
77 }
78
78
79 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
79 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 {
80 {
81 // _wrappedClassName is already set earlier in the class setup
81 // _wrappedClassName is already set earlier in the class setup
82 _isQObject = true;
82 _isQObject = true;
83 _meta = meta;
83 _meta = meta;
84 }
84 }
85
85
86 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
86 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 {
87 {
88 _isQObject = false;
88 _isQObject = false;
89 _wrappedClassName = classname;
89 _wrappedClassName = classname;
90 _metaTypeId = QMetaType::type(classname);
90 _metaTypeId = QMetaType::type(classname);
91 }
91 }
92
92
93 void PythonQtClassInfo::clearCachedMembers()
93 void PythonQtClassInfo::clearCachedMembers()
94 {
94 {
95 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
95 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 while (i.hasNext()) {
96 while (i.hasNext()) {
97 PythonQtMemberInfo member = i.next().value();
97 PythonQtMemberInfo member = i.next().value();
98 if (member._type== PythonQtMemberInfo::Slot) {
98 if (member._type== PythonQtMemberInfo::Slot) {
99 PythonQtSlotInfo* info = member._slot;
99 PythonQtSlotInfo* info = member._slot;
100 while (info) {
100 while (info) {
101 PythonQtSlotInfo* next = info->nextInfo();
101 PythonQtSlotInfo* next = info->nextInfo();
102 delete info;
102 delete info;
103 info = next;
103 info = next;
104 }
104 }
105 }
105 }
106 }
106 }
107 }
107 }
108
108
109 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
109 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 {
110 {
111 const char* sigEnd = sigStart;
111 const char* sigEnd = sigStart;
112 char c;
112 char c;
113 do {
113 do {
114 c = *sigEnd++;
114 c = *sigEnd++;
115 } while (c!=someChar && c!=0);
115 } while (c!=someChar && c!=0);
116 return sigEnd-sigStart-1;
116 return sigEnd-sigStart-1;
117 }
117 }
118
118
119 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
119 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 {
120 {
121 bool found = false;
121 bool found = false;
122 bool nameMapped = false;
122 bool nameMapped = false;
123 const char* attributeName = memberName;
123 const char* attributeName = memberName;
124 // look for properties
124 // look for properties
125 int i = _meta->indexOfProperty(attributeName);
125 int i = _meta->indexOfProperty(attributeName);
126 if (i==-1) {
126 if (i==-1) {
127 // try to map name to objectName
127 // try to map name to objectName
128 if (qstrcmp(attributeName, "name")==0) {
128 if (qstrcmp(attributeName, "name")==0) {
129 attributeName = "objectName";
129 attributeName = "objectName";
130 nameMapped = true;
130 nameMapped = true;
131 i = _meta->indexOfProperty(attributeName);
131 i = _meta->indexOfProperty(attributeName);
132 }
132 }
133 }
133 }
134 if (i!=-1) {
134 if (i!=-1) {
135 PythonQtMemberInfo newInfo(_meta->property(i));
135 PythonQtMemberInfo newInfo(_meta->property(i));
136 _cachedMembers.insert(attributeName, newInfo);
136 _cachedMembers.insert(attributeName, newInfo);
137 if (nameMapped) {
137 if (nameMapped) {
138 _cachedMembers.insert(memberName, newInfo);
138 _cachedMembers.insert(memberName, newInfo);
139 }
139 }
140 #ifdef PYTHONQT_DEBUG
140 #ifdef PYTHONQT_DEBUG
141 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
141 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
142 #endif
142 #endif
143 found = true;
143 found = true;
144 }
144 }
145 return found;
145 return found;
146 }
146 }
147
147
148 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
148 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
149 {
149 {
150 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
150 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
151 foreach(const ParentClassInfo& info, _parentClasses) {
151 foreach(const ParentClassInfo& info, _parentClasses) {
152 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
152 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
153 }
153 }
154 return inputInfo;
154 return inputInfo;
155 }
155 }
156
156
157 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
157 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
158 QObject* decoratorProvider = decorator();
158 QObject* decoratorProvider = decorator();
159 int memberNameLen = strlen(memberName);
159 int memberNameLen = strlen(memberName);
160 if (decoratorProvider) {
160 if (decoratorProvider) {
161 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
161 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
162 const QMetaObject* meta = decoratorProvider->metaObject();
162 const QMetaObject* meta = decoratorProvider->metaObject();
163 int numMethods = meta->methodCount();
163 int numMethods = meta->methodCount();
164 int startFrom = QObject::staticMetaObject.methodCount();
164 int startFrom = QObject::staticMetaObject.methodCount();
165 for (int i = startFrom; i < numMethods; i++) {
165 for (int i = startFrom; i < numMethods; i++) {
166 QMetaMethod m = meta->method(i);
166 QMetaMethod m = meta->method(i);
167 if ((m.methodType() == QMetaMethod::Method ||
167 if ((m.methodType() == QMetaMethod::Method ||
168 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
168 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
169
169
170 const char* sigStart = m.signature();
170 const char* sigStart = m.signature();
171 bool isClassDeco = false;
171 bool isClassDeco = false;
172 if (qstrncmp(sigStart, "static_", 7)==0) {
172 if (qstrncmp(sigStart, "static_", 7)==0) {
173 // skip the static_classname_ part of the string
173 // skip the static_classname_ part of the string
174 sigStart += 7 + 1 + strlen(className());
174 sigStart += 7 + 1 + strlen(className());
175 isClassDeco = true;
175 isClassDeco = true;
176 } else if (qstrncmp(sigStart, "new_", 4)==0) {
176 } else if (qstrncmp(sigStart, "new_", 4)==0) {
177 isClassDeco = true;
177 isClassDeco = true;
178 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
178 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
179 isClassDeco = true;
179 isClassDeco = true;
180 }
180 }
181 // find the first '('
181 // find the first '('
182 int offset = findCharOffset(sigStart, '(');
182 int offset = findCharOffset(sigStart, '(');
183
183
184 // XXX no checking is currently done if the slots have correct first argument or not...
184 // XXX no checking is currently done if the slots have correct first argument or not...
185
185
186 // check if same length and same name
186 // check if same length and same name
187 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
187 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
188 found = true;
188 found = true;
189 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
189 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
190 info->setUpcastingOffset(upcastingOffset);
190 info->setUpcastingOffset(upcastingOffset);
191 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
191 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
192 if (tail) {
192 if (tail) {
193 tail->setNextInfo(info);
193 tail->setNextInfo(info);
194 } else {
194 } else {
195 PythonQtMemberInfo newInfo(info);
195 PythonQtMemberInfo newInfo(info);
196 memberCache.insert(memberName, newInfo);
196 memberCache.insert(memberName, newInfo);
197 }
197 }
198 tail = info;
198 tail = info;
199 }
199 }
200 }
200 }
201 }
201 }
202 }
202 }
203
203
204 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
204 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
205
205
206 return tail;
206 return tail;
207 }
207 }
208
208
209 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
209 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
210 {
210 {
211 bool found = false;
211 bool found = false;
212 int memberNameLen = strlen(memberName);
212 int memberNameLen = strlen(memberName);
213 PythonQtSlotInfo* tail = NULL;
213 PythonQtSlotInfo* tail = NULL;
214 if (_meta) {
214 if (_meta) {
215 int numMethods = _meta->methodCount();
215 int numMethods = _meta->methodCount();
216 for (int i = 0; i < numMethods; i++) {
216 for (int i = 0; i < numMethods; i++) {
217 QMetaMethod m = _meta->method(i);
217 QMetaMethod m = _meta->method(i);
218 if ((m.methodType() == QMetaMethod::Method ||
218 if ((m.methodType() == QMetaMethod::Method ||
219 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
219 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
220
220
221 const char* sigStart = m.signature();
221 const char* sigStart = m.signature();
222 // find the first '('
222 // find the first '('
223 int offset = findCharOffset(sigStart, '(');
223 int offset = findCharOffset(sigStart, '(');
224
224
225 // check if same length and same name
225 // check if same length and same name
226 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
226 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
227 found = true;
227 found = true;
228 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
228 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
229 if (tail) {
229 if (tail) {
230 tail->setNextInfo(info);
230 tail->setNextInfo(info);
231 } else {
231 } else {
232 PythonQtMemberInfo newInfo(info);
232 PythonQtMemberInfo newInfo(info);
233 _cachedMembers.insert(memberName, newInfo);
233 _cachedMembers.insert(memberName, newInfo);
234 }
234 }
235 tail = info;
235 tail = info;
236 }
236 }
237 }
237 }
238 }
238 }
239 }
239 }
240
240
241 // look for dynamic decorators in this class and in derived classes
241 // look for dynamic decorators in this class and in derived classes
242 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
242 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
243
243
244 return found;
244 return found;
245 }
245 }
246
246
247 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
247 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
248 {
248 {
249 bool found = false;
249 bool found = false;
250 // look for enum values
250 // look for enum values
251 int enumCount = meta->enumeratorCount();
251 int enumCount = meta->enumeratorCount();
252 for (int i=0;i<enumCount; i++) {
252 for (int i=0;i<enumCount; i++) {
253 QMetaEnum e = meta->enumerator(i);
253 QMetaEnum e = meta->enumerator(i);
254 // we do not want flags, they will cause our values to appear two times
254 // we do not want flags, they will cause our values to appear two times
255 if (e.isFlag()) continue;
255 if (e.isFlag()) continue;
256
256
257 for (int j=0; j < e.keyCount(); j++) {
257 for (int j=0; j < e.keyCount(); j++) {
258 if (qstrcmp(e.key(j), memberName)==0) {
258 if (qstrcmp(e.key(j), memberName)==0) {
259 PyObject* enumType = findEnumWrapper(e.name());
259 PyObject* enumType = findEnumWrapper(e.name());
260 if (enumType) {
260 if (enumType) {
261 PyObject* args = Py_BuildValue("(i)", e.value(j));
262 PyObject* enumValue = PyObject_Call(enumType, args, NULL);
263 Py_DECREF(args);
264 PythonQtObjectPtr enumValuePtr;
261 PythonQtObjectPtr enumValuePtr;
265 enumValuePtr.setNewRef(enumValue);
262 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
266 PythonQtMemberInfo newInfo(enumValuePtr);
263 PythonQtMemberInfo newInfo(enumValuePtr);
267 _cachedMembers.insert(memberName, newInfo);
264 _cachedMembers.insert(memberName, newInfo);
268 #ifdef PYTHONQT_DEBUG
265 #ifdef PYTHONQT_DEBUG
269 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
266 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
270 #endif
267 #endif
271 found = true;
268 found = true;
272 break;
269 break;
273 } else {
270 } else {
274 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
271 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
275 }
272 }
276 }
273 }
277 }
274 }
278 }
275 }
279 return found;
276 return found;
280 }
277 }
281
278
282 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
279 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
283 {
280 {
284 PythonQtMemberInfo info = _cachedMembers.value(memberName);
281 PythonQtMemberInfo info = _cachedMembers.value(memberName);
285 if (info._type != PythonQtMemberInfo::Invalid) {
282 if (info._type != PythonQtMemberInfo::Invalid) {
286 return info;
283 return info;
287 } else {
284 } else {
288 bool found = false;
285 bool found = false;
289
286
290 found = lookForPropertyAndCache(memberName);
287 found = lookForPropertyAndCache(memberName);
291 if (!found) {
288 if (!found) {
292 found = lookForMethodAndCache(memberName);
289 found = lookForMethodAndCache(memberName);
293 }
290 }
294 if (!found) {
291 if (!found) {
295 if (_meta) {
292 if (_meta) {
296 // check enums in our meta object directly
293 // check enums in our meta object directly
297 found = lookForEnumAndCache(_meta, memberName);
294 found = lookForEnumAndCache(_meta, memberName);
298 }
295 }
299 if (!found) {
296 if (!found) {
300 // check enums in the class hierachy of CPP classes
297 // check enums in the class hierachy of CPP classes
301 // look for dynamic decorators in this class and in derived classes
298 // look for dynamic decorators in this class and in derived classes
302 QList<QObject*> decoObjects;
299 QList<QObject*> decoObjects;
303 recursiveCollectDecoratorObjects(decoObjects);
300 recursiveCollectDecoratorObjects(decoObjects);
304 foreach(QObject* deco, decoObjects) {
301 foreach(QObject* deco, decoObjects) {
305 // call on ourself for caching, but with different metaObject():
302 // call on ourself for caching, but with different metaObject():
306 found = lookForEnumAndCache(deco->metaObject(), memberName);
303 found = lookForEnumAndCache(deco->metaObject(), memberName);
307 if (found) {
304 if (found) {
308 break;
305 break;
309 }
306 }
310 }
307 }
311 }
308 }
312 }
309 }
313 if (!found) {
310 if (!found) {
314 PyObject* p = findEnumWrapper(memberName);
311 PyObject* p = findEnumWrapper(memberName);
315 if (p) {
312 if (p) {
316 info._type = PythonQtMemberInfo::EnumWrapper;
313 info._type = PythonQtMemberInfo::EnumWrapper;
317 info._enumWrapper = p;
314 info._enumWrapper = p;
318 _cachedMembers.insert(memberName, info);
315 _cachedMembers.insert(memberName, info);
319 found = true;
316 found = true;
320 }
317 }
321 }
318 }
322 if (!found) {
319 if (!found) {
323 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
320 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
324 info._type = PythonQtMemberInfo::NotFound;
321 info._type = PythonQtMemberInfo::NotFound;
325 _cachedMembers.insert(memberName, info);
322 _cachedMembers.insert(memberName, info);
326 }
323 }
327 }
324 }
328
325
329 return _cachedMembers.value(memberName);
326 return _cachedMembers.value(memberName);
330 }
327 }
331
328
332 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
329 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
333 QObject* deco = decorator();
330 QObject* deco = decorator();
334 if (deco) {
331 if (deco) {
335 decoratorObjects.append(deco);
332 decoratorObjects.append(deco);
336 }
333 }
337 foreach(const ParentClassInfo& info, _parentClasses) {
334 foreach(const ParentClassInfo& info, _parentClasses) {
338 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
335 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
339 }
336 }
340 }
337 }
341
338
342 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
339 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
343 classInfoObjects.append(this);
340 classInfoObjects.append(this);
344 foreach(const ParentClassInfo& info, _parentClasses) {
341 foreach(const ParentClassInfo& info, _parentClasses) {
345 info._parent->recursiveCollectClassInfos(classInfoObjects);
342 info._parent->recursiveCollectClassInfos(classInfoObjects);
346 }
343 }
347 }
344 }
348
345
349 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
346 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
350 {
347 {
351 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
348 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
352 while (it.hasNext()) {
349 while (it.hasNext()) {
353
350
354 PythonQtSlotInfo* infoOrig = it.next();
351 PythonQtSlotInfo* infoOrig = it.next();
355
352
356 const char* sigStart = infoOrig->metaMethod()->signature();
353 const char* sigStart = infoOrig->metaMethod()->signature();
357 if (qstrncmp("static_", sigStart, 7)==0) {
354 if (qstrncmp("static_", sigStart, 7)==0) {
358 sigStart += 7;
355 sigStart += 7;
359 sigStart += findCharOffset(sigStart, '_')+1;
356 sigStart += findCharOffset(sigStart, '_')+1;
360 }
357 }
361 int offset = findCharOffset(sigStart, '(');
358 int offset = findCharOffset(sigStart, '(');
362 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
359 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
363 //make a copy, otherwise we will have trouble on overloads!
360 //make a copy, otherwise we will have trouble on overloads!
364 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
361 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
365 info->setUpcastingOffset(upcastingOffset);
362 info->setUpcastingOffset(upcastingOffset);
366 found = true;
363 found = true;
367 if (tail) {
364 if (tail) {
368 tail->setNextInfo(info);
365 tail->setNextInfo(info);
369 } else {
366 } else {
370 PythonQtMemberInfo newInfo(info);
367 PythonQtMemberInfo newInfo(info);
371 memberCache.insert(memberName, newInfo);
368 memberCache.insert(memberName, newInfo);
372 }
369 }
373 tail = info;
370 tail = info;
374 }
371 }
375 }
372 }
376 return tail;
373 return tail;
377 }
374 }
378
375
379 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
376 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
380 QObject* decoratorProvider = decorator();
377 QObject* decoratorProvider = decorator();
381 if (decoratorProvider) {
378 if (decoratorProvider) {
382 const QMetaObject* meta = decoratorProvider->metaObject();
379 const QMetaObject* meta = decoratorProvider->metaObject();
383 int numMethods = meta->methodCount();
380 int numMethods = meta->methodCount();
384 int startFrom = QObject::staticMetaObject.methodCount();
381 int startFrom = QObject::staticMetaObject.methodCount();
385 for (int i = startFrom; i < numMethods; i++) {
382 for (int i = startFrom; i < numMethods; i++) {
386 QMetaMethod m = meta->method(i);
383 QMetaMethod m = meta->method(i);
387 if ((m.methodType() == QMetaMethod::Method ||
384 if ((m.methodType() == QMetaMethod::Method ||
388 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
385 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
389
386
390 const char* sigStart = m.signature();
387 const char* sigStart = m.signature();
391 bool isClassDeco = false;
388 bool isClassDeco = false;
392 if (qstrncmp(sigStart, "static_", 7)==0) {
389 if (qstrncmp(sigStart, "static_", 7)==0) {
393 // skip the static_classname_ part of the string
390 // skip the static_classname_ part of the string
394 sigStart += 7 + 1 + strlen(className());
391 sigStart += 7 + 1 + strlen(className());
395 isClassDeco = true;
392 isClassDeco = true;
396 } else if (qstrncmp(sigStart, "new_", 4)==0) {
393 } else if (qstrncmp(sigStart, "new_", 4)==0) {
397 continue;
394 continue;
398 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
395 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
399 continue;
396 continue;
400 }
397 }
401 // find the first '('
398 // find the first '('
402 int offset = findCharOffset(sigStart, '(');
399 int offset = findCharOffset(sigStart, '(');
403
400
404 // XXX no checking is currently done if the slots have correct first argument or not...
401 // XXX no checking is currently done if the slots have correct first argument or not...
405 if (!metaOnly || isClassDeco) {
402 if (!metaOnly || isClassDeco) {
406 list << QString::fromLatin1(sigStart, offset);
403 list << QString::fromLatin1(sigStart, offset);
407 }
404 }
408 }
405 }
409 }
406 }
410 }
407 }
411
408
412 // look for global decorator slots
409 // look for global decorator slots
413 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
410 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
414 while (it.hasNext()) {
411 while (it.hasNext()) {
415 PythonQtSlotInfo* slot = it.next();
412 PythonQtSlotInfo* slot = it.next();
416 if (metaOnly) {
413 if (metaOnly) {
417 if (slot->isClassDecorator()) {
414 if (slot->isClassDecorator()) {
418 QByteArray first = slot->slotName();
415 QByteArray first = slot->slotName();
419 if (first.startsWith("static_")) {
416 if (first.startsWith("static_")) {
420 int idx = first.indexOf('_');
417 int idx = first.indexOf('_');
421 idx = first.indexOf('_', idx+1);
418 idx = first.indexOf('_', idx+1);
422 first = first.mid(idx+1);
419 first = first.mid(idx+1);
423 }
420 }
424 list << first;
421 list << first;
425 }
422 }
426 } else {
423 } else {
427 list << slot->slotName();
424 list << slot->slotName();
428 }
425 }
429 }
426 }
430 }
427 }
431
428
432 QStringList PythonQtClassInfo::propertyList()
429 QStringList PythonQtClassInfo::propertyList()
433 {
430 {
434 QStringList l;
431 QStringList l;
435 if (_isQObject && _meta) {
432 if (_isQObject && _meta) {
436 int i;
433 int i;
437 int numProperties = _meta->propertyCount();
434 int numProperties = _meta->propertyCount();
438 for (i = 0; i < numProperties; i++) {
435 for (i = 0; i < numProperties; i++) {
439 QMetaProperty p = _meta->property(i);
436 QMetaProperty p = _meta->property(i);
440 l << QString(p.name());
437 l << QString(p.name());
441 }
438 }
442 }
439 }
443 return l;
440 return l;
444 }
441 }
445
442
446 QStringList PythonQtClassInfo::memberList(bool metaOnly)
443 QStringList PythonQtClassInfo::memberList(bool metaOnly)
447 {
444 {
448 decorator();
445 decorator();
449
446
450 QStringList l;
447 QStringList l;
451 QString h;
448 QString h;
452 if (_isQObject && _meta && !metaOnly) {
449 if (_isQObject && _meta && !metaOnly) {
453 l = propertyList();
450 l = propertyList();
454 }
451 }
455
452
456 // normal slots of QObject (or wrapper QObject)
453 // normal slots of QObject (or wrapper QObject)
457 if (!metaOnly && _meta) {
454 if (!metaOnly && _meta) {
458 int numMethods = _meta->methodCount();
455 int numMethods = _meta->methodCount();
459 bool skipQObj = !_isQObject;
456 bool skipQObj = !_isQObject;
460 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
457 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
461 QMetaMethod m = _meta->method(i);
458 QMetaMethod m = _meta->method(i);
462 if ((m.methodType() == QMetaMethod::Method ||
459 if ((m.methodType() == QMetaMethod::Method ||
463 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
460 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
464 QByteArray signa(m.signature());
461 QByteArray signa(m.signature());
465 signa = signa.left(signa.indexOf('('));
462 signa = signa.left(signa.indexOf('('));
466 l << signa;
463 l << signa;
467 }
464 }
468 }
465 }
469 }
466 }
470
467
471 {
468 {
472 // look for dynamic decorators in this class and in derived classes
469 // look for dynamic decorators in this class and in derived classes
473 QList<PythonQtClassInfo*> infos;
470 QList<PythonQtClassInfo*> infos;
474 recursiveCollectClassInfos(infos);
471 recursiveCollectClassInfos(infos);
475 foreach(PythonQtClassInfo* info, infos) {
472 foreach(PythonQtClassInfo* info, infos) {
476 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
473 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
477 }
474 }
478 }
475 }
479
476
480 // List enumerator keys...
477 // List enumerator keys...
481 QList<const QMetaObject*> enumMetaObjects;
478 QList<const QMetaObject*> enumMetaObjects;
482 if (_meta) {
479 if (_meta) {
483 enumMetaObjects << _meta;
480 enumMetaObjects << _meta;
484 }
481 }
485 // check enums in the class hierachy of CPP classes
482 // check enums in the class hierachy of CPP classes
486 QList<QObject*> decoObjects;
483 QList<QObject*> decoObjects;
487 recursiveCollectDecoratorObjects(decoObjects);
484 recursiveCollectDecoratorObjects(decoObjects);
488 foreach(QObject* deco, decoObjects) {
485 foreach(QObject* deco, decoObjects) {
489 enumMetaObjects << deco->metaObject();
486 enumMetaObjects << deco->metaObject();
490 }
487 }
491
488
492 foreach(const QMetaObject* meta, enumMetaObjects) {
489 foreach(const QMetaObject* meta, enumMetaObjects) {
493 for (int i = 0; i<meta->enumeratorCount(); i++) {
490 for (int i = 0; i<meta->enumeratorCount(); i++) {
494 QMetaEnum e = meta->enumerator(i);
491 QMetaEnum e = meta->enumerator(i);
495 l << e.name();
492 l << e.name();
496 // we do not want flags, they will cause our values to appear two times
493 // we do not want flags, they will cause our values to appear two times
497 if (e.isFlag()) continue;
494 if (e.isFlag()) continue;
498
495
499 for (int j=0; j < e.keyCount(); j++) {
496 for (int j=0; j < e.keyCount(); j++) {
500 l << QString(e.key(j));
497 l << QString(e.key(j));
501 }
498 }
502 }
499 }
503 }
500 }
504
501
505 return QSet<QString>::fromList(l).toList();
502 return QSet<QString>::fromList(l).toList();
506 }
503 }
507
504
508 const char* PythonQtClassInfo::className()
505 const char* PythonQtClassInfo::className()
509 {
506 {
510 return _wrappedClassName.constData();
507 return _wrappedClassName.constData();
511 }
508 }
512
509
513 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
510 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
514 {
511 {
515 if (ptr==NULL) {
512 if (ptr==NULL) {
516 return NULL;
513 return NULL;
517 }
514 }
518 if (_wrappedClassName == classname) {
515 if (_wrappedClassName == classname) {
519 return ptr;
516 return ptr;
520 }
517 }
521 foreach(const ParentClassInfo& info, _parentClasses) {
518 foreach(const ParentClassInfo& info, _parentClasses) {
522 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
519 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
523 if (result) {
520 if (result) {
524 return result;
521 return result;
525 }
522 }
526 }
523 }
527 return NULL;
524 return NULL;
528 }
525 }
529
526
530 bool PythonQtClassInfo::inherits(const char* name)
527 bool PythonQtClassInfo::inherits(const char* name)
531 {
528 {
532 if (_wrappedClassName == name) {
529 if (_wrappedClassName == name) {
533 return true;
530 return true;
534 }
531 }
535 foreach(const ParentClassInfo& info, _parentClasses) {
532 foreach(const ParentClassInfo& info, _parentClasses) {
536 if (info._parent->inherits(name)) {
533 if (info._parent->inherits(name)) {
537 return true;
534 return true;
538 }
535 }
539 }
536 }
540 return false;
537 return false;
541 }
538 }
542
539
543 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
540 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
544 {
541 {
545 if (classInfo == this) {
542 if (classInfo == this) {
546 return true;
543 return true;
547 }
544 }
548 foreach(const ParentClassInfo& info, _parentClasses) {
545 foreach(const ParentClassInfo& info, _parentClasses) {
549 if (info._parent->inherits(classInfo)) {
546 if (info._parent->inherits(classInfo)) {
550 return true;
547 return true;
551 }
548 }
552 }
549 }
553 return false;
550 return false;
554 }
551 }
555
552
556 QString PythonQtClassInfo::help()
553 QString PythonQtClassInfo::help()
557 {
554 {
558 decorator();
555 decorator();
559 QString h;
556 QString h;
560 h += QString("--- ") + QString(className()) + QString(" ---\n");
557 h += QString("--- ") + QString(className()) + QString(" ---\n");
561
558
562 if (_isQObject) {
559 if (_isQObject) {
563 h += "Properties:\n";
560 h += "Properties:\n";
564
561
565 int i;
562 int i;
566 int numProperties = _meta->propertyCount();
563 int numProperties = _meta->propertyCount();
567 for (i = 0; i < numProperties; i++) {
564 for (i = 0; i < numProperties; i++) {
568 QMetaProperty p = _meta->property(i);
565 QMetaProperty p = _meta->property(i);
569 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
566 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
570 }
567 }
571 }
568 }
572
569
573 if (constructors()) {
570 if (constructors()) {
574 h += "Constructors:\n";
571 h += "Constructors:\n";
575 PythonQtSlotInfo* constr = constructors();
572 PythonQtSlotInfo* constr = constructors();
576 while (constr) {
573 while (constr) {
577 h += constr->fullSignature() + "\n";
574 h += constr->fullSignature() + "\n";
578 constr = constr->nextInfo();
575 constr = constr->nextInfo();
579 }
576 }
580 }
577 }
581
578
582 h += "Slots:\n";
579 h += "Slots:\n";
583 h += "QString help()\n";
580 h += "QString help()\n";
584 h += "QString className()\n";
581 h += "QString className()\n";
585
582
586 if (_meta) {
583 if (_meta) {
587 int numMethods = _meta->methodCount();
584 int numMethods = _meta->methodCount();
588 for (int i = 0; i < numMethods; i++) {
585 for (int i = 0; i < numMethods; i++) {
589 QMetaMethod m = _meta->method(i);
586 QMetaMethod m = _meta->method(i);
590 if ((m.methodType() == QMetaMethod::Method ||
587 if ((m.methodType() == QMetaMethod::Method ||
591 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
588 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
592 PythonQtSlotInfo slot(this, m, i);
589 PythonQtSlotInfo slot(this, m, i);
593 h += slot.fullSignature()+ "\n";
590 h += slot.fullSignature()+ "\n";
594 }
591 }
595 }
592 }
596 }
593 }
597
594
598 // TODO xxx : decorators and enums from decorator() are missing...
595 // TODO xxx : decorators and enums from decorator() are missing...
599 // maybe we can reuse memberlist()?
596 // maybe we can reuse memberlist()?
600
597
601 if (_meta && _meta->enumeratorCount()) {
598 if (_meta && _meta->enumeratorCount()) {
602 h += "Enums:\n";
599 h += "Enums:\n";
603 for (int i = 0; i<_meta->enumeratorCount(); i++) {
600 for (int i = 0; i<_meta->enumeratorCount(); i++) {
604 QMetaEnum e = _meta->enumerator(i);
601 QMetaEnum e = _meta->enumerator(i);
605 h += QString(e.name()) + " {";
602 h += QString(e.name()) + " {";
606 for (int j=0; j < e.keyCount(); j++) {
603 for (int j=0; j < e.keyCount(); j++) {
607 if (j) { h+= ", "; }
604 if (j) { h+= ", "; }
608 h += e.key(j);
605 h += e.key(j);
609 }
606 }
610 h += " }\n";
607 h += " }\n";
611 }
608 }
612 }
609 }
613
610
614 if (_isQObject && _meta) {
611 if (_isQObject && _meta) {
615 int numMethods = _meta->methodCount();
612 int numMethods = _meta->methodCount();
616 if (numMethods>0) {
613 if (numMethods>0) {
617 h += "Signals:\n";
614 h += "Signals:\n";
618 for (int i = 0; i < numMethods; i++) {
615 for (int i = 0; i < numMethods; i++) {
619 QMetaMethod m = _meta->method(i);
616 QMetaMethod m = _meta->method(i);
620 if (m.methodType() == QMetaMethod::Signal) {
617 if (m.methodType() == QMetaMethod::Signal) {
621 h += QString(m.signature()) + "\n";
618 h += QString(m.signature()) + "\n";
622 }
619 }
623 }
620 }
624 }
621 }
625 }
622 }
626 return h;
623 return h;
627 }
624 }
628
625
629 PythonQtSlotInfo* PythonQtClassInfo::constructors()
626 PythonQtSlotInfo* PythonQtClassInfo::constructors()
630 {
627 {
631 if (!_constructors) {
628 if (!_constructors) {
632 // force creation of lazy decorator, which will register the decorators
629 // force creation of lazy decorator, which will register the decorators
633 decorator();
630 decorator();
634 }
631 }
635 return _constructors;
632 return _constructors;
636 }
633 }
637
634
638 PythonQtSlotInfo* PythonQtClassInfo::destructor()
635 PythonQtSlotInfo* PythonQtClassInfo::destructor()
639 {
636 {
640 if (!_destructor) {
637 if (!_destructor) {
641 // force creation of lazy decorator, which will register the decorators
638 // force creation of lazy decorator, which will register the decorators
642 decorator();
639 decorator();
643 }
640 }
644 return _destructor;
641 return _destructor;
645 }
642 }
646
643
647 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
644 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
648 {
645 {
649 PythonQtSlotInfo* prev = constructors();
646 PythonQtSlotInfo* prev = constructors();
650 if (prev) {
647 if (prev) {
651 info->setNextInfo(prev->nextInfo());
648 info->setNextInfo(prev->nextInfo());
652 prev->setNextInfo(info);
649 prev->setNextInfo(info);
653 } else {
650 } else {
654 _constructors = info;
651 _constructors = info;
655 }
652 }
656 }
653 }
657
654
658 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
655 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
659 {
656 {
660 _decoratorSlots.append(info);
657 _decoratorSlots.append(info);
661 }
658 }
662
659
663 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
660 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
664 {
661 {
665 if (_destructor) {
662 if (_destructor) {
666 _destructor->deleteOverloadsAndThis();
663 _destructor->deleteOverloadsAndThis();
667 }
664 }
668 _destructor = info;
665 _destructor = info;
669 }
666 }
670
667
671 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
668 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
672 {
669 {
673 _meta = meta;
670 _meta = meta;
674 clearCachedMembers();
671 clearCachedMembers();
675 }
672 }
676
673
677 QObject* PythonQtClassInfo::decorator()
674 QObject* PythonQtClassInfo::decorator()
678 {
675 {
679 if (!_decoratorProvider && _decoratorProviderCB) {
676 if (!_decoratorProvider && _decoratorProviderCB) {
680 _decoratorProvider = (*_decoratorProviderCB)();
677 _decoratorProvider = (*_decoratorProviderCB)();
681 if (_decoratorProvider) {
678 if (_decoratorProvider) {
682 _decoratorProvider->setParent(PythonQt::priv());
679 _decoratorProvider->setParent(PythonQt::priv());
683 // setup enums early, since they might be needed by the constructor decorators:
680 // setup enums early, since they might be needed by the constructor decorators:
684 if (!_enumsCreated) {
681 if (!_enumsCreated) {
685 createEnumWrappers();
682 createEnumWrappers();
686 }
683 }
687 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
684 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
688 }
685 }
689 }
686 }
690 // check if enums need to be created and create them if they are not yet created
687 // check if enums need to be created and create them if they are not yet created
691 if (!_enumsCreated) {
688 if (!_enumsCreated) {
692 createEnumWrappers();
689 createEnumWrappers();
693 }
690 }
694 return _decoratorProvider;
691 return _decoratorProvider;
695 }
692 }
696
693
697 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
694 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
698 {
695 {
699 PythonQtMemberInfo info = member("hasOwner");
696 PythonQtMemberInfo info = member("hasOwner");
700 if (info._type == PythonQtMemberInfo::Slot) {
697 if (info._type == PythonQtMemberInfo::Slot) {
701 void* obj = object;
698 void* obj = object;
702 bool result = false;
699 bool result = false;
703 void* args[2];
700 void* args[2];
704 args[0] = &result;
701 args[0] = &result;
705 args[1] = &obj;
702 args[1] = &obj;
706 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
703 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
707 return !result;
704 return !result;
708 } else {
705 } else {
709 return false;
706 return false;
710 }
707 }
711 }
708 }
712
709
713 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
710 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
714 {
711 {
715 if (!_polymorphicHandlers.isEmpty()) {
712 if (!_polymorphicHandlers.isEmpty()) {
716 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
713 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
717 void* resultPtr = (*cb)(ptr, resultClassName);
714 void* resultPtr = (*cb)(ptr, resultClassName);
718 if (resultPtr) {
715 if (resultPtr) {
719 return resultPtr;
716 return resultPtr;
720 }
717 }
721 }
718 }
722 }
719 }
723 foreach(const ParentClassInfo& info, _parentClasses) {
720 foreach(const ParentClassInfo& info, _parentClasses) {
724 if (!info._parent->isQObject()) {
721 if (!info._parent->isQObject()) {
725 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
722 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
726 if (resultPtr) {
723 if (resultPtr) {
727 return resultPtr;
724 return resultPtr;
728 }
725 }
729 }
726 }
730 }
727 }
731 return NULL;
728 return NULL;
732 }
729 }
733
730
734 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
731 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
735 {
732 {
736 char* className;
733 char* className;
737 // this would do downcasting recursively...
734 // this would do downcasting recursively...
738 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
735 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
739
736
740 // we only do downcasting on the base object, not on the whole inheritance tree...
737 // we only do downcasting on the base object, not on the whole inheritance tree...
741 void* resultPtr = NULL;
738 void* resultPtr = NULL;
742 if (!_polymorphicHandlers.isEmpty()) {
739 if (!_polymorphicHandlers.isEmpty()) {
743 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
740 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
744 resultPtr = (*cb)(ptr, &className);
741 resultPtr = (*cb)(ptr, &className);
745 if (resultPtr) {
742 if (resultPtr) {
746 break;
743 break;
747 }
744 }
748 }
745 }
749 }
746 }
750 if (resultPtr) {
747 if (resultPtr) {
751 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
748 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
752 } else {
749 } else {
753 *resultClassInfo = this;
750 *resultClassInfo = this;
754 resultPtr = ptr;
751 resultPtr = ptr;
755 }
752 }
756 return resultPtr;
753 return resultPtr;
757 }
754 }
758
755
759 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool& isLocalEnum)
756 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool& isLocalEnum)
760 {
757 {
761 isLocalEnum = true;
758 isLocalEnum = true;
762 int scopePos = name.lastIndexOf("::");
759 int scopePos = name.lastIndexOf("::");
763 if (scopePos != -1) {
760 if (scopePos != -1) {
764 isLocalEnum = false;
761 isLocalEnum = false;
765 // slit into scope and enum name
762 // slit into scope and enum name
766 QByteArray enumScope = name.mid(0,scopePos);
763 QByteArray enumScope = name.mid(0,scopePos);
767 QByteArray enumName = name.mid(scopePos+2);
764 QByteArray enumName = name.mid(scopePos+2);
768 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
765 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
769 if (info) {
766 if (info) {
770 return info->findEnumWrapper(enumName);
767 return info->findEnumWrapper(enumName);
771 } else{
768 } else{
772 return NULL;
769 return NULL;
773 }
770 }
774 }
771 }
775 if (localScope) {
772 if (localScope) {
776 return localScope->findEnumWrapper(name);
773 return localScope->findEnumWrapper(name);
777 } else {
774 } else {
778 return NULL;
775 return NULL;
779 }
776 }
780 }
777 }
781
778
782 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
779 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
783 {
780 {
784 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
781 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
785 QMetaEnum e = meta->enumerator(i);
782 QMetaEnum e = meta->enumerator(i);
786 PythonQtObjectPtr p;
783 PythonQtObjectPtr p;
787 p.setNewRef(PythonQt::priv()->createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
784 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
788 _enumWrappers.append(p);
785 _enumWrappers.append(p);
789 }
786 }
790 }
787 }
791
788
792 void PythonQtClassInfo::createEnumWrappers()
789 void PythonQtClassInfo::createEnumWrappers()
793 {
790 {
794 if (!_enumsCreated) {
791 if (!_enumsCreated) {
795 _enumsCreated = true;
792 _enumsCreated = true;
796 if (_meta) {
793 if (_meta) {
797 createEnumWrappers(_meta);
794 createEnumWrappers(_meta);
798 }
795 }
799 if (decorator()) {
796 if (decorator()) {
800 createEnumWrappers(decorator()->metaObject());
797 createEnumWrappers(decorator()->metaObject());
801 }
798 }
802 foreach(const ParentClassInfo& info, _parentClasses) {
799 foreach(const ParentClassInfo& info, _parentClasses) {
803 info._parent->createEnumWrappers();
800 info._parent->createEnumWrappers();
804 }
801 }
805 }
802 }
806 }
803 }
807
804
808 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
805 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
806 // force enum creation
807 if (!_enumsCreated) {
808 createEnumWrappers();
809 }
809 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
810 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
810 const char* className = ((PyTypeObject*)p.object())->tp_name;
811 const char* className = ((PyTypeObject*)p.object())->tp_name;
811 if (qstrcmp(className, name)==0) {
812 if (qstrcmp(className, name)==0) {
812 return p.object();
813 return p.object();
813 }
814 }
814 }
815 }
815 foreach(const ParentClassInfo& info, _parentClasses) {
816 foreach(const ParentClassInfo& info, _parentClasses) {
816 PyObject* p = info._parent->findEnumWrapper(name);
817 PyObject* p = info._parent->findEnumWrapper(name);
817 if (p) return p;
818 if (p) return p;
818 }
819 }
819 return NULL;
820 return NULL;
820 }
821 }
821
822
@@ -1,1115 +1,1129
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtConversion.cpp
35 // \file PythonQtConversion.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtConversion.h"
42 #include "PythonQtConversion.h"
43 #include "PythonQtVariants.h"
43 #include "PythonQtVariants.h"
44 #include <QDateTime>
44 #include <QDateTime>
45 #include <QTime>
45 #include <QTime>
46 #include <QDate>
46 #include <QDate>
47
47
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
50 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
51
51
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
54
54
55 PyObject* PythonQtConv::GetPyBool(bool val)
55 PyObject* PythonQtConv::GetPyBool(bool val)
56 {
56 {
57 PyObject* r = val?Py_True:Py_False;
57 PyObject* r = val?Py_True:Py_False;
58 Py_INCREF(r);
58 Py_INCREF(r);
59 return r;
59 return r;
60 }
60 }
61
61
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
63 // is it an enum value?
64 if (info.enumWrapper) {
65 if (!info.isPointer) {
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
67 } else {
68 // we do not support pointers to enums (who needs them?)
69 Py_INCREF(Py_None);
70 return Py_None;
71 }
72 }
73
63 if (info.typeId == QMetaType::Void) {
74 if (info.typeId == QMetaType::Void) {
64 Py_INCREF(Py_None);
75 Py_INCREF(Py_None);
65 return Py_None;
76 return Py_None;
66 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
77 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
67 // 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:
68 return PyString_FromString(*((char**)data));
79 return PyString_FromString(*((char**)data));
69 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
80 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
70 info.name.startsWith("QList<")) {
81 info.name.startsWith("QList<")) {
71 // it is a QList template:
82 // it is a QList template:
72 // (TODO: check what happens if this is a pointer type?!)
83 // (TODO: check what happens if this is a pointer type?!)
73 QByteArray innerType = info.name.mid(6,info.name.length()-7);
84 QByteArray innerType = info.name.mid(6,info.name.length()-7);
74 if (innerType.endsWith("*")) {
85 if (innerType.endsWith("*")) {
75 innerType.truncate(innerType.length()-1);
86 innerType.truncate(innerType.length()-1);
76 return ConvertQListOfPointerTypeToPythonList((QList<void*>*)data, innerType);
87 return ConvertQListOfPointerTypeToPythonList((QList<void*>*)data, innerType);
77 }
88 }
78 }
89 }
79
90
80 if (info.typeId >= QMetaType::User) {
91 if (info.typeId >= QMetaType::User) {
81 // if a converter is registered, we use is:
92 // if a converter is registered, we use is:
82 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
93 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
83 if (converter) {
94 if (converter) {
84 return (*converter)(data, info.typeId);
95 return (*converter)(data, info.typeId);
85 }
96 }
86 }
97 }
87
98
88 // special handling did not match, so we convert the usual way (either pointer or value version):
99 // special handling did not match, so we convert the usual way (either pointer or value version):
89 if (info.isPointer) {
100 if (info.isPointer) {
90 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
101 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
91 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
102 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
92 } else {
103 } else {
93 // handle values that are not yet handled and not pointers
104 // handle values that are not yet handled and not pointers
94 return ConvertQtValueToPythonInternal(info.typeId, data);
105 return ConvertQtValueToPythonInternal(info.typeId, data);
95 }
106 }
96 }
107 }
97
108
98 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
109 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
99 switch (type) {
110 switch (type) {
100 case QMetaType::Void:
111 case QMetaType::Void:
101 Py_INCREF(Py_None);
112 Py_INCREF(Py_None);
102 return Py_None;
113 return Py_None;
103 case QMetaType::Char:
114 case QMetaType::Char:
104 return PyInt_FromLong(*((char*)data));
115 return PyInt_FromLong(*((char*)data));
105 case QMetaType::UChar:
116 case QMetaType::UChar:
106 return PyInt_FromLong(*((unsigned char*)data));
117 return PyInt_FromLong(*((unsigned char*)data));
107 case QMetaType::Short:
118 case QMetaType::Short:
108 return PyInt_FromLong(*((short*)data));
119 return PyInt_FromLong(*((short*)data));
109 case QMetaType::UShort:
120 case QMetaType::UShort:
110 return PyInt_FromLong(*((unsigned short*)data));
121 return PyInt_FromLong(*((unsigned short*)data));
111 case QMetaType::Long:
122 case QMetaType::Long:
112 return PyInt_FromLong(*((long*)data));
123 return PyInt_FromLong(*((long*)data));
113 case QMetaType::ULong:
124 case QMetaType::ULong:
114 // does not fit into simple int of python
125 // does not fit into simple int of python
115 return PyLong_FromUnsignedLong(*((unsigned long*)data));
126 return PyLong_FromUnsignedLong(*((unsigned long*)data));
116 case QMetaType::Bool:
127 case QMetaType::Bool:
117 return PythonQtConv::GetPyBool(*((bool*)data));
128 return PythonQtConv::GetPyBool(*((bool*)data));
118 case QMetaType::Int:
129 case QMetaType::Int:
119 return PyInt_FromLong(*((int*)data));
130 return PyInt_FromLong(*((int*)data));
120 case QMetaType::UInt:
131 case QMetaType::UInt:
121 return PyInt_FromLong(*((unsigned int*)data));
132 return PyInt_FromLong(*((unsigned int*)data));
122 case QMetaType::QChar:
133 case QMetaType::QChar:
123 return PyInt_FromLong(*((short*)data));
134 return PyInt_FromLong(*((short*)data));
124 case QMetaType::Float:
135 case QMetaType::Float:
125 return PyFloat_FromDouble(*((float*)data));
136 return PyFloat_FromDouble(*((float*)data));
126 case QMetaType::Double:
137 case QMetaType::Double:
127 return PyFloat_FromDouble(*((double*)data));
138 return PyFloat_FromDouble(*((double*)data));
128 case QMetaType::LongLong:
139 case QMetaType::LongLong:
129 return PyLong_FromLongLong(*((qint64*)data));
140 return PyLong_FromLongLong(*((qint64*)data));
130 case QMetaType::ULongLong:
141 case QMetaType::ULongLong:
131 return PyLong_FromUnsignedLongLong(*((quint64*)data));
142 return PyLong_FromUnsignedLongLong(*((quint64*)data));
132 case QMetaType::QByteArray: {
143 case QMetaType::QByteArray: {
133 QByteArray* v = (QByteArray*) data;
144 QByteArray* v = (QByteArray*) data;
134 return PyString_FromStringAndSize(*v, v->size());
145 return PyString_FromStringAndSize(*v, v->size());
135 }
146 }
136 case QMetaType::QVariantMap:
147 case QMetaType::QVariantMap:
137 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
148 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
138 case QMetaType::QVariantList:
149 case QMetaType::QVariantList:
139 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
150 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
140 case QMetaType::QString:
151 case QMetaType::QString:
141 return PythonQtConv::QStringToPyObject(*((QString*)data));
152 return PythonQtConv::QStringToPyObject(*((QString*)data));
142 case QMetaType::QStringList:
153 case QMetaType::QStringList:
143 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
154 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
144
155
145 case PythonQtMethodInfo::Variant:
156 case PythonQtMethodInfo::Variant:
146 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
157 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
147 case QMetaType::QObjectStar:
158 case QMetaType::QObjectStar:
148 case QMetaType::QWidgetStar:
159 case QMetaType::QWidgetStar:
149 return PythonQt::priv()->wrapQObject(*((QObject**)data));
160 return PythonQt::priv()->wrapQObject(*((QObject**)data));
150
161
151 default:
162 default:
152 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
163 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
153 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
164 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
154 PyObject* o = ((PythonQtObjectPtr*)data)->object();
165 PyObject* o = ((PythonQtObjectPtr*)data)->object();
155 Py_INCREF(o);
166 Py_INCREF(o);
156 return o;
167 return o;
157 } else {
168 } else {
158 if (type > 0) {
169 if (type > 0) {
159 // if the type is known, we can construct it via QMetaType::construct
170 // if the type is known, we can construct it via QMetaType::construct
160 void* newCPPObject = QMetaType::construct(type, data);
171 void* newCPPObject = QMetaType::construct(type, data);
161 // XXX this could be optimized by using metatypeid directly
172 // XXX this could be optimized by using metatypeid directly
162 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
173 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
163 wrap->_ownedByPythonQt = true;
174 wrap->_ownedByPythonQt = true;
164 wrap->_useQMetaTypeDestroy = true;
175 wrap->_useQMetaTypeDestroy = true;
165 return (PyObject*)wrap;
176 return (PyObject*)wrap;
166 }
177 }
167 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
178 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
168 }
179 }
169 }
180 }
170 Py_INCREF(Py_None);
181 Py_INCREF(Py_None);
171 return Py_None;
182 return Py_None;
172 }
183 }
173
184
174 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
185 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
175 void* ptr = NULL;
186 void* ptr = NULL;
176 if (info.isPointer) {
187 if (info.isPointer) {
177 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
188 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
189 } else if (info.enumWrapper) {
190 // create enum return value
191 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
178 } else {
192 } else {
179 switch (info.typeId) {
193 switch (info.typeId) {
180 case QMetaType::Char:
194 case QMetaType::Char:
181 case QMetaType::UChar:
195 case QMetaType::UChar:
182 case QMetaType::Short:
196 case QMetaType::Short:
183 case QMetaType::UShort:
197 case QMetaType::UShort:
184 case QMetaType::Long:
198 case QMetaType::Long:
185 case QMetaType::ULong:
199 case QMetaType::ULong:
186 case QMetaType::Bool:
200 case QMetaType::Bool:
187 case QMetaType::Int:
201 case QMetaType::Int:
188 case QMetaType::UInt:
202 case QMetaType::UInt:
189 case QMetaType::QChar:
203 case QMetaType::QChar:
190 case QMetaType::Float:
204 case QMetaType::Float:
191 case QMetaType::Double:
205 case QMetaType::Double:
192 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
206 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
193 break;
207 break;
194 case PythonQtMethodInfo::Variant:
208 case PythonQtMethodInfo::Variant:
195 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
209 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
196 // return the ptr to the variant
210 // return the ptr to the variant
197 break;
211 break;
198 default:
212 default:
199 if (info.typeId == PythonQtMethodInfo::Unknown) {
213 if (info.typeId == PythonQtMethodInfo::Unknown) {
200 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
214 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
201 if (info.name.startsWith("QList<")) {
215 if (info.name.startsWith("QList<")) {
202 QByteArray innerType = info.name.mid(6,info.name.length()-7);
216 QByteArray innerType = info.name.mid(6,info.name.length()-7);
203 if (innerType.endsWith("*")) {
217 if (innerType.endsWith("*")) {
204 static int id = QMetaType::type("QList<void*>");
218 static int id = QMetaType::type("QList<void*>");
205 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
219 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
206 // return the constData pointer that will be filled with the result value later on
220 // return the constData pointer that will be filled with the result value later on
207 ptr = (void*)((QVariant*)ptr)->constData();
221 ptr = (void*)((QVariant*)ptr)->constData();
208 }
222 }
209 }
223 }
210 }
224 }
211
225
212 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
226 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
213 // everything else is stored in a QVariant, if we know the meta type...
227 // everything else is stored in a QVariant, if we know the meta type...
214 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
228 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
215 // return the constData pointer that will be filled with the result value later on
229 // return the constData pointer that will be filled with the result value later on
216 ptr = (void*)((QVariant*)ptr)->constData();
230 ptr = (void*)((QVariant*)ptr)->constData();
217 }
231 }
218 }
232 }
219 }
233 }
220 return ptr;
234 return ptr;
221 }
235 }
222
236
223 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
237 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
224 {
238 {
225 void* object;
239 void* object;
226 if (wrapper->classInfo()->isCPPWrapper()) {
240 if (wrapper->classInfo()->isCPPWrapper()) {
227 object = wrapper->_wrappedPtr;
241 object = wrapper->_wrappedPtr;
228 } else {
242 } else {
229 QObject* tmp = wrapper->_obj;
243 QObject* tmp = wrapper->_obj;
230 object = tmp;
244 object = tmp;
231 }
245 }
232 if (object) {
246 if (object) {
233 // if we can be upcasted to the given name, we pass the casted pointer in:
247 // if we can be upcasted to the given name, we pass the casted pointer in:
234 object = wrapper->classInfo()->castTo(object, className);
248 object = wrapper->classInfo()->castTo(object, className);
235 ok = object!=NULL;
249 ok = object!=NULL;
236 } else {
250 } else {
237 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
251 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
238 ok = wrapper->classInfo()->inherits(className);
252 ok = wrapper->classInfo()->inherits(className);
239 }
253 }
240 return object;
254 return object;
241 }
255 }
242
256
243 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
257 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
244 {
258 {
245 bool ok;
259 bool ok;
246 void* ptr = NULL;
260 void* ptr = NULL;
247 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
261 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
248 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
262 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
249 // (the Variant case is handled below in a switch)
263 // (the Variant case is handled below in a switch)
250
264
251 // a C++ wrapper (can be passed as pointer or reference)
265 // a C++ wrapper (can be passed as pointer or reference)
252 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
266 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
253 bool ok;
267 bool ok;
254 void* object = castWrapperTo(wrap, info.name, ok);
268 void* object = castWrapperTo(wrap, info.name, ok);
255 if (ok) {
269 if (ok) {
256 if (info.isPointer) {
270 if (info.isPointer) {
257 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
271 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
258 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
272 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
259 } else {
273 } else {
260 // store the wrapped pointer directly, since we are a reference
274 // store the wrapped pointer directly, since we are a reference
261 ptr = object;
275 ptr = object;
262 }
276 }
263 } else {
277 } else {
264 // not matching
278 // not matching
265 }
279 }
266 } else if (info.isPointer) {
280 } else if (info.isPointer) {
267 // a pointer
281 // a pointer
268 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
282 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
269 {
283 {
270 QString str = PyObjGetString(obj, strict, ok);
284 QString str = PyObjGetString(obj, strict, ok);
271 if (ok) {
285 if (ok) {
272 void* ptr2 = NULL;
286 void* ptr2 = NULL;
273 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
287 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
274 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
288 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
275 }
289 }
276 } else if (info.name == "PyObject") {
290 } else if (info.name == "PyObject") {
277 // handle low level PyObject directly
291 // handle low level PyObject directly
278 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
292 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
279 } else if (obj == Py_None) {
293 } else if (obj == Py_None) {
280 // None is treated as a NULL ptr
294 // None is treated as a NULL ptr
281 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
295 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
282 } else {
296 } else {
283 // if we are not strict, we try if we are passed a 0 integer
297 // if we are not strict, we try if we are passed a 0 integer
284 if (!strict) {
298 if (!strict) {
285 bool ok;
299 bool ok;
286 int value = PyObjGetInt(obj, true, ok);
300 int value = PyObjGetInt(obj, true, ok);
287 if (ok && value==0) {
301 if (ok && value==0) {
288 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
302 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
289 }
303 }
290 }
304 }
291 }
305 }
292 } else {
306 } else {
293 // not a pointer
307 // not a pointer
294 switch (info.typeId) {
308 switch (info.typeId) {
295 case QMetaType::Char:
309 case QMetaType::Char:
296 {
310 {
297 int val = PyObjGetInt(obj, strict, ok);
311 int val = PyObjGetInt(obj, strict, ok);
298 if (ok) {
312 if (ok) {
299 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
313 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
300 }
314 }
301 }
315 }
302 break;
316 break;
303 case QMetaType::UChar:
317 case QMetaType::UChar:
304 {
318 {
305 int val = PyObjGetInt(obj, strict, ok);
319 int val = PyObjGetInt(obj, strict, ok);
306 if (ok) {
320 if (ok) {
307 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
321 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
308 }
322 }
309 }
323 }
310 break;
324 break;
311 case QMetaType::Short:
325 case QMetaType::Short:
312 {
326 {
313 int val = PyObjGetInt(obj, strict, ok);
327 int val = PyObjGetInt(obj, strict, ok);
314 if (ok) {
328 if (ok) {
315 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
329 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
316 }
330 }
317 }
331 }
318 break;
332 break;
319 case QMetaType::UShort:
333 case QMetaType::UShort:
320 {
334 {
321 int val = PyObjGetInt(obj, strict, ok);
335 int val = PyObjGetInt(obj, strict, ok);
322 if (ok) {
336 if (ok) {
323 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
337 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
324 }
338 }
325 }
339 }
326 break;
340 break;
327 case QMetaType::Long:
341 case QMetaType::Long:
328 {
342 {
329 long val = (long)PyObjGetLongLong(obj, strict, ok);
343 long val = (long)PyObjGetLongLong(obj, strict, ok);
330 if (ok) {
344 if (ok) {
331 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
345 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
332 }
346 }
333 }
347 }
334 break;
348 break;
335 case QMetaType::ULong:
349 case QMetaType::ULong:
336 {
350 {
337 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
351 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
338 if (ok) {
352 if (ok) {
339 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
353 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
340 }
354 }
341 }
355 }
342 break;
356 break;
343 case QMetaType::Bool:
357 case QMetaType::Bool:
344 {
358 {
345 bool val = PyObjGetBool(obj, strict, ok);
359 bool val = PyObjGetBool(obj, strict, ok);
346 if (ok) {
360 if (ok) {
347 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
361 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
348 }
362 }
349 }
363 }
350 break;
364 break;
351 case QMetaType::Int:
365 case QMetaType::Int:
352 {
366 {
353 int val = PyObjGetInt(obj, strict, ok);
367 int val = PyObjGetInt(obj, strict, ok);
354 if (ok) {
368 if (ok) {
355 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
369 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
356 }
370 }
357 }
371 }
358 break;
372 break;
359 case QMetaType::UInt:
373 case QMetaType::UInt:
360 {
374 {
361 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
375 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
362 if (ok) {
376 if (ok) {
363 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
377 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
364 }
378 }
365 }
379 }
366 break;
380 break;
367 case QMetaType::QChar:
381 case QMetaType::QChar:
368 {
382 {
369 int val = PyObjGetInt(obj, strict, ok);
383 int val = PyObjGetInt(obj, strict, ok);
370 if (ok) {
384 if (ok) {
371 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
385 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
372 }
386 }
373 }
387 }
374 break;
388 break;
375 case QMetaType::Float:
389 case QMetaType::Float:
376 {
390 {
377 float val = (float)PyObjGetDouble(obj, strict, ok);
391 float val = (float)PyObjGetDouble(obj, strict, ok);
378 if (ok) {
392 if (ok) {
379 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
393 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
380 }
394 }
381 }
395 }
382 break;
396 break;
383 case QMetaType::Double:
397 case QMetaType::Double:
384 {
398 {
385 double val = (double)PyObjGetDouble(obj, strict, ok);
399 double val = (double)PyObjGetDouble(obj, strict, ok);
386 if (ok) {
400 if (ok) {
387 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
401 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
388 }
402 }
389 }
403 }
390 break;
404 break;
391 case QMetaType::LongLong:
405 case QMetaType::LongLong:
392 {
406 {
393 qint64 val = PyObjGetLongLong(obj, strict, ok);
407 qint64 val = PyObjGetLongLong(obj, strict, ok);
394 if (ok) {
408 if (ok) {
395 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
409 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
396 }
410 }
397 }
411 }
398 break;
412 break;
399 case QMetaType::ULongLong:
413 case QMetaType::ULongLong:
400 {
414 {
401 quint64 val = PyObjGetULongLong(obj, strict, ok);
415 quint64 val = PyObjGetULongLong(obj, strict, ok);
402 if (ok) {
416 if (ok) {
403 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
417 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
404 }
418 }
405 }
419 }
406 break;
420 break;
407 case QMetaType::QByteArray:
421 case QMetaType::QByteArray:
408 {
422 {
409 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
423 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
410 if (ok) {
424 if (ok) {
411 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
425 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
412 ptr = (void*)((QVariant*)ptr)->constData();
426 ptr = (void*)((QVariant*)ptr)->constData();
413 }
427 }
414 }
428 }
415 break;
429 break;
416 case QMetaType::QString:
430 case QMetaType::QString:
417 {
431 {
418 QString str = PyObjGetString(obj, strict, ok);
432 QString str = PyObjGetString(obj, strict, ok);
419 if (ok) {
433 if (ok) {
420 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
434 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
421 ptr = (void*)((QVariant*)ptr)->constData();
435 ptr = (void*)((QVariant*)ptr)->constData();
422 }
436 }
423 }
437 }
424 break;
438 break;
425 case QMetaType::QStringList:
439 case QMetaType::QStringList:
426 {
440 {
427 QStringList l = PyObjToStringList(obj, strict, ok);
441 QStringList l = PyObjToStringList(obj, strict, ok);
428 if (ok) {
442 if (ok) {
429 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
443 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
430 ptr = (void*)((QVariant*)ptr)->constData();
444 ptr = (void*)((QVariant*)ptr)->constData();
431 }
445 }
432 }
446 }
433 break;
447 break;
434
448
435 case PythonQtMethodInfo::Variant:
449 case PythonQtMethodInfo::Variant:
436 {
450 {
437 QVariant v = PyObjToQVariant(obj);
451 QVariant v = PyObjToQVariant(obj);
438 if (v.isValid()) {
452 if (v.isValid()) {
439 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
453 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
440 }
454 }
441 }
455 }
442 break;
456 break;
443 default:
457 default:
444 {
458 {
445 // check for enum case
459 // check for enum case
446 if (info.enumWrapper) {
460 if (info.enumWrapper) {
447 unsigned int val;
461 unsigned int val;
448 if ((PyObject*)obj->ob_type == info.enumWrapper) {
462 if ((PyObject*)obj->ob_type == info.enumWrapper) {
449 // we have a direct enum type match:
463 // we have a direct enum type match:
450 val = PyInt_AS_LONG(obj);
464 val = PyInt_AS_LONG(obj);
451 ok = true;
465 ok = true;
452 } else {
466 } else {
453 // we try to get an integer, and in strict mode, it may not be a derived int class, so that no other enum can be taken as an int
467 // we try to get an integer, and in strict mode, it may not be a derived int class, so that no other enum can be taken as an int
454 val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
468 val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
455 }
469 }
456 if (ok) {
470 if (ok) {
457 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
471 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
458 return ptr;
472 return ptr;
459 } else {
473 } else {
460 return NULL;
474 return NULL;
461 }
475 }
462 }
476 }
463
477
464 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
478 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
465 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
479 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
466 if (info.name.startsWith("QList<")) {
480 if (info.name.startsWith("QList<")) {
467 QByteArray innerType = info.name.mid(6,info.name.length()-7);
481 QByteArray innerType = info.name.mid(6,info.name.length()-7);
468 if (innerType.endsWith("*")) {
482 if (innerType.endsWith("*")) {
469 innerType.truncate(innerType.length()-1);
483 innerType.truncate(innerType.length()-1);
470 static int id = QMetaType::type("QList<void*>");
484 static int id = QMetaType::type("QList<void*>");
471 if (!alreadyAllocatedCPPObject) {
485 if (!alreadyAllocatedCPPObject) {
472 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
486 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
473 ptr = (void*)((QVariant*)ptr)->constData();
487 ptr = (void*)((QVariant*)ptr)->constData();
474 } else {
488 } else {
475 ptr = alreadyAllocatedCPPObject;
489 ptr = alreadyAllocatedCPPObject;
476 }
490 }
477 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
491 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
478 if (ok) {
492 if (ok) {
479 return ptr;
493 return ptr;
480 } else {
494 } else {
481 return NULL;
495 return NULL;
482 }
496 }
483 }
497 }
484 }
498 }
485 }
499 }
486
500
487 // We only do this for registered type > QMetaType::User for performance reasons.
501 // We only do this for registered type > QMetaType::User for performance reasons.
488 if (info.typeId >= QMetaType::User) {
502 if (info.typeId >= QMetaType::User) {
489 // Maybe we have a special converter that is registered for that type:
503 // Maybe we have a special converter that is registered for that type:
490 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
504 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
491 if (converter) {
505 if (converter) {
492 if (!alreadyAllocatedCPPObject) {
506 if (!alreadyAllocatedCPPObject) {
493 // create a new empty variant of concrete type:
507 // create a new empty variant of concrete type:
494 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
508 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
495 ptr = (void*)((QVariant*)ptr)->constData();
509 ptr = (void*)((QVariant*)ptr)->constData();
496 } else {
510 } else {
497 ptr = alreadyAllocatedCPPObject;
511 ptr = alreadyAllocatedCPPObject;
498 }
512 }
499 // now call the converter, passing the internal object of the variant
513 // now call the converter, passing the internal object of the variant
500 ok = (*converter)(obj, ptr, info.typeId, strict);
514 ok = (*converter)(obj, ptr, info.typeId, strict);
501 if (ok) {
515 if (ok) {
502 return ptr;
516 return ptr;
503 } else {
517 } else {
504 return NULL;
518 return NULL;
505 }
519 }
506 }
520 }
507 }
521 }
508 // if no type id is available, conversion to a QVariant makes no sense/is not possible
522 // if no type id is available, conversion to a QVariant makes no sense/is not possible
509 if (info.typeId != PythonQtMethodInfo::Unknown) {
523 if (info.typeId != PythonQtMethodInfo::Unknown) {
510 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
524 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
511 QVariant v = PyObjToQVariant(obj, info.typeId);
525 QVariant v = PyObjToQVariant(obj, info.typeId);
512 if (v.isValid()) {
526 if (v.isValid()) {
513 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
527 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
514 ptr = (void*)((QVariant*)ptr)->constData();
528 ptr = (void*)((QVariant*)ptr)->constData();
515 }
529 }
516 }
530 }
517 }
531 }
518 }
532 }
519 }
533 }
520 return ptr;
534 return ptr;
521 }
535 }
522
536
523
537
524 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
538 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
525 QStringList v;
539 QStringList v;
526 ok = false;
540 ok = false;
527 // if we are strict, we do not want to convert a string to a stringlist
541 // if we are strict, we do not want to convert a string to a stringlist
528 // (strings in python are detected to be sequences)
542 // (strings in python are detected to be sequences)
529 if (strict &&
543 if (strict &&
530 (val->ob_type == &PyString_Type ||
544 (val->ob_type == &PyString_Type ||
531 PyUnicode_Check(val))) {
545 PyUnicode_Check(val))) {
532 ok = false;
546 ok = false;
533 return v;
547 return v;
534 }
548 }
535 if (PySequence_Check(val)) {
549 if (PySequence_Check(val)) {
536 int count = PySequence_Size(val);
550 int count = PySequence_Size(val);
537 for (int i = 0;i<count;i++) {
551 for (int i = 0;i<count;i++) {
538 PyObject* value = PySequence_GetItem(val,i);
552 PyObject* value = PySequence_GetItem(val,i);
539 v.append(PyObjGetString(value,false,ok));
553 v.append(PyObjGetString(value,false,ok));
540 }
554 }
541 ok = true;
555 ok = true;
542 }
556 }
543 return v;
557 return v;
544 }
558 }
545
559
546 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
560 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
547 {
561 {
548 QString r;
562 QString r;
549 PyObject* str = PyObject_Repr(val);
563 PyObject* str = PyObject_Repr(val);
550 if (str) {
564 if (str) {
551 r = QString(PyString_AS_STRING(str));
565 r = QString(PyString_AS_STRING(str));
552 Py_DECREF(str);
566 Py_DECREF(str);
553 }
567 }
554 return r;
568 return r;
555 }
569 }
556
570
557 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
571 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
558 QString r;
572 QString r;
559 ok = true;
573 ok = true;
560 if (val->ob_type == &PyString_Type) {
574 if (val->ob_type == &PyString_Type) {
561 r = QString(PyString_AS_STRING(val));
575 r = QString(PyString_AS_STRING(val));
562 } else if (PyUnicode_Check(val)) {
576 } else if (PyUnicode_Check(val)) {
563 #ifdef WIN32
577 #ifdef WIN32
564 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
578 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
565 #else
579 #else
566 PyObject *ptmp = PyUnicode_AsUTF8String(val);
580 PyObject *ptmp = PyUnicode_AsUTF8String(val);
567 if(ptmp) {
581 if(ptmp) {
568 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
582 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
569 Py_DECREF(ptmp);
583 Py_DECREF(ptmp);
570 }
584 }
571 #endif
585 #endif
572 } else if (!strict) {
586 } else if (!strict) {
573 // EXTRA: could also use _Unicode, but why should we?
587 // EXTRA: could also use _Unicode, but why should we?
574 PyObject* str = PyObject_Str(val);
588 PyObject* str = PyObject_Str(val);
575 if (str) {
589 if (str) {
576 r = QString(PyString_AS_STRING(str));
590 r = QString(PyString_AS_STRING(str));
577 Py_DECREF(str);
591 Py_DECREF(str);
578 } else {
592 } else {
579 ok = false;
593 ok = false;
580 }
594 }
581 } else {
595 } else {
582 ok = false;
596 ok = false;
583 }
597 }
584 return r;
598 return r;
585 }
599 }
586
600
587 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
601 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
588 QByteArray r;
602 QByteArray r;
589 ok = true;
603 ok = true;
590 if (val->ob_type == &PyString_Type) {
604 if (val->ob_type == &PyString_Type) {
591 long size = PyString_GET_SIZE(val);
605 long size = PyString_GET_SIZE(val);
592 r = QByteArray(PyString_AS_STRING(val), size);
606 r = QByteArray(PyString_AS_STRING(val), size);
593 } else {
607 } else {
594 ok = false;
608 ok = false;
595 }
609 }
596 return r;
610 return r;
597 }
611 }
598
612
599 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
613 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
600 bool d = false;
614 bool d = false;
601 ok = false;
615 ok = false;
602 if (val == Py_False) {
616 if (val == Py_False) {
603 d = false;
617 d = false;
604 ok = true;
618 ok = true;
605 } else if (val == Py_True) {
619 } else if (val == Py_True) {
606 d = true;
620 d = true;
607 ok = true;
621 ok = true;
608 } else if (!strict) {
622 } else if (!strict) {
609 d = PyObjGetInt(val, false, ok)!=0;
623 d = PyObjGetInt(val, false, ok)!=0;
610 ok = true;
624 ok = true;
611 }
625 }
612 return d;
626 return d;
613 }
627 }
614
628
615 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
629 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
616 int d = 0;
630 int d = 0;
617 ok = true;
631 ok = true;
618 if (val->ob_type == &PyInt_Type) {
632 if (val->ob_type == &PyInt_Type) {
619 d = PyInt_AS_LONG(val);
633 d = PyInt_AS_LONG(val);
620 } else if (!strict) {
634 } else if (!strict) {
621 if (PyObject_TypeCheck(val, &PyInt_Type)) {
635 if (PyObject_TypeCheck(val, &PyInt_Type)) {
622 // support for derived int classes, e.g. for our enums
636 // support for derived int classes, e.g. for our enums
623 d = PyInt_AS_LONG(val);
637 d = PyInt_AS_LONG(val);
624 } else if (val->ob_type == &PyFloat_Type) {
638 } else if (val->ob_type == &PyFloat_Type) {
625 d = floor(PyFloat_AS_DOUBLE(val));
639 d = floor(PyFloat_AS_DOUBLE(val));
626 } else if (val->ob_type == &PyLong_Type) {
640 } else if (val->ob_type == &PyLong_Type) {
627 // handle error on overflow!
641 // handle error on overflow!
628 d = PyLong_AsLong(val);
642 d = PyLong_AsLong(val);
629 } else if (val == Py_False) {
643 } else if (val == Py_False) {
630 d = 0;
644 d = 0;
631 } else if (val == Py_True) {
645 } else if (val == Py_True) {
632 d = 1;
646 d = 1;
633 } else {
647 } else {
634 ok = false;
648 ok = false;
635 }
649 }
636 } else {
650 } else {
637 ok = false;
651 ok = false;
638 }
652 }
639 return d;
653 return d;
640 }
654 }
641
655
642 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
656 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
643 qint64 d = 0;
657 qint64 d = 0;
644 ok = true;
658 ok = true;
645 if (val->ob_type == &PyInt_Type) {
659 if (val->ob_type == &PyInt_Type) {
646 d = PyInt_AS_LONG(val);
660 d = PyInt_AS_LONG(val);
647 } else if (val->ob_type == &PyLong_Type) {
661 } else if (val->ob_type == &PyLong_Type) {
648 d = PyLong_AsLongLong(val);
662 d = PyLong_AsLongLong(val);
649 } else if (!strict) {
663 } else if (!strict) {
650 if (PyObject_TypeCheck(val, &PyInt_Type)) {
664 if (PyObject_TypeCheck(val, &PyInt_Type)) {
651 // support for derived int classes, e.g. for our enums
665 // support for derived int classes, e.g. for our enums
652 d = PyInt_AS_LONG(val);
666 d = PyInt_AS_LONG(val);
653 } else if (val->ob_type == &PyFloat_Type) {
667 } else if (val->ob_type == &PyFloat_Type) {
654 d = floor(PyFloat_AS_DOUBLE(val));
668 d = floor(PyFloat_AS_DOUBLE(val));
655 } else if (val == Py_False) {
669 } else if (val == Py_False) {
656 d = 0;
670 d = 0;
657 } else if (val == Py_True) {
671 } else if (val == Py_True) {
658 d = 1;
672 d = 1;
659 } else {
673 } else {
660 ok = false;
674 ok = false;
661 }
675 }
662 } else {
676 } else {
663 ok = false;
677 ok = false;
664 }
678 }
665 return d;
679 return d;
666 }
680 }
667
681
668 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
682 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
669 quint64 d = 0;
683 quint64 d = 0;
670 ok = true;
684 ok = true;
671 if (PyObject_TypeCheck(val, &PyInt_Type)) {
685 if (PyObject_TypeCheck(val, &PyInt_Type)) {
672 d = PyInt_AS_LONG(val);
686 d = PyInt_AS_LONG(val);
673 } else if (val->ob_type == &PyLong_Type) {
687 } else if (val->ob_type == &PyLong_Type) {
674 d = PyLong_AsLongLong(val);
688 d = PyLong_AsLongLong(val);
675 } else if (!strict) {
689 } else if (!strict) {
676 if (PyObject_TypeCheck(val, &PyInt_Type)) {
690 if (PyObject_TypeCheck(val, &PyInt_Type)) {
677 // support for derived int classes, e.g. for our enums
691 // support for derived int classes, e.g. for our enums
678 d = PyInt_AS_LONG(val);
692 d = PyInt_AS_LONG(val);
679 } else if (val->ob_type == &PyFloat_Type) {
693 } else if (val->ob_type == &PyFloat_Type) {
680 d = floor(PyFloat_AS_DOUBLE(val));
694 d = floor(PyFloat_AS_DOUBLE(val));
681 } else if (val == Py_False) {
695 } else if (val == Py_False) {
682 d = 0;
696 d = 0;
683 } else if (val == Py_True) {
697 } else if (val == Py_True) {
684 d = 1;
698 d = 1;
685 } else {
699 } else {
686 ok = false;
700 ok = false;
687 }
701 }
688 } else {
702 } else {
689 ok = false;
703 ok = false;
690 }
704 }
691 return d;
705 return d;
692 }
706 }
693
707
694 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
708 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
695 double d = 0;
709 double d = 0;
696 ok = true;
710 ok = true;
697 if (val->ob_type == &PyFloat_Type) {
711 if (val->ob_type == &PyFloat_Type) {
698 d = PyFloat_AS_DOUBLE(val);
712 d = PyFloat_AS_DOUBLE(val);
699 } else if (!strict) {
713 } else if (!strict) {
700 if (PyObject_TypeCheck(val, &PyInt_Type)) {
714 if (PyObject_TypeCheck(val, &PyInt_Type)) {
701 d = PyInt_AS_LONG(val);
715 d = PyInt_AS_LONG(val);
702 } else if (val->ob_type == &PyLong_Type) {
716 } else if (val->ob_type == &PyLong_Type) {
703 d = PyLong_AsLong(val);
717 d = PyLong_AsLong(val);
704 } else if (val == Py_False) {
718 } else if (val == Py_False) {
705 d = 0;
719 d = 0;
706 } else if (val == Py_True) {
720 } else if (val == Py_True) {
707 d = 1;
721 d = 1;
708 } else {
722 } else {
709 ok = false;
723 ok = false;
710 }
724 }
711 } else {
725 } else {
712 ok = false;
726 ok = false;
713 }
727 }
714 return d;
728 return d;
715 }
729 }
716
730
717 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
731 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
718 {
732 {
719 QVariant v;
733 QVariant v;
720 bool ok = true;
734 bool ok = true;
721
735
722 if (type==-1) {
736 if (type==-1) {
723 // no special type requested
737 // no special type requested
724 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
738 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
725 type = QVariant::String;
739 type = QVariant::String;
726 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
740 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
727 type = QVariant::Int;
741 type = QVariant::Int;
728 } else if (val->ob_type==&PyLong_Type) {
742 } else if (val->ob_type==&PyLong_Type) {
729 type = QVariant::LongLong;
743 type = QVariant::LongLong;
730 } else if (val->ob_type==&PyFloat_Type) {
744 } else if (val->ob_type==&PyFloat_Type) {
731 type = QVariant::Double;
745 type = QVariant::Double;
732 } else if (val == Py_False || val == Py_True) {
746 } else if (val == Py_False || val == Py_True) {
733 type = QVariant::Bool;
747 type = QVariant::Bool;
734 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
748 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
735 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
749 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
736 // c++ wrapper, check if the class names of the c++ objects match
750 // c++ wrapper, check if the class names of the c++ objects match
737 if (wrap->classInfo()->isCPPWrapper()) {
751 if (wrap->classInfo()->isCPPWrapper()) {
738 if (wrap->classInfo()->metaTypeId()>0) {
752 if (wrap->classInfo()->metaTypeId()>0) {
739 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
753 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
740 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
754 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
741 } else {
755 } else {
742 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
756 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
743 // the pointer here...
757 // the pointer here...
744 // is this worth anything? we loose the knowledge of the cpp object type
758 // is this worth anything? we loose the knowledge of the cpp object type
745 v = qVariantFromValue(wrap->_wrappedPtr);
759 v = qVariantFromValue(wrap->_wrappedPtr);
746 }
760 }
747 } else {
761 } else {
748 // this gives us a QObject pointer
762 // this gives us a QObject pointer
749 QObject* myObject = wrap->_obj;
763 QObject* myObject = wrap->_obj;
750 v = qVariantFromValue(myObject);
764 v = qVariantFromValue(myObject);
751 }
765 }
752 return v;
766 return v;
753 } else if (val->ob_type==&PyDict_Type) {
767 } else if (val->ob_type==&PyDict_Type) {
754 type = QVariant::Map;
768 type = QVariant::Map;
755 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
769 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
756 type = QVariant::List;
770 type = QVariant::List;
757 } else if (val == Py_None) {
771 } else if (val == Py_None) {
758 // none is invalid
772 // none is invalid
759 type = QVariant::Invalid;
773 type = QVariant::Invalid;
760 } else {
774 } else {
761 // this used to be:
775 // this used to be:
762 // type = QVariant::String;
776 // type = QVariant::String;
763 // but now we want to transport the Python Objects directly:
777 // but now we want to transport the Python Objects directly:
764 PythonQtObjectPtr o(val);
778 PythonQtObjectPtr o(val);
765 v = qVariantFromValue(o);
779 v = qVariantFromValue(o);
766 return v;
780 return v;
767 }
781 }
768 }
782 }
769 // special type request:
783 // special type request:
770 switch (type) {
784 switch (type) {
771 case QVariant::Invalid:
785 case QVariant::Invalid:
772 return v;
786 return v;
773 break;
787 break;
774 case QVariant::Int:
788 case QVariant::Int:
775 {
789 {
776 int d = PyObjGetInt(val, false, ok);
790 int d = PyObjGetInt(val, false, ok);
777 if (ok) return QVariant(d);
791 if (ok) return QVariant(d);
778 }
792 }
779 break;
793 break;
780 case QVariant::UInt:
794 case QVariant::UInt:
781 {
795 {
782 int d = PyObjGetInt(val, false,ok);
796 int d = PyObjGetInt(val, false,ok);
783 if (ok) v = QVariant((unsigned int)d);
797 if (ok) v = QVariant((unsigned int)d);
784 }
798 }
785 break;
799 break;
786 case QVariant::Bool:
800 case QVariant::Bool:
787 {
801 {
788 int d = PyObjGetBool(val,false,ok);
802 int d = PyObjGetBool(val,false,ok);
789 if (ok) v = QVariant((bool)(d!=0));
803 if (ok) v = QVariant((bool)(d!=0));
790 }
804 }
791 break;
805 break;
792 case QVariant::Double:
806 case QVariant::Double:
793 {
807 {
794 double d = PyObjGetDouble(val,false,ok);
808 double d = PyObjGetDouble(val,false,ok);
795 if (ok) v = QVariant(d);
809 if (ok) v = QVariant(d);
796 break;
810 break;
797 }
811 }
798 case QMetaType::Float:
812 case QMetaType::Float:
799 {
813 {
800 float d = (float) PyObjGetDouble(val,false,ok);
814 float d = (float) PyObjGetDouble(val,false,ok);
801 if (ok) v = qVariantFromValue(d);
815 if (ok) v = qVariantFromValue(d);
802 break;
816 break;
803 }
817 }
804 case QMetaType::Long:
818 case QMetaType::Long:
805 {
819 {
806 long d = (long) PyObjGetLongLong(val,false,ok);
820 long d = (long) PyObjGetLongLong(val,false,ok);
807 if (ok) v = qVariantFromValue(d);
821 if (ok) v = qVariantFromValue(d);
808 break;
822 break;
809 }
823 }
810 case QMetaType::ULong:
824 case QMetaType::ULong:
811 {
825 {
812 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
826 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
813 if (ok) v = qVariantFromValue(d);
827 if (ok) v = qVariantFromValue(d);
814 break;
828 break;
815 }
829 }
816 case QMetaType::Short:
830 case QMetaType::Short:
817 {
831 {
818 short d = (short) PyObjGetInt(val,false,ok);
832 short d = (short) PyObjGetInt(val,false,ok);
819 if (ok) v = qVariantFromValue(d);
833 if (ok) v = qVariantFromValue(d);
820 break;
834 break;
821 }
835 }
822 case QMetaType::UShort:
836 case QMetaType::UShort:
823 {
837 {
824 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
838 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
825 if (ok) v = qVariantFromValue(d);
839 if (ok) v = qVariantFromValue(d);
826 break;
840 break;
827 }
841 }
828 case QMetaType::Char:
842 case QMetaType::Char:
829 {
843 {
830 char d = (char) PyObjGetInt(val,false,ok);
844 char d = (char) PyObjGetInt(val,false,ok);
831 if (ok) v = qVariantFromValue(d);
845 if (ok) v = qVariantFromValue(d);
832 break;
846 break;
833 }
847 }
834 case QMetaType::UChar:
848 case QMetaType::UChar:
835 {
849 {
836 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
850 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
837 if (ok) v = qVariantFromValue(d);
851 if (ok) v = qVariantFromValue(d);
838 break;
852 break;
839 }
853 }
840
854
841 case QVariant::ByteArray:
855 case QVariant::ByteArray:
842 case QVariant::String:
856 case QVariant::String:
843 {
857 {
844 bool ok;
858 bool ok;
845 v = QVariant(PyObjGetString(val, false, ok));
859 v = QVariant(PyObjGetString(val, false, ok));
846 }
860 }
847 break;
861 break;
848
862
849 // these are important for MeVisLab
863 // these are important for MeVisLab
850 case QVariant::Map:
864 case QVariant::Map:
851 {
865 {
852 if (PyMapping_Check(val)) {
866 if (PyMapping_Check(val)) {
853 QMap<QString,QVariant> map;
867 QMap<QString,QVariant> map;
854 PyObject* items = PyMapping_Items(val);
868 PyObject* items = PyMapping_Items(val);
855 if (items) {
869 if (items) {
856 int count = PyList_Size(items);
870 int count = PyList_Size(items);
857 PyObject* value;
871 PyObject* value;
858 PyObject* key;
872 PyObject* key;
859 PyObject* tuple;
873 PyObject* tuple;
860 for (int i = 0;i<count;i++) {
874 for (int i = 0;i<count;i++) {
861 tuple = PyList_GetItem(items,i);
875 tuple = PyList_GetItem(items,i);
862 key = PyTuple_GetItem(tuple, 0);
876 key = PyTuple_GetItem(tuple, 0);
863 value = PyTuple_GetItem(tuple, 1);
877 value = PyTuple_GetItem(tuple, 1);
864 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
878 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
865 }
879 }
866 Py_DECREF(items);
880 Py_DECREF(items);
867 v = map;
881 v = map;
868 }
882 }
869 }
883 }
870 }
884 }
871 break;
885 break;
872 case QVariant::List:
886 case QVariant::List:
873 if (PySequence_Check(val)) {
887 if (PySequence_Check(val)) {
874 QVariantList list;
888 QVariantList list;
875 int count = PySequence_Size(val);
889 int count = PySequence_Size(val);
876 PyObject* value;
890 PyObject* value;
877 for (int i = 0;i<count;i++) {
891 for (int i = 0;i<count;i++) {
878 value = PySequence_GetItem(val,i);
892 value = PySequence_GetItem(val,i);
879 list.append(PyObjToQVariant(value, -1));
893 list.append(PyObjToQVariant(value, -1));
880 }
894 }
881 v = list;
895 v = list;
882 }
896 }
883 break;
897 break;
884 case QVariant::StringList:
898 case QVariant::StringList:
885 {
899 {
886 bool ok;
900 bool ok;
887 QStringList l = PyObjToStringList(val, false, ok);
901 QStringList l = PyObjToStringList(val, false, ok);
888 if (ok) {
902 if (ok) {
889 v = l;
903 v = l;
890 }
904 }
891 }
905 }
892 break;
906 break;
893
907
894 default:
908 default:
895 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
909 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
896 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
910 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
897 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
911 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
898 // construct a new variant from the C++ object if it has the same meta type
912 // construct a new variant from the C++ object if it has the same meta type
899 v = QVariant(type, wrap->_wrappedPtr);
913 v = QVariant(type, wrap->_wrappedPtr);
900 } else {
914 } else {
901 v = QVariant();
915 v = QVariant();
902 }
916 }
903 } else {
917 } else {
904 v = QVariant();
918 v = QVariant();
905 }
919 }
906 }
920 }
907 return v;
921 return v;
908 }
922 }
909
923
910 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
924 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
911 {
925 {
912 if (str.isNull()) {
926 if (str.isNull()) {
913 return PyString_FromString("");
927 return PyString_FromString("");
914 } else {
928 } else {
915 #ifdef WIN32
929 #ifdef WIN32
916 // return PyString_FromString(str.toLatin1().data());
930 // return PyString_FromString(str.toLatin1().data());
917 return PyUnicode_FromUnicode(str.utf16(), str.length());
931 return PyUnicode_FromUnicode(str.utf16(), str.length());
918 #else
932 #else
919 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
933 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
920 #endif
934 #endif
921 }
935 }
922 }
936 }
923
937
924 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
938 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
925 {
939 {
926 PyObject* result = PyTuple_New(list.count());
940 PyObject* result = PyTuple_New(list.count());
927 int i = 0;
941 int i = 0;
928 QString str;
942 QString str;
929 foreach (str, list) {
943 foreach (str, list) {
930 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
944 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
931 i++;
945 i++;
932 }
946 }
933 // why is the error state bad after this?
947 // why is the error state bad after this?
934 PyErr_Clear();
948 PyErr_Clear();
935 return result;
949 return result;
936 }
950 }
937
951
938 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
952 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
939 {
953 {
940 PyObject* result = PyList_New(list.count());
954 PyObject* result = PyList_New(list.count());
941 int i = 0;
955 int i = 0;
942 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
956 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
943 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
957 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
944 i++;
958 i++;
945 }
959 }
946 return result;
960 return result;
947 }
961 }
948
962
949 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
963 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
950 {
964 {
951 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
965 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
952 }
966 }
953
967
954 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
968 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
955 PyObject* result = PyDict_New();
969 PyObject* result = PyDict_New();
956 QVariantMap::const_iterator t = m.constBegin();
970 QVariantMap::const_iterator t = m.constBegin();
957 PyObject* key;
971 PyObject* key;
958 PyObject* val;
972 PyObject* val;
959 for (;t!=m.end();t++) {
973 for (;t!=m.end();t++) {
960 key = QStringToPyObject(t.key());
974 key = QStringToPyObject(t.key());
961 val = QVariantToPyObject(t.value());
975 val = QVariantToPyObject(t.value());
962 PyDict_SetItem(result, key, val);
976 PyDict_SetItem(result, key, val);
963 Py_DECREF(key);
977 Py_DECREF(key);
964 Py_DECREF(val);
978 Py_DECREF(val);
965 }
979 }
966 return result;
980 return result;
967 }
981 }
968
982
969 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
983 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
970 PyObject* result = PyTuple_New(l.count());
984 PyObject* result = PyTuple_New(l.count());
971 int i = 0;
985 int i = 0;
972 QVariant v;
986 QVariant v;
973 foreach (v, l) {
987 foreach (v, l) {
974 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
988 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
975 i++;
989 i++;
976 }
990 }
977 // why is the error state bad after this?
991 // why is the error state bad after this?
978 PyErr_Clear();
992 PyErr_Clear();
979 return result;
993 return result;
980 }
994 }
981
995
982 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
996 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
983 {
997 {
984 PyObject* result = PyTuple_New(list->count());
998 PyObject* result = PyTuple_New(list->count());
985 int i = 0;
999 int i = 0;
986 foreach (void* value, *list) {
1000 foreach (void* value, *list) {
987 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1001 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
988 i++;
1002 i++;
989 }
1003 }
990 return result;
1004 return result;
991 }
1005 }
992
1006
993 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1007 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
994 {
1008 {
995 bool result = false;
1009 bool result = false;
996 if (PySequence_Check(obj)) {
1010 if (PySequence_Check(obj)) {
997 result = true;
1011 result = true;
998 int count = PySequence_Size(obj);
1012 int count = PySequence_Size(obj);
999 PyObject* value;
1013 PyObject* value;
1000 for (int i = 0;i<count;i++) {
1014 for (int i = 0;i<count;i++) {
1001 value = PySequence_GetItem(obj,i);
1015 value = PySequence_GetItem(obj,i);
1002 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1016 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1003 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1017 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1004 bool ok;
1018 bool ok;
1005 void* object = castWrapperTo(wrap, type, ok);
1019 void* object = castWrapperTo(wrap, type, ok);
1006 if (ok) {
1020 if (ok) {
1007 list->append(object);
1021 list->append(object);
1008 } else {
1022 } else {
1009 result = false;
1023 result = false;
1010 break;
1024 break;
1011 }
1025 }
1012 }
1026 }
1013 }
1027 }
1014 }
1028 }
1015 return result;
1029 return result;
1016 }
1030 }
1017
1031
1018 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1032 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1019 {
1033 {
1020 int idx = typeName.indexOf("<");
1034 int idx = typeName.indexOf("<");
1021 if (idx>0) {
1035 if (idx>0) {
1022 int idx2 = typeName.indexOf(">");
1036 int idx2 = typeName.indexOf(">");
1023 if (idx2>0) {
1037 if (idx2>0) {
1024 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1038 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1025 return QMetaType::type(innerType.constData());
1039 return QMetaType::type(innerType.constData());
1026 }
1040 }
1027 }
1041 }
1028 return QMetaType::Void;
1042 return QMetaType::Void;
1029 }
1043 }
1030
1044
1031
1045
1032
1046
1033 QString PythonQtConv::qVariantToString(const QVariant& v) {
1047 QString PythonQtConv::qVariantToString(const QVariant& v) {
1034 return CPPObjectToString(v.userType(), v.constData());
1048 return CPPObjectToString(v.userType(), v.constData());
1035 }
1049 }
1036
1050
1037 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1051 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1038 QString r;
1052 QString r;
1039 switch (type) {
1053 switch (type) {
1040 case QVariant::Size: {
1054 case QVariant::Size: {
1041 const QSize* s = static_cast<const QSize*>(data);
1055 const QSize* s = static_cast<const QSize*>(data);
1042 r = QString::number(s->width()) + ", " + QString::number(s->height());
1056 r = QString::number(s->width()) + ", " + QString::number(s->height());
1043 }
1057 }
1044 break;
1058 break;
1045 case QVariant::SizeF: {
1059 case QVariant::SizeF: {
1046 const QSizeF* s = static_cast<const QSizeF*>(data);
1060 const QSizeF* s = static_cast<const QSizeF*>(data);
1047 r = QString::number(s->width()) + ", " + QString::number(s->height());
1061 r = QString::number(s->width()) + ", " + QString::number(s->height());
1048 }
1062 }
1049 break;
1063 break;
1050 case QVariant::Point: {
1064 case QVariant::Point: {
1051 const QPoint* s = static_cast<const QPoint*>(data);
1065 const QPoint* s = static_cast<const QPoint*>(data);
1052 r = QString::number(s->x()) + ", " + QString::number(s->y());
1066 r = QString::number(s->x()) + ", " + QString::number(s->y());
1053 }
1067 }
1054 break;
1068 break;
1055 case QVariant::PointF: {
1069 case QVariant::PointF: {
1056 const QPointF* s = static_cast<const QPointF*>(data);
1070 const QPointF* s = static_cast<const QPointF*>(data);
1057 r = QString::number(s->x()) + ", " + QString::number(s->y());
1071 r = QString::number(s->x()) + ", " + QString::number(s->y());
1058 }
1072 }
1059 break;
1073 break;
1060 case QVariant::Rect: {
1074 case QVariant::Rect: {
1061 const QRect* s = static_cast<const QRect*>(data);
1075 const QRect* s = static_cast<const QRect*>(data);
1062 r = QString::number(s->x()) + ", " + QString::number(s->y());
1076 r = QString::number(s->x()) + ", " + QString::number(s->y());
1063 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1077 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1064 }
1078 }
1065 break;
1079 break;
1066 case QVariant::RectF: {
1080 case QVariant::RectF: {
1067 const QRectF* s = static_cast<const QRectF*>(data);
1081 const QRectF* s = static_cast<const QRectF*>(data);
1068 r = QString::number(s->x()) + ", " + QString::number(s->y());
1082 r = QString::number(s->x()) + ", " + QString::number(s->y());
1069 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1083 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1070 }
1084 }
1071 break;
1085 break;
1072 case QVariant::Date: {
1086 case QVariant::Date: {
1073 const QDate* s = static_cast<const QDate*>(data);
1087 const QDate* s = static_cast<const QDate*>(data);
1074 r = s->toString(Qt::ISODate);
1088 r = s->toString(Qt::ISODate);
1075 }
1089 }
1076 break;
1090 break;
1077 case QVariant::DateTime: {
1091 case QVariant::DateTime: {
1078 const QDateTime* s = static_cast<const QDateTime*>(data);
1092 const QDateTime* s = static_cast<const QDateTime*>(data);
1079 r = s->toString(Qt::ISODate);
1093 r = s->toString(Qt::ISODate);
1080 }
1094 }
1081 break;
1095 break;
1082 case QVariant::Time: {
1096 case QVariant::Time: {
1083 const QTime* s = static_cast<const QTime*>(data);
1097 const QTime* s = static_cast<const QTime*>(data);
1084 r = s->toString(Qt::ISODate);
1098 r = s->toString(Qt::ISODate);
1085 }
1099 }
1086 break;
1100 break;
1087 case QVariant::Pixmap:
1101 case QVariant::Pixmap:
1088 {
1102 {
1089 const QPixmap* s = static_cast<const QPixmap*>(data);
1103 const QPixmap* s = static_cast<const QPixmap*>(data);
1090 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1104 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1091 }
1105 }
1092 break;
1106 break;
1093 case QVariant::Image:
1107 case QVariant::Image:
1094 {
1108 {
1095 const QImage* s = static_cast<const QImage*>(data);
1109 const QImage* s = static_cast<const QImage*>(data);
1096 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1110 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1097 }
1111 }
1098 break;
1112 break;
1099 case QVariant::Url:
1113 case QVariant::Url:
1100 {
1114 {
1101 const QUrl* s = static_cast<const QUrl*>(data);
1115 const QUrl* s = static_cast<const QUrl*>(data);
1102 r = s->toString();
1116 r = s->toString();
1103 }
1117 }
1104 break;
1118 break;
1105 //TODO: add more printing for other variant types
1119 //TODO: add more printing for other variant types
1106 default:
1120 default:
1107 // this creates a copy, but that should not be expensive for typical simple variants
1121 // this creates a copy, but that should not be expensive for typical simple variants
1108 // (but we do not want to do this for our won user types!
1122 // (but we do not want to do this for our won user types!
1109 if (type>0 && type < (int)QVariant::UserType) {
1123 if (type>0 && type < (int)QVariant::UserType) {
1110 QVariant v(type, data);
1124 QVariant v(type, data);
1111 r = v.toString();
1125 r = v.toString();
1112 }
1126 }
1113 }
1127 }
1114 return r;
1128 return r;
1115 }
1129 }
@@ -1,513 +1,500
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtSlot.cpp
35 // \file PythonQtSlot.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 "PythonQtSlot.h"
43 #include "PythonQtSlot.h"
44 #include "PythonQtInstanceWrapper.h"
44 #include "PythonQtInstanceWrapper.h"
45 #include "PythonQtClassInfo.h"
45 #include "PythonQtClassInfo.h"
46 #include "PythonQtMisc.h"
46 #include "PythonQtMisc.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include <iostream>
48 #include <iostream>
49
49
50 #define PYTHONQT_MAX_ARGS 32
50 #define PYTHONQT_MAX_ARGS 32
51
51
52
52
53 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
53 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
54 {
54 {
55 static unsigned int recursiveEntry = 0;
55 static unsigned int recursiveEntry = 0;
56
56
57 if (directReturnValuePointer) {
57 if (directReturnValuePointer) {
58 *directReturnValuePointer = NULL;
58 *directReturnValuePointer = NULL;
59 }
59 }
60 // store the current storage position, so that we can get back to this state after a slot is called
60 // store the current storage position, so that we can get back to this state after a slot is called
61 // (do this locally, so that we have all positions on the stack
61 // (do this locally, so that we have all positions on the stack
62 PythonQtValueStoragePosition globalValueStoragePos;
62 PythonQtValueStoragePosition globalValueStoragePos;
63 PythonQtValueStoragePosition globalPtrStoragePos;
63 PythonQtValueStoragePosition globalPtrStoragePos;
64 PythonQtValueStoragePosition globalVariantStoragePos;
64 PythonQtValueStoragePosition globalVariantStoragePos;
65 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
65 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
66 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
66 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
67 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
67 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
68
68
69 recursiveEntry++;
69 recursiveEntry++;
70
70
71 // the arguments that are passed to qt_metacall
71 // the arguments that are passed to qt_metacall
72 void* argList[PYTHONQT_MAX_ARGS];
72 void* argList[PYTHONQT_MAX_ARGS];
73 PyObject* result = NULL;
73 PyObject* result = NULL;
74 int argc = info->parameterCount();
74 int argc = info->parameterCount();
75 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
75 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
76
76
77 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
77 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
78 // set return argument to NULL
78 // set return argument to NULL
79 argList[0] = NULL;
79 argList[0] = NULL;
80
80
81 bool ok = true;
81 bool ok = true;
82 bool skipFirst = false;
82 bool skipFirst = false;
83 if (info->isInstanceDecorator()) {
83 if (info->isInstanceDecorator()) {
84 skipFirst = true;
84 skipFirst = true;
85
85
86 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
86 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
87 void* arg1 = firstArgument;
87 void* arg1 = firstArgument;
88 if (!arg1) {
88 if (!arg1) {
89 arg1 = objectToCall;
89 arg1 = objectToCall;
90 }
90 }
91 if (arg1) {
91 if (arg1) {
92 // upcast to correct parent class
92 // upcast to correct parent class
93 arg1 = ((char*)arg1)+info->upcastingOffset();
93 arg1 = ((char*)arg1)+info->upcastingOffset();
94 }
94 }
95
95
96 argList[1] = &arg1;
96 argList[1] = &arg1;
97 if (ok) {
97 if (ok) {
98 for (int i = 2; i<argc && ok; i++) {
98 for (int i = 2; i<argc && ok; i++) {
99 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
99 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
100 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
100 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
101 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
101 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
102 if (argList[i]==NULL) {
102 if (argList[i]==NULL) {
103 ok = false;
103 ok = false;
104 break;
104 break;
105 }
105 }
106 }
106 }
107 }
107 }
108 } else {
108 } else {
109 for (int i = 1; i<argc && ok; i++) {
109 for (int i = 1; i<argc && ok; i++) {
110 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
110 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
111 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
111 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
112 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
112 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
113 if (argList[i]==NULL) {
113 if (argList[i]==NULL) {
114 ok = false;
114 ok = false;
115 break;
115 break;
116 }
116 }
117 }
117 }
118 }
118 }
119
119
120 if (ok) {
120 if (ok) {
121 bool returnValueIsEnum = false;
122
123 // parameters are ok, now create the qt return value which is assigned to by metacall
121 // parameters are ok, now create the qt return value which is assigned to by metacall
124 if (returnValueParam.typeId != QMetaType::Void) {
122 if (returnValueParam.typeId != QMetaType::Void) {
125 // extra handling of enum return value
126 if (!returnValueParam.isPointer && returnValueParam.enumWrapper) {
127 // create enum return value
128 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
129 returnValueIsEnum = true;
130 } else {
131 // create empty default value for the return value
123 // create empty default value for the return value
132 if (!directReturnValuePointer) {
124 if (!directReturnValuePointer) {
133 // create empty default value for the return value
125 // create empty default value for the return value
134 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
126 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
135 if (argList[0]==NULL) {
127 if (argList[0]==NULL) {
136 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
128 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
137 // pass its internal pointer
129 // pass its internal pointer
138 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
130 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
139 if (info && info->pythonQtClassWrapper()) {
131 if (info && info->pythonQtClassWrapper()) {
140 PyObject* emptyTuple = PyTuple_New(0);
132 PyObject* emptyTuple = PyTuple_New(0);
141 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
133 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
142 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
134 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
143 if (result) {
135 if (result) {
144 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
136 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
145 }
137 }
146 Py_DECREF(emptyTuple);
138 Py_DECREF(emptyTuple);
147 }
139 }
148 }
140 }
149 } else {
141 } else {
150 // we can use our pointer directly!
142 // we can use our pointer directly!
151 argList[0] = directReturnValuePointer;
143 argList[0] = directReturnValuePointer;
152 }
144 }
153 }
145 }
154 }
155
146
156 // invoke the slot via metacall
147 // invoke the slot via metacall
157 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
148 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
158
149
159 // handle the return value (which in most cases still needs to be converted to a Python object)
150 // handle the return value (which in most cases still needs to be converted to a Python object)
160 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
151 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
161 if (directReturnValuePointer) {
152 if (directReturnValuePointer) {
162 result = NULL;
153 result = NULL;
163 } else {
154 } else {
164 if (!returnValueIsEnum) {
165 // the resulting object maybe present already, because we created it above at 1)...
155 // the resulting object maybe present already, because we created it above at 1)...
166 if (!result) {
156 if (!result) {
167 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
157 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
168 }
158 }
169 } else {
170 result = PyInt_FromLong(*((unsigned int*)argList[0]));
171 }
172 }
159 }
173 } else {
160 } else {
174 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
161 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
175 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
162 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
176 result = NULL;
163 result = NULL;
177 }
164 }
178 }
165 }
179 recursiveEntry--;
166 recursiveEntry--;
180
167
181 // reset the parameter storage position to the stored pos to "pop" the parameter stack
168 // reset the parameter storage position to the stored pos to "pop" the parameter stack
182 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
169 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
183 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
170 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
184 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
171 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
185
172
186 *pythonReturnValue = result;
173 *pythonReturnValue = result;
187 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
174 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
188 return result || (directReturnValuePointer && *directReturnValuePointer);
175 return result || (directReturnValuePointer && *directReturnValuePointer);
189 }
176 }
190
177
191 //-----------------------------------------------------------------------------------
178 //-----------------------------------------------------------------------------------
192
179
193 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
180 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
194
181
195 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
182 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
196 {
183 {
197 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
184 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
198 PythonQtSlotInfo* info = f->m_ml;
185 PythonQtSlotInfo* info = f->m_ml;
199 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
186 if (PyObject_TypeCheck(f->m_self, &PythonQtInstanceWrapper_Type)) {
200 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
187 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) f->m_self;
201 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
188 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
202 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
189 } else if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
203 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
190 PythonQtClassWrapper* type = (PythonQtClassWrapper*) f->m_self;
204 if (info->isClassDecorator()) {
191 if (info->isClassDecorator()) {
205 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
192 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
206 } else {
193 } else {
207 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
194 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
208 Py_ssize_t argc = PyTuple_Size(args);
195 Py_ssize_t argc = PyTuple_Size(args);
209 if (argc>0) {
196 if (argc>0) {
210 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
197 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
211 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
198 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
212 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
199 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
213 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
200 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
214 // strip the first argument...
201 // strip the first argument...
215 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
202 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
216 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
203 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
217 Py_DECREF(newargs);
204 Py_DECREF(newargs);
218 return result;
205 return result;
219 } else {
206 } else {
220 // first arg is not of correct type!
207 // first arg is not of correct type!
221 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
208 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
222 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
209 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
223 return NULL;
210 return NULL;
224 }
211 }
225 } else {
212 } else {
226 // wrong number of args
213 // wrong number of args
227 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
214 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
228 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
215 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
229 return NULL;
216 return NULL;
230 }
217 }
231 }
218 }
232 }
219 }
233 return NULL;
220 return NULL;
234 }
221 }
235
222
236 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
223 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
237 {
224 {
238 int argc = PyTuple_Size(args);
225 int argc = PyTuple_Size(args);
239
226
240 #ifdef PYTHONQT_DEBUG
227 #ifdef PYTHONQT_DEBUG
241 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
228 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
242 #endif
229 #endif
243
230
244 PyObject* r = NULL;
231 PyObject* r = NULL;
245 bool ok = false;
232 bool ok = false;
246 if (directReturnValuePointer) {
233 if (directReturnValuePointer) {
247 *directReturnValuePointer = NULL;
234 *directReturnValuePointer = NULL;
248 }
235 }
249 if (info->nextInfo()) {
236 if (info->nextInfo()) {
250 // overloaded slot call, try on all slots with strict conversion first
237 // overloaded slot call, try on all slots with strict conversion first
251 bool strict = true;
238 bool strict = true;
252 PythonQtSlotInfo* i = info;
239 PythonQtSlotInfo* i = info;
253 while (i) {
240 while (i) {
254 bool skipFirst = i->isInstanceDecorator();
241 bool skipFirst = i->isInstanceDecorator();
255 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
242 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
256 PyErr_Clear();
243 PyErr_Clear();
257 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
244 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
258 if (PyErr_Occurred() || ok) break;
245 if (PyErr_Occurred() || ok) break;
259 }
246 }
260 i = i->nextInfo();
247 i = i->nextInfo();
261 if (!i) {
248 if (!i) {
262 if (strict) {
249 if (strict) {
263 // one more run without being strict
250 // one more run without being strict
264 strict = false;
251 strict = false;
265 i = info;
252 i = info;
266 }
253 }
267 }
254 }
268 }
255 }
269 if (!ok && !PyErr_Occurred()) {
256 if (!ok && !PyErr_Occurred()) {
270 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
257 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
271 PythonQtSlotInfo* i = info;
258 PythonQtSlotInfo* i = info;
272 while (i) {
259 while (i) {
273 e += QString(i->fullSignature()) + "\n";
260 e += QString(i->fullSignature()) + "\n";
274 i = i->nextInfo();
261 i = i->nextInfo();
275 }
262 }
276 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
263 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
277 }
264 }
278 } else {
265 } else {
279 // simple (non-overloaded) slot call
266 // simple (non-overloaded) slot call
280 bool skipFirst = info->isInstanceDecorator();
267 bool skipFirst = info->isInstanceDecorator();
281 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
268 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
282 PyErr_Clear();
269 PyErr_Clear();
283 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
270 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
284 if (!ok && !PyErr_Occurred()) {
271 if (!ok && !PyErr_Occurred()) {
285 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
272 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
286 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
273 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
287 }
274 }
288 } else {
275 } else {
289 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
276 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
290 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
277 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
291 }
278 }
292 }
279 }
293
280
294 return r;
281 return r;
295 }
282 }
296
283
297 PyObject *
284 PyObject *
298 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
285 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
299 {
286 {
300 PythonQtSlotFunctionObject *op;
287 PythonQtSlotFunctionObject *op;
301 op = pythonqtslot_free_list;
288 op = pythonqtslot_free_list;
302 if (op != NULL) {
289 if (op != NULL) {
303 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
290 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
304 PyObject_INIT(op, &PythonQtSlotFunction_Type);
291 PyObject_INIT(op, &PythonQtSlotFunction_Type);
305 }
292 }
306 else {
293 else {
307 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
294 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
308 if (op == NULL)
295 if (op == NULL)
309 return NULL;
296 return NULL;
310 }
297 }
311 op->m_ml = ml;
298 op->m_ml = ml;
312 Py_XINCREF(self);
299 Py_XINCREF(self);
313 op->m_self = self;
300 op->m_self = self;
314 Py_XINCREF(module);
301 Py_XINCREF(module);
315 op->m_module = module;
302 op->m_module = module;
316 PyObject_GC_Track(op);
303 PyObject_GC_Track(op);
317 return (PyObject *)op;
304 return (PyObject *)op;
318 }
305 }
319
306
320 PythonQtSlotInfo*
307 PythonQtSlotInfo*
321 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
308 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
322 {
309 {
323 if (!PythonQtSlotFunction_Check(op)) {
310 if (!PythonQtSlotFunction_Check(op)) {
324 PyErr_BadInternalCall();
311 PyErr_BadInternalCall();
325 return NULL;
312 return NULL;
326 }
313 }
327 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
314 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
328 }
315 }
329
316
330 PyObject *
317 PyObject *
331 PythonQtSlotFunction_GetSelf(PyObject *op)
318 PythonQtSlotFunction_GetSelf(PyObject *op)
332 {
319 {
333 if (!PythonQtSlotFunction_Check(op)) {
320 if (!PythonQtSlotFunction_Check(op)) {
334 PyErr_BadInternalCall();
321 PyErr_BadInternalCall();
335 return NULL;
322 return NULL;
336 }
323 }
337 return ((PythonQtSlotFunctionObject *)op) -> m_self;
324 return ((PythonQtSlotFunctionObject *)op) -> m_self;
338 }
325 }
339
326
340 /* Methods (the standard built-in methods, that is) */
327 /* Methods (the standard built-in methods, that is) */
341
328
342 static void
329 static void
343 meth_dealloc(PythonQtSlotFunctionObject *m)
330 meth_dealloc(PythonQtSlotFunctionObject *m)
344 {
331 {
345 PyObject_GC_UnTrack(m);
332 PyObject_GC_UnTrack(m);
346 Py_XDECREF(m->m_self);
333 Py_XDECREF(m->m_self);
347 Py_XDECREF(m->m_module);
334 Py_XDECREF(m->m_module);
348 m->m_self = (PyObject *)pythonqtslot_free_list;
335 m->m_self = (PyObject *)pythonqtslot_free_list;
349 pythonqtslot_free_list = m;
336 pythonqtslot_free_list = m;
350 }
337 }
351
338
352 static PyObject *
339 static PyObject *
353 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
340 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
354 {
341 {
355 Py_INCREF(Py_None);
342 Py_INCREF(Py_None);
356 return Py_None;
343 return Py_None;
357 }
344 }
358
345
359 static PyObject *
346 static PyObject *
360 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
347 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
361 {
348 {
362 return PyString_FromString(m->m_ml->metaMethod()->signature());
349 return PyString_FromString(m->m_ml->metaMethod()->signature());
363 }
350 }
364
351
365 static int
352 static int
366 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
353 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
367 {
354 {
368 int err;
355 int err;
369 if (m->m_self != NULL) {
356 if (m->m_self != NULL) {
370 err = visit(m->m_self, arg);
357 err = visit(m->m_self, arg);
371 if (err)
358 if (err)
372 return err;
359 return err;
373 }
360 }
374 if (m->m_module != NULL) {
361 if (m->m_module != NULL) {
375 err = visit(m->m_module, arg);
362 err = visit(m->m_module, arg);
376 if (err)
363 if (err)
377 return err;
364 return err;
378 }
365 }
379 return 0;
366 return 0;
380 }
367 }
381
368
382 static PyObject *
369 static PyObject *
383 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
370 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
384 {
371 {
385 PyObject *self;
372 PyObject *self;
386 if (PyEval_GetRestricted()) {
373 if (PyEval_GetRestricted()) {
387 PyErr_SetString(PyExc_RuntimeError,
374 PyErr_SetString(PyExc_RuntimeError,
388 "method.__self__ not accessible in restricted mode");
375 "method.__self__ not accessible in restricted mode");
389 return NULL;
376 return NULL;
390 }
377 }
391 self = m->m_self;
378 self = m->m_self;
392 if (self == NULL)
379 if (self == NULL)
393 self = Py_None;
380 self = Py_None;
394 Py_INCREF(self);
381 Py_INCREF(self);
395 return self;
382 return self;
396 }
383 }
397
384
398 static PyGetSetDef meth_getsets [] = {
385 static PyGetSetDef meth_getsets [] = {
399 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
386 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
400 {"__name__", (getter)meth_get__name__, NULL, NULL},
387 {"__name__", (getter)meth_get__name__, NULL, NULL},
401 {"__self__", (getter)meth_get__self__, NULL, NULL},
388 {"__self__", (getter)meth_get__self__, NULL, NULL},
402 {NULL, NULL, NULL,NULL},
389 {NULL, NULL, NULL,NULL},
403 };
390 };
404
391
405 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
392 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
406 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
393 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
407 #endif
394 #endif
408
395
409 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
396 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
410
397
411 static PyMemberDef meth_members[] = {
398 static PyMemberDef meth_members[] = {
412 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
399 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
413 {NULL}
400 {NULL}
414 };
401 };
415
402
416 static PyObject *
403 static PyObject *
417 meth_repr(PythonQtSlotFunctionObject *f)
404 meth_repr(PythonQtSlotFunctionObject *f)
418 {
405 {
419 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
406 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
420 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
407 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
421 return PyString_FromFormat("<unbound qt slot %s of %s type>",
408 return PyString_FromFormat("<unbound qt slot %s of %s type>",
422 f->m_ml->slotName().data(),
409 f->m_ml->slotName().data(),
423 self->classInfo()->className());
410 self->classInfo()->className());
424 } else {
411 } else {
425 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
412 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
426 f->m_ml->slotName().data(),
413 f->m_ml->slotName().data(),
427 f->m_self->ob_type->tp_name,
414 f->m_self->ob_type->tp_name,
428 f->m_self);
415 f->m_self);
429 }
416 }
430 }
417 }
431
418
432 static int
419 static int
433 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
420 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
434 {
421 {
435 if (a->m_self != b->m_self)
422 if (a->m_self != b->m_self)
436 return (a->m_self < b->m_self) ? -1 : 1;
423 return (a->m_self < b->m_self) ? -1 : 1;
437 if (a->m_ml == b->m_ml)
424 if (a->m_ml == b->m_ml)
438 return 0;
425 return 0;
439 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
426 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
440 return -1;
427 return -1;
441 else
428 else
442 return 1;
429 return 1;
443 }
430 }
444
431
445 static long
432 static long
446 meth_hash(PythonQtSlotFunctionObject *a)
433 meth_hash(PythonQtSlotFunctionObject *a)
447 {
434 {
448 long x,y;
435 long x,y;
449 if (a->m_self == NULL)
436 if (a->m_self == NULL)
450 x = 0;
437 x = 0;
451 else {
438 else {
452 x = PyObject_Hash(a->m_self);
439 x = PyObject_Hash(a->m_self);
453 if (x == -1)
440 if (x == -1)
454 return -1;
441 return -1;
455 }
442 }
456 y = _Py_HashPointer((void*)(a->m_ml));
443 y = _Py_HashPointer((void*)(a->m_ml));
457 if (y == -1)
444 if (y == -1)
458 return -1;
445 return -1;
459 x ^= y;
446 x ^= y;
460 if (x == -1)
447 if (x == -1)
461 x = -2;
448 x = -2;
462 return x;
449 return x;
463 }
450 }
464
451
465
452
466 PyTypeObject PythonQtSlotFunction_Type = {
453 PyTypeObject PythonQtSlotFunction_Type = {
467 PyObject_HEAD_INIT(&PyType_Type)
454 PyObject_HEAD_INIT(&PyType_Type)
468 0,
455 0,
469 "builtin_qt_slot",
456 "builtin_qt_slot",
470 sizeof(PythonQtSlotFunctionObject),
457 sizeof(PythonQtSlotFunctionObject),
471 0,
458 0,
472 (destructor)meth_dealloc, /* tp_dealloc */
459 (destructor)meth_dealloc, /* tp_dealloc */
473 0, /* tp_print */
460 0, /* tp_print */
474 0, /* tp_getattr */
461 0, /* tp_getattr */
475 0, /* tp_setattr */
462 0, /* tp_setattr */
476 (cmpfunc)meth_compare, /* tp_compare */
463 (cmpfunc)meth_compare, /* tp_compare */
477 (reprfunc)meth_repr, /* tp_repr */
464 (reprfunc)meth_repr, /* tp_repr */
478 0, /* tp_as_number */
465 0, /* tp_as_number */
479 0, /* tp_as_sequence */
466 0, /* tp_as_sequence */
480 0, /* tp_as_mapping */
467 0, /* tp_as_mapping */
481 (hashfunc)meth_hash, /* tp_hash */
468 (hashfunc)meth_hash, /* tp_hash */
482 PythonQtSlotFunction_Call, /* tp_call */
469 PythonQtSlotFunction_Call, /* tp_call */
483 0, /* tp_str */
470 0, /* tp_str */
484 PyObject_GenericGetAttr, /* tp_getattro */
471 PyObject_GenericGetAttr, /* tp_getattro */
485 0, /* tp_setattro */
472 0, /* tp_setattro */
486 0, /* tp_as_buffer */
473 0, /* tp_as_buffer */
487 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
474 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
488 0, /* tp_doc */
475 0, /* tp_doc */
489 (traverseproc)meth_traverse, /* tp_traverse */
476 (traverseproc)meth_traverse, /* tp_traverse */
490 0, /* tp_clear */
477 0, /* tp_clear */
491 0, /* tp_richcompare */
478 0, /* tp_richcompare */
492 0, /* tp_weaklistoffset */
479 0, /* tp_weaklistoffset */
493 0, /* tp_iter */
480 0, /* tp_iter */
494 0, /* tp_iternext */
481 0, /* tp_iternext */
495 0, /* tp_methods */
482 0, /* tp_methods */
496 meth_members, /* tp_members */
483 meth_members, /* tp_members */
497 meth_getsets, /* tp_getset */
484 meth_getsets, /* tp_getset */
498 0, /* tp_base */
485 0, /* tp_base */
499 0, /* tp_dict */
486 0, /* tp_dict */
500 };
487 };
501
488
502 /* Clear out the free list */
489 /* Clear out the free list */
503
490
504 void
491 void
505 PythonQtSlotFunction_Fini(void)
492 PythonQtSlotFunction_Fini(void)
506 {
493 {
507 while (pythonqtslot_free_list) {
494 while (pythonqtslot_free_list) {
508 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
495 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
509 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
496 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
510 PyObject_GC_Del(v);
497 PyObject_GC_Del(v);
511 }
498 }
512 }
499 }
513
500
General Comments 0
You need to be logged in to leave comments. Login now