##// END OF EJS Templates
- added call method that does a direct call on the ObjectType...
florianlink -
r36:1d1e7c03e848
parent child
Show More
@@ -1,1181 +1,1189
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) {
279 bool PythonQtPrivate::isEnumType(const QMetaObject* meta, const QByteArray& name) {
280 int i = meta?meta->indexOfEnumerator(name.constData()):-1;
280 int i = meta?meta->indexOfEnumerator(name.constData()):-1;
281 if (i!=-1) {
281 if (i!=-1) {
282 return true;
282 return true;
283 } else {
283 } else {
284 // look for scope
284 // look for scope
285 int scopePos = name.indexOf("::");
285 int scopePos = name.indexOf("::");
286 if (scopePos != -1) {
286 if (scopePos != -1) {
287 // slit into scope and enum name
287 // slit into scope and enum name
288 QByteArray enumScope = name.mid(0,scopePos);
288 QByteArray enumScope = name.mid(0,scopePos);
289 QByteArray enumName = name.mid(scopePos+2);
289 QByteArray enumName = name.mid(scopePos+2);
290 if (enumScope == "Qt") {
290 if (enumScope == "Qt") {
291 // special qt namespace case
291 // special qt namespace case
292 return isEnumType(&staticQtMetaObject, enumName);
292 return isEnumType(&staticQtMetaObject, enumName);
293 } else {
293 } else {
294 // look for known classes as scope
294 // look for known classes as scope
295 // TODO: Q_GADGETS are not yet handled
295 // TODO: Q_GADGETS are not yet handled
296 PythonQtClassInfo* info = _knownClassInfos.value(enumScope);
296 PythonQtClassInfo* info = _knownClassInfos.value(enumScope);
297 if (info) {
297 if (info) {
298 return isEnumType(info->metaObject(), enumName);
298 return isEnumType(info->metaObject(), enumName);
299 }
299 }
300 }
300 }
301 }
301 }
302 }
302 }
303 return false;
303 return false;
304 }
304 }
305
305
306 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
306 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
307 {
307 {
308 if (!obj) {
308 if (!obj) {
309 Py_INCREF(Py_None);
309 Py_INCREF(Py_None);
310 return Py_None;
310 return Py_None;
311 }
311 }
312 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
312 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
313 if (!wrap) {
313 if (!wrap) {
314 // smuggling it in...
314 // smuggling it in...
315 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
315 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
316 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
316 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
317 registerClass(obj->metaObject());
317 registerClass(obj->metaObject());
318 classInfo = _knownClassInfos.value(obj->metaObject()->className());
318 classInfo = _knownClassInfos.value(obj->metaObject()->className());
319 }
319 }
320 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
320 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
321 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
321 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
322 } else {
322 } else {
323 Py_INCREF(wrap);
323 Py_INCREF(wrap);
324 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
324 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
325 }
325 }
326 return (PyObject*)wrap;
326 return (PyObject*)wrap;
327 }
327 }
328
328
329 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
329 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
330 {
330 {
331 if (!ptr) {
331 if (!ptr) {
332 Py_INCREF(Py_None);
332 Py_INCREF(Py_None);
333 return Py_None;
333 return Py_None;
334 }
334 }
335
335
336 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
336 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
337 if (!wrap) {
337 if (!wrap) {
338 PythonQtClassInfo* info = _knownClassInfos.value(name);
338 PythonQtClassInfo* info = _knownClassInfos.value(name);
339 if (!info) {
339 if (!info) {
340 // maybe it is a PyObject, which we can return directly
340 // maybe it is a PyObject, which we can return directly
341 if (name == "PyObject") {
341 if (name == "PyObject") {
342 PyObject* p = (PyObject*)ptr;
342 PyObject* p = (PyObject*)ptr;
343 Py_INCREF(p);
343 Py_INCREF(p);
344 return p;
344 return p;
345 }
345 }
346
346
347 // we do not know the metaobject yet, but we might know it by it's name:
347 // we do not know the metaobject yet, but we might know it by it's name:
348 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
348 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
349 // yes, we know it, so we can convert to QObject
349 // yes, we know it, so we can convert to QObject
350 QObject* qptr = (QObject*)ptr;
350 QObject* qptr = (QObject*)ptr;
351 registerClass(qptr->metaObject());
351 registerClass(qptr->metaObject());
352 info = _knownClassInfos.value(qptr->metaObject()->className());
352 info = _knownClassInfos.value(qptr->metaObject()->className());
353 }
353 }
354 }
354 }
355 if (info && info->isQObject()) {
355 if (info && info->isQObject()) {
356 QObject* qptr = (QObject*)ptr;
356 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:
357 // 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())) {
358 if (name!=(qptr->metaObject()->className())) {
359 registerClass(qptr->metaObject());
359 registerClass(qptr->metaObject());
360 info = _knownClassInfos.value(qptr->metaObject()->className());
360 info = _knownClassInfos.value(qptr->metaObject()->className());
361 }
361 }
362 wrap = createNewPythonQtInstanceWrapper(qptr, info);
362 wrap = createNewPythonQtInstanceWrapper(qptr, info);
363 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
363 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
364 return (PyObject*)wrap;
364 return (PyObject*)wrap;
365 }
365 }
366
366
367 // not a known QObject, so try our wrapper factory:
367 // not a known QObject, so try our wrapper factory:
368 QObject* wrapper = NULL;
368 QObject* wrapper = NULL;
369 for (int i=0; i<_cppWrapperFactories.size(); i++) {
369 for (int i=0; i<_cppWrapperFactories.size(); i++) {
370 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
370 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
371 if (wrapper) {
371 if (wrapper) {
372 break;
372 break;
373 }
373 }
374 }
374 }
375
375
376 if (info) {
376 if (info) {
377 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
377 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
378 ptr = info->castDownIfPossible(ptr, &info);
378 ptr = info->castDownIfPossible(ptr, &info);
379 }
379 }
380
380
381 if (!info || info->pythonQtClassWrapper()==NULL) {
381 if (!info || info->pythonQtClassWrapper()==NULL) {
382 // still unknown, register as CPP class
382 // still unknown, register as CPP class
383 registerCPPClass(name.constData());
383 registerCPPClass(name.constData());
384 info = _knownClassInfos.value(name);
384 info = _knownClassInfos.value(name);
385 }
385 }
386 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
386 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
387 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
387 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
388 info->setMetaObject(wrapper->metaObject());
388 info->setMetaObject(wrapper->metaObject());
389 }
389 }
390 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
390 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
391 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
391 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
392 } else {
392 } else {
393 Py_INCREF(wrap);
393 Py_INCREF(wrap);
394 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
394 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
395 }
395 }
396 return (PyObject*)wrap;
396 return (PyObject*)wrap;
397 }
397 }
398
398
399 PyObject* PythonQtPrivate::dummyTuple() {
399 PyObject* PythonQtPrivate::dummyTuple() {
400 static PyObject* dummyTuple = NULL;
400 static PyObject* dummyTuple = NULL;
401 if (dummyTuple==NULL) {
401 if (dummyTuple==NULL) {
402 dummyTuple = PyTuple_New(1);
402 dummyTuple = PyTuple_New(1);
403 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
403 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
404 }
404 }
405 return dummyTuple;
405 return dummyTuple;
406 }
406 }
407
407
408
408
409 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
409 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
410 // call the associated class type to create a new instance...
410 // call the associated class type to create a new instance...
411 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
411 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
412
412
413 result->setQObject(obj);
413 result->setQObject(obj);
414 result->_wrappedPtr = wrappedPtr;
414 result->_wrappedPtr = wrappedPtr;
415 result->_ownedByPythonQt = false;
415 result->_ownedByPythonQt = false;
416 result->_useQMetaTypeDestroy = false;
416 result->_useQMetaTypeDestroy = false;
417
417
418 if (wrappedPtr) {
418 if (wrappedPtr) {
419 _wrappedObjects.insert(wrappedPtr, result);
419 _wrappedObjects.insert(wrappedPtr, result);
420 } else {
420 } else {
421 _wrappedObjects.insert(obj, result);
421 _wrappedObjects.insert(obj, result);
422 if (obj->parent()== NULL && _wrappedCB) {
422 if (obj->parent()== NULL && _wrappedCB) {
423 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
423 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
424 (*_wrappedCB)(obj);
424 (*_wrappedCB)(obj);
425 }
425 }
426 }
426 }
427 return result;
427 return result;
428 }
428 }
429
429
430 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) {
430 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) {
431 PythonQtClassWrapper* result;
431 PythonQtClassWrapper* result;
432
432
433 PyObject* className = PyString_FromString(info->className());
433 PyObject* className = PyString_FromString(info->className());
434
434
435 PyObject* baseClasses = PyTuple_New(1);
435 PyObject* baseClasses = PyTuple_New(1);
436 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
436 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
437
437
438 PyObject* typeDict = PyDict_New();
438 PyObject* typeDict = PyDict_New();
439 QByteArray moduleName("PythonQt");
439 QByteArray moduleName("PythonQt");
440 if (package && strcmp(package, "")!=0) {
440 if (package && strcmp(package, "")!=0) {
441 moduleName += ".";
441 moduleName += ".";
442 moduleName += package;
442 moduleName += package;
443 }
443 }
444 PyDict_SetItemString(typeDict, "__module__", PyString_FromString(moduleName.constData()));
444 PyDict_SetItemString(typeDict, "__module__", PyString_FromString(moduleName.constData()));
445
445
446 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
446 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
447
447
448 // set the class info so that PythonQtClassWrapper_new can read it
448 // set the class info so that PythonQtClassWrapper_new can read it
449 _currentClassInfoForClassWrapperCreation = info;
449 _currentClassInfoForClassWrapperCreation = info;
450 // create the new type object by calling the type
450 // create the new type object by calling the type
451 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
451 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
452
452
453 Py_DECREF(baseClasses);
453 Py_DECREF(baseClasses);
454 Py_DECREF(typeDict);
454 Py_DECREF(typeDict);
455 Py_DECREF(args);
455 Py_DECREF(args);
456 Py_DECREF(className);
456 Py_DECREF(className);
457
457
458 return result;
458 return result;
459 }
459 }
460
460
461
461
462 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
462 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
463 {
463 {
464 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
464 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
465 if (!r) {
465 if (!r) {
466 r = new PythonQtSignalReceiver(obj);
466 r = new PythonQtSignalReceiver(obj);
467 _p->_signalReceivers.insert(obj, r);
467 _p->_signalReceivers.insert(obj, r);
468 }
468 }
469 return r;
469 return r;
470 }
470 }
471
471
472 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
472 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
473 {
473 {
474 bool flag = false;
474 bool flag = false;
475 PythonQtObjectPtr callable = lookupCallable(module, objectname);
475 PythonQtObjectPtr callable = lookupCallable(module, objectname);
476 if (callable) {
476 if (callable) {
477 PythonQtSignalReceiver* r = getSignalReceiver(obj);
477 PythonQtSignalReceiver* r = getSignalReceiver(obj);
478 flag = r->addSignalHandler(signal, callable);
478 flag = r->addSignalHandler(signal, callable);
479 if (!flag) {
479 if (!flag) {
480 // signal not found
480 // signal not found
481 }
481 }
482 } else {
482 } else {
483 // callable not found
483 // callable not found
484 }
484 }
485 return flag;
485 return flag;
486 }
486 }
487
487
488 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
488 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
489 {
489 {
490 bool flag = false;
490 bool flag = false;
491 PythonQtSignalReceiver* r = getSignalReceiver(obj);
491 PythonQtSignalReceiver* r = getSignalReceiver(obj);
492 if (r) {
492 if (r) {
493 flag = r->addSignalHandler(signal, receiver);
493 flag = r->addSignalHandler(signal, receiver);
494 }
494 }
495 return flag;
495 return flag;
496 }
496 }
497
497
498 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
498 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
499 {
499 {
500 bool flag = false;
500 bool flag = false;
501 PythonQtObjectPtr callable = lookupCallable(module, objectname);
501 PythonQtObjectPtr callable = lookupCallable(module, objectname);
502 if (callable) {
502 if (callable) {
503 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
503 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
504 if (r) {
504 if (r) {
505 flag = r->removeSignalHandler(signal, callable);
505 flag = r->removeSignalHandler(signal, callable);
506 }
506 }
507 } else {
507 } else {
508 // callable not found
508 // callable not found
509 }
509 }
510 return flag;
510 return flag;
511 }
511 }
512
512
513 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
513 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
514 {
514 {
515 bool flag = false;
515 bool flag = false;
516 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
516 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
517 if (r) {
517 if (r) {
518 flag = r->removeSignalHandler(signal, receiver);
518 flag = r->removeSignalHandler(signal, receiver);
519 }
519 }
520 return flag;
520 return flag;
521 }
521 }
522
522
523 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
523 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
524 {
524 {
525 PythonQtObjectPtr p = lookupObject(module, name);
525 PythonQtObjectPtr p = lookupObject(module, name);
526 if (p) {
526 if (p) {
527 if (PyCallable_Check(p)) {
527 if (PyCallable_Check(p)) {
528 return p;
528 return p;
529 }
529 }
530 }
530 }
531 PyErr_Clear();
531 PyErr_Clear();
532 return NULL;
532 return NULL;
533 }
533 }
534
534
535 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
535 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
536 {
536 {
537 QStringList l = name.split('.');
537 QStringList l = name.split('.');
538 PythonQtObjectPtr p = module;
538 PythonQtObjectPtr p = module;
539 PythonQtObjectPtr prev;
539 PythonQtObjectPtr prev;
540 QString s;
540 QString s;
541 QByteArray b;
541 QByteArray b;
542 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
542 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
543 prev = p;
543 prev = p;
544 b = (*i).toLatin1();
544 b = (*i).toLatin1();
545 if (PyDict_Check(p)) {
545 if (PyDict_Check(p)) {
546 p = PyDict_GetItemString(p, b.data());
546 p = PyDict_GetItemString(p, b.data());
547 } else {
547 } else {
548 p.setNewRef(PyObject_GetAttrString(p, b.data()));
548 p.setNewRef(PyObject_GetAttrString(p, b.data()));
549 }
549 }
550 }
550 }
551 PyErr_Clear();
551 PyErr_Clear();
552 return p;
552 return p;
553 }
553 }
554
554
555 PythonQtObjectPtr PythonQt::getMainModule() {
555 PythonQtObjectPtr PythonQt::getMainModule() {
556 //both borrowed
556 //both borrowed
557 PythonQtObjectPtr dict = PyImport_GetModuleDict();
557 PythonQtObjectPtr dict = PyImport_GetModuleDict();
558 return PyDict_GetItemString(dict, "__main__");
558 return PyDict_GetItemString(dict, "__main__");
559 }
559 }
560
560
561 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
561 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
562 QVariant result;
562 QVariant result;
563 if (pycode) {
563 if (pycode) {
564 PyObject* dict = NULL;
564 PyObject* dict = NULL;
565 if (PyModule_Check(object)) {
565 if (PyModule_Check(object)) {
566 dict = PyModule_GetDict(object);
566 dict = PyModule_GetDict(object);
567 } else if (PyDict_Check(object)) {
567 } else if (PyDict_Check(object)) {
568 dict = object;
568 dict = object;
569 }
569 }
570 PyObject* r = NULL;
570 PyObject* r = NULL;
571 if (dict) {
571 if (dict) {
572 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
572 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
573 }
573 }
574 if (r) {
574 if (r) {
575 result = PythonQtConv::PyObjToQVariant(r);
575 result = PythonQtConv::PyObjToQVariant(r);
576 Py_DECREF(r);
576 Py_DECREF(r);
577 } else {
577 } else {
578 handleError();
578 handleError();
579 }
579 }
580 } else {
580 } else {
581 handleError();
581 handleError();
582 }
582 }
583 return result;
583 return result;
584 }
584 }
585
585
586 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
586 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
587 {
587 {
588 QVariant result;
588 QVariant result;
589 PythonQtObjectPtr p;
589 PythonQtObjectPtr p;
590 PyObject* dict = NULL;
590 PyObject* dict = NULL;
591 if (PyModule_Check(object)) {
591 if (PyModule_Check(object)) {
592 dict = PyModule_GetDict(object);
592 dict = PyModule_GetDict(object);
593 } else if (PyDict_Check(object)) {
593 } else if (PyDict_Check(object)) {
594 dict = object;
594 dict = object;
595 }
595 }
596 if (dict) {
596 if (dict) {
597 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
597 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
598 }
598 }
599 if (p) {
599 if (p) {
600 result = PythonQtConv::PyObjToQVariant(p);
600 result = PythonQtConv::PyObjToQVariant(p);
601 } else {
601 } else {
602 handleError();
602 handleError();
603 }
603 }
604 return result;
604 return result;
605 }
605 }
606
606
607 void PythonQt::evalFile(PyObject* module, const QString& filename)
607 void PythonQt::evalFile(PyObject* module, const QString& filename)
608 {
608 {
609 PythonQtObjectPtr code = parseFile(filename);
609 PythonQtObjectPtr code = parseFile(filename);
610 if (code) {
610 if (code) {
611 evalCode(module, code);
611 evalCode(module, code);
612 } else {
612 } else {
613 handleError();
613 handleError();
614 }
614 }
615 }
615 }
616
616
617 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
617 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
618 {
618 {
619 PythonQtObjectPtr p;
619 PythonQtObjectPtr p;
620 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
620 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
621 if (!p) {
621 if (!p) {
622 handleError();
622 handleError();
623 }
623 }
624 return p;
624 return p;
625 }
625 }
626
626
627 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
627 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
628 {
628 {
629 PythonQtObjectPtr code = parseFile(filename);
629 PythonQtObjectPtr code = parseFile(filename);
630 PythonQtObjectPtr module = _p->createModule(name, code);
630 PythonQtObjectPtr module = _p->createModule(name, code);
631 return module;
631 return module;
632 }
632 }
633
633
634 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
634 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
635 {
635 {
636 PyErr_Clear();
636 PyErr_Clear();
637 QString scriptCode = script;
637 QString scriptCode = script;
638 if (scriptCode.isEmpty()) {
638 if (scriptCode.isEmpty()) {
639 // we always need at least a linefeed
639 // we always need at least a linefeed
640 scriptCode = "\n";
640 scriptCode = "\n";
641 }
641 }
642 PythonQtObjectPtr pycode;
642 PythonQtObjectPtr pycode;
643 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
643 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
644 PythonQtObjectPtr module = _p->createModule(name, pycode);
644 PythonQtObjectPtr module = _p->createModule(name, pycode);
645 return module;
645 return module;
646 }
646 }
647
647
648 PythonQtObjectPtr PythonQt::createUniqueModule()
648 PythonQtObjectPtr PythonQt::createUniqueModule()
649 {
649 {
650 static QString pyQtStr("PythonQt_module");
650 static QString pyQtStr("PythonQt_module");
651 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
651 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
652 return createModuleFromScript(moduleName);
652 return createModuleFromScript(moduleName);
653 }
653 }
654
654
655 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
655 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
656 {
656 {
657 if (PyModule_Check(object)) {
657 if (PyModule_Check(object)) {
658 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
658 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
659 } else if (PyDict_Check(object)) {
659 } else if (PyDict_Check(object)) {
660 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
660 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
661 } else {
661 } else {
662 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
662 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
663 }
663 }
664 }
664 }
665
665
666 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
666 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
667 {
667 {
668 if (PyModule_Check(object)) {
668 if (PyModule_Check(object)) {
669 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
669 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
670 } else if (PyDict_Check(object)) {
670 } else if (PyDict_Check(object)) {
671 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
671 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
672 } else {
672 } else {
673 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
673 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
674 }
674 }
675 }
675 }
676
676
677 void PythonQt::removeVariable(PyObject* object, const QString& name)
677 void PythonQt::removeVariable(PyObject* object, const QString& name)
678 {
678 {
679 if (PyDict_Check(object)) {
679 if (PyDict_Check(object)) {
680 PyDict_DelItemString(object, name.toLatin1().data());
680 PyDict_DelItemString(object, name.toLatin1().data());
681 } else {
681 } else {
682 PyObject_DelAttrString(object, name.toLatin1().data());
682 PyObject_DelAttrString(object, name.toLatin1().data());
683 }
683 }
684 }
684 }
685
685
686 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
686 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
687 {
687 {
688 QVariant result;
688 QVariant result;
689 PythonQtObjectPtr obj = lookupObject(object, objectname);
689 PythonQtObjectPtr obj = lookupObject(object, objectname);
690 if (obj) {
690 if (obj) {
691 result = PythonQtConv::PyObjToQVariant(obj);
691 result = PythonQtConv::PyObjToQVariant(obj);
692 }
692 }
693 return result;
693 return result;
694 }
694 }
695
695
696 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
696 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
697 {
697 {
698 QStringList results;
698 QStringList results;
699
699
700 PythonQtObjectPtr object;
700 PythonQtObjectPtr object;
701 if (objectname.isEmpty()) {
701 if (objectname.isEmpty()) {
702 object = module;
702 object = module;
703 } else {
703 } else {
704 object = lookupObject(module, objectname);
704 object = lookupObject(module, objectname);
705 if (!object && type == CallOverloads) {
705 if (!object && type == CallOverloads) {
706 PyObject* dict = lookupObject(module, "__builtins__");
706 PyObject* dict = lookupObject(module, "__builtins__");
707 if (dict) {
707 if (dict) {
708 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
708 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
709 }
709 }
710 }
710 }
711 }
711 }
712
712
713 if (object) {
713 if (object) {
714 if (type == CallOverloads) {
714 if (type == CallOverloads) {
715 if (PythonQtSlotFunction_Check(object)) {
715 if (PythonQtSlotFunction_Check(object)) {
716 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
716 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
717 PythonQtSlotInfo* info = o->m_ml;
717 PythonQtSlotInfo* info = o->m_ml;
718
718
719 while (info) {
719 while (info) {
720 results << info->fullSignature();
720 results << info->fullSignature();
721 info = info->nextInfo();
721 info = info->nextInfo();
722 }
722 }
723 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
723 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
724 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
724 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
725 PythonQtSlotInfo* info = o->classInfo()->constructors();
725 PythonQtSlotInfo* info = o->classInfo()->constructors();
726
726
727 while (info) {
727 while (info) {
728 results << info->fullSignature();
728 results << info->fullSignature();
729 info = info->nextInfo();
729 info = info->nextInfo();
730 }
730 }
731 } else {
731 } else {
732 //TODO: use pydoc!
732 //TODO: use pydoc!
733 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
733 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
734 if (doc) {
734 if (doc) {
735 results << PyString_AsString(doc);
735 results << PyString_AsString(doc);
736 Py_DECREF(doc);
736 Py_DECREF(doc);
737 }
737 }
738 }
738 }
739 } else {
739 } else {
740 PyObject* keys = NULL;
740 PyObject* keys = NULL;
741 bool isDict = false;
741 bool isDict = false;
742 if (PyDict_Check(object)) {
742 if (PyDict_Check(object)) {
743 keys = PyDict_Keys(object);
743 keys = PyDict_Keys(object);
744 isDict = true;
744 isDict = true;
745 } else {
745 } else {
746 keys = PyObject_Dir(object);
746 keys = PyObject_Dir(object);
747 }
747 }
748 if (keys) {
748 if (keys) {
749 int count = PyList_Size(keys);
749 int count = PyList_Size(keys);
750 PyObject* key;
750 PyObject* key;
751 PyObject* value;
751 PyObject* value;
752 QString keystr;
752 QString keystr;
753 for (int i = 0;i<count;i++) {
753 for (int i = 0;i<count;i++) {
754 key = PyList_GetItem(keys,i);
754 key = PyList_GetItem(keys,i);
755 if (isDict) {
755 if (isDict) {
756 value = PyDict_GetItem(object, key);
756 value = PyDict_GetItem(object, key);
757 Py_INCREF(value);
757 Py_INCREF(value);
758 } else {
758 } else {
759 value = PyObject_GetAttr(object, key);
759 value = PyObject_GetAttr(object, key);
760 }
760 }
761 if (!value) continue;
761 if (!value) continue;
762 keystr = PyString_AsString(key);
762 keystr = PyString_AsString(key);
763 static const QString underscoreStr("__tmp");
763 static const QString underscoreStr("__tmp");
764 if (!keystr.startsWith(underscoreStr)) {
764 if (!keystr.startsWith(underscoreStr)) {
765 switch (type) {
765 switch (type) {
766 case Anything:
766 case Anything:
767 results << keystr;
767 results << keystr;
768 break;
768 break;
769 case Class:
769 case Class:
770 if (value->ob_type == &PyClass_Type) {
770 if (value->ob_type == &PyClass_Type) {
771 results << keystr;
771 results << keystr;
772 }
772 }
773 break;
773 break;
774 case Variable:
774 case Variable:
775 if (value->ob_type != &PyClass_Type
775 if (value->ob_type != &PyClass_Type
776 && value->ob_type != &PyCFunction_Type
776 && value->ob_type != &PyCFunction_Type
777 && value->ob_type != &PyFunction_Type
777 && value->ob_type != &PyFunction_Type
778 && value->ob_type != &PyModule_Type
778 && value->ob_type != &PyModule_Type
779 ) {
779 ) {
780 results << keystr;
780 results << keystr;
781 }
781 }
782 break;
782 break;
783 case Function:
783 case Function:
784 if (value->ob_type == &PyFunction_Type ||
784 if (value->ob_type == &PyFunction_Type ||
785 value->ob_type == &PyMethod_Type
785 value->ob_type == &PyMethod_Type
786 ) {
786 ) {
787 results << keystr;
787 results << keystr;
788 }
788 }
789 break;
789 break;
790 case Module:
790 case Module:
791 if (value->ob_type == &PyModule_Type) {
791 if (value->ob_type == &PyModule_Type) {
792 results << keystr;
792 results << keystr;
793 }
793 }
794 break;
794 break;
795 default:
795 default:
796 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
796 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
797 }
797 }
798 }
798 }
799 Py_DECREF(value);
799 Py_DECREF(value);
800 }
800 }
801 Py_DECREF(keys);
801 Py_DECREF(keys);
802 }
802 }
803 }
803 }
804 }
804 }
805 return results;
805 return results;
806 }
806 }
807
807
808 QVariant PythonQt::call(PyObject* module, const QString& name, const QVariantList& args)
808 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
809 {
810 PythonQtObjectPtr callable = lookupCallable(object, name);
811 if (callable) {
812 return call(callable, args);
813 } else {
814 return QVariant();
815 }
816 }
817
818 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
809 {
819 {
810 QVariant r;
820 QVariant r;
811
812 PythonQtObjectPtr callable = lookupCallable(module, name);
813 if (callable) {
821 if (callable) {
814 PythonQtObjectPtr pargs;
822 PythonQtObjectPtr pargs;
815 int count = args.size();
823 int count = args.size();
816 if (count>0) {
824 if (count>0) {
817 pargs.setNewRef(PyTuple_New(count));
825 pargs.setNewRef(PyTuple_New(count));
818 }
826 }
819 bool err = false;
827 bool err = false;
820 // transform QVariants to Python
828 // transform QVariants to Python
821 for (int i = 0; i < count; i++) {
829 for (int i = 0; i < count; i++) {
822 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
830 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
823 if (arg) {
831 if (arg) {
824 // steals reference, no unref
832 // steals reference, no unref
825 PyTuple_SetItem(pargs, i,arg);
833 PyTuple_SetItem(pargs, i,arg);
826 } else {
834 } else {
827 err = true;
835 err = true;
828 break;
836 break;
829 }
837 }
830 }
838 }
831
839
832 if (!err) {
840 if (!err) {
833 PyErr_Clear();
841 PyErr_Clear();
834 PythonQtObjectPtr result;
842 PythonQtObjectPtr result;
835 result.setNewRef(PyObject_CallObject(callable, pargs));
843 result.setNewRef(PyObject_CallObject(callable, pargs));
836 if (result) {
844 if (result) {
837 // ok
845 // ok
838 r = PythonQtConv::PyObjToQVariant(result);
846 r = PythonQtConv::PyObjToQVariant(result);
839 } else {
847 } else {
840 PythonQt::self()->handleError();
848 PythonQt::self()->handleError();
841 }
849 }
842 }
850 }
843 }
851 }
844 return r;
852 return r;
845 }
853 }
846
854
847 void PythonQt::addInstanceDecorators(QObject* o)
855 void PythonQt::addInstanceDecorators(QObject* o)
848 {
856 {
849 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
857 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
850 }
858 }
851
859
852 void PythonQt::addClassDecorators(QObject* o)
860 void PythonQt::addClassDecorators(QObject* o)
853 {
861 {
854 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
862 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
855 }
863 }
856
864
857 void PythonQt::addDecorators(QObject* o)
865 void PythonQt::addDecorators(QObject* o)
858 {
866 {
859 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
867 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
860 }
868 }
861
869
862 void PythonQt::registerQObjectClassNames(const QStringList& names)
870 void PythonQt::registerQObjectClassNames(const QStringList& names)
863 {
871 {
864 _p->registerQObjectClassNames(names);
872 _p->registerQObjectClassNames(names);
865 }
873 }
866
874
867 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
875 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
868 {
876 {
869 PythonQtImport::init();
877 PythonQtImport::init();
870 _p->_importInterface = importInterface;
878 _p->_importInterface = importInterface;
871 }
879 }
872
880
873 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
881 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
874 {
882 {
875 _p->_importIgnorePaths = paths;
883 _p->_importIgnorePaths = paths;
876 }
884 }
877
885
878 const QStringList& PythonQt::getImporterIgnorePaths()
886 const QStringList& PythonQt::getImporterIgnorePaths()
879 {
887 {
880 return _p->_importIgnorePaths;
888 return _p->_importIgnorePaths;
881 }
889 }
882
890
883 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
891 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
884 {
892 {
885 _p->_cppWrapperFactories.append(factory);
893 _p->_cppWrapperFactories.append(factory);
886 }
894 }
887
895
888 //---------------------------------------------------------------------------------------------------
896 //---------------------------------------------------------------------------------------------------
889 PythonQtPrivate::PythonQtPrivate()
897 PythonQtPrivate::PythonQtPrivate()
890 {
898 {
891 _importInterface = NULL;
899 _importInterface = NULL;
892 _defaultImporter = new PythonQtQFileImporter;
900 _defaultImporter = new PythonQtQFileImporter;
893 _noLongerWrappedCB = NULL;
901 _noLongerWrappedCB = NULL;
894 _wrappedCB = NULL;
902 _wrappedCB = NULL;
895 _currentClassInfoForClassWrapperCreation = NULL;
903 _currentClassInfoForClassWrapperCreation = NULL;
896 }
904 }
897
905
898 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
906 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
899 {
907 {
900 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
908 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
901 _currentClassInfoForClassWrapperCreation = NULL;
909 _currentClassInfoForClassWrapperCreation = NULL;
902 return info;
910 return info;
903 }
911 }
904
912
905 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
913 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
906 {
914 {
907 o->setParent(this);
915 o->setParent(this);
908 int numMethods = o->metaObject()->methodCount();
916 int numMethods = o->metaObject()->methodCount();
909 for (int i = 0; i < numMethods; i++) {
917 for (int i = 0; i < numMethods; i++) {
910 QMetaMethod m = o->metaObject()->method(i);
918 QMetaMethod m = o->metaObject()->method(i);
911 if ((m.methodType() == QMetaMethod::Method ||
919 if ((m.methodType() == QMetaMethod::Method ||
912 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
920 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
913 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m);
921 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m);
914 if (qstrncmp(m.signature(), "new_", 4)==0) {
922 if (qstrncmp(m.signature(), "new_", 4)==0) {
915 if ((decoTypes & ConstructorDecorator) == 0) continue;
923 if ((decoTypes & ConstructorDecorator) == 0) continue;
916 // either it returns a * or a QVariant and the name starts with "new_"
924 // either it returns a * or a QVariant and the name starts with "new_"
917 bool isVariantReturn = info->parameters().at(0).typeId == PythonQtMethodInfo::Variant;
925 bool isVariantReturn = info->parameters().at(0).typeId == PythonQtMethodInfo::Variant;
918 if ((info->parameters().at(0).isPointer || isVariantReturn)) {
926 if ((info->parameters().at(0).isPointer || isVariantReturn)) {
919 QByteArray signature = m.signature();
927 QByteArray signature = m.signature();
920 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
928 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
921 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
929 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
922 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
930 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
923 classInfo->addConstructor(newSlot);
931 classInfo->addConstructor(newSlot);
924 }
932 }
925 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
933 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
926 if ((decoTypes & DestructorDecorator) == 0) continue;
934 if ((decoTypes & DestructorDecorator) == 0) continue;
927 QByteArray signature = m.signature();
935 QByteArray signature = m.signature();
928 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
936 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
929 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
937 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
930 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
938 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
931 classInfo->setDestructor(newSlot);
939 classInfo->setDestructor(newSlot);
932 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
940 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
933 if ((decoTypes & StaticDecorator) == 0) continue;
941 if ((decoTypes & StaticDecorator) == 0) continue;
934 QByteArray signature = m.signature();
942 QByteArray signature = m.signature();
935 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
943 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
936 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
944 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
937 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
945 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
938 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
946 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
939 classInfo->addDecoratorSlot(newSlot);
947 classInfo->addDecoratorSlot(newSlot);
940 } else {
948 } else {
941 if ((decoTypes & InstanceDecorator) == 0) continue;
949 if ((decoTypes & InstanceDecorator) == 0) continue;
942 if (info->parameters().count()>1) {
950 if (info->parameters().count()>1) {
943 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
951 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
944 if (p.isPointer) {
952 if (p.isPointer) {
945 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
953 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
946 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::InstanceDecorator);
954 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::InstanceDecorator);
947 classInfo->addDecoratorSlot(newSlot);
955 classInfo->addDecoratorSlot(newSlot);
948 }
956 }
949 }
957 }
950 }
958 }
951 }
959 }
952 }
960 }
953 }
961 }
954
962
955 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
963 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
956 {
964 {
957 foreach(QString name, names) {
965 foreach(QString name, names) {
958 _knownQObjectClassNames.insert(name.toLatin1(), true);
966 _knownQObjectClassNames.insert(name.toLatin1(), true);
959 }
967 }
960 }
968 }
961
969
962 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
970 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
963 {
971 {
964 _signalReceivers.remove(obj);
972 _signalReceivers.remove(obj);
965 }
973 }
966
974
967 bool PythonQt::handleError()
975 bool PythonQt::handleError()
968 {
976 {
969 bool flag = false;
977 bool flag = false;
970 if (PyErr_Occurred()) {
978 if (PyErr_Occurred()) {
971
979
972 // currently we just print the error and the stderr handler parses the errors
980 // currently we just print the error and the stderr handler parses the errors
973 PyErr_Print();
981 PyErr_Print();
974
982
975 /*
983 /*
976 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
984 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
977 PyObject *ptype;
985 PyObject *ptype;
978 PyObject *pvalue;
986 PyObject *pvalue;
979 PyObject *ptraceback;
987 PyObject *ptraceback;
980 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
988 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
981
989
982 Py_XDECREF(ptype);
990 Py_XDECREF(ptype);
983 Py_XDECREF(pvalue);
991 Py_XDECREF(pvalue);
984 Py_XDECREF(ptraceback);
992 Py_XDECREF(ptraceback);
985 */
993 */
986 PyErr_Clear();
994 PyErr_Clear();
987 flag = true;
995 flag = true;
988 }
996 }
989 return flag;
997 return flag;
990 }
998 }
991
999
992 void PythonQt::addSysPath(const QString& path)
1000 void PythonQt::addSysPath(const QString& path)
993 {
1001 {
994 PythonQtObjectPtr sys;
1002 PythonQtObjectPtr sys;
995 sys.setNewRef(PyImport_ImportModule("sys"));
1003 sys.setNewRef(PyImport_ImportModule("sys"));
996 PythonQtObjectPtr obj = lookupObject(sys, "path");
1004 PythonQtObjectPtr obj = lookupObject(sys, "path");
997 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1005 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
998 }
1006 }
999
1007
1000 void PythonQt::overwriteSysPath(const QStringList& paths)
1008 void PythonQt::overwriteSysPath(const QStringList& paths)
1001 {
1009 {
1002 PythonQtObjectPtr sys;
1010 PythonQtObjectPtr sys;
1003 sys.setNewRef(PyImport_ImportModule("sys"));
1011 sys.setNewRef(PyImport_ImportModule("sys"));
1004 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1012 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1005 }
1013 }
1006
1014
1007 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1015 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1008 {
1016 {
1009 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1017 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1010 }
1018 }
1011
1019
1012 void PythonQt::stdOutRedirectCB(const QString& str)
1020 void PythonQt::stdOutRedirectCB(const QString& str)
1013 {
1021 {
1014 emit PythonQt::self()->pythonStdOut(str);
1022 emit PythonQt::self()->pythonStdOut(str);
1015 }
1023 }
1016
1024
1017 void PythonQt::stdErrRedirectCB(const QString& str)
1025 void PythonQt::stdErrRedirectCB(const QString& str)
1018 {
1026 {
1019 emit PythonQt::self()->pythonStdErr(str);
1027 emit PythonQt::self()->pythonStdErr(str);
1020 }
1028 }
1021
1029
1022 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1030 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1023 {
1031 {
1024 _p->_wrappedCB = cb;
1032 _p->_wrappedCB = cb;
1025 }
1033 }
1026
1034
1027 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1035 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1028 {
1036 {
1029 _p->_noLongerWrappedCB = cb;
1037 _p->_noLongerWrappedCB = cb;
1030 }
1038 }
1031
1039
1032
1040
1033
1041
1034 static PyMethodDef PythonQtMethods[] = {
1042 static PyMethodDef PythonQtMethods[] = {
1035 {NULL, NULL, 0, NULL}
1043 {NULL, NULL, 0, NULL}
1036 };
1044 };
1037
1045
1038 void PythonQt::initPythonQtModule(bool redirectStdOut)
1046 void PythonQt::initPythonQtModule(bool redirectStdOut)
1039 {
1047 {
1040 _p->_pythonQtModule = Py_InitModule("PythonQt", PythonQtMethods);
1048 _p->_pythonQtModule = Py_InitModule("PythonQt", PythonQtMethods);
1041
1049
1042 if (redirectStdOut) {
1050 if (redirectStdOut) {
1043 PythonQtObjectPtr sys;
1051 PythonQtObjectPtr sys;
1044 PythonQtObjectPtr out;
1052 PythonQtObjectPtr out;
1045 PythonQtObjectPtr err;
1053 PythonQtObjectPtr err;
1046 sys.setNewRef(PyImport_ImportModule("sys"));
1054 sys.setNewRef(PyImport_ImportModule("sys"));
1047 // create a redirection object for stdout and stderr
1055 // create a redirection object for stdout and stderr
1048 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1056 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1049 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1057 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1050 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1058 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1051 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1059 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1052 // replace the built in file objects with our own objects
1060 // replace the built in file objects with our own objects
1053 PyModule_AddObject(sys, "stdout", out);
1061 PyModule_AddObject(sys, "stdout", out);
1054 PyModule_AddObject(sys, "stderr", err);
1062 PyModule_AddObject(sys, "stderr", err);
1055 }
1063 }
1056 }
1064 }
1057
1065
1058 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1066 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1059 {
1067 {
1060 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1068 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1061 }
1069 }
1062
1070
1063
1071
1064 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1072 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1065 {
1073 {
1066 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1074 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1067 if (!info) {
1075 if (!info) {
1068 info = new PythonQtClassInfo();
1076 info = new PythonQtClassInfo();
1069 info->setupCPPObject(typeName);
1077 info->setupCPPObject(typeName);
1070 _knownClassInfos.insert(typeName, info);
1078 _knownClassInfos.insert(typeName, info);
1071 }
1079 }
1072 return info;
1080 return info;
1073 }
1081 }
1074
1082
1075 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1083 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1076 {
1084 {
1077 _p->addPolymorphicHandler(typeName, cb);
1085 _p->addPolymorphicHandler(typeName, cb);
1078 }
1086 }
1079
1087
1080 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1088 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1081 {
1089 {
1082 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1090 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1083 info->addPolymorphicHandler(cb);
1091 info->addPolymorphicHandler(cb);
1084 }
1092 }
1085
1093
1086 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1094 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1087 {
1095 {
1088 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1096 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1089 }
1097 }
1090
1098
1091 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1099 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1092 {
1100 {
1093 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1101 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1094 if (info) {
1102 if (info) {
1095 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1103 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1096 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1104 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1097 return true;
1105 return true;
1098 } else {
1106 } else {
1099 return false;
1107 return false;
1100 }
1108 }
1101 }
1109 }
1102
1110
1103 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1111 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1104 {
1112 {
1105 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1113 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1106 if (!info->pythonQtClassWrapper()) {
1114 if (!info->pythonQtClassWrapper()) {
1107 info->setupCPPObject(typeName);
1115 info->setupCPPObject(typeName);
1108 createPythonQtClassWrapper(info, package);
1116 createPythonQtClassWrapper(info, package);
1109 }
1117 }
1110 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1118 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1111 addParentClass(typeName, parentTypeName, 0);
1119 addParentClass(typeName, parentTypeName, 0);
1112 }
1120 }
1113 if (wrapperCreator) {
1121 if (wrapperCreator) {
1114 info->setDecoratorProvider(wrapperCreator);
1122 info->setDecoratorProvider(wrapperCreator);
1115 }
1123 }
1116 if (shell) {
1124 if (shell) {
1117 info->setShellSetInstanceWrapperCB(shell);
1125 info->setShellSetInstanceWrapperCB(shell);
1118 }
1126 }
1119 }
1127 }
1120
1128
1121 PyObject* PythonQtPrivate::packageByName(const char* name)
1129 PyObject* PythonQtPrivate::packageByName(const char* name)
1122 {
1130 {
1123 if (name==NULL || name[0]==0) {
1131 if (name==NULL || name[0]==0) {
1124 return _pythonQtModule;
1132 return _pythonQtModule;
1125 }
1133 }
1126 PyObject* v = _packages.value(name);
1134 PyObject* v = _packages.value(name);
1127 if (!v) {
1135 if (!v) {
1128 v = PyImport_AddModule((QByteArray("PythonQt.") + name).constData());
1136 v = PyImport_AddModule((QByteArray("PythonQt.") + name).constData());
1129 _packages.insert(name, v);
1137 _packages.insert(name, v);
1130 // AddObject steals the reference, so increment it!
1138 // AddObject steals the reference, so increment it!
1131 Py_INCREF(v);
1139 Py_INCREF(v);
1132 PyModule_AddObject(_pythonQtModule, name, v);
1140 PyModule_AddObject(_pythonQtModule, name, v);
1133 }
1141 }
1134 return v;
1142 return v;
1135 }
1143 }
1136
1144
1137
1145
1138 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1146 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1139 {
1147 {
1140 if (_p->_initFlags & ExternalHelp) {
1148 if (_p->_initFlags & ExternalHelp) {
1141 emit pythonHelpRequest(QByteArray(info->className()));
1149 emit pythonHelpRequest(QByteArray(info->className()));
1142 return Py_BuildValue("");
1150 return Py_BuildValue("");
1143 } else {
1151 } else {
1144 return PyString_FromString(info->help().toLatin1().data());
1152 return PyString_FromString(info->help().toLatin1().data());
1145 }
1153 }
1146 }
1154 }
1147
1155
1148 void PythonQtPrivate::removeWrapperPointer(void* obj)
1156 void PythonQtPrivate::removeWrapperPointer(void* obj)
1149 {
1157 {
1150 _wrappedObjects.remove(obj);
1158 _wrappedObjects.remove(obj);
1151 }
1159 }
1152
1160
1153 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1161 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1154 {
1162 {
1155 _wrappedObjects.insert(obj, wrapper);
1163 _wrappedObjects.insert(obj, wrapper);
1156 }
1164 }
1157
1165
1158 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1166 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1159 {
1167 {
1160 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1168 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1161 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1169 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1162 // this is a wrapper whose QObject was already removed due to destruction
1170 // this is a wrapper whose QObject was already removed due to destruction
1163 // so the obj pointer has to be a new QObject with the same address...
1171 // so the obj pointer has to be a new QObject with the same address...
1164 // we remove the old one and set the copy to NULL
1172 // we remove the old one and set the copy to NULL
1165 wrap->_objPointerCopy = NULL;
1173 wrap->_objPointerCopy = NULL;
1166 removeWrapperPointer(obj);
1174 removeWrapperPointer(obj);
1167 wrap = NULL;
1175 wrap = NULL;
1168 }
1176 }
1169 return wrap;
1177 return wrap;
1170 }
1178 }
1171
1179
1172 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1180 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1173 {
1181 {
1174 PythonQtObjectPtr result;
1182 PythonQtObjectPtr result;
1175 if (pycode) {
1183 if (pycode) {
1176 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1184 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1177 } else {
1185 } else {
1178 PythonQt::self()->handleError();
1186 PythonQt::self()->handleError();
1179 }
1187 }
1180 return result;
1188 return result;
1181 }
1189 }
@@ -1,518 +1,521
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 method, 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* module, const QString& callable, const QVariantList& args = QVariantList());
232 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
233
234 //! call the given python object, returns the result converted to a QVariant
235 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
233
236
234 //@}
237 //@}
235
238
236 //@{ Decorations, constructors, wrappers...
239 //@{ Decorations, constructors, wrappers...
237
240
238
241
239 //! 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
240 //! other QObjects or CPP classes. The slots need to follow the
243 //! other QObjects or CPP classes. The slots need to follow the
241 //! 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.
242 //! (ownership is passed to PythonQt)
245 //! (ownership is passed to PythonQt)
243 /*!
246 /*!
244 Example:
247 Example:
245
248
246 A slot with the signature
249 A slot with the signature
247
250
248 \code
251 \code
249 bool doSomething(QWidget* w, int a)
252 bool doSomething(QWidget* w, int a)
250 \endcode
253 \endcode
251
254
252 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
253 that will be called with the concrete instance as first argument.
256 that will be called with the concrete instance as first argument.
254 So in Python you can now e.g. call
257 So in Python you can now e.g. call
255
258
256 \code
259 \code
257 someWidget.doSomething(12)
260 someWidget.doSomething(12)
258 \endcode
261 \endcode
259
262
260 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
261 of Qt classes callable by forwarding them with such decorator slots
264 of Qt classes callable by forwarding them with such decorator slots
262 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.
263 */
266 */
264 void addInstanceDecorators(QObject* o);
267 void addInstanceDecorators(QObject* o);
265
268
266 //! 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
267 //! class objects (ownership is passed to PythonQt)
270 //! class objects (ownership is passed to PythonQt)
268 /*!
271 /*!
269 The slots need to follow the following convention:
272 The slots need to follow the following convention:
270 - SomeClass* new_SomeClass(...)
273 - SomeClass* new_SomeClass(...)
271 - QVariant new_SomeClass(...)
274 - QVariant new_SomeClass(...)
272 - void delete_SomeClass(SomeClass*)
275 - void delete_SomeClass(SomeClass*)
273 - ... static_SomeClass_someName(...)
276 - ... static_SomeClass_someName(...)
274
277
275 This will add:
278 This will add:
276 - a constructor
279 - a constructor
277 - a constructor which generates a QVariant
280 - a constructor which generates a QVariant
278 - a destructor (only useful for CPP objects)
281 - a destructor (only useful for CPP objects)
279 - 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)
280
283
281 */
284 */
282 void addClassDecorators(QObject* o);
285 void addClassDecorators(QObject* o);
283
286
284 //! 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)
285 void addDecorators(QObject* o);
288 void addDecorators(QObject* o);
286
289
287 //! add the given factory to PythonQt (ownership stays with caller)
290 //! add the given factory to PythonQt (ownership stays with caller)
288 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
291 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
289
292
290 //@}
293 //@}
291
294
292 //@{ Custom importer (to replace internal import implementation of python)
295 //@{ Custom importer (to replace internal import implementation of python)
293
296
294 //! 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)
295 //! (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().
296 //! 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".
297 //! This is not reversible, so even setting setImporter(NULL) afterwards will
300 //! This is not reversible, so even setting setImporter(NULL) afterwards will
298 //! keep the custom PythonQt importer with a QFile default import interface.
301 //! keep the custom PythonQt importer with a QFile default import interface.
299 //! Subsequent python import calls will make use of the passed importInterface
302 //! Subsequent python import calls will make use of the passed importInterface
300 //! which forwards all import calls to the given \c importInterface.
303 //! which forwards all import calls to the given \c importInterface.
301 //! Passing NULL will install a default QFile importer.
304 //! Passing NULL will install a default QFile importer.
302 //! (\c importInterface ownership stays with caller)
305 //! (\c importInterface ownership stays with caller)
303 void setImporter(PythonQtImportFileInterface* importInterface);
306 void setImporter(PythonQtImportFileInterface* importInterface);
304
307
305 //! 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))
306 //! (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
307 //! mechanism is in place)
310 //! mechanism is in place)
308 //! 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,
309 //! 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
310 //! "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.
311 void installDefaultImporter() { setImporter(NULL); }
314 void installDefaultImporter() { setImporter(NULL); }
312
315
313 //! set paths that the importer should ignore
316 //! set paths that the importer should ignore
314 void setImporterIgnorePaths(const QStringList& paths);
317 void setImporterIgnorePaths(const QStringList& paths);
315
318
316 //! get paths that the importer should ignore
319 //! get paths that the importer should ignore
317 const QStringList& getImporterIgnorePaths();
320 const QStringList& getImporterIgnorePaths();
318
321
319 //@}
322 //@}
320
323
321 //! 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)
322 static PythonQtPrivate* priv() { return _self->_p; }
325 static PythonQtPrivate* priv() { return _self->_p; }
323
326
324 //! get access to the file importer (if set)
327 //! get access to the file importer (if set)
325 static PythonQtImportFileInterface* importInterface();
328 static PythonQtImportFileInterface* importInterface();
326
329
327 //! 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.
328 //! 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
329 bool handleError();
332 bool handleError();
330
333
331 //! 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
332 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
335 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
333 //! 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
334 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
337 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
335
338
336 //! call the callback if it is set
339 //! call the callback if it is set
337 static void qObjectNoLongerWrappedCB(QObject* o);
340 static void qObjectNoLongerWrappedCB(QObject* o);
338
341
339 signals:
342 signals:
340 //! 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)
341 void pythonStdOut(const QString& str);
344 void pythonStdOut(const QString& str);
342 //! 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)
343 void pythonStdErr(const QString& str);
346 void pythonStdErr(const QString& str);
344
347
345 //! 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
346 void pythonHelpRequest(const QByteArray& cppClassName);
349 void pythonHelpRequest(const QByteArray& cppClassName);
347
350
348
351
349 public:
352 public:
350 //! called by internal help methods
353 //! called by internal help methods
351 PyObject* helpCalled(PythonQtClassInfo* info);
354 PyObject* helpCalled(PythonQtClassInfo* info);
352
355
353 //! returns the found object or NULL
356 //! returns the found object or NULL
354 //! @return new reference
357 //! @return new reference
355 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
358 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
356
359
357 private:
360 private:
358 void initPythonQtModule(bool redirectStdOut);
361 void initPythonQtModule(bool redirectStdOut);
359
362
360 //! callback for stdout redirection, emits pythonStdOut signal
363 //! callback for stdout redirection, emits pythonStdOut signal
361 static void stdOutRedirectCB(const QString& str);
364 static void stdOutRedirectCB(const QString& str);
362 //! callback for stderr redirection, emits pythonStdErr signal
365 //! callback for stderr redirection, emits pythonStdErr signal
363 static void stdErrRedirectCB(const QString& str);
366 static void stdErrRedirectCB(const QString& str);
364
367
365 //! 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
366 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
369 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
367
370
368 PythonQt(int flags);
371 PythonQt(int flags);
369 ~PythonQt();
372 ~PythonQt();
370
373
371 static PythonQt* _self;
374 static PythonQt* _self;
372 static int _uniqueModuleCount;
375 static int _uniqueModuleCount;
373
376
374 PythonQtPrivate* _p;
377 PythonQtPrivate* _p;
375
378
376 };
379 };
377
380
378 //! internal PythonQt details
381 //! internal PythonQt details
379 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
382 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
380
383
381 Q_OBJECT
384 Q_OBJECT
382
385
383 public:
386 public:
384 PythonQtPrivate();
387 PythonQtPrivate();
385 ~PythonQtPrivate();
388 ~PythonQtPrivate();
386
389
387 enum DecoratorTypes {
390 enum DecoratorTypes {
388 StaticDecorator = 1,
391 StaticDecorator = 1,
389 ConstructorDecorator = 2,
392 ConstructorDecorator = 2,
390 DestructorDecorator = 4,
393 DestructorDecorator = 4,
391 InstanceDecorator = 8,
394 InstanceDecorator = 8,
392 AllDecorators = 0xffff
395 AllDecorators = 0xffff
393 };
396 };
394
397
395 //! returns if the id is the id for PythonQtObjectPtr
398 //! returns if the id is the id for PythonQtObjectPtr
396 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
399 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
397
400
398 //! 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)
399 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
402 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
400 //! remove the wrapper ptr again
403 //! remove the wrapper ptr again
401 void removeWrapperPointer(void* obj);
404 void removeWrapperPointer(void* obj);
402
405
403 //! add parent class relation
406 //! add parent class relation
404 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
407 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
405
408
406 //! add a handler for polymorphic downcasting
409 //! add a handler for polymorphic downcasting
407 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
410 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
408
411
409 //! lookup existing classinfo and return new if not yet present
412 //! lookup existing classinfo and return new if not yet present
410 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
413 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
411
414
412 //! 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
413 void removeSignalEmitter(QObject* obj);
416 void removeSignalEmitter(QObject* obj);
414
417
415 //! 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!)
416 PyObject* wrapQObject(QObject* obj);
419 PyObject* wrapQObject(QObject* obj);
417
420
418 //! 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
419 PyObject* wrapPtr(void* ptr, const QByteArray& name);
422 PyObject* wrapPtr(void* ptr, const QByteArray& name);
420
423
421 //! 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)
422 /* 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,
423 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 */
424 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);
425
428
426 //! 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
427 //! (ownership of wrapper is passed to PythonQt)
430 //! (ownership of wrapper is passed to PythonQt)
428 /*! 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!
429
432
430 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.
431 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
432 a variant object that contains such a type.
435 a variant object that contains such a type.
433 */
436 */
434 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);
435
438
436 //! 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
437 //! 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
438 void registerQObjectClassNames(const QStringList& names);
441 void registerQObjectClassNames(const QStringList& names);
439
442
440 //! add a decorator object
443 //! add a decorator object
441 void addDecorators(QObject* o, int decoTypes);
444 void addDecorators(QObject* o, int decoTypes);
442
445
443 //! check if the enum is either part of the \c meta class or contains a scope and is
446 //! check if the enum is either part of the \c meta class or contains a scope and is
444 //! an enum of another known metaobject (and as last resort, of the Qt namespace)
447 //! an enum of another known metaobject (and as last resort, of the Qt namespace)
445 bool isEnumType(const QMetaObject* meta, const QByteArray& name);
448 bool isEnumType(const QMetaObject* meta, const QByteArray& name);
446
449
447 //! helper method that creates a PythonQtClassWrapper object
450 //! helper method that creates a PythonQtClassWrapper object
448 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package = NULL);
451 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package = NULL);
449
452
450 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
453 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
451 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
454 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
452
455
453 //! get the class info for a meta object (if available)
456 //! get the class info for a meta object (if available)
454 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
457 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
455
458
456 //! get the class info for a meta object (if available)
459 //! get the class info for a meta object (if available)
457 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
460 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
458
461
459 //! creates the new module from the given pycode
462 //! creates the new module from the given pycode
460 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
463 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
461
464
462 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
465 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
463 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
466 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
464
467
465 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
468 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
466 static PyObject* dummyTuple();
469 static PyObject* dummyTuple();
467
470
468 private:
471 private:
469
472
470 //! create a new pythonqt class wrapper and place it in the pythonqt module
473 //! create a new pythonqt class wrapper and place it in the pythonqt module
471 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package);
474 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package);
472
475
473 //! get/create new package module (the returned object is a borrowed reference)
476 //! get/create new package module (the returned object is a borrowed reference)
474 PyObject* packageByName(const char* name);
477 PyObject* packageByName(const char* name);
475
478
476 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
479 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
477 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
480 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
478
481
479 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
482 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
480 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
483 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
481
484
482 //! stores the meta info of known Qt classes
485 //! stores the meta info of known Qt classes
483 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
486 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
484
487
485 //! names of qobject derived classes that can be casted to qobject savely
488 //! names of qobject derived classes that can be casted to qobject savely
486 QHash<QByteArray, bool> _knownQObjectClassNames;
489 QHash<QByteArray, bool> _knownQObjectClassNames;
487
490
488 //! stores signal receivers for QObjects
491 //! stores signal receivers for QObjects
489 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
492 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
490
493
491 //! the PythonQt python module
494 //! the PythonQt python module
492 PythonQtObjectPtr _pythonQtModule;
495 PythonQtObjectPtr _pythonQtModule;
493
496
494 //! the importer interface (if set)
497 //! the importer interface (if set)
495 PythonQtImportFileInterface* _importInterface;
498 PythonQtImportFileInterface* _importInterface;
496
499
497 //! the default importer
500 //! the default importer
498 PythonQtQFileImporter* _defaultImporter;
501 PythonQtQFileImporter* _defaultImporter;
499
502
500 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
503 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
501 PythonQtQObjectWrappedCB* _wrappedCB;
504 PythonQtQObjectWrappedCB* _wrappedCB;
502
505
503 QStringList _importIgnorePaths;
506 QStringList _importIgnorePaths;
504
507
505 //! the cpp object wrapper factories
508 //! the cpp object wrapper factories
506 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
509 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
507
510
508 QHash<QByteArray, PyObject*> _packages;
511 QHash<QByteArray, PyObject*> _packages;
509
512
510 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
513 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
511
514
512 int _initFlags;
515 int _initFlags;
513 int _PythonQtObjectPtr_metaId;
516 int _PythonQtObjectPtr_metaId;
514
517
515 friend class PythonQt;
518 friend class PythonQt;
516 };
519 };
517
520
518 #endif
521 #endif
@@ -1,1095 +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, const QMetaObject* 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 (meta && PythonQt::priv()->isEnumType(meta, info.name)) {
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
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
725 // the pointer here...
724 // 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
725 v = qVariantFromValue(wrap->_wrappedPtr);
727 v = qVariantFromValue(wrap->_wrappedPtr);
726 }
728 }
727 } else {
729 } else {
728 // this gives us a QObject pointer
730 // this gives us a QObject pointer
729 QObject* myObject = wrap->_obj;
731 QObject* myObject = wrap->_obj;
730 v = qVariantFromValue(myObject);
732 v = qVariantFromValue(myObject);
731 }
733 }
732 return v;
734 return v;
733 } else if (val->ob_type==&PyDict_Type) {
735 } else if (val->ob_type==&PyDict_Type) {
734 type = QVariant::Map;
736 type = QVariant::Map;
735 } 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)) {
736 type = QVariant::List;
738 type = QVariant::List;
737 } else if (val == Py_None) {
739 } else if (val == Py_None) {
738 // none is invalid
740 // none is invalid
739 type = QVariant::Invalid;
741 type = QVariant::Invalid;
740 } else {
742 } else {
741 // this used to be:
743 // this used to be:
742 // type = QVariant::String;
744 // type = QVariant::String;
743 // but now we want to transport the Python Objects directly:
745 // but now we want to transport the Python Objects directly:
744 PythonQtObjectPtr o(val);
746 PythonQtObjectPtr o(val);
745 v = qVariantFromValue(o);
747 v = qVariantFromValue(o);
746 return v;
748 return v;
747 }
749 }
748 }
750 }
749 // special type request:
751 // special type request:
750 switch (type) {
752 switch (type) {
751 case QVariant::Invalid:
753 case QVariant::Invalid:
752 return v;
754 return v;
753 break;
755 break;
754 case QVariant::Int:
756 case QVariant::Int:
755 {
757 {
756 int d = PyObjGetInt(val, false, ok);
758 int d = PyObjGetInt(val, false, ok);
757 if (ok) return QVariant(d);
759 if (ok) return QVariant(d);
758 }
760 }
759 break;
761 break;
760 case QVariant::UInt:
762 case QVariant::UInt:
761 {
763 {
762 int d = PyObjGetInt(val, false,ok);
764 int d = PyObjGetInt(val, false,ok);
763 if (ok) v = QVariant((unsigned int)d);
765 if (ok) v = QVariant((unsigned int)d);
764 }
766 }
765 break;
767 break;
766 case QVariant::Bool:
768 case QVariant::Bool:
767 {
769 {
768 int d = PyObjGetBool(val,false,ok);
770 int d = PyObjGetBool(val,false,ok);
769 if (ok) v = QVariant((bool)(d!=0));
771 if (ok) v = QVariant((bool)(d!=0));
770 }
772 }
771 break;
773 break;
772 case QVariant::Double:
774 case QVariant::Double:
773 {
775 {
774 double d = PyObjGetDouble(val,false,ok);
776 double d = PyObjGetDouble(val,false,ok);
775 if (ok) v = QVariant(d);
777 if (ok) v = QVariant(d);
776 break;
778 break;
777 }
779 }
778 case QMetaType::Float:
780 case QMetaType::Float:
779 {
781 {
780 float d = (float) PyObjGetDouble(val,false,ok);
782 float d = (float) PyObjGetDouble(val,false,ok);
781 if (ok) v = qVariantFromValue(d);
783 if (ok) v = qVariantFromValue(d);
782 break;
784 break;
783 }
785 }
784 case QMetaType::Long:
786 case QMetaType::Long:
785 {
787 {
786 long d = (long) PyObjGetLongLong(val,false,ok);
788 long d = (long) PyObjGetLongLong(val,false,ok);
787 if (ok) v = qVariantFromValue(d);
789 if (ok) v = qVariantFromValue(d);
788 break;
790 break;
789 }
791 }
790 case QMetaType::ULong:
792 case QMetaType::ULong:
791 {
793 {
792 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
794 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
793 if (ok) v = qVariantFromValue(d);
795 if (ok) v = qVariantFromValue(d);
794 break;
796 break;
795 }
797 }
796 case QMetaType::Short:
798 case QMetaType::Short:
797 {
799 {
798 short d = (short) PyObjGetInt(val,false,ok);
800 short d = (short) PyObjGetInt(val,false,ok);
799 if (ok) v = qVariantFromValue(d);
801 if (ok) v = qVariantFromValue(d);
800 break;
802 break;
801 }
803 }
802 case QMetaType::UShort:
804 case QMetaType::UShort:
803 {
805 {
804 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
806 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
805 if (ok) v = qVariantFromValue(d);
807 if (ok) v = qVariantFromValue(d);
806 break;
808 break;
807 }
809 }
808 case QMetaType::Char:
810 case QMetaType::Char:
809 {
811 {
810 char d = (char) PyObjGetInt(val,false,ok);
812 char d = (char) PyObjGetInt(val,false,ok);
811 if (ok) v = qVariantFromValue(d);
813 if (ok) v = qVariantFromValue(d);
812 break;
814 break;
813 }
815 }
814 case QMetaType::UChar:
816 case QMetaType::UChar:
815 {
817 {
816 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
818 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
817 if (ok) v = qVariantFromValue(d);
819 if (ok) v = qVariantFromValue(d);
818 break;
820 break;
819 }
821 }
820
822
821 case QVariant::ByteArray:
823 case QVariant::ByteArray:
822 case QVariant::String:
824 case QVariant::String:
823 {
825 {
824 bool ok;
826 bool ok;
825 v = QVariant(PyObjGetString(val, false, ok));
827 v = QVariant(PyObjGetString(val, false, ok));
826 }
828 }
827 break;
829 break;
828
830
829 // these are important for MeVisLab
831 // these are important for MeVisLab
830 case QVariant::Map:
832 case QVariant::Map:
831 {
833 {
832 if (PyMapping_Check(val)) {
834 if (PyMapping_Check(val)) {
833 QMap<QString,QVariant> map;
835 QMap<QString,QVariant> map;
834 PyObject* items = PyMapping_Items(val);
836 PyObject* items = PyMapping_Items(val);
835 if (items) {
837 if (items) {
836 int count = PyList_Size(items);
838 int count = PyList_Size(items);
837 PyObject* value;
839 PyObject* value;
838 PyObject* key;
840 PyObject* key;
839 PyObject* tuple;
841 PyObject* tuple;
840 for (int i = 0;i<count;i++) {
842 for (int i = 0;i<count;i++) {
841 tuple = PyList_GetItem(items,i);
843 tuple = PyList_GetItem(items,i);
842 key = PyTuple_GetItem(tuple, 0);
844 key = PyTuple_GetItem(tuple, 0);
843 value = PyTuple_GetItem(tuple, 1);
845 value = PyTuple_GetItem(tuple, 1);
844 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
846 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
845 }
847 }
846 Py_DECREF(items);
848 Py_DECREF(items);
847 v = map;
849 v = map;
848 }
850 }
849 }
851 }
850 }
852 }
851 break;
853 break;
852 case QVariant::List:
854 case QVariant::List:
853 if (PySequence_Check(val)) {
855 if (PySequence_Check(val)) {
854 QVariantList list;
856 QVariantList list;
855 int count = PySequence_Size(val);
857 int count = PySequence_Size(val);
856 PyObject* value;
858 PyObject* value;
857 for (int i = 0;i<count;i++) {
859 for (int i = 0;i<count;i++) {
858 value = PySequence_GetItem(val,i);
860 value = PySequence_GetItem(val,i);
859 list.append(PyObjToQVariant(value, -1));
861 list.append(PyObjToQVariant(value, -1));
860 }
862 }
861 v = list;
863 v = list;
862 }
864 }
863 break;
865 break;
864 case QVariant::StringList:
866 case QVariant::StringList:
865 {
867 {
866 bool ok;
868 bool ok;
867 QStringList l = PyObjToStringList(val, false, ok);
869 QStringList l = PyObjToStringList(val, false, ok);
868 if (ok) {
870 if (ok) {
869 v = l;
871 v = l;
870 }
872 }
871 }
873 }
872 break;
874 break;
873
875
874 default:
876 default:
875 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
877 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
876 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
878 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
877 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
879 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
878 // 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
879 v = QVariant(type, wrap->_wrappedPtr);
881 v = QVariant(type, wrap->_wrappedPtr);
880 } else {
882 } else {
881 v = QVariant();
883 v = QVariant();
882 }
884 }
883 } else {
885 } else {
884 v = QVariant();
886 v = QVariant();
885 }
887 }
886 }
888 }
887 return v;
889 return v;
888 }
890 }
889
891
890 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
892 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
891 {
893 {
892 if (str.isNull()) {
894 if (str.isNull()) {
893 return PyString_FromString("");
895 return PyString_FromString("");
894 } else {
896 } else {
895 #ifdef WIN32
897 #ifdef WIN32
896 // return PyString_FromString(str.toLatin1().data());
898 // return PyString_FromString(str.toLatin1().data());
897 return PyUnicode_FromUnicode(str.utf16(), str.length());
899 return PyUnicode_FromUnicode(str.utf16(), str.length());
898 #else
900 #else
899 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);
900 #endif
902 #endif
901 }
903 }
902 }
904 }
903
905
904 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
906 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
905 {
907 {
906 PyObject* result = PyTuple_New(list.count());
908 PyObject* result = PyTuple_New(list.count());
907 int i = 0;
909 int i = 0;
908 QString str;
910 QString str;
909 foreach (str, list) {
911 foreach (str, list) {
910 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
912 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
911 i++;
913 i++;
912 }
914 }
913 // why is the error state bad after this?
915 // why is the error state bad after this?
914 PyErr_Clear();
916 PyErr_Clear();
915 return result;
917 return result;
916 }
918 }
917
919
918 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
920 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
919 {
921 {
920 PyObject* result = PyList_New(list.count());
922 PyObject* result = PyList_New(list.count());
921 int i = 0;
923 int i = 0;
922 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
924 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
923 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
925 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
924 i++;
926 i++;
925 }
927 }
926 return result;
928 return result;
927 }
929 }
928
930
929 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
931 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
930 {
932 {
931 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
933 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
932 }
934 }
933
935
934 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
936 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
935 PyObject* result = PyDict_New();
937 PyObject* result = PyDict_New();
936 QVariantMap::const_iterator t = m.constBegin();
938 QVariantMap::const_iterator t = m.constBegin();
937 PyObject* key;
939 PyObject* key;
938 PyObject* val;
940 PyObject* val;
939 for (;t!=m.end();t++) {
941 for (;t!=m.end();t++) {
940 key = QStringToPyObject(t.key());
942 key = QStringToPyObject(t.key());
941 val = QVariantToPyObject(t.value());
943 val = QVariantToPyObject(t.value());
942 PyDict_SetItem(result, key, val);
944 PyDict_SetItem(result, key, val);
943 Py_DECREF(key);
945 Py_DECREF(key);
944 Py_DECREF(val);
946 Py_DECREF(val);
945 }
947 }
946 return result;
948 return result;
947 }
949 }
948
950
949 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
951 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
950 PyObject* result = PyTuple_New(l.count());
952 PyObject* result = PyTuple_New(l.count());
951 int i = 0;
953 int i = 0;
952 QVariant v;
954 QVariant v;
953 foreach (v, l) {
955 foreach (v, l) {
954 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
956 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
955 i++;
957 i++;
956 }
958 }
957 // why is the error state bad after this?
959 // why is the error state bad after this?
958 PyErr_Clear();
960 PyErr_Clear();
959 return result;
961 return result;
960 }
962 }
961
963
962 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
964 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
963 {
965 {
964 PyObject* result = PyTuple_New(list->count());
966 PyObject* result = PyTuple_New(list->count());
965 int i = 0;
967 int i = 0;
966 foreach (void* value, *list) {
968 foreach (void* value, *list) {
967 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
969 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
968 i++;
970 i++;
969 }
971 }
970 return result;
972 return result;
971 }
973 }
972
974
973 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*/)
974 {
976 {
975 bool result = false;
977 bool result = false;
976 if (PySequence_Check(obj)) {
978 if (PySequence_Check(obj)) {
977 result = true;
979 result = true;
978 int count = PySequence_Size(obj);
980 int count = PySequence_Size(obj);
979 PyObject* value;
981 PyObject* value;
980 for (int i = 0;i<count;i++) {
982 for (int i = 0;i<count;i++) {
981 value = PySequence_GetItem(obj,i);
983 value = PySequence_GetItem(obj,i);
982 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
984 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
983 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
985 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
984 bool ok;
986 bool ok;
985 void* object = castWrapperTo(wrap, type, ok);
987 void* object = castWrapperTo(wrap, type, ok);
986 if (ok) {
988 if (ok) {
987 list->append(object);
989 list->append(object);
988 } else {
990 } else {
989 result = false;
991 result = false;
990 break;
992 break;
991 }
993 }
992 }
994 }
993 }
995 }
994 }
996 }
995 return result;
997 return result;
996 }
998 }
997
999
998 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1000 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
999 {
1001 {
1000 int idx = typeName.indexOf("<");
1002 int idx = typeName.indexOf("<");
1001 if (idx>0) {
1003 if (idx>0) {
1002 int idx2 = typeName.indexOf(">");
1004 int idx2 = typeName.indexOf(">");
1003 if (idx2>0) {
1005 if (idx2>0) {
1004 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1006 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1005 return QMetaType::type(innerType.constData());
1007 return QMetaType::type(innerType.constData());
1006 }
1008 }
1007 }
1009 }
1008 return QMetaType::Void;
1010 return QMetaType::Void;
1009 }
1011 }
1010
1012
1011
1013
1012
1014
1013 QString PythonQtConv::qVariantToString(const QVariant& v) {
1015 QString PythonQtConv::qVariantToString(const QVariant& v) {
1014 return CPPObjectToString(v.userType(), v.constData());
1016 return CPPObjectToString(v.userType(), v.constData());
1015 }
1017 }
1016
1018
1017 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1019 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1018 QString r;
1020 QString r;
1019 switch (type) {
1021 switch (type) {
1020 case QVariant::Size: {
1022 case QVariant::Size: {
1021 const QSize* s = static_cast<const QSize*>(data);
1023 const QSize* s = static_cast<const QSize*>(data);
1022 r = QString::number(s->width()) + ", " + QString::number(s->height());
1024 r = QString::number(s->width()) + ", " + QString::number(s->height());
1023 }
1025 }
1024 break;
1026 break;
1025 case QVariant::SizeF: {
1027 case QVariant::SizeF: {
1026 const QSizeF* s = static_cast<const QSizeF*>(data);
1028 const QSizeF* s = static_cast<const QSizeF*>(data);
1027 r = QString::number(s->width()) + ", " + QString::number(s->height());
1029 r = QString::number(s->width()) + ", " + QString::number(s->height());
1028 }
1030 }
1029 break;
1031 break;
1030 case QVariant::Point: {
1032 case QVariant::Point: {
1031 const QPoint* s = static_cast<const QPoint*>(data);
1033 const QPoint* s = static_cast<const QPoint*>(data);
1032 r = QString::number(s->x()) + ", " + QString::number(s->y());
1034 r = QString::number(s->x()) + ", " + QString::number(s->y());
1033 }
1035 }
1034 break;
1036 break;
1035 case QVariant::PointF: {
1037 case QVariant::PointF: {
1036 const QPointF* s = static_cast<const QPointF*>(data);
1038 const QPointF* s = static_cast<const QPointF*>(data);
1037 r = QString::number(s->x()) + ", " + QString::number(s->y());
1039 r = QString::number(s->x()) + ", " + QString::number(s->y());
1038 }
1040 }
1039 break;
1041 break;
1040 case QVariant::Rect: {
1042 case QVariant::Rect: {
1041 const QRect* s = static_cast<const QRect*>(data);
1043 const QRect* s = static_cast<const QRect*>(data);
1042 r = QString::number(s->x()) + ", " + QString::number(s->y());
1044 r = QString::number(s->x()) + ", " + QString::number(s->y());
1043 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1045 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1044 }
1046 }
1045 break;
1047 break;
1046 case QVariant::RectF: {
1048 case QVariant::RectF: {
1047 const QRectF* s = static_cast<const QRectF*>(data);
1049 const QRectF* s = static_cast<const QRectF*>(data);
1048 r = QString::number(s->x()) + ", " + QString::number(s->y());
1050 r = QString::number(s->x()) + ", " + QString::number(s->y());
1049 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1051 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1050 }
1052 }
1051 break;
1053 break;
1052 case QVariant::Date: {
1054 case QVariant::Date: {
1053 const QDate* s = static_cast<const QDate*>(data);
1055 const QDate* s = static_cast<const QDate*>(data);
1054 r = s->toString(Qt::ISODate);
1056 r = s->toString(Qt::ISODate);
1055 }
1057 }
1056 break;
1058 break;
1057 case QVariant::DateTime: {
1059 case QVariant::DateTime: {
1058 const QDateTime* s = static_cast<const QDateTime*>(data);
1060 const QDateTime* s = static_cast<const QDateTime*>(data);
1059 r = s->toString(Qt::ISODate);
1061 r = s->toString(Qt::ISODate);
1060 }
1062 }
1061 break;
1063 break;
1062 case QVariant::Time: {
1064 case QVariant::Time: {
1063 const QTime* s = static_cast<const QTime*>(data);
1065 const QTime* s = static_cast<const QTime*>(data);
1064 r = s->toString(Qt::ISODate);
1066 r = s->toString(Qt::ISODate);
1065 }
1067 }
1066 break;
1068 break;
1067 case QVariant::Pixmap:
1069 case QVariant::Pixmap:
1068 {
1070 {
1069 const QPixmap* s = static_cast<const QPixmap*>(data);
1071 const QPixmap* s = static_cast<const QPixmap*>(data);
1070 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1072 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1071 }
1073 }
1072 break;
1074 break;
1073 case QVariant::Image:
1075 case QVariant::Image:
1074 {
1076 {
1075 const QImage* s = static_cast<const QImage*>(data);
1077 const QImage* s = static_cast<const QImage*>(data);
1076 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1078 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1077 }
1079 }
1078 break;
1080 break;
1079 case QVariant::Url:
1081 case QVariant::Url:
1080 {
1082 {
1081 const QUrl* s = static_cast<const QUrl*>(data);
1083 const QUrl* s = static_cast<const QUrl*>(data);
1082 r = s->toString();
1084 r = s->toString();
1083 }
1085 }
1084 break;
1086 break;
1085 //TODO: add more printing for other variant types
1087 //TODO: add more printing for other variant types
1086 default:
1088 default:
1087 // 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
1088 // (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!
1089 if (type>0 && type < (int)QVariant::UserType) {
1091 if (type>0 && type < (int)QVariant::UserType) {
1090 QVariant v(type, data);
1092 QVariant v(type, data);
1091 r = v.toString();
1093 r = v.toString();
1092 }
1094 }
1093 }
1095 }
1094 return r;
1096 return r;
1095 }
1097 }
@@ -1,507 +1,508
1 #ifndef _PYTHONQTDOC_H
1 #ifndef _PYTHONQTDOC_H
2 #define _PYTHONQTDOC_H
2 #define _PYTHONQTDOC_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 PythonQtDoc.h
38 // \file PythonQtDoc.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-10
41 // \date 2006-10
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 /*!
45 /*!
46 \if USE_GLOBAL_DOXYGEN_DOC
46 \if USE_GLOBAL_DOXYGEN_DOC
47 \page PythonQtPage PythonQt Overview
47 \page PythonQtPage PythonQt Overview
48 \else
48 \else
49 \mainpage PythonQt Overview
49 \mainpage PythonQt Overview
50 \endif
50 \endif
51
51
52 \section Introduction
52 \section Introduction
53
53
54 \b PythonQt is a dynamic Python (http://www.python.org) binding for Qt (http://www.qtsoftware.com).
54 \b PythonQt is a dynamic Python (http://www.python.org) binding for Qt (http://www.qtsoftware.com).
55 It offers an easy way to embed the Python scripting language into
55 It offers an easy way to embed the Python scripting language into
56 your Qt applications. It makes heavy use of the QMetaObject system and thus requires Qt4.x.
56 your Qt applications. It makes heavy use of the QMetaObject system and thus requires Qt4.x.
57
57
58 The focus of PythonQt is on embedding Python into an existing C++ application, not on writing the whole
58 The focus of PythonQt is on embedding Python into an existing C++ application, not on writing the whole
59 application completely in Python. If you want to write your whole application in Python,
59 application completely in Python. If you want to write your whole application in Python,
60 you should use <a href="http://www.riverbankcomputing.co.uk/pyqt/">PyQt</a> instead.
60 you should use <a href="http://www.riverbankcomputing.co.uk/pyqt/">PyQt</a> instead.
61
61
62 If you are looking for a simple way to embed Python objects into your C++/Qt Application
62 If you are looking for a simple way to embed Python objects into your C++/Qt Application
63 and to script parts of your application via Python, PythonQt is the way to go!
63 and to script parts of your application via Python, PythonQt is the way to go!
64
64
65 PythonQt is a stable library that was developed to make the
65 PythonQt is a stable library that was developed to make the
66 Image Processing and Visualization platform MeVisLab (http://www.mevislab.de)
66 Image Processing and Visualization platform MeVisLab (http://www.mevislab.de)
67 scriptable from Python.
67 scriptable from Python.
68
68
69 \section Download
69 \section Download
70
70
71 PythonQt is hosted on SourceForge at http://sourceforge.net/projects/pythonqt , you can access it via SVN
71 PythonQt is hosted on SourceForge at http://sourceforge.net/projects/pythonqt , you can access it via SVN
72 or download a tarball.
72 or download a tarball.
73
73
74 \section Licensing
74 \section Licensing
75
75
76 PythonQt is distributed under the LGPL license, so it pairs well with the LGPL of the Qt 4.5 release and allows
76 PythonQt is distributed under the LGPL license, so it pairs well with the LGPL of the Qt 4.5 release and allows
77 to be used in commercial applications when following the LGPL 2.1 obligations.
77 to be used in commercial applications when following the LGPL 2.1 obligations.
78
78
79 \section LicensingWrapper Licensing of Wrapper Generator
79 \section LicensingWrapper Licensing of Wrapper Generator
80
80
81 The build system of PythonQt makes use of a modified version of the GPL'ed QtScript generator,
81 The build system of PythonQt makes use of a modified version of the GPL'ed QtScript generator,
82 located in the "generator" directory.
82 located in the "generator" directory.
83
83
84 See http://labs.trolltech.com/page/Projects/QtScript/Generator for details on the original project.
84 See http://labs.trolltech.com/page/Projects/QtScript/Generator for details on the original project.
85 Thanks a lot to the QtJambi guys and the QtScript Generator project for the C++ parser and
85 Thanks a lot to the QtJambi guys and the QtScript Generator project for the C++ parser and
86 Qt typesystem files!
86 Qt typesystem files!
87
87
88 The PythonQt wrappers generated by the generator located in the "generated_cpp" directory are distributed under the LGPL,
88 The PythonQt wrappers generated by the generator located in the "generated_cpp" directory are distributed under the LGPL,
89 they are not restriced by the GPL.
89 they are not restriced by the GPL.
90
90
91 The generated wrappers are pre-generated and checked-in for Qt 4.4.3, so you only need to build and run the
91 The generated wrappers are pre-generated and checked-in for Qt 4.4.3, so you only need to build and run the
92 generator when you want to build additional wrappers or you want to upgrade/downgrade to an newer Qt version.
92 generator when you want to build additional wrappers or you want to upgrade/downgrade to an newer Qt version.
93 You may use the generator to generate C++ bindings for your own C++ classes (e.g. to make them deriveable in Python),
93 You may use the generator to generate C++ bindings for your own C++ classes (e.g. to make them deriveable in Python),
94 , but this is currently not documented and involves creating your own typesystem files.
94 , but this is currently not documented and involves creating your own typesystem files.
95
95
96 \section Features
96 \section Features
97
97
98 The following are the built-in features of the PythonQt library:
98 The following are the built-in features of the PythonQt library:
99
99
100 - Access all \b slots, \b properties, children and registered enums of any QObject derived class from Python
100 - Access all \b slots, \b properties, children and registered enums of any QObject derived class from Python
101 - Connecting Qt Signals to Python functions (both from within Python and from C++)
101 - Connecting Qt Signals to Python functions (both from within Python and from C++)
102 - Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
102 - Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
103 - Convenient conversions to/from QVariant for PythonQtObjectPtr.
103 - Convenient conversions to/from QVariant for PythonQtObjectPtr.
104 - Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
104 - Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
105 - Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
105 - Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
106 - StdOut/Err redirection to Qt signals instead of cout
106 - StdOut/Err redirection to Qt signals instead of cout
107 - Interface for creating your own \c import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
107 - Interface for creating your own \c import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
108 - Mapping of plain-old-datatypes and ALL QVariant types to and from Python
108 - Mapping of plain-old-datatypes and ALL QVariant types to and from Python
109 - Support for wrapping of user QVariant types which are registerd via QMetaType
109 - Support for wrapping of user QVariant types which are registerd via QMetaType
110 - Support for Qt namespace (with all enumerators)
110 - Support for Qt namespace (with all enumerators)
111 - All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
111 - All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
112 - No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the \b moc)
112 - No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the \b moc)
113 - Multiple inheritance for C++ objects (e.g. a QWidget is derived from QObject and QPaintDevice, PythonQt will automatically cast a QWidget to a QPaintDevice when needed)
113 - Multiple inheritance for C++ objects (e.g. a QWidget is derived from QObject and QPaintDevice, PythonQt will automatically cast a QWidget to a QPaintDevice when needed)
114 - Polymorphic downcasting (if e.g. PythonQt sees a QEvent, it can downcast it depending on the type(), so the Python e.g. sees a QPaintEvent instead of a plain QEvent)
114 - Polymorphic downcasting (if e.g. PythonQt sees a QEvent, it can downcast it depending on the type(), so the Python e.g. sees a QPaintEvent instead of a plain QEvent)
115 - Deriving C++ objects from Python and overwriting virtual method with a Python implementation (requires usage of wrapper generator or manual work!)
115 - Deriving C++ objects from Python and overwriting virtual method with a Python implementation (requires usage of wrapper generator or manual work!)
116 - Extensible handler for Python/C++ conversion of complex types, e.g. mapping of QVector<SomeObject> to/from a Python array
116 - Extensible handler for Python/C++ conversion of complex types, e.g. mapping of QVector<SomeObject> to/from a Python array
117
117
118 \section FeaturesQtAll Features (with PythonQt_QtAll linked in)
118 \section FeaturesQtAll Features (with PythonQt_QtAll linked in)
119
119
120 Thanks to the new wrapper generator, PythonQt now offers the additional PythonQt_QtAll library which wraps the complete Qt API, including all C++ classes and all non-slots on QObject derived classes.
120 Thanks to the new wrapper generator, PythonQt now offers the additional PythonQt_QtAll library which wraps the complete Qt API, including all C++ classes and all non-slots on QObject derived classes.
121 This offers the following features:
121 This offers the following features:
122
122
123 - Complete Qt API wrapped and accessible
123 - Complete Qt API wrapped and accessible
124 - The following modules are available as submodule of the PythonQt module:
124 - The following modules are available as submodule of the PythonQt module:
125 - QtCore
125 - QtCore
126 - QtGui
126 - QtGui
127 - QtNetwork
127 - QtNetwork
128 - QtOpenGL
128 - QtOpenGL
129 - QtSql
129 - QtSql
130 - QtSvg
130 - QtSvg
131 - QtUiTools
131 - QtUiTools
132 - QtWebKit
132 - QtWebKit
133 - QtXml
133 - QtXml
134 - QtXmlPatterns
134 - QtXmlPatterns
135 - (phonon, QtHelp, assistant, designer are currently not supported, this would require some additional effort on the code generator)
135 - (phonon, QtHelp, assistant, designer are currently not supported, this would require some additional effort on the code generator)
136 - For convenience, all classes are also available in the PythonQt.Qt module, for people who do not care in which module a class is located
136 - For convenience, all classes are also available in the PythonQt.Qt module, for people who do not care in which module a class is located
137 - Any Qt class that has virtual methods can be easily derived from Python and the virtual methods can be reimplemented in Python
137 - Any Qt class that has virtual methods can be easily derived from Python and the virtual methods can be reimplemented in Python
138 - Polymorphic downcasting on QEvent, QGraphicsItem, QStyleOption, ...
138 - Polymorphic downcasting on QEvent, QGraphicsItem, QStyleOption, ...
139 - Multiple inheritance support (e.g. QGraphicsTextItem is a QObject AND a QGraphicsItem, PythonQt will handle this well)
139 - Multiple inheritance support (e.g. QGraphicsTextItem is a QObject AND a QGraphicsItem, PythonQt will handle this well)
140
140
141 \section Comparision Comparision with PyQt
141 \section Comparision Comparision with PyQt
142
142
143 - PythonQt is not as Pythonic as PyQt in many details (e.g. operator mapping, pickling, translation support, ...) and it is maily thought for embedding and intercommunication between Qt/Cpp and Python
143 - PythonQt is not as Pythonic as PyQt in many details (e.g. operator mapping, pickling, translation support, ...) and it is maily thought for embedding and intercommunication between Qt/Cpp and Python
144 - PythonQt allows to communicate in both directions, e.g. calling a Python object from C++ AND calling a C++ method from Python, while PyQt only handles the Python->C++ direction
144 - PythonQt allows to communicate in both directions, e.g. calling a Python object from C++ AND calling a C++ method from Python, while PyQt only handles the Python->C++ direction
145 - PythonQt offers properties as Python attributes, while PyQt offers them as setter/getter methods (e.g. QWidget.width is a property in PythonQt and a method in PyQt)
145 - PythonQt offers properties as Python attributes, while PyQt offers them as setter/getter methods (e.g. QWidget.width is a property in PythonQt and a method in PyQt)
146 - PythonQt does not auto-convert objects, e.g. when a QPainter expects a QBrush and you pass a QColor, it is rejected, you will need to write QBrush(QColor(1,2,3)) instead
146 - PythonQt does not auto-convert objects, e.g. when a QPainter expects a QBrush and you pass a QColor, it is rejected, you will need to write QBrush(QColor(1,2,3)) instead
147 - PythonQt returns/handles enums/flags as integers, which can cause problems on overloads that take ints and enums, a future version might use an own enum type (like PyQt does)
147 - Probably there are lots of details that differ, I do not know PyQt that well to list them all.
148 - Probably there are lots of details that differ, I do not know PyQt that well to list them all.
148
149
149
150
150 \section Interface
151 \section Interface
151
152
152 The main interface to PythonQt is the PythonQt singleton.
153 The main interface to PythonQt is the PythonQt singleton.
153 PythonQt needs to be initialized via PythonQt::init() once.
154 PythonQt needs to be initialized via PythonQt::init() once.
154 Afterwards you communicate with the singleton via PythonQt::self().
155 Afterwards you communicate with the singleton via PythonQt::self().
155 PythonQt offers a complete Qt binding, which
156 PythonQt offers a complete Qt binding, which
156 needs to be enabled via PythonQt_QtAll::init().
157 needs to be enabled via PythonQt_QtAll::init().
157
158
158
159
159 \section Datatype Datatype Mapping
160 \section Datatype Datatype Mapping
160
161
161 The following table shows the mapping between Python and Qt objects:
162 The following table shows the mapping between Python and Qt objects:
162 <table>
163 <table>
163 <tr><th>Qt/C++</th><th>Python</th></tr>
164 <tr><th>Qt/C++</th><th>Python</th></tr>
164 <tr><td>bool</td><td>bool</td></tr>
165 <tr><td>bool</td><td>bool</td></tr>
165 <tr><td>double</td><td>float</td></tr>
166 <tr><td>double</td><td>float</td></tr>
166 <tr><td>float</td><td>float</td></tr>
167 <tr><td>float</td><td>float</td></tr>
167 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
168 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
168 <tr><td>long</td><td>integer</td></tr>
169 <tr><td>long</td><td>integer</td></tr>
169 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
170 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
170 <tr><td>QString</td><td>unicode string</td></tr>
171 <tr><td>QString</td><td>unicode string</td></tr>
171 <tr><td>QByteArray</td><td>str</td></tr>
172 <tr><td>QByteArray</td><td>str</td></tr>
172 <tr><td>char*</td><td>str</td></tr>
173 <tr><td>char*</td><td>str</td></tr>
173 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
174 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
174 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
175 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
175 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
176 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
176 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
177 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
177 <tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant wrapper that supports complete API of the respective Qt classes</td></tr>
178 <tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant wrapper that supports complete API of the respective Qt classes</td></tr>
178 <tr><td>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional information/wrapping provided by registerCPPClass()</td></tr>
179 <tr><td>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional information/wrapping provided by registerCPPClass()</td></tr>
179 <tr><td>QList<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
180 <tr><td>QList<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
180 <tr><td>EnumType</td><td>integer (all enums that are known via the moc and the Qt namespace are supported)</td></tr>
181 <tr><td>EnumType</td><td>integer (all enums that are known via the moc and the Qt namespace are supported)</td></tr>
181 <tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
182 <tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
182 <tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
183 <tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
183 <tr><td>PyObject</td><td>PyObject</td></tr>
184 <tr><td>PyObject</td><td>PyObject</td></tr>
184 </table>
185 </table>
185
186
186 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
187 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
187 a Qt slot.
188 a Qt slot.
188 QVariants are mapped recursively as given above, e.g. a dictionary can
189 QVariants are mapped recursively as given above, e.g. a dictionary can
189 contain lists of dictionaries of doubles.
190 contain lists of dictionaries of doubles.
190 For example a QVariant of type "String" is mapped to a python unicode string.
191 For example a QVariant of type "String" is mapped to a python unicode string.
191 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
192 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
192
193
193 \section QObject QObject Wrapping
194 \section QObject QObject Wrapping
194
195
195 All classes derived from QObject are automatically wrapped with a python wrapper class
196 All classes derived from QObject are automatically wrapped with a python wrapper class
196 when they become visible to the Python interpreter. This can happen via
197 when they become visible to the Python interpreter. This can happen via
197 - the PythonQt::addObject() method
198 - the PythonQt::addObject() method
198 - when a Qt \b slot returns a QObject derived object to python
199 - when a Qt \b slot returns a QObject derived object to python
199 - when a Qt \b signal contains a QObject and is connected to a python function
200 - when a Qt \b signal contains a QObject and is connected to a python function
200
201
201 It is important that you call PythonQt::registerClass() for any QObject derived class
202 It is important that you call PythonQt::registerClass() for any QObject derived class
202 that may become visible to Python, except when you add it via PythonQt::addObject().
203 that may become visible to Python, except when you add it via PythonQt::addObject().
203 This will register the complete parent hierachy of the registered class, so that
204 This will register the complete parent hierachy of the registered class, so that
204 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
205 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
205 parents).
206 parents).
206
207
207 From Python, you can talk to the returned QObjects in a natural way by calling
208 From Python, you can talk to the returned QObjects in a natural way by calling
208 their slots and receiving the return values. You can also read/write all
209 their slots and receiving the return values. You can also read/write all
209 properties of the objects as if they where normal python properties.
210 properties of the objects as if they where normal python properties.
210
211
211 In addition to this, the wrapped objects support
212 In addition to this, the wrapped objects support
212 - className() - returns a string that reprents the classname of the QObject
213 - className() - returns a string that reprents the classname of the QObject
213 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
214 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
214 - delete() - deletes the object (use with care, especially if you passed the ownership to C++)
215 - delete() - deletes the object (use with care, especially if you passed the ownership to C++)
215 - connect(signal, function) - connect the signal of the given object to a python function
216 - connect(signal, function) - connect the signal of the given object to a python function
216 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
217 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
217 - disconnect(signal, function) - disconnect the signal of the given object from a python function
218 - disconnect(signal, function) - disconnect the signal of the given object from a python function
218 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
219 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
219 - children() - returns the children of the object
220 - children() - returns the children of the object
220 - setParent(QObject) - set the parent
221 - setParent(QObject) - set the parent
221 - QObject* parent() - get the parent
222 - QObject* parent() - get the parent
222
223
223 The below example shows how to connect signals in Python:
224 The below example shows how to connect signals in Python:
224
225
225 \code
226 \code
226 # define a signal handler function
227 # define a signal handler function
227 def someFunction(flag):
228 def someFunction(flag):
228 print flag
229 print flag
229
230
230 # button1 is a QPushButton that has been added to Python via addObject()
231 # button1 is a QPushButton that has been added to Python via addObject()
231 # connect the clicked signal to a python function:
232 # connect the clicked signal to a python function:
232 button1.connect("clicked(bool)", someFunction)
233 button1.connect("clicked(bool)", someFunction)
233
234
234 \endcode
235 \endcode
235
236
236 \section CPP CPP Wrapping
237 \section CPP CPP Wrapping
237
238
238 You can create dedicated wrapper QObjects for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
239 You can create dedicated wrapper QObjects for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
239 and adding your factory via addWrapperFactory().
240 and adding your factory via addWrapperFactory().
240 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
241 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
241 and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
242 and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
242 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
243 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
243 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
244 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
244
245
245 \section MetaObject Meta Object/Class access
246 \section MetaObject Meta Object/Class access
246
247
247 For each known C++ class, PythonQt provides a Python class. These classes are visible
248 For each known C++ class, PythonQt provides a Python class. These classes are visible
248 inside of the "PythonQt" python module or in subpackages if a package is given when the class is registered.
249 inside of the "PythonQt" python module or in subpackages if a package is given when the class is registered.
249
250
250 A Meta class supports:
251 A Meta class supports:
251
252
252 - access to all declared enum values
253 - access to all declared enum values
253 - constructors
254 - constructors
254 - static methods
255 - static methods
255 - unbound non-static methods
256 - unbound non-static methods
256 - help() and className()
257 - help() and className()
257
258
258 From within Python, you can import the module "PythonQt" to access these classes and the Qt namespace.
259 From within Python, you can import the module "PythonQt" to access these classes and the Qt namespace.
259
260
260 \code
261 \code
261 from PythonQt import QtCore
262 from PythonQt import QtCore
262
263
263 # namespace access:
264 # namespace access:
264 print QtCore.Qt.AlignLeft
265 print QtCore.Qt.AlignLeft
265
266
266 # constructors
267 # constructors
267 a = QtCore.QSize(12,13)
268 a = QtCore.QSize(12,13)
268 b = QtCore.QFont()
269 b = QtCore.QFont()
269
270
270 # static method
271 # static method
271 QtCore.QDate.currentDate()
272 QtCore.QDate.currentDate()
272
273
273 # enum value
274 # enum value
274 QtCore.QFont.UltraCondensed
275 QtCore.QFont.UltraCondensed
275
276
276 \endcode
277 \endcode
277
278
278 \section Decorators Decorator slots
279 \section Decorators Decorator slots
279
280
280 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
281 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
281
282
282 - constructors
283 - constructors
283 - destructors (for CPP objects)
284 - destructors (for CPP objects)
284 - additional slots
285 - additional slots
285 - static slots (callable on both the Meta object and the instances)
286 - static slots (callable on both the Meta object and the instances)
286
287
287 The idea behind decorators is that we wanted to make it as easy as possible to extend
288 The idea behind decorators is that we wanted to make it as easy as possible to extend
288 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
289 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
289 Python, it looked promising to use this approach for the extension of wrapped objects as well.
290 Python, it looked promising to use this approach for the extension of wrapped objects as well.
290 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
291 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
291 Qt when he wants to create static methods, constructors and additional member functions.
292 Qt when he wants to create static methods, constructors and additional member functions.
292
293
293 The basic idea about decorators is to create a QObject derived class that implements slots
294 The basic idea about decorators is to create a QObject derived class that implements slots
294 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
295 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
295 These slots are then assigned to other classes via the naming convention.
296 These slots are then assigned to other classes via the naming convention.
296
297
297 - SomeClassName* new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a new object of type SomeClassName (where SomeClassName can be any CPP class, not just QObject classes)
298 - SomeClassName* new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a new object of type SomeClassName (where SomeClassName can be any CPP class, not just QObject classes)
298 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
299 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
299 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
300 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
300 - anything someMethodName(SomeClassName* o, ...) - defines a slot that will be available on SomeClassName instances (and derived instances). When such a slot is called the first argument is the pointer to the instance and the rest of the arguments can be used to make a call on the instance.
301 - anything someMethodName(SomeClassName* o, ...) - defines a slot that will be available on SomeClassName instances (and derived instances). When such a slot is called the first argument is the pointer to the instance and the rest of the arguments can be used to make a call on the instance.
301
302
302 The below example shows all kinds of decorators in action:
303 The below example shows all kinds of decorators in action:
303
304
304 \code
305 \code
305
306
306 // an example CPP object
307 // an example CPP object
307 class YourCPPObject {
308 class YourCPPObject {
308 public:
309 public:
309 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
310 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
310
311
311 float doSomething(int arg1) { return arg1*a*b; };
312 float doSomething(int arg1) { return arg1*a*b; };
312
313
313 private:
314 private:
314
315
315 int a;
316 int a;
316 float b;
317 float b;
317 };
318 };
318
319
319 // an example decorator
320 // an example decorator
320 class ExampleDecorator : public QObject
321 class ExampleDecorator : public QObject
321 {
322 {
322 Q_OBJECT
323 Q_OBJECT
323
324
324 public slots:
325 public slots:
325 // add a constructor to QSize that takes a QPoint
326 // add a constructor to QSize that takes a QPoint
326 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
327 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
327
328
328 // add a constructor for QPushButton that takes a text and a parent widget
329 // add a constructor for QPushButton that takes a text and a parent widget
329 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
330 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
330
331
331 // add a constructor for a CPP object
332 // add a constructor for a CPP object
332 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
333 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
333
334
334 // add a destructor for a CPP object
335 // add a destructor for a CPP object
335 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
336 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
336
337
337 // add a static method to QWidget
338 // add a static method to QWidget
338 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
339 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
339
340
340 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
341 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
341 void move(QWidget* w, const QPoint& p) { w->move(p); }
342 void move(QWidget* w, const QPoint& p) { w->move(p); }
342
343
343 // add an additional slot to QWidget, overloading the above move method
344 // add an additional slot to QWidget, overloading the above move method
344 void move(QWidget* w, int x, int y) { w->move(x,y); }
345 void move(QWidget* w, int x, int y) { w->move(x,y); }
345
346
346 // add a method to your own CPP object
347 // add a method to your own CPP object
347 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
348 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
348 };
349 };
349
350
350 ...
351 ...
351
352
352 PythonQt::self()->addDecorators(new ExampleDecorator());
353 PythonQt::self()->addDecorators(new ExampleDecorator());
353 PythonQt::self()->registerCPPClass("YourCPPObject");
354 PythonQt::self()->registerCPPClass("YourCPPObject");
354
355
355 \endcode
356 \endcode
356
357
357 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
358 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
358 (all these calls are mapped to the above decorator slots):
359 (all these calls are mapped to the above decorator slots):
359
360
360 \code
361 \code
361 from PythonQt import QtCore, QtGui, YourCPPObject
362 from PythonQt import QtCore, QtGui, YourCPPObject
362
363
363 # call our new constructor of QSize
364 # call our new constructor of QSize
364 size = QtCore.QSize(QPoint(1,2));
365 size = QtCore.QSize(QPoint(1,2));
365
366
366 # call our new QPushButton constructor
367 # call our new QPushButton constructor
367 button = QtGui.QPushButton("sometext");
368 button = QtGui.QPushButton("sometext");
368
369
369 # call the move slot (overload1)
370 # call the move slot (overload1)
370 button.move(QPoint(0,0))
371 button.move(QPoint(0,0))
371
372
372 # call the move slot (overload2)
373 # call the move slot (overload2)
373 button.move(0,0)
374 button.move(0,0)
374
375
375 # call the static method
376 # call the static method
376 grabber = QtGui.QWidget.mouseWrapper();
377 grabber = QtGui.QWidget.mouseWrapper();
377
378
378 # create a CPP object via constructor
379 # create a CPP object via constructor
379 yourCpp = YourCPPObject(1,11.5)
380 yourCpp = YourCPPObject(1,11.5)
380
381
381 # call the wrapped method on CPP object
382 # call the wrapped method on CPP object
382 print yourCpp.doSomething(1);
383 print yourCpp.doSomething(1);
383
384
384 # destructor will be called:
385 # destructor will be called:
385 yourCpp = None
386 yourCpp = None
386
387
387 \endcode
388 \endcode
388
389
389 \section Building
390 \section Building
390
391
391 PythonQt requires at least Qt 4.2.2 (or higher) and Python 2.3, 2.4, 2.5 or 2.6 on Windows, Linux and MacOS X. It has not yet been tested with Python 3.x, but it should only require minor changes.
392 PythonQt requires at least Qt 4.2.2 (or higher) and Python 2.3, 2.4, 2.5 or 2.6 on Windows, Linux and MacOS X. It has not yet been tested with Python 3.x, but it should only require minor changes.
392 To compile PythonQt, you will need a python developer installation which includes Python's header files and
393 To compile PythonQt, you will need a python developer installation which includes Python's header files and
393 the python2x.[lib | dll | so | dynlib].
394 the python2x.[lib | dll | so | dynlib].
394 The build scripts a currently set to use Python 2.5.
395 The build scripts a currently set to use Python 2.5.
395 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
396 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
396
397
397 \subsection Windows
398 \subsection Windows
398
399
399 On Windows, the (non-source) Python Windows installer can be used.
400 On Windows, the (non-source) Python Windows installer can be used.
400 Make sure that you use the same compiler, the current Python distribution is built
401 Make sure that you use the same compiler, the current Python distribution is built
401 with Visual Studio 2003. If you want to use another compiler, you will need to build
402 with Visual Studio 2003. If you want to use another compiler, you will need to build
402 Python yourself, using your compiler.
403 Python yourself, using your compiler.
403
404
404 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
405 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
405 dir of the python installation and \b PYTHON_LIB to point to
406 dir of the python installation and \b PYTHON_LIB to point to
406 the directory where the python lib file is located.
407 the directory where the python lib file is located.
407
408
408 When using the prebuild Python installer, this will be:
409 When using the prebuild Python installer, this will be:
409
410
410 \code
411 \code
411 > set PYTHON_PATH = c:\Python25
412 > set PYTHON_PATH = c:\Python25
412 > set PYTHON_LIB = c:\Python25\libs
413 > set PYTHON_LIB = c:\Python25\libs
413 \endcode
414 \endcode
414
415
415 When using the python sources, this will be something like:
416 When using the python sources, this will be something like:
416
417
417 \code
418 \code
418 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
419 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
419 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
420 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
420 \endcode
421 \endcode
421
422
422 To build all, do the following (after setting the above variables):
423 To build all, do the following (after setting the above variables):
423
424
424 \code
425 \code
425 > cd PythonQtRoot
426 > cd PythonQtRoot
426 > vcvars32
427 > vcvars32
427 > qmake
428 > qmake
428 > nmake
429 > nmake
429 \endcode
430 \endcode
430
431
431 This should build everything. If Python can not be linked or include files can not be found,
432 This should build everything. If Python can not be linked or include files can not be found,
432 you probably need to tweak \b build/python.prf
433 you probably need to tweak \b build/python.prf
433
434
434 The tests and examples are located in PythonQt/lib.
435 The tests and examples are located in PythonQt/lib.
435
436
436 \subsection Linux
437 \subsection Linux
437
438
438 On Linux, you need to install a Python-dev package.
439 On Linux, you need to install a Python-dev package.
439 If Python can not be linked or include files can not be found,
440 If Python can not be linked or include files can not be found,
440 you probably need to tweak \b build/python.prf
441 you probably need to tweak \b build/python.prf
441
442
442 To build PythonQt, just do a:
443 To build PythonQt, just do a:
443
444
444 \code
445 \code
445 > cd PythonQtRoot
446 > cd PythonQtRoot
446 > qmake
447 > qmake
447 > make all
448 > make all
448 \endcode
449 \endcode
449
450
450 The tests and examples are located in PythonQt/lib.
451 The tests and examples are located in PythonQt/lib.
451 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
452 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
452 linker can find the *.so files.
453 linker can find the *.so files.
453
454
454 \subsection MacOsX
455 \subsection MacOsX
455
456
456 On Mac, Python is installed as a Framework, so you should not need to install it.
457 On Mac, Python is installed as a Framework, so you should not need to install it.
457 To build PythonQt, just do a:
458 To build PythonQt, just do a:
458
459
459 \code
460 \code
460 > cd PythonQtRoot
461 > cd PythonQtRoot
461 > qmake
462 > qmake
462 > make all
463 > make all
463 \endcode
464 \endcode
464
465
465 \section Tests
466 \section Tests
466
467
467 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
468 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
468
469
469 \section Examples
470 \section Examples
470
471
471 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
472 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
472 interactive scripting console that shows how to script a simple application.
473 interactive scripting console that shows how to script a simple application.
473
474
474 The following shows how to integrate PythonQt into you Qt application:
475 The following shows how to integrate PythonQt into you Qt application:
475
476
476 \code
477 \code
477 #include "PythonQt.h"
478 #include "PythonQt.h"
478 #include <QApplication>
479 #include <QApplication>
479 ...
480 ...
480
481
481 int main( int argc, char **argv )
482 int main( int argc, char **argv )
482 {
483 {
483
484
484 QApplication qapp(argc, argv);
485 QApplication qapp(argc, argv);
485
486
486 // init PythonQt and Python itself
487 // init PythonQt and Python itself
487 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
488 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
488
489
489
490
490 // get a smart pointer to the __main__ module of the Python interpreter
491 // get a smart pointer to the __main__ module of the Python interpreter
491 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
492 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
492
493
493 // add a QObject as variable of name "example" to the namespace of the __main__ module
494 // add a QObject as variable of name "example" to the namespace of the __main__ module
494 PyExampleObject example;
495 PyExampleObject example;
495 PythonQt::self()->addObject(mainContext, "example", &example);
496 PythonQt::self()->addObject(mainContext, "example", &example);
496
497
497 // do something
498 // do something
498 PythonQt::self()->runScript(mainContext, "print example\n");
499 PythonQt::self()->runScript(mainContext, "print example\n");
499 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
500 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
500 QVariantList args;
501 QVariantList args;
501 args << 42 << 47;
502 args << 42 << 47;
502 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
503 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
503 ...
504 ...
504 \endcode
505 \endcode
505
506
506
507
507 */
508 */
@@ -1,96 +1,101
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 PythonQtObjectPtr.cpp
35 // \file PythonQtObjectPtr.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
43
44 QVariant PythonQtObjectPtr::evalScript(const QString& script, int start)
44 QVariant PythonQtObjectPtr::evalScript(const QString& script, int start)
45 {
45 {
46 return PythonQt::self()->evalScript(_object, script, start);
46 return PythonQt::self()->evalScript(_object, script, start);
47 }
47 }
48
48
49 void PythonQtObjectPtr::evalFile(const QString& file)
49 void PythonQtObjectPtr::evalFile(const QString& file)
50 {
50 {
51 PythonQt::self()->evalFile(_object, file);
51 PythonQt::self()->evalFile(_object, file);
52 }
52 }
53
53
54 QVariant PythonQtObjectPtr::evalCode(PyObject* pycode)
54 QVariant PythonQtObjectPtr::evalCode(PyObject* pycode)
55 {
55 {
56 return PythonQt::self()->evalCode(_object, pycode);
56 return PythonQt::self()->evalCode(_object, pycode);
57 }
57 }
58
58
59 void PythonQtObjectPtr::addObject(const QString& name, QObject* object)
59 void PythonQtObjectPtr::addObject(const QString& name, QObject* object)
60 {
60 {
61 PythonQt::self()->addObject(_object, name, object);
61 PythonQt::self()->addObject(_object, name, object);
62 }
62 }
63
63
64 void PythonQtObjectPtr::addVariable(const QString& name, const QVariant& v)
64 void PythonQtObjectPtr::addVariable(const QString& name, const QVariant& v)
65 {
65 {
66 PythonQt::self()->addVariable(_object, name, v);
66 PythonQt::self()->addVariable(_object, name, v);
67 }
67 }
68
68
69 void PythonQtObjectPtr::removeVariable(const QString& name)
69 void PythonQtObjectPtr::removeVariable(const QString& name)
70 {
70 {
71 PythonQt::self()->removeVariable(_object, name);
71 PythonQt::self()->removeVariable(_object, name);
72 }
72 }
73
73
74 QVariant PythonQtObjectPtr::getVariable(const QString& name)
74 QVariant PythonQtObjectPtr::getVariable(const QString& name)
75 {
75 {
76 return PythonQt::self()->getVariable(_object, name);
76 return PythonQt::self()->getVariable(_object, name);
77 }
77 }
78
78
79
79
80 QVariant PythonQtObjectPtr::call(const QString& callable, const QVariantList& args)
80 QVariant PythonQtObjectPtr::call(const QString& callable, const QVariantList& args)
81 {
81 {
82 return PythonQt::self()->call(_object, callable, args);
82 return PythonQt::self()->call(_object, callable, args);
83 }
83 }
84
84
85 QVariant PythonQtObjectPtr::call(const QVariantList& args)
86 {
87 return PythonQt::self()->call(_object, args);
88 }
89
85 bool PythonQtObjectPtr::fromVariant(const QVariant& variant)
90 bool PythonQtObjectPtr::fromVariant(const QVariant& variant)
86 {
91 {
87 if (!variant.isNull()) {
92 if (!variant.isNull()) {
88 setObject(qVariantValue<PythonQtObjectPtr>(variant));
93 setObject(qVariantValue<PythonQtObjectPtr>(variant));
89 return true;
94 return true;
90 }
95 }
91 else {
96 else {
92 setObject(0);
97 setObject(0);
93 return false;
98 return false;
94 }
99 }
95
100
96 }
101 }
@@ -1,174 +1,174
1 #ifndef _PYTHONQTOBJECTPTR_H
1 #ifndef _PYTHONQTOBJECTPTR_H
2 #define _PYTHONQTOBJECTPTR_H
2 #define _PYTHONQTOBJECTPTR_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 PythonQtObjectPtr.h
38 // \file PythonQtObjectPtr.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 <QVariant>
47 #include <QVariant>
48 #include <QVariantList>
48 #include <QVariantList>
49
49
50 //! a smart pointer that stores a PyObject pointer and that handles reference counting automatically
50 //! a smart pointer that stores a PyObject pointer and that handles reference counting automatically
51 class PYTHONQT_EXPORT PythonQtObjectPtr
51 class PYTHONQT_EXPORT PythonQtObjectPtr
52 {
52 {
53 public:
53 public:
54 PythonQtObjectPtr():_object(NULL) {}
54 PythonQtObjectPtr():_object(NULL) {}
55
55
56 PythonQtObjectPtr(const PythonQtObjectPtr &p):_object(NULL) {
56 PythonQtObjectPtr(const PythonQtObjectPtr &p):_object(NULL) {
57 setObject(p.object());
57 setObject(p.object());
58 }
58 }
59
59
60 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
60 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
61 PythonQtObjectPtr(const QVariant& variant):_object(NULL) {
61 PythonQtObjectPtr(const QVariant& variant):_object(NULL) {
62 fromVariant(variant);
62 fromVariant(variant);
63 }
63 }
64
64
65 PythonQtObjectPtr(PyObject* o) {
65 PythonQtObjectPtr(PyObject* o) {
66 _object = o;
66 _object = o;
67 if (o) Py_INCREF(_object);
67 if (o) Py_INCREF(_object);
68 }
68 }
69
69
70 ~PythonQtObjectPtr() { if (_object) Py_DECREF(_object); }
70 ~PythonQtObjectPtr() { if (_object) Py_DECREF(_object); }
71
71
72 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
72 //! If the given variant holds a PythonQtObjectPtr, extract the value from it and hold onto the reference. This results in an increment of the reference count.
73 bool fromVariant(const QVariant& variant);
73 bool fromVariant(const QVariant& variant);
74
74
75 PythonQtObjectPtr &operator=(const PythonQtObjectPtr &p) {
75 PythonQtObjectPtr &operator=(const PythonQtObjectPtr &p) {
76 setObject(p.object());
76 setObject(p.object());
77 return *this;
77 return *this;
78 }
78 }
79
79
80 PythonQtObjectPtr &operator=(PyObject* o) {
80 PythonQtObjectPtr &operator=(PyObject* o) {
81 setObject(o);
81 setObject(o);
82 return *this;
82 return *this;
83 }
83 }
84
84
85
85
86 PythonQtObjectPtr &operator=(const QVariant& variant) {
86 PythonQtObjectPtr &operator=(const QVariant& variant) {
87 fromVariant(variant);
87 fromVariant(variant);
88 return *this;
88 return *this;
89 }
89 }
90
90
91
91
92 bool operator==( const PythonQtObjectPtr &p ) const {
92 bool operator==( const PythonQtObjectPtr &p ) const {
93 return object() == p.object();
93 return object() == p.object();
94 }
94 }
95
95
96 bool operator!= ( const PythonQtObjectPtr& p ) const {
96 bool operator!= ( const PythonQtObjectPtr& p ) const {
97 return !( *this == p );
97 return !( *this == p );
98 }
98 }
99
99
100 bool operator==( PyObject* p ) const {
100 bool operator==( PyObject* p ) const {
101 return object() == p;
101 return object() == p;
102 }
102 }
103
103
104 bool operator!= ( PyObject* p ) const {
104 bool operator!= ( PyObject* p ) const {
105 return object() != p;
105 return object() != p;
106 }
106 }
107
107
108 bool isNull() const { return !object(); }
108 bool isNull() const { return !object(); }
109
109
110 PyObject* operator->() const { return object(); }
110 PyObject* operator->() const { return object(); }
111
111
112 PyObject& operator*() const { return *( object() ); }
112 PyObject& operator*() const { return *( object() ); }
113
113
114 operator PyObject*() const { return object(); }
114 operator PyObject*() const { return object(); }
115
115
116 //! sets the object and passes the ownership (stealing the reference, in Python slang)
116 //! sets the object and passes the ownership (stealing the reference, in Python slang)
117 void setNewRef(PyObject* o) {
117 void setNewRef(PyObject* o) {
118 if (o != _object) {
118 if (o != _object) {
119 if (_object) Py_DECREF(_object);
119 if (_object) Py_DECREF(_object);
120 _object = o;
120 _object = o;
121 }
121 }
122 }
122 }
123
123
124 PyObject* object() const {
124 PyObject* object() const {
125 return _object;
125 return _object;
126 }
126 }
127
127
128 //! evaluates the given script code in the context of this object and returns the result value
128 //! evaluates the given script code in the context of this object and returns the result value
129 QVariant evalScript(const QString& script, int start = Py_file_input);
129 QVariant evalScript(const QString& script, int start = Py_file_input);
130
130
131 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
131 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
132 //! If pycode is NULL, a python error is printed.
132 //! If pycode is NULL, a python error is printed.
133 QVariant evalCode(PyObject* pycode);
133 QVariant evalCode(PyObject* pycode);
134
134
135 //! evaluates the given code in the context
135 //! evaluates the given code in the context
136 void evalFile(const QString& filename);
136 void evalFile(const QString& filename);
137
137
138 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
138 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
139 void addObject(const QString& name, QObject* object);
139 void addObject(const QString& name, QObject* object);
140
140
141 //! add the given variable to the module
141 //! add the given variable to the module
142 void addVariable(const QString& name, const QVariant& v);
142 void addVariable(const QString& name, const QVariant& v);
143
143
144 //! remove the given variable
144 //! remove the given variable
145 void removeVariable(const QString& name);
145 void removeVariable(const QString& name);
146
146
147 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
147 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
148 QVariant getVariable(const QString& name);
148 QVariant getVariable(const QString& name);
149
149
150 //! call the given python object (in the scope of the current object), returns the result converted to a QVariant
150 //! call the given python object (in the scope of the current object), returns the result converted to a QVariant
151 QVariant call(const QString& callable, const QVariantList& args = QVariantList());
151 QVariant call(const QString& callable, const QVariantList& args = QVariantList());
152
152
153
153 //! call the contained python object directly, returns the result converted to a QVariant
154
154 QVariant call(const QVariantList& args = QVariantList());
155
155
156 protected:
156 protected:
157
157
158 void setObject(PyObject* o) {
158 void setObject(PyObject* o) {
159 if (o != _object) {
159 if (o != _object) {
160 if (_object) Py_DECREF(_object);
160 if (_object) Py_DECREF(_object);
161 _object = o;
161 _object = o;
162 if (_object) Py_INCREF(_object);
162 if (_object) Py_INCREF(_object);
163 }
163 }
164 }
164 }
165
165
166 private:
166 private:
167 PyObject* _object;
167 PyObject* _object;
168 };
168 };
169
169
170
170
171 // register it to the meta type system
171 // register it to the meta type system
172 Q_DECLARE_METATYPE(PythonQtObjectPtr)
172 Q_DECLARE_METATYPE(PythonQtObjectPtr)
173
173
174 #endif No newline at end of file
174 #endif
General Comments 0
You need to be logged in to leave comments. Login now