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