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