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