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