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