##// END OF EJS Templates
cleanup of code and addition of (yet unused) classinfo passed to method/slot info to allow local enum support on creation...
florianlink -
r54:8f57e6dac237
parent child
Show More
@@ -1,1186 +1,1184
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 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
279 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
280 {
280 {
281 if (!obj) {
281 if (!obj) {
282 Py_INCREF(Py_None);
282 Py_INCREF(Py_None);
283 return Py_None;
283 return Py_None;
284 }
284 }
285 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
285 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
286 if (!wrap) {
286 if (!wrap) {
287 // smuggling it in...
287 // smuggling it in...
288 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
288 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
289 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
289 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
290 registerClass(obj->metaObject());
290 registerClass(obj->metaObject());
291 classInfo = _knownClassInfos.value(obj->metaObject()->className());
291 classInfo = _knownClassInfos.value(obj->metaObject()->className());
292 }
292 }
293 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
293 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
294 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
294 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
295 } else {
295 } else {
296 Py_INCREF(wrap);
296 Py_INCREF(wrap);
297 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
297 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
298 }
298 }
299 return (PyObject*)wrap;
299 return (PyObject*)wrap;
300 }
300 }
301
301
302 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
302 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
303 {
303 {
304 if (!ptr) {
304 if (!ptr) {
305 Py_INCREF(Py_None);
305 Py_INCREF(Py_None);
306 return Py_None;
306 return Py_None;
307 }
307 }
308
308
309 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
309 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
310 if (!wrap) {
310 if (!wrap) {
311 PythonQtClassInfo* info = _knownClassInfos.value(name);
311 PythonQtClassInfo* info = _knownClassInfos.value(name);
312 if (!info) {
312 if (!info) {
313 // maybe it is a PyObject, which we can return directly
313 // maybe it is a PyObject, which we can return directly
314 if (name == "PyObject") {
314 if (name == "PyObject") {
315 PyObject* p = (PyObject*)ptr;
315 PyObject* p = (PyObject*)ptr;
316 Py_INCREF(p);
316 Py_INCREF(p);
317 return p;
317 return p;
318 }
318 }
319
319
320 // we do not know the metaobject yet, but we might know it by it's name:
320 // we do not know the metaobject yet, but we might know it by it's name:
321 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
321 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
322 // yes, we know it, so we can convert to QObject
322 // yes, we know it, so we can convert to QObject
323 QObject* qptr = (QObject*)ptr;
323 QObject* qptr = (QObject*)ptr;
324 registerClass(qptr->metaObject());
324 registerClass(qptr->metaObject());
325 info = _knownClassInfos.value(qptr->metaObject()->className());
325 info = _knownClassInfos.value(qptr->metaObject()->className());
326 }
326 }
327 }
327 }
328 if (info && info->isQObject()) {
328 if (info && info->isQObject()) {
329 QObject* qptr = (QObject*)ptr;
329 QObject* qptr = (QObject*)ptr;
330 // if the object is a derived object, we want to switch the class info to the one of the derived class:
330 // if the object is a derived object, we want to switch the class info to the one of the derived class:
331 if (name!=(qptr->metaObject()->className())) {
331 if (name!=(qptr->metaObject()->className())) {
332 registerClass(qptr->metaObject());
332 registerClass(qptr->metaObject());
333 info = _knownClassInfos.value(qptr->metaObject()->className());
333 info = _knownClassInfos.value(qptr->metaObject()->className());
334 }
334 }
335 wrap = createNewPythonQtInstanceWrapper(qptr, info);
335 wrap = createNewPythonQtInstanceWrapper(qptr, info);
336 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
336 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
337 return (PyObject*)wrap;
337 return (PyObject*)wrap;
338 }
338 }
339
339
340 // not a known QObject, so try our wrapper factory:
340 // not a known QObject, so try our wrapper factory:
341 QObject* wrapper = NULL;
341 QObject* wrapper = NULL;
342 for (int i=0; i<_cppWrapperFactories.size(); i++) {
342 for (int i=0; i<_cppWrapperFactories.size(); i++) {
343 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
343 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
344 if (wrapper) {
344 if (wrapper) {
345 break;
345 break;
346 }
346 }
347 }
347 }
348
348
349 if (info) {
349 if (info) {
350 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
350 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
351 ptr = info->castDownIfPossible(ptr, &info);
351 ptr = info->castDownIfPossible(ptr, &info);
352 }
352 }
353
353
354 if (!info || info->pythonQtClassWrapper()==NULL) {
354 if (!info || info->pythonQtClassWrapper()==NULL) {
355 // still unknown, register as CPP class
355 // still unknown, register as CPP class
356 registerCPPClass(name.constData());
356 registerCPPClass(name.constData());
357 info = _knownClassInfos.value(name);
357 info = _knownClassInfos.value(name);
358 }
358 }
359 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
359 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
360 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
360 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
361 info->setMetaObject(wrapper->metaObject());
361 info->setMetaObject(wrapper->metaObject());
362 }
362 }
363 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
363 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
364 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
364 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
365 } else {
365 } else {
366 Py_INCREF(wrap);
366 Py_INCREF(wrap);
367 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
367 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
368 }
368 }
369 return (PyObject*)wrap;
369 return (PyObject*)wrap;
370 }
370 }
371
371
372 PyObject* PythonQtPrivate::dummyTuple() {
372 PyObject* PythonQtPrivate::dummyTuple() {
373 static PyObject* dummyTuple = NULL;
373 static PyObject* dummyTuple = NULL;
374 if (dummyTuple==NULL) {
374 if (dummyTuple==NULL) {
375 dummyTuple = PyTuple_New(1);
375 dummyTuple = PyTuple_New(1);
376 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
376 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
377 }
377 }
378 return dummyTuple;
378 return dummyTuple;
379 }
379 }
380
380
381
381
382 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
382 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
383 // call the associated class type to create a new instance...
383 // call the associated class type to create a new instance...
384 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
384 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
385
385
386 result->setQObject(obj);
386 result->setQObject(obj);
387 result->_wrappedPtr = wrappedPtr;
387 result->_wrappedPtr = wrappedPtr;
388 result->_ownedByPythonQt = false;
388 result->_ownedByPythonQt = false;
389 result->_useQMetaTypeDestroy = false;
389 result->_useQMetaTypeDestroy = false;
390
390
391 if (wrappedPtr) {
391 if (wrappedPtr) {
392 _wrappedObjects.insert(wrappedPtr, result);
392 _wrappedObjects.insert(wrappedPtr, result);
393 } else {
393 } else {
394 _wrappedObjects.insert(obj, result);
394 _wrappedObjects.insert(obj, result);
395 if (obj->parent()== NULL && _wrappedCB) {
395 if (obj->parent()== NULL && _wrappedCB) {
396 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
396 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
397 (*_wrappedCB)(obj);
397 (*_wrappedCB)(obj);
398 }
398 }
399 }
399 }
400 return result;
400 return result;
401 }
401 }
402
402
403 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) {
403 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) {
404 PythonQtClassWrapper* result;
404 PythonQtClassWrapper* result;
405
405
406 PyObject* className = PyString_FromString(info->className());
406 PyObject* className = PyString_FromString(info->className());
407
407
408 PyObject* baseClasses = PyTuple_New(1);
408 PyObject* baseClasses = PyTuple_New(1);
409 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
409 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
410
410
411 PyObject* typeDict = PyDict_New();
411 PyObject* typeDict = PyDict_New();
412 QByteArray moduleName("PythonQt");
412 QByteArray moduleName("PythonQt");
413 if (package && strcmp(package, "")!=0) {
413 if (package && strcmp(package, "")!=0) {
414 moduleName += ".";
414 moduleName += ".";
415 moduleName += package;
415 moduleName += package;
416 }
416 }
417 PyDict_SetItemString(typeDict, "__module__", PyString_FromString(moduleName.constData()));
417 PyDict_SetItemString(typeDict, "__module__", PyString_FromString(moduleName.constData()));
418
418
419 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
419 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
420
420
421 // set the class info so that PythonQtClassWrapper_new can read it
421 // set the class info so that PythonQtClassWrapper_new can read it
422 _currentClassInfoForClassWrapperCreation = info;
422 _currentClassInfoForClassWrapperCreation = info;
423 // create the new type object by calling the type
423 // create the new type object by calling the type
424 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
424 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
425
425
426 Py_DECREF(baseClasses);
426 Py_DECREF(baseClasses);
427 Py_DECREF(typeDict);
427 Py_DECREF(typeDict);
428 Py_DECREF(args);
428 Py_DECREF(args);
429 Py_DECREF(className);
429 Py_DECREF(className);
430
430
431 return result;
431 return result;
432 }
432 }
433
433
434 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
434 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
435 PyObject* result;
435 PyObject* result;
436
436
437 PyObject* className = PyString_FromString(enumName);
437 PyObject* className = PyString_FromString(enumName);
438
438
439 PyObject* baseClasses = PyTuple_New(1);
439 PyObject* baseClasses = PyTuple_New(1);
440 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
440 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
441
441
442 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
442 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
443 PyObject* typeDict = PyDict_New();
443 PyObject* typeDict = PyDict_New();
444 PyDict_SetItemString(typeDict, "__module__", module);
444 PyDict_SetItemString(typeDict, "__module__", module);
445
445
446 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
446 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
447
447
448 // create the new int derived type object by calling the core type
448 // create the new int derived type object by calling the core type
449 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
449 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
450
450
451 Py_DECREF(baseClasses);
451 Py_DECREF(baseClasses);
452 Py_DECREF(typeDict);
452 Py_DECREF(typeDict);
453 Py_DECREF(args);
453 Py_DECREF(args);
454 Py_DECREF(className);
454 Py_DECREF(className);
455
455
456 return result;
456 return result;
457 }
457 }
458
458
459 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
459 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
460 {
460 {
461 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
461 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
462 if (!r) {
462 if (!r) {
463 r = new PythonQtSignalReceiver(obj);
463 r = new PythonQtSignalReceiver(obj);
464 _p->_signalReceivers.insert(obj, r);
464 _p->_signalReceivers.insert(obj, r);
465 }
465 }
466 return r;
466 return r;
467 }
467 }
468
468
469 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
469 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
470 {
470 {
471 bool flag = false;
471 bool flag = false;
472 PythonQtObjectPtr callable = lookupCallable(module, objectname);
472 PythonQtObjectPtr callable = lookupCallable(module, objectname);
473 if (callable) {
473 if (callable) {
474 PythonQtSignalReceiver* r = getSignalReceiver(obj);
474 PythonQtSignalReceiver* r = getSignalReceiver(obj);
475 flag = r->addSignalHandler(signal, callable);
475 flag = r->addSignalHandler(signal, callable);
476 if (!flag) {
476 if (!flag) {
477 // signal not found
477 // signal not found
478 }
478 }
479 } else {
479 } else {
480 // callable not found
480 // callable not found
481 }
481 }
482 return flag;
482 return flag;
483 }
483 }
484
484
485 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
485 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
486 {
486 {
487 bool flag = false;
487 bool flag = false;
488 PythonQtSignalReceiver* r = getSignalReceiver(obj);
488 PythonQtSignalReceiver* r = getSignalReceiver(obj);
489 if (r) {
489 if (r) {
490 flag = r->addSignalHandler(signal, receiver);
490 flag = r->addSignalHandler(signal, receiver);
491 }
491 }
492 return flag;
492 return flag;
493 }
493 }
494
494
495 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
495 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
496 {
496 {
497 bool flag = false;
497 bool flag = false;
498 PythonQtObjectPtr callable = lookupCallable(module, objectname);
498 PythonQtObjectPtr callable = lookupCallable(module, objectname);
499 if (callable) {
499 if (callable) {
500 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
500 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
501 if (r) {
501 if (r) {
502 flag = r->removeSignalHandler(signal, callable);
502 flag = r->removeSignalHandler(signal, callable);
503 }
503 }
504 } else {
504 } else {
505 // callable not found
505 // callable not found
506 }
506 }
507 return flag;
507 return flag;
508 }
508 }
509
509
510 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
510 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
511 {
511 {
512 bool flag = false;
512 bool flag = false;
513 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
513 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
514 if (r) {
514 if (r) {
515 flag = r->removeSignalHandler(signal, receiver);
515 flag = r->removeSignalHandler(signal, receiver);
516 }
516 }
517 return flag;
517 return flag;
518 }
518 }
519
519
520 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
520 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
521 {
521 {
522 PythonQtObjectPtr p = lookupObject(module, name);
522 PythonQtObjectPtr p = lookupObject(module, name);
523 if (p) {
523 if (p) {
524 if (PyCallable_Check(p)) {
524 if (PyCallable_Check(p)) {
525 return p;
525 return p;
526 }
526 }
527 }
527 }
528 PyErr_Clear();
528 PyErr_Clear();
529 return NULL;
529 return NULL;
530 }
530 }
531
531
532 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
532 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
533 {
533 {
534 QStringList l = name.split('.');
534 QStringList l = name.split('.');
535 PythonQtObjectPtr p = module;
535 PythonQtObjectPtr p = module;
536 PythonQtObjectPtr prev;
536 PythonQtObjectPtr prev;
537 QString s;
537 QString s;
538 QByteArray b;
538 QByteArray b;
539 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
539 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
540 prev = p;
540 prev = p;
541 b = (*i).toLatin1();
541 b = (*i).toLatin1();
542 if (PyDict_Check(p)) {
542 if (PyDict_Check(p)) {
543 p = PyDict_GetItemString(p, b.data());
543 p = PyDict_GetItemString(p, b.data());
544 } else {
544 } else {
545 p.setNewRef(PyObject_GetAttrString(p, b.data()));
545 p.setNewRef(PyObject_GetAttrString(p, b.data()));
546 }
546 }
547 }
547 }
548 PyErr_Clear();
548 PyErr_Clear();
549 return p;
549 return p;
550 }
550 }
551
551
552 PythonQtObjectPtr PythonQt::getMainModule() {
552 PythonQtObjectPtr PythonQt::getMainModule() {
553 //both borrowed
553 //both borrowed
554 PythonQtObjectPtr dict = PyImport_GetModuleDict();
554 PythonQtObjectPtr dict = PyImport_GetModuleDict();
555 return PyDict_GetItemString(dict, "__main__");
555 return PyDict_GetItemString(dict, "__main__");
556 }
556 }
557
557
558 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
558 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
559 QVariant result;
559 QVariant result;
560 if (pycode) {
560 if (pycode) {
561 PyObject* dict = NULL;
561 PyObject* dict = NULL;
562 if (PyModule_Check(object)) {
562 if (PyModule_Check(object)) {
563 dict = PyModule_GetDict(object);
563 dict = PyModule_GetDict(object);
564 } else if (PyDict_Check(object)) {
564 } else if (PyDict_Check(object)) {
565 dict = object;
565 dict = object;
566 }
566 }
567 PyObject* r = NULL;
567 PyObject* r = NULL;
568 if (dict) {
568 if (dict) {
569 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
569 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
570 }
570 }
571 if (r) {
571 if (r) {
572 result = PythonQtConv::PyObjToQVariant(r);
572 result = PythonQtConv::PyObjToQVariant(r);
573 Py_DECREF(r);
573 Py_DECREF(r);
574 } else {
574 } else {
575 handleError();
575 handleError();
576 }
576 }
577 } else {
577 } else {
578 handleError();
578 handleError();
579 }
579 }
580 return result;
580 return result;
581 }
581 }
582
582
583 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
583 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
584 {
584 {
585 QVariant result;
585 QVariant result;
586 PythonQtObjectPtr p;
586 PythonQtObjectPtr p;
587 PyObject* dict = NULL;
587 PyObject* dict = NULL;
588 if (PyModule_Check(object)) {
588 if (PyModule_Check(object)) {
589 dict = PyModule_GetDict(object);
589 dict = PyModule_GetDict(object);
590 } else if (PyDict_Check(object)) {
590 } else if (PyDict_Check(object)) {
591 dict = object;
591 dict = object;
592 }
592 }
593 if (dict) {
593 if (dict) {
594 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
594 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
595 }
595 }
596 if (p) {
596 if (p) {
597 result = PythonQtConv::PyObjToQVariant(p);
597 result = PythonQtConv::PyObjToQVariant(p);
598 } else {
598 } else {
599 handleError();
599 handleError();
600 }
600 }
601 return result;
601 return result;
602 }
602 }
603
603
604 void PythonQt::evalFile(PyObject* module, const QString& filename)
604 void PythonQt::evalFile(PyObject* module, const QString& filename)
605 {
605 {
606 PythonQtObjectPtr code = parseFile(filename);
606 PythonQtObjectPtr code = parseFile(filename);
607 if (code) {
607 if (code) {
608 evalCode(module, code);
608 evalCode(module, code);
609 } else {
609 } else {
610 handleError();
610 handleError();
611 }
611 }
612 }
612 }
613
613
614 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
614 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
615 {
615 {
616 PythonQtObjectPtr p;
616 PythonQtObjectPtr p;
617 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
617 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
618 if (!p) {
618 if (!p) {
619 handleError();
619 handleError();
620 }
620 }
621 return p;
621 return p;
622 }
622 }
623
623
624 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
624 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
625 {
625 {
626 PythonQtObjectPtr code = parseFile(filename);
626 PythonQtObjectPtr code = parseFile(filename);
627 PythonQtObjectPtr module = _p->createModule(name, code);
627 PythonQtObjectPtr module = _p->createModule(name, code);
628 return module;
628 return module;
629 }
629 }
630
630
631 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
631 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
632 {
632 {
633 PyErr_Clear();
633 PyErr_Clear();
634 QString scriptCode = script;
634 QString scriptCode = script;
635 if (scriptCode.isEmpty()) {
635 if (scriptCode.isEmpty()) {
636 // we always need at least a linefeed
636 // we always need at least a linefeed
637 scriptCode = "\n";
637 scriptCode = "\n";
638 }
638 }
639 PythonQtObjectPtr pycode;
639 PythonQtObjectPtr pycode;
640 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
640 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
641 PythonQtObjectPtr module = _p->createModule(name, pycode);
641 PythonQtObjectPtr module = _p->createModule(name, pycode);
642 return module;
642 return module;
643 }
643 }
644
644
645 PythonQtObjectPtr PythonQt::createUniqueModule()
645 PythonQtObjectPtr PythonQt::createUniqueModule()
646 {
646 {
647 static QString pyQtStr("PythonQt_module");
647 static QString pyQtStr("PythonQt_module");
648 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
648 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
649 return createModuleFromScript(moduleName);
649 return createModuleFromScript(moduleName);
650 }
650 }
651
651
652 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
652 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
653 {
653 {
654 if (PyModule_Check(object)) {
654 if (PyModule_Check(object)) {
655 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
655 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
656 } else if (PyDict_Check(object)) {
656 } else if (PyDict_Check(object)) {
657 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
657 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
658 } else {
658 } else {
659 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
659 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
660 }
660 }
661 }
661 }
662
662
663 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
663 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
664 {
664 {
665 if (PyModule_Check(object)) {
665 if (PyModule_Check(object)) {
666 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
666 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
667 } else if (PyDict_Check(object)) {
667 } else if (PyDict_Check(object)) {
668 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
668 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
669 } else {
669 } else {
670 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
670 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
671 }
671 }
672 }
672 }
673
673
674 void PythonQt::removeVariable(PyObject* object, const QString& name)
674 void PythonQt::removeVariable(PyObject* object, const QString& name)
675 {
675 {
676 if (PyDict_Check(object)) {
676 if (PyDict_Check(object)) {
677 PyDict_DelItemString(object, name.toLatin1().data());
677 PyDict_DelItemString(object, name.toLatin1().data());
678 } else {
678 } else {
679 PyObject_DelAttrString(object, name.toLatin1().data());
679 PyObject_DelAttrString(object, name.toLatin1().data());
680 }
680 }
681 }
681 }
682
682
683 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
683 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
684 {
684 {
685 QVariant result;
685 QVariant result;
686 PythonQtObjectPtr obj = lookupObject(object, objectname);
686 PythonQtObjectPtr obj = lookupObject(object, objectname);
687 if (obj) {
687 if (obj) {
688 result = PythonQtConv::PyObjToQVariant(obj);
688 result = PythonQtConv::PyObjToQVariant(obj);
689 }
689 }
690 return result;
690 return result;
691 }
691 }
692
692
693 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
693 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
694 {
694 {
695 QStringList results;
695 QStringList results;
696
696
697 PythonQtObjectPtr object;
697 PythonQtObjectPtr object;
698 if (objectname.isEmpty()) {
698 if (objectname.isEmpty()) {
699 object = module;
699 object = module;
700 } else {
700 } else {
701 object = lookupObject(module, objectname);
701 object = lookupObject(module, objectname);
702 if (!object && type == CallOverloads) {
702 if (!object && type == CallOverloads) {
703 PyObject* dict = lookupObject(module, "__builtins__");
703 PyObject* dict = lookupObject(module, "__builtins__");
704 if (dict) {
704 if (dict) {
705 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
705 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
706 }
706 }
707 }
707 }
708 }
708 }
709
709
710 if (object) {
710 if (object) {
711 if (type == CallOverloads) {
711 if (type == CallOverloads) {
712 if (PythonQtSlotFunction_Check(object)) {
712 if (PythonQtSlotFunction_Check(object)) {
713 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
713 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
714 PythonQtSlotInfo* info = o->m_ml;
714 PythonQtSlotInfo* info = o->m_ml;
715
715
716 while (info) {
716 while (info) {
717 results << info->fullSignature();
717 results << info->fullSignature();
718 info = info->nextInfo();
718 info = info->nextInfo();
719 }
719 }
720 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
720 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
721 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
721 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
722 PythonQtSlotInfo* info = o->classInfo()->constructors();
722 PythonQtSlotInfo* info = o->classInfo()->constructors();
723
723
724 while (info) {
724 while (info) {
725 results << info->fullSignature();
725 results << info->fullSignature();
726 info = info->nextInfo();
726 info = info->nextInfo();
727 }
727 }
728 } else {
728 } else {
729 //TODO: use pydoc!
729 //TODO: use pydoc!
730 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
730 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
731 if (doc) {
731 if (doc) {
732 results << PyString_AsString(doc);
732 results << PyString_AsString(doc);
733 Py_DECREF(doc);
733 Py_DECREF(doc);
734 }
734 }
735 }
735 }
736 } else {
736 } else {
737 PyObject* keys = NULL;
737 PyObject* keys = NULL;
738 bool isDict = false;
738 bool isDict = false;
739 if (PyDict_Check(object)) {
739 if (PyDict_Check(object)) {
740 keys = PyDict_Keys(object);
740 keys = PyDict_Keys(object);
741 isDict = true;
741 isDict = true;
742 } else {
742 } else {
743 keys = PyObject_Dir(object);
743 keys = PyObject_Dir(object);
744 }
744 }
745 if (keys) {
745 if (keys) {
746 int count = PyList_Size(keys);
746 int count = PyList_Size(keys);
747 PyObject* key;
747 PyObject* key;
748 PyObject* value;
748 PyObject* value;
749 QString keystr;
749 QString keystr;
750 for (int i = 0;i<count;i++) {
750 for (int i = 0;i<count;i++) {
751 key = PyList_GetItem(keys,i);
751 key = PyList_GetItem(keys,i);
752 if (isDict) {
752 if (isDict) {
753 value = PyDict_GetItem(object, key);
753 value = PyDict_GetItem(object, key);
754 Py_INCREF(value);
754 Py_INCREF(value);
755 } else {
755 } else {
756 value = PyObject_GetAttr(object, key);
756 value = PyObject_GetAttr(object, key);
757 }
757 }
758 if (!value) continue;
758 if (!value) continue;
759 keystr = PyString_AsString(key);
759 keystr = PyString_AsString(key);
760 static const QString underscoreStr("__tmp");
760 static const QString underscoreStr("__tmp");
761 if (!keystr.startsWith(underscoreStr)) {
761 if (!keystr.startsWith(underscoreStr)) {
762 switch (type) {
762 switch (type) {
763 case Anything:
763 case Anything:
764 results << keystr;
764 results << keystr;
765 break;
765 break;
766 case Class:
766 case Class:
767 if (value->ob_type == &PyClass_Type) {
767 if (value->ob_type == &PyClass_Type) {
768 results << keystr;
768 results << keystr;
769 }
769 }
770 break;
770 break;
771 case Variable:
771 case Variable:
772 if (value->ob_type != &PyClass_Type
772 if (value->ob_type != &PyClass_Type
773 && value->ob_type != &PyCFunction_Type
773 && value->ob_type != &PyCFunction_Type
774 && value->ob_type != &PyFunction_Type
774 && value->ob_type != &PyFunction_Type
775 && value->ob_type != &PyModule_Type
775 && value->ob_type != &PyModule_Type
776 ) {
776 ) {
777 results << keystr;
777 results << keystr;
778 }
778 }
779 break;
779 break;
780 case Function:
780 case Function:
781 if (value->ob_type == &PyFunction_Type ||
781 if (value->ob_type == &PyFunction_Type ||
782 value->ob_type == &PyMethod_Type
782 value->ob_type == &PyMethod_Type
783 ) {
783 ) {
784 results << keystr;
784 results << keystr;
785 }
785 }
786 break;
786 break;
787 case Module:
787 case Module:
788 if (value->ob_type == &PyModule_Type) {
788 if (value->ob_type == &PyModule_Type) {
789 results << keystr;
789 results << keystr;
790 }
790 }
791 break;
791 break;
792 default:
792 default:
793 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
793 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
794 }
794 }
795 }
795 }
796 Py_DECREF(value);
796 Py_DECREF(value);
797 }
797 }
798 Py_DECREF(keys);
798 Py_DECREF(keys);
799 }
799 }
800 }
800 }
801 }
801 }
802 return results;
802 return results;
803 }
803 }
804
804
805 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
805 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
806 {
806 {
807 PythonQtObjectPtr callable = lookupCallable(object, name);
807 PythonQtObjectPtr callable = lookupCallable(object, name);
808 if (callable) {
808 if (callable) {
809 return call(callable, args);
809 return call(callable, args);
810 } else {
810 } else {
811 return QVariant();
811 return QVariant();
812 }
812 }
813 }
813 }
814
814
815 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
815 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
816 {
816 {
817 QVariant r;
817 QVariant r;
818 if (callable) {
818 if (callable) {
819 PythonQtObjectPtr pargs;
819 PythonQtObjectPtr pargs;
820 int count = args.size();
820 int count = args.size();
821 if (count>0) {
821 if (count>0) {
822 pargs.setNewRef(PyTuple_New(count));
822 pargs.setNewRef(PyTuple_New(count));
823 }
823 }
824 bool err = false;
824 bool err = false;
825 // transform QVariants to Python
825 // transform QVariants to Python
826 for (int i = 0; i < count; i++) {
826 for (int i = 0; i < count; i++) {
827 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
827 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
828 if (arg) {
828 if (arg) {
829 // steals reference, no unref
829 // steals reference, no unref
830 PyTuple_SetItem(pargs, i,arg);
830 PyTuple_SetItem(pargs, i,arg);
831 } else {
831 } else {
832 err = true;
832 err = true;
833 break;
833 break;
834 }
834 }
835 }
835 }
836
836
837 if (!err) {
837 if (!err) {
838 PyErr_Clear();
838 PyErr_Clear();
839 PythonQtObjectPtr result;
839 PythonQtObjectPtr result;
840 result.setNewRef(PyObject_CallObject(callable, pargs));
840 result.setNewRef(PyObject_CallObject(callable, pargs));
841 if (result) {
841 if (result) {
842 // ok
842 // ok
843 r = PythonQtConv::PyObjToQVariant(result);
843 r = PythonQtConv::PyObjToQVariant(result);
844 } else {
844 } else {
845 PythonQt::self()->handleError();
845 PythonQt::self()->handleError();
846 }
846 }
847 }
847 }
848 }
848 }
849 return r;
849 return r;
850 }
850 }
851
851
852 void PythonQt::addInstanceDecorators(QObject* o)
852 void PythonQt::addInstanceDecorators(QObject* o)
853 {
853 {
854 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
854 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
855 }
855 }
856
856
857 void PythonQt::addClassDecorators(QObject* o)
857 void PythonQt::addClassDecorators(QObject* o)
858 {
858 {
859 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
859 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
860 }
860 }
861
861
862 void PythonQt::addDecorators(QObject* o)
862 void PythonQt::addDecorators(QObject* o)
863 {
863 {
864 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
864 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
865 }
865 }
866
866
867 void PythonQt::registerQObjectClassNames(const QStringList& names)
867 void PythonQt::registerQObjectClassNames(const QStringList& names)
868 {
868 {
869 _p->registerQObjectClassNames(names);
869 _p->registerQObjectClassNames(names);
870 }
870 }
871
871
872 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
872 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
873 {
873 {
874 PythonQtImport::init();
874 PythonQtImport::init();
875 _p->_importInterface = importInterface;
875 _p->_importInterface = importInterface;
876 }
876 }
877
877
878 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
878 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
879 {
879 {
880 _p->_importIgnorePaths = paths;
880 _p->_importIgnorePaths = paths;
881 }
881 }
882
882
883 const QStringList& PythonQt::getImporterIgnorePaths()
883 const QStringList& PythonQt::getImporterIgnorePaths()
884 {
884 {
885 return _p->_importIgnorePaths;
885 return _p->_importIgnorePaths;
886 }
886 }
887
887
888 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
888 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
889 {
889 {
890 _p->_cppWrapperFactories.append(factory);
890 _p->_cppWrapperFactories.append(factory);
891 }
891 }
892
892
893 //---------------------------------------------------------------------------------------------------
893 //---------------------------------------------------------------------------------------------------
894 PythonQtPrivate::PythonQtPrivate()
894 PythonQtPrivate::PythonQtPrivate()
895 {
895 {
896 _importInterface = NULL;
896 _importInterface = NULL;
897 _defaultImporter = new PythonQtQFileImporter;
897 _defaultImporter = new PythonQtQFileImporter;
898 _noLongerWrappedCB = NULL;
898 _noLongerWrappedCB = NULL;
899 _wrappedCB = NULL;
899 _wrappedCB = NULL;
900 _currentClassInfoForClassWrapperCreation = NULL;
900 _currentClassInfoForClassWrapperCreation = NULL;
901 }
901 }
902
902
903 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
903 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
904 {
904 {
905 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
905 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
906 _currentClassInfoForClassWrapperCreation = NULL;
906 _currentClassInfoForClassWrapperCreation = NULL;
907 return info;
907 return info;
908 }
908 }
909
909
910 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
910 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
911 {
911 {
912 o->setParent(this);
912 o->setParent(this);
913 int numMethods = o->metaObject()->methodCount();
913 int numMethods = o->metaObject()->methodCount();
914 for (int i = 0; i < numMethods; i++) {
914 for (int i = 0; i < numMethods; i++) {
915 QMetaMethod m = o->metaObject()->method(i);
915 QMetaMethod m = o->metaObject()->method(i);
916 if ((m.methodType() == QMetaMethod::Method ||
916 if ((m.methodType() == QMetaMethod::Method ||
917 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
917 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
918 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m);
918 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
919 if (qstrncmp(m.signature(), "new_", 4)==0) {
919 if (qstrncmp(m.signature(), "new_", 4)==0) {
920 if ((decoTypes & ConstructorDecorator) == 0) continue;
920 if ((decoTypes & ConstructorDecorator) == 0) continue;
921 // either it returns a * or a QVariant and the name starts with "new_"
921 if (info->parameters().at(0).isPointer) {
922 bool isVariantReturn = info->parameters().at(0).typeId == PythonQtMethodInfo::Variant;
923 if ((info->parameters().at(0).isPointer || isVariantReturn)) {
924 QByteArray signature = m.signature();
922 QByteArray signature = m.signature();
925 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
923 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
926 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
924 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
927 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
925 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
928 classInfo->addConstructor(newSlot);
926 classInfo->addConstructor(newSlot);
929 }
927 }
930 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
928 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
931 if ((decoTypes & DestructorDecorator) == 0) continue;
929 if ((decoTypes & DestructorDecorator) == 0) continue;
932 QByteArray signature = m.signature();
930 QByteArray signature = m.signature();
933 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
931 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
934 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
932 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
935 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
933 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
936 classInfo->setDestructor(newSlot);
934 classInfo->setDestructor(newSlot);
937 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
935 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
938 if ((decoTypes & StaticDecorator) == 0) continue;
936 if ((decoTypes & StaticDecorator) == 0) continue;
939 QByteArray signature = m.signature();
937 QByteArray signature = m.signature();
940 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
938 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
941 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
939 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
942 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
940 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
943 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
941 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
944 classInfo->addDecoratorSlot(newSlot);
942 classInfo->addDecoratorSlot(newSlot);
945 } else {
943 } else {
946 if ((decoTypes & InstanceDecorator) == 0) continue;
944 if ((decoTypes & InstanceDecorator) == 0) continue;
947 if (info->parameters().count()>1) {
945 if (info->parameters().count()>1) {
948 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
946 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
949 if (p.isPointer) {
947 if (p.isPointer) {
950 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
948 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
951 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::InstanceDecorator);
949 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
952 classInfo->addDecoratorSlot(newSlot);
950 classInfo->addDecoratorSlot(newSlot);
953 }
951 }
954 }
952 }
955 }
953 }
956 }
954 }
957 }
955 }
958 }
956 }
959
957
960 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
958 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
961 {
959 {
962 foreach(QString name, names) {
960 foreach(QString name, names) {
963 _knownQObjectClassNames.insert(name.toLatin1(), true);
961 _knownQObjectClassNames.insert(name.toLatin1(), true);
964 }
962 }
965 }
963 }
966
964
967 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
965 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
968 {
966 {
969 _signalReceivers.remove(obj);
967 _signalReceivers.remove(obj);
970 }
968 }
971
969
972 bool PythonQt::handleError()
970 bool PythonQt::handleError()
973 {
971 {
974 bool flag = false;
972 bool flag = false;
975 if (PyErr_Occurred()) {
973 if (PyErr_Occurred()) {
976
974
977 // currently we just print the error and the stderr handler parses the errors
975 // currently we just print the error and the stderr handler parses the errors
978 PyErr_Print();
976 PyErr_Print();
979
977
980 /*
978 /*
981 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
979 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
982 PyObject *ptype;
980 PyObject *ptype;
983 PyObject *pvalue;
981 PyObject *pvalue;
984 PyObject *ptraceback;
982 PyObject *ptraceback;
985 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
983 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
986
984
987 Py_XDECREF(ptype);
985 Py_XDECREF(ptype);
988 Py_XDECREF(pvalue);
986 Py_XDECREF(pvalue);
989 Py_XDECREF(ptraceback);
987 Py_XDECREF(ptraceback);
990 */
988 */
991 PyErr_Clear();
989 PyErr_Clear();
992 flag = true;
990 flag = true;
993 }
991 }
994 return flag;
992 return flag;
995 }
993 }
996
994
997 void PythonQt::addSysPath(const QString& path)
995 void PythonQt::addSysPath(const QString& path)
998 {
996 {
999 PythonQtObjectPtr sys;
997 PythonQtObjectPtr sys;
1000 sys.setNewRef(PyImport_ImportModule("sys"));
998 sys.setNewRef(PyImport_ImportModule("sys"));
1001 PythonQtObjectPtr obj = lookupObject(sys, "path");
999 PythonQtObjectPtr obj = lookupObject(sys, "path");
1002 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1000 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1003 }
1001 }
1004
1002
1005 void PythonQt::overwriteSysPath(const QStringList& paths)
1003 void PythonQt::overwriteSysPath(const QStringList& paths)
1006 {
1004 {
1007 PythonQtObjectPtr sys;
1005 PythonQtObjectPtr sys;
1008 sys.setNewRef(PyImport_ImportModule("sys"));
1006 sys.setNewRef(PyImport_ImportModule("sys"));
1009 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1007 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1010 }
1008 }
1011
1009
1012 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1010 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1013 {
1011 {
1014 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1012 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1015 }
1013 }
1016
1014
1017 void PythonQt::stdOutRedirectCB(const QString& str)
1015 void PythonQt::stdOutRedirectCB(const QString& str)
1018 {
1016 {
1019 emit PythonQt::self()->pythonStdOut(str);
1017 emit PythonQt::self()->pythonStdOut(str);
1020 }
1018 }
1021
1019
1022 void PythonQt::stdErrRedirectCB(const QString& str)
1020 void PythonQt::stdErrRedirectCB(const QString& str)
1023 {
1021 {
1024 emit PythonQt::self()->pythonStdErr(str);
1022 emit PythonQt::self()->pythonStdErr(str);
1025 }
1023 }
1026
1024
1027 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1025 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1028 {
1026 {
1029 _p->_wrappedCB = cb;
1027 _p->_wrappedCB = cb;
1030 }
1028 }
1031
1029
1032 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1030 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1033 {
1031 {
1034 _p->_noLongerWrappedCB = cb;
1032 _p->_noLongerWrappedCB = cb;
1035 }
1033 }
1036
1034
1037
1035
1038
1036
1039 static PyMethodDef PythonQtMethods[] = {
1037 static PyMethodDef PythonQtMethods[] = {
1040 {NULL, NULL, 0, NULL}
1038 {NULL, NULL, 0, NULL}
1041 };
1039 };
1042
1040
1043 void PythonQt::initPythonQtModule(bool redirectStdOut)
1041 void PythonQt::initPythonQtModule(bool redirectStdOut)
1044 {
1042 {
1045 _p->_pythonQtModule = Py_InitModule("PythonQt", PythonQtMethods);
1043 _p->_pythonQtModule = Py_InitModule("PythonQt", PythonQtMethods);
1046
1044
1047 if (redirectStdOut) {
1045 if (redirectStdOut) {
1048 PythonQtObjectPtr sys;
1046 PythonQtObjectPtr sys;
1049 PythonQtObjectPtr out;
1047 PythonQtObjectPtr out;
1050 PythonQtObjectPtr err;
1048 PythonQtObjectPtr err;
1051 sys.setNewRef(PyImport_ImportModule("sys"));
1049 sys.setNewRef(PyImport_ImportModule("sys"));
1052 // create a redirection object for stdout and stderr
1050 // create a redirection object for stdout and stderr
1053 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1051 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1054 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1052 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1055 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1053 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1056 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1054 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1057 // replace the built in file objects with our own objects
1055 // replace the built in file objects with our own objects
1058 PyModule_AddObject(sys, "stdout", out);
1056 PyModule_AddObject(sys, "stdout", out);
1059 PyModule_AddObject(sys, "stderr", err);
1057 PyModule_AddObject(sys, "stderr", err);
1060 }
1058 }
1061 }
1059 }
1062
1060
1063 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1061 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1064 {
1062 {
1065 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1063 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1066 }
1064 }
1067
1065
1068
1066
1069 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1067 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1070 {
1068 {
1071 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1069 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1072 if (!info) {
1070 if (!info) {
1073 info = new PythonQtClassInfo();
1071 info = new PythonQtClassInfo();
1074 info->setupCPPObject(typeName);
1072 info->setupCPPObject(typeName);
1075 _knownClassInfos.insert(typeName, info);
1073 _knownClassInfos.insert(typeName, info);
1076 }
1074 }
1077 return info;
1075 return info;
1078 }
1076 }
1079
1077
1080 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1078 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1081 {
1079 {
1082 _p->addPolymorphicHandler(typeName, cb);
1080 _p->addPolymorphicHandler(typeName, cb);
1083 }
1081 }
1084
1082
1085 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1083 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1086 {
1084 {
1087 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1085 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1088 info->addPolymorphicHandler(cb);
1086 info->addPolymorphicHandler(cb);
1089 }
1087 }
1090
1088
1091 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1089 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1092 {
1090 {
1093 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1091 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1094 }
1092 }
1095
1093
1096 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1094 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1097 {
1095 {
1098 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1096 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1099 if (info) {
1097 if (info) {
1100 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1098 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1101 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1099 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1102 return true;
1100 return true;
1103 } else {
1101 } else {
1104 return false;
1102 return false;
1105 }
1103 }
1106 }
1104 }
1107
1105
1108 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1106 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1109 {
1107 {
1110 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1108 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1111 if (!info->pythonQtClassWrapper()) {
1109 if (!info->pythonQtClassWrapper()) {
1112 info->setupCPPObject(typeName);
1110 info->setupCPPObject(typeName);
1113 createPythonQtClassWrapper(info, package);
1111 createPythonQtClassWrapper(info, package);
1114 }
1112 }
1115 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1113 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1116 addParentClass(typeName, parentTypeName, 0);
1114 addParentClass(typeName, parentTypeName, 0);
1117 }
1115 }
1118 if (wrapperCreator) {
1116 if (wrapperCreator) {
1119 info->setDecoratorProvider(wrapperCreator);
1117 info->setDecoratorProvider(wrapperCreator);
1120 }
1118 }
1121 if (shell) {
1119 if (shell) {
1122 info->setShellSetInstanceWrapperCB(shell);
1120 info->setShellSetInstanceWrapperCB(shell);
1123 }
1121 }
1124 }
1122 }
1125
1123
1126 PyObject* PythonQtPrivate::packageByName(const char* name)
1124 PyObject* PythonQtPrivate::packageByName(const char* name)
1127 {
1125 {
1128 if (name==NULL || name[0]==0) {
1126 if (name==NULL || name[0]==0) {
1129 return _pythonQtModule;
1127 return _pythonQtModule;
1130 }
1128 }
1131 PyObject* v = _packages.value(name);
1129 PyObject* v = _packages.value(name);
1132 if (!v) {
1130 if (!v) {
1133 v = PyImport_AddModule((QByteArray("PythonQt.") + name).constData());
1131 v = PyImport_AddModule((QByteArray("PythonQt.") + name).constData());
1134 _packages.insert(name, v);
1132 _packages.insert(name, v);
1135 // AddObject steals the reference, so increment it!
1133 // AddObject steals the reference, so increment it!
1136 Py_INCREF(v);
1134 Py_INCREF(v);
1137 PyModule_AddObject(_pythonQtModule, name, v);
1135 PyModule_AddObject(_pythonQtModule, name, v);
1138 }
1136 }
1139 return v;
1137 return v;
1140 }
1138 }
1141
1139
1142
1140
1143 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1141 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1144 {
1142 {
1145 if (_p->_initFlags & ExternalHelp) {
1143 if (_p->_initFlags & ExternalHelp) {
1146 emit pythonHelpRequest(QByteArray(info->className()));
1144 emit pythonHelpRequest(QByteArray(info->className()));
1147 return Py_BuildValue("");
1145 return Py_BuildValue("");
1148 } else {
1146 } else {
1149 return PyString_FromString(info->help().toLatin1().data());
1147 return PyString_FromString(info->help().toLatin1().data());
1150 }
1148 }
1151 }
1149 }
1152
1150
1153 void PythonQtPrivate::removeWrapperPointer(void* obj)
1151 void PythonQtPrivate::removeWrapperPointer(void* obj)
1154 {
1152 {
1155 _wrappedObjects.remove(obj);
1153 _wrappedObjects.remove(obj);
1156 }
1154 }
1157
1155
1158 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1156 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1159 {
1157 {
1160 _wrappedObjects.insert(obj, wrapper);
1158 _wrappedObjects.insert(obj, wrapper);
1161 }
1159 }
1162
1160
1163 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1161 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1164 {
1162 {
1165 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1163 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1166 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1164 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1167 // this is a wrapper whose QObject was already removed due to destruction
1165 // this is a wrapper whose QObject was already removed due to destruction
1168 // so the obj pointer has to be a new QObject with the same address...
1166 // so the obj pointer has to be a new QObject with the same address...
1169 // we remove the old one and set the copy to NULL
1167 // we remove the old one and set the copy to NULL
1170 wrap->_objPointerCopy = NULL;
1168 wrap->_objPointerCopy = NULL;
1171 removeWrapperPointer(obj);
1169 removeWrapperPointer(obj);
1172 wrap = NULL;
1170 wrap = NULL;
1173 }
1171 }
1174 return wrap;
1172 return wrap;
1175 }
1173 }
1176
1174
1177 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1175 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1178 {
1176 {
1179 PythonQtObjectPtr result;
1177 PythonQtObjectPtr result;
1180 if (pycode) {
1178 if (pycode) {
1181 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1179 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1182 } else {
1180 } else {
1183 PythonQt::self()->handleError();
1181 PythonQt::self()->handleError();
1184 }
1182 }
1185 return result;
1183 return result;
1186 }
1184 }
@@ -1,836 +1,834
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 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaEnum>
47 #include <QMetaEnum>
48
48
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
50
50
51 PythonQtClassInfo::PythonQtClassInfo() {
51 PythonQtClassInfo::PythonQtClassInfo() {
52 _meta = NULL;
52 _meta = NULL;
53 _constructors = NULL;
53 _constructors = NULL;
54 _destructor = NULL;
54 _destructor = NULL;
55 _decoratorProvider = NULL;
55 _decoratorProvider = NULL;
56 _decoratorProviderCB = NULL;
56 _decoratorProviderCB = NULL;
57 _pythonQtClassWrapper = NULL;
57 _pythonQtClassWrapper = NULL;
58 _shellSetInstanceWrapperCB = NULL;
58 _shellSetInstanceWrapperCB = NULL;
59 _metaTypeId = -1;
59 _metaTypeId = -1;
60 _isQObject = false;
60 _isQObject = false;
61 _enumsCreated = false;
61 _enumsCreated = false;
62 }
62 }
63
63
64 PythonQtClassInfo::~PythonQtClassInfo()
64 PythonQtClassInfo::~PythonQtClassInfo()
65 {
65 {
66 clearCachedMembers();
66 clearCachedMembers();
67
67
68 if (_constructors) {
68 if (_constructors) {
69 _constructors->deleteOverloadsAndThis();
69 _constructors->deleteOverloadsAndThis();
70 }
70 }
71 if (_destructor) {
71 if (_destructor) {
72 _destructor->deleteOverloadsAndThis();
72 _destructor->deleteOverloadsAndThis();
73 }
73 }
74 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
74 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 info->deleteOverloadsAndThis();
75 info->deleteOverloadsAndThis();
76 }
76 }
77 }
77 }
78
78
79 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
79 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 {
80 {
81 // _wrappedClassName is already set earlier in the class setup
81 // _wrappedClassName is already set earlier in the class setup
82 _isQObject = true;
82 _isQObject = true;
83 _meta = meta;
83 _meta = meta;
84 }
84 }
85
85
86 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
86 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 {
87 {
88 _isQObject = false;
88 _isQObject = false;
89 _wrappedClassName = classname;
89 _wrappedClassName = classname;
90 _metaTypeId = QMetaType::type(classname);
90 _metaTypeId = QMetaType::type(classname);
91 }
91 }
92
92
93 void PythonQtClassInfo::clearCachedMembers()
93 void PythonQtClassInfo::clearCachedMembers()
94 {
94 {
95 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
95 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 while (i.hasNext()) {
96 while (i.hasNext()) {
97 PythonQtMemberInfo member = i.next().value();
97 PythonQtMemberInfo member = i.next().value();
98 if (member._type== PythonQtMemberInfo::Slot) {
98 if (member._type== PythonQtMemberInfo::Slot) {
99 PythonQtSlotInfo* info = member._slot;
99 PythonQtSlotInfo* info = member._slot;
100 while (info) {
100 while (info) {
101 PythonQtSlotInfo* next = info->nextInfo();
101 PythonQtSlotInfo* next = info->nextInfo();
102 delete info;
102 delete info;
103 info = next;
103 info = next;
104 }
104 }
105 }
105 }
106 }
106 }
107 }
107 }
108
108
109 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
109 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 {
110 {
111 const char* sigEnd = sigStart;
111 const char* sigEnd = sigStart;
112 char c;
112 char c;
113 do {
113 do {
114 c = *sigEnd++;
114 c = *sigEnd++;
115 } while (c!=someChar && c!=0);
115 } while (c!=someChar && c!=0);
116 return sigEnd-sigStart-1;
116 return sigEnd-sigStart-1;
117 }
117 }
118
118
119 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
119 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 {
120 {
121 bool found = false;
121 bool found = false;
122 bool nameMapped = false;
122 bool nameMapped = false;
123 const char* attributeName = memberName;
123 const char* attributeName = memberName;
124 // look for properties
124 // look for properties
125 int i = _meta->indexOfProperty(attributeName);
125 int i = _meta->indexOfProperty(attributeName);
126 if (i==-1) {
126 if (i==-1) {
127 // try to map name to objectName
127 // try to map name to objectName
128 if (qstrcmp(attributeName, "name")==0) {
128 if (qstrcmp(attributeName, "name")==0) {
129 attributeName = "objectName";
129 attributeName = "objectName";
130 nameMapped = true;
130 nameMapped = true;
131 i = _meta->indexOfProperty(attributeName);
131 i = _meta->indexOfProperty(attributeName);
132 }
132 }
133 }
133 }
134 if (i!=-1) {
134 if (i!=-1) {
135 PythonQtMemberInfo newInfo(_meta->property(i));
135 PythonQtMemberInfo newInfo(_meta->property(i));
136 _cachedMembers.insert(attributeName, newInfo);
136 _cachedMembers.insert(attributeName, newInfo);
137 if (nameMapped) {
137 if (nameMapped) {
138 _cachedMembers.insert(memberName, newInfo);
138 _cachedMembers.insert(memberName, newInfo);
139 }
139 }
140 #ifdef PYTHONQT_DEBUG
140 #ifdef PYTHONQT_DEBUG
141 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
141 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
142 #endif
142 #endif
143 found = true;
143 found = true;
144 }
144 }
145 return found;
145 return found;
146 }
146 }
147
147
148 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
148 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
149 {
149 {
150 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
150 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
151 foreach(const ParentClassInfo& info, _parentClasses) {
151 foreach(const ParentClassInfo& info, _parentClasses) {
152 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
152 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
153 }
153 }
154 return inputInfo;
154 return inputInfo;
155 }
155 }
156
156
157 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
157 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
158 QObject* decoratorProvider = decorator();
158 QObject* decoratorProvider = decorator();
159 int memberNameLen = strlen(memberName);
159 int memberNameLen = strlen(memberName);
160 if (decoratorProvider) {
160 if (decoratorProvider) {
161 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
161 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
162 const QMetaObject* meta = decoratorProvider->metaObject();
162 const QMetaObject* meta = decoratorProvider->metaObject();
163 int numMethods = meta->methodCount();
163 int numMethods = meta->methodCount();
164 int startFrom = QObject::staticMetaObject.methodCount();
164 int startFrom = QObject::staticMetaObject.methodCount();
165 for (int i = startFrom; i < numMethods; i++) {
165 for (int i = startFrom; i < numMethods; i++) {
166 QMetaMethod m = meta->method(i);
166 QMetaMethod m = meta->method(i);
167 if ((m.methodType() == QMetaMethod::Method ||
167 if ((m.methodType() == QMetaMethod::Method ||
168 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
168 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
169
169
170 const char* sigStart = m.signature();
170 const char* sigStart = m.signature();
171 bool isClassDeco = false;
171 bool isClassDeco = false;
172 if (qstrncmp(sigStart, "static_", 7)==0) {
172 if (qstrncmp(sigStart, "static_", 7)==0) {
173 // skip the static_classname_ part of the string
173 // skip the static_classname_ part of the string
174 sigStart += 7 + 1 + strlen(className());
174 sigStart += 7 + 1 + strlen(className());
175 isClassDeco = true;
175 isClassDeco = true;
176 } else if (qstrncmp(sigStart, "new_", 4)==0) {
176 } else if (qstrncmp(sigStart, "new_", 4)==0) {
177 isClassDeco = true;
177 isClassDeco = true;
178 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
178 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
179 isClassDeco = true;
179 isClassDeco = true;
180 }
180 }
181 // find the first '('
181 // find the first '('
182 int offset = findCharOffset(sigStart, '(');
182 int offset = findCharOffset(sigStart, '(');
183
183
184 // XXX no checking is currently done if the slots have correct first argument or not...
184 // XXX no checking is currently done if the slots have correct first argument or not...
185
185
186 // check if same length and same name
186 // check if same length and same name
187 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
187 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
188 found = true;
188 found = true;
189 PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
189 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
190 info->setUpcastingOffset(upcastingOffset);
190 info->setUpcastingOffset(upcastingOffset);
191 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
191 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
192 if (tail) {
192 if (tail) {
193 tail->setNextInfo(info);
193 tail->setNextInfo(info);
194 } else {
194 } else {
195 PythonQtMemberInfo newInfo(info);
195 PythonQtMemberInfo newInfo(info);
196 memberCache.insert(memberName, newInfo);
196 memberCache.insert(memberName, newInfo);
197 }
197 }
198 tail = info;
198 tail = info;
199 }
199 }
200 }
200 }
201 }
201 }
202 }
202 }
203
203
204 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
204 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
205
205
206 return tail;
206 return tail;
207 }
207 }
208
208
209 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
209 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
210 {
210 {
211 bool found = false;
211 bool found = false;
212 int memberNameLen = strlen(memberName);
212 int memberNameLen = strlen(memberName);
213 PythonQtSlotInfo* tail = NULL;
213 PythonQtSlotInfo* tail = NULL;
214 if (_meta) {
214 if (_meta) {
215 int numMethods = _meta->methodCount();
215 int numMethods = _meta->methodCount();
216 for (int i = 0; i < numMethods; i++) {
216 for (int i = 0; i < numMethods; i++) {
217 QMetaMethod m = _meta->method(i);
217 QMetaMethod m = _meta->method(i);
218 if ((m.methodType() == QMetaMethod::Method ||
218 if ((m.methodType() == QMetaMethod::Method ||
219 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
219 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
220
220
221 const char* sigStart = m.signature();
221 const char* sigStart = m.signature();
222 // find the first '('
222 // find the first '('
223 int offset = findCharOffset(sigStart, '(');
223 int offset = findCharOffset(sigStart, '(');
224
224
225 // check if same length and same name
225 // check if same length and same name
226 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
226 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
227 found = true;
227 found = true;
228 PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i);
228 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
229 if (tail) {
229 if (tail) {
230 tail->setNextInfo(info);
230 tail->setNextInfo(info);
231 } else {
231 } else {
232 PythonQtMemberInfo newInfo(info);
232 PythonQtMemberInfo newInfo(info);
233 _cachedMembers.insert(memberName, newInfo);
233 _cachedMembers.insert(memberName, newInfo);
234 }
234 }
235 tail = info;
235 tail = info;
236 }
236 }
237 }
237 }
238 }
238 }
239 }
239 }
240
240
241 // look for dynamic decorators in this class and in derived classes
241 // look for dynamic decorators in this class and in derived classes
242 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
242 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
243
243
244 return found;
244 return found;
245 }
245 }
246
246
247 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
247 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
248 {
248 {
249 bool found = false;
249 bool found = false;
250 // look for enum values
250 // look for enum values
251 int enumCount = meta->enumeratorCount();
251 int enumCount = meta->enumeratorCount();
252 for (int i=0;i<enumCount; i++) {
252 for (int i=0;i<enumCount; i++) {
253 QMetaEnum e = meta->enumerator(i);
253 QMetaEnum e = meta->enumerator(i);
254 for (int j=0; j < e.keyCount(); j++) {
254 for (int j=0; j < e.keyCount(); j++) {
255 if (qstrcmp(e.key(j), memberName)==0) {
255 if (qstrcmp(e.key(j), memberName)==0) {
256 PyObject* enumType = findEnumWrapper(e.name());
256 PyObject* enumType = findEnumWrapper(e.name());
257 if (enumType) {
257 if (enumType) {
258 PyObject* args = Py_BuildValue("(i)", e.value(j));
258 PyObject* args = Py_BuildValue("(i)", e.value(j));
259 PyObject* enumValue = PyObject_Call(enumType, args, NULL);
259 PyObject* enumValue = PyObject_Call(enumType, args, NULL);
260 Py_DECREF(args);
260 Py_DECREF(args);
261 PythonQtObjectPtr enumValuePtr;
261 PythonQtObjectPtr enumValuePtr;
262 enumValuePtr.setNewRef(enumValue);
262 enumValuePtr.setNewRef(enumValue);
263 PythonQtMemberInfo newInfo(enumValuePtr);
263 PythonQtMemberInfo newInfo(enumValuePtr);
264 _cachedMembers.insert(memberName, newInfo);
264 _cachedMembers.insert(memberName, newInfo);
265 #ifdef PYTHONQT_DEBUG
265 #ifdef PYTHONQT_DEBUG
266 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
266 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
267 #endif
267 #endif
268 found = true;
268 found = true;
269 break;
269 break;
270 } else {
270 } else {
271 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
271 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
272 }
272 }
273 }
273 }
274 }
274 }
275 }
275 }
276 return found;
276 return found;
277 }
277 }
278
278
279 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
279 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
280 {
280 {
281 PythonQtMemberInfo info = _cachedMembers.value(memberName);
281 PythonQtMemberInfo info = _cachedMembers.value(memberName);
282 if (info._type != PythonQtMemberInfo::Invalid) {
282 if (info._type != PythonQtMemberInfo::Invalid) {
283 return info;
283 return info;
284 } else {
284 } else {
285 bool found = false;
285 bool found = false;
286
286
287 found = lookForPropertyAndCache(memberName);
287 found = lookForPropertyAndCache(memberName);
288 if (!found) {
288 if (!found) {
289 found = lookForMethodAndCache(memberName);
289 found = lookForMethodAndCache(memberName);
290 }
290 }
291 if (!found) {
291 if (!found) {
292 if (_meta) {
292 if (_meta) {
293 // check enums in our meta object directly
293 // check enums in our meta object directly
294 found = lookForEnumAndCache(_meta, memberName);
294 found = lookForEnumAndCache(_meta, memberName);
295 }
295 }
296 if (!found) {
296 if (!found) {
297 // check enums in the class hierachy of CPP classes
297 // check enums in the class hierachy of CPP classes
298 // look for dynamic decorators in this class and in derived classes
298 // look for dynamic decorators in this class and in derived classes
299 QList<QObject*> decoObjects;
299 QList<QObject*> decoObjects;
300 recursiveCollectDecoratorObjects(decoObjects);
300 recursiveCollectDecoratorObjects(decoObjects);
301 foreach(QObject* deco, decoObjects) {
301 foreach(QObject* deco, decoObjects) {
302 // call on ourself for caching, but with different metaObject():
302 // call on ourself for caching, but with different metaObject():
303 found = lookForEnumAndCache(deco->metaObject(), memberName);
303 found = lookForEnumAndCache(deco->metaObject(), memberName);
304 if (found) {
304 if (found) {
305 break;
305 break;
306 }
306 }
307 }
307 }
308 }
308 }
309 }
309 }
310 if (!found) {
310 if (!found) {
311 PyObject* p = findEnumWrapper(memberName);
311 PyObject* p = findEnumWrapper(memberName);
312 if (p) {
312 if (p) {
313 info._type = PythonQtMemberInfo::EnumWrapper;
313 info._type = PythonQtMemberInfo::EnumWrapper;
314 info._enumWrapper = p;
314 info._enumWrapper = p;
315 _cachedMembers.insert(memberName, info);
315 _cachedMembers.insert(memberName, info);
316 found = true;
316 found = true;
317 }
317 }
318 }
318 }
319 if (!found) {
319 if (!found) {
320 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
320 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
321 info._type = PythonQtMemberInfo::NotFound;
321 info._type = PythonQtMemberInfo::NotFound;
322 _cachedMembers.insert(memberName, info);
322 _cachedMembers.insert(memberName, info);
323 }
323 }
324 }
324 }
325
325
326 return _cachedMembers.value(memberName);
326 return _cachedMembers.value(memberName);
327 }
327 }
328
328
329 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
329 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
330 QObject* deco = decorator();
330 QObject* deco = decorator();
331 if (deco) {
331 if (deco) {
332 decoratorObjects.append(deco);
332 decoratorObjects.append(deco);
333 }
333 }
334 foreach(const ParentClassInfo& info, _parentClasses) {
334 foreach(const ParentClassInfo& info, _parentClasses) {
335 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
335 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
336 }
336 }
337 }
337 }
338
338
339 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
339 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
340 classInfoObjects.append(this);
340 classInfoObjects.append(this);
341 foreach(const ParentClassInfo& info, _parentClasses) {
341 foreach(const ParentClassInfo& info, _parentClasses) {
342 info._parent->recursiveCollectClassInfos(classInfoObjects);
342 info._parent->recursiveCollectClassInfos(classInfoObjects);
343 }
343 }
344 }
344 }
345
345
346 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
346 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
347 {
347 {
348 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
348 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
349 while (it.hasNext()) {
349 while (it.hasNext()) {
350
350
351 PythonQtSlotInfo* infoOrig = it.next();
351 PythonQtSlotInfo* infoOrig = it.next();
352
352
353 const char* sigStart = infoOrig->metaMethod()->signature();
353 const char* sigStart = infoOrig->metaMethod()->signature();
354 if (qstrncmp("static_", sigStart, 7)==0) {
354 if (qstrncmp("static_", sigStart, 7)==0) {
355 sigStart += 7;
355 sigStart += 7;
356 sigStart += findCharOffset(sigStart, '_')+1;
356 sigStart += findCharOffset(sigStart, '_')+1;
357 }
357 }
358 int offset = findCharOffset(sigStart, '(');
358 int offset = findCharOffset(sigStart, '(');
359 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
359 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
360 //make a copy, otherwise we will have trouble on overloads!
360 //make a copy, otherwise we will have trouble on overloads!
361 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
361 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
362 info->setUpcastingOffset(upcastingOffset);
362 info->setUpcastingOffset(upcastingOffset);
363 found = true;
363 found = true;
364 if (tail) {
364 if (tail) {
365 tail->setNextInfo(info);
365 tail->setNextInfo(info);
366 } else {
366 } else {
367 PythonQtMemberInfo newInfo(info);
367 PythonQtMemberInfo newInfo(info);
368 memberCache.insert(memberName, newInfo);
368 memberCache.insert(memberName, newInfo);
369 }
369 }
370 tail = info;
370 tail = info;
371 }
371 }
372 }
372 }
373 return tail;
373 return tail;
374 }
374 }
375
375
376 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
376 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
377 QObject* decoratorProvider = decorator();
377 QObject* decoratorProvider = decorator();
378 if (decoratorProvider) {
378 if (decoratorProvider) {
379 const QMetaObject* meta = decoratorProvider->metaObject();
379 const QMetaObject* meta = decoratorProvider->metaObject();
380 int numMethods = meta->methodCount();
380 int numMethods = meta->methodCount();
381 int startFrom = QObject::staticMetaObject.methodCount();
381 int startFrom = QObject::staticMetaObject.methodCount();
382 for (int i = startFrom; i < numMethods; i++) {
382 for (int i = startFrom; i < numMethods; i++) {
383 QMetaMethod m = meta->method(i);
383 QMetaMethod m = meta->method(i);
384 if ((m.methodType() == QMetaMethod::Method ||
384 if ((m.methodType() == QMetaMethod::Method ||
385 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
385 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
386
386
387 const char* sigStart = m.signature();
387 const char* sigStart = m.signature();
388 bool isClassDeco = false;
388 bool isClassDeco = false;
389 if (qstrncmp(sigStart, "static_", 7)==0) {
389 if (qstrncmp(sigStart, "static_", 7)==0) {
390 // skip the static_classname_ part of the string
390 // skip the static_classname_ part of the string
391 sigStart += 7 + 1 + strlen(className());
391 sigStart += 7 + 1 + strlen(className());
392 isClassDeco = true;
392 isClassDeco = true;
393 } else if (qstrncmp(sigStart, "new_", 4)==0) {
393 } else if (qstrncmp(sigStart, "new_", 4)==0) {
394 continue;
394 continue;
395 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
395 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
396 continue;
396 continue;
397 }
397 }
398 // find the first '('
398 // find the first '('
399 int offset = findCharOffset(sigStart, '(');
399 int offset = findCharOffset(sigStart, '(');
400
400
401 // XXX no checking is currently done if the slots have correct first argument or not...
401 // XXX no checking is currently done if the slots have correct first argument or not...
402 if (!metaOnly || isClassDeco) {
402 if (!metaOnly || isClassDeco) {
403 list << QString::fromLatin1(sigStart, offset);
403 list << QString::fromLatin1(sigStart, offset);
404 }
404 }
405 }
405 }
406 }
406 }
407 }
407 }
408
408
409 // look for global decorator slots
409 // look for global decorator slots
410 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
410 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
411 while (it.hasNext()) {
411 while (it.hasNext()) {
412 PythonQtSlotInfo* slot = it.next();
412 PythonQtSlotInfo* slot = it.next();
413 if (metaOnly) {
413 if (metaOnly) {
414 if (slot->isClassDecorator()) {
414 if (slot->isClassDecorator()) {
415 QByteArray first = slot->slotName();
415 QByteArray first = slot->slotName();
416 if (first.startsWith("static_")) {
416 if (first.startsWith("static_")) {
417 int idx = first.indexOf('_');
417 int idx = first.indexOf('_');
418 idx = first.indexOf('_', idx+1);
418 idx = first.indexOf('_', idx+1);
419 first = first.mid(idx+1);
419 first = first.mid(idx+1);
420 }
420 }
421 list << first;
421 list << first;
422 }
422 }
423 } else {
423 } else {
424 list << slot->slotName();
424 list << slot->slotName();
425 }
425 }
426 }
426 }
427 }
427 }
428
428
429 QStringList PythonQtClassInfo::propertyList()
429 QStringList PythonQtClassInfo::propertyList()
430 {
430 {
431 QStringList l;
431 QStringList l;
432 if (_isQObject && _meta) {
432 if (_isQObject && _meta) {
433 int i;
433 int i;
434 int numProperties = _meta->propertyCount();
434 int numProperties = _meta->propertyCount();
435 for (i = 0; i < numProperties; i++) {
435 for (i = 0; i < numProperties; i++) {
436 QMetaProperty p = _meta->property(i);
436 QMetaProperty p = _meta->property(i);
437 l << QString(p.name());
437 l << QString(p.name());
438 }
438 }
439 }
439 }
440 return l;
440 return l;
441 }
441 }
442
442
443 QStringList PythonQtClassInfo::memberList(bool metaOnly)
443 QStringList PythonQtClassInfo::memberList(bool metaOnly)
444 {
444 {
445 decorator();
445 decorator();
446
446
447 QStringList l;
447 QStringList l;
448 QString h;
448 QString h;
449 if (_isQObject && _meta && !metaOnly) {
449 if (_isQObject && _meta && !metaOnly) {
450 l = propertyList();
450 l = propertyList();
451 }
451 }
452
452
453 // normal slots of QObject (or wrapper QObject)
453 // normal slots of QObject (or wrapper QObject)
454 if (!metaOnly && _meta) {
454 if (!metaOnly && _meta) {
455 int numMethods = _meta->methodCount();
455 int numMethods = _meta->methodCount();
456 bool skipQObj = !_isQObject;
456 bool skipQObj = !_isQObject;
457 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
457 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
458 QMetaMethod m = _meta->method(i);
458 QMetaMethod m = _meta->method(i);
459 if ((m.methodType() == QMetaMethod::Method ||
459 if ((m.methodType() == QMetaMethod::Method ||
460 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
460 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
461 QByteArray signa(m.signature());
461 QByteArray signa(m.signature());
462 if (signa.startsWith("new_")) continue;
462 signa = signa.left(signa.indexOf('('));
463 if (signa.startsWith("delete_")) continue;
463 l << signa;
464 if (signa.startsWith("static_")) continue;
465 PythonQtSlotInfo slot(m, i);
466 l << slot.slotName();
467 }
464 }
468 }
465 }
469 }
466 }
470
467
471 {
468 {
472 // look for dynamic decorators in this class and in derived classes
469 // look for dynamic decorators in this class and in derived classes
473 QList<PythonQtClassInfo*> infos;
470 QList<PythonQtClassInfo*> infos;
474 recursiveCollectClassInfos(infos);
471 recursiveCollectClassInfos(infos);
475 foreach(PythonQtClassInfo* info, infos) {
472 foreach(PythonQtClassInfo* info, infos) {
476 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
473 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
477 }
474 }
478 }
475 }
479
476
480 // List enumerator keys...
477 // List enumerator keys...
481 QList<const QMetaObject*> enumMetaObjects;
478 QList<const QMetaObject*> enumMetaObjects;
482 if (_meta) {
479 if (_meta) {
483 enumMetaObjects << _meta;
480 enumMetaObjects << _meta;
484 }
481 }
485 // check enums in the class hierachy of CPP classes
482 // check enums in the class hierachy of CPP classes
486 QList<QObject*> decoObjects;
483 QList<QObject*> decoObjects;
487 recursiveCollectDecoratorObjects(decoObjects);
484 recursiveCollectDecoratorObjects(decoObjects);
488 foreach(QObject* deco, decoObjects) {
485 foreach(QObject* deco, decoObjects) {
489 enumMetaObjects << deco->metaObject();
486 enumMetaObjects << deco->metaObject();
490 }
487 }
491
488
492 foreach(const QMetaObject* meta, enumMetaObjects) {
489 foreach(const QMetaObject* meta, enumMetaObjects) {
493 for (int i = 0; i<meta->enumeratorCount(); i++) {
490 for (int i = 0; i<meta->enumeratorCount(); i++) {
494 QMetaEnum e = meta->enumerator(i);
491 QMetaEnum e = meta->enumerator(i);
495 l << e.name();
492 l << e.name();
496 for (int j=0; j < e.keyCount(); j++) {
493 for (int j=0; j < e.keyCount(); j++) {
497 l << QString(e.key(j));
494 l << QString(e.key(j));
498 }
495 }
499 }
496 }
500 }
497 }
501
498
502 return QSet<QString>::fromList(l).toList();
499 return QSet<QString>::fromList(l).toList();
503 }
500 }
504
501
505 const char* PythonQtClassInfo::className()
502 const char* PythonQtClassInfo::className()
506 {
503 {
507 return _wrappedClassName.constData();
504 return _wrappedClassName.constData();
508 }
505 }
509
506
510 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
507 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
511 {
508 {
512 if (ptr==NULL) {
509 if (ptr==NULL) {
513 return NULL;
510 return NULL;
514 }
511 }
515 if (_wrappedClassName == classname) {
512 if (_wrappedClassName == classname) {
516 return ptr;
513 return ptr;
517 }
514 }
518 foreach(const ParentClassInfo& info, _parentClasses) {
515 foreach(const ParentClassInfo& info, _parentClasses) {
519 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
516 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
520 if (result) {
517 if (result) {
521 return result;
518 return result;
522 }
519 }
523 }
520 }
524 return NULL;
521 return NULL;
525 }
522 }
526
523
527 bool PythonQtClassInfo::inherits(const char* name)
524 bool PythonQtClassInfo::inherits(const char* name)
528 {
525 {
529 if (_wrappedClassName == name) {
526 if (_wrappedClassName == name) {
530 return true;
527 return true;
531 }
528 }
532 foreach(const ParentClassInfo& info, _parentClasses) {
529 foreach(const ParentClassInfo& info, _parentClasses) {
533 if (info._parent->inherits(name)) {
530 if (info._parent->inherits(name)) {
534 return true;
531 return true;
535 }
532 }
536 }
533 }
537 return false;
534 return false;
538 }
535 }
539
536
540 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
537 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
541 {
538 {
542 if (classInfo == this) {
539 if (classInfo == this) {
543 return true;
540 return true;
544 }
541 }
545 foreach(const ParentClassInfo& info, _parentClasses) {
542 foreach(const ParentClassInfo& info, _parentClasses) {
546 if (info._parent->inherits(classInfo)) {
543 if (info._parent->inherits(classInfo)) {
547 return true;
544 return true;
548 }
545 }
549 }
546 }
550 return false;
547 return false;
551 }
548 }
552
549
553 QString PythonQtClassInfo::help()
550 QString PythonQtClassInfo::help()
554 {
551 {
555 decorator();
552 decorator();
556 QString h;
553 QString h;
557 h += QString("--- ") + QString(className()) + QString(" ---\n");
554 h += QString("--- ") + QString(className()) + QString(" ---\n");
558
555
559 if (_isQObject) {
556 if (_isQObject) {
560 h += "Properties:\n";
557 h += "Properties:\n";
561
558
562 int i;
559 int i;
563 int numProperties = _meta->propertyCount();
560 int numProperties = _meta->propertyCount();
564 for (i = 0; i < numProperties; i++) {
561 for (i = 0; i < numProperties; i++) {
565 QMetaProperty p = _meta->property(i);
562 QMetaProperty p = _meta->property(i);
566 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
563 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
567 }
564 }
568 }
565 }
569
566
570 if (constructors()) {
567 if (constructors()) {
571 h += "Constructors:\n";
568 h += "Constructors:\n";
572 PythonQtSlotInfo* constr = constructors();
569 PythonQtSlotInfo* constr = constructors();
573 while (constr) {
570 while (constr) {
574 h += constr->fullSignature() + "\n";
571 h += constr->fullSignature() + "\n";
575 constr = constr->nextInfo();
572 constr = constr->nextInfo();
576 }
573 }
577 }
574 }
578
575
579 h += "Slots:\n";
576 h += "Slots:\n";
580 h += "QString help()\n";
577 h += "QString help()\n";
581 h += "QString className()\n";
578 h += "QString className()\n";
582
579
583 if (_meta) {
580 if (_meta) {
584 int numMethods = _meta->methodCount();
581 int numMethods = _meta->methodCount();
585 for (int i = 0; i < numMethods; i++) {
582 for (int i = 0; i < numMethods; i++) {
586 QMetaMethod m = _meta->method(i);
583 QMetaMethod m = _meta->method(i);
587 if ((m.methodType() == QMetaMethod::Method ||
584 if ((m.methodType() == QMetaMethod::Method ||
588 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
585 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
589 QByteArray signa(m.signature());
586 PythonQtSlotInfo slot(this, m, i);
590 if (signa.startsWith("new_")) continue;
591 if (signa.startsWith("delete_")) continue;
592 if (signa.startsWith("static_")) continue;
593 PythonQtSlotInfo slot(m, i);
594 h += slot.fullSignature()+ "\n";
587 h += slot.fullSignature()+ "\n";
595 }
588 }
596 }
589 }
597 }
590 }
598
591
599 // TODO xxx : decorators and enums from decorator() are missing...
592 // TODO xxx : decorators and enums from decorator() are missing...
600 // maybe we can reuse memberlist()?
593 // maybe we can reuse memberlist()?
601
594
602 if (_meta && _meta->enumeratorCount()) {
595 if (_meta && _meta->enumeratorCount()) {
603 h += "Enums:\n";
596 h += "Enums:\n";
604 for (int i = 0; i<_meta->enumeratorCount(); i++) {
597 for (int i = 0; i<_meta->enumeratorCount(); i++) {
605 QMetaEnum e = _meta->enumerator(i);
598 QMetaEnum e = _meta->enumerator(i);
606 h += QString(e.name()) + " {";
599 h += QString(e.name()) + " {";
607 for (int j=0; j < e.keyCount(); j++) {
600 for (int j=0; j < e.keyCount(); j++) {
608 if (j) { h+= ", "; }
601 if (j) { h+= ", "; }
609 h += e.key(j);
602 h += e.key(j);
610 }
603 }
611 h += " }\n";
604 h += " }\n";
612 }
605 }
613 }
606 }
614
607
615 if (_isQObject && _meta) {
608 if (_isQObject && _meta) {
616 int numMethods = _meta->methodCount();
609 int numMethods = _meta->methodCount();
617 if (numMethods>0) {
610 if (numMethods>0) {
618 h += "Signals:\n";
611 h += "Signals:\n";
619 for (int i = 0; i < numMethods; i++) {
612 for (int i = 0; i < numMethods; i++) {
620 QMetaMethod m = _meta->method(i);
613 QMetaMethod m = _meta->method(i);
621 if (m.methodType() == QMetaMethod::Signal) {
614 if (m.methodType() == QMetaMethod::Signal) {
622 h += QString(m.signature()) + "\n";
615 h += QString(m.signature()) + "\n";
623 }
616 }
624 }
617 }
625 }
618 }
626 }
619 }
627 return h;
620 return h;
628 }
621 }
629
622
630 PythonQtSlotInfo* PythonQtClassInfo::constructors()
623 PythonQtSlotInfo* PythonQtClassInfo::constructors()
631 {
624 {
632 if (!_constructors) {
625 if (!_constructors) {
633 // force creation of lazy decorator, which will register the decorators
626 // force creation of lazy decorator, which will register the decorators
634 decorator();
627 decorator();
635 }
628 }
636 return _constructors;
629 return _constructors;
637 }
630 }
638
631
639 PythonQtSlotInfo* PythonQtClassInfo::destructor()
632 PythonQtSlotInfo* PythonQtClassInfo::destructor()
640 {
633 {
641 if (!_destructor) {
634 if (!_destructor) {
642 // force creation of lazy decorator, which will register the decorators
635 // force creation of lazy decorator, which will register the decorators
643 decorator();
636 decorator();
644 }
637 }
645 return _destructor;
638 return _destructor;
646 }
639 }
647
640
648 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
641 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
649 {
642 {
650 PythonQtSlotInfo* prev = constructors();
643 PythonQtSlotInfo* prev = constructors();
651 if (prev) {
644 if (prev) {
652 info->setNextInfo(prev->nextInfo());
645 info->setNextInfo(prev->nextInfo());
653 prev->setNextInfo(info);
646 prev->setNextInfo(info);
654 } else {
647 } else {
655 _constructors = info;
648 _constructors = info;
656 }
649 }
657 }
650 }
658
651
659 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
652 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
660 {
653 {
661 _decoratorSlots.append(info);
654 _decoratorSlots.append(info);
662 }
655 }
663
656
664 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
657 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
665 {
658 {
666 if (_destructor) {
659 if (_destructor) {
667 _destructor->deleteOverloadsAndThis();
660 _destructor->deleteOverloadsAndThis();
668 }
661 }
669 _destructor = info;
662 _destructor = info;
670 }
663 }
671
664
672 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
665 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
673 {
666 {
674 _meta = meta;
667 _meta = meta;
675 clearCachedMembers();
668 clearCachedMembers();
676 }
669 }
677
670
678 QObject* PythonQtClassInfo::decorator()
671 QObject* PythonQtClassInfo::decorator()
679 {
672 {
680 if (!_decoratorProvider && _decoratorProviderCB) {
673 if (!_decoratorProvider && _decoratorProviderCB) {
681 _decoratorProvider = (*_decoratorProviderCB)();
674 _decoratorProvider = (*_decoratorProviderCB)();
682 if (_decoratorProvider) {
675 if (_decoratorProvider) {
683 _decoratorProvider->setParent(PythonQt::priv());
676 _decoratorProvider->setParent(PythonQt::priv());
677 // setup enums early, since they might be needed by the constructor decorators:
678 if (!_enumsCreated) {
679 createEnumWrappers();
680 }
684 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
681 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
685 }
682 }
686 }
683 }
684 // check if enums need to be created and create them if they are not yet created
687 if (!_enumsCreated) {
685 if (!_enumsCreated) {
688 createEnumWrappers();
686 createEnumWrappers();
689 }
687 }
690 return _decoratorProvider;
688 return _decoratorProvider;
691 }
689 }
692
690
693 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
691 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
694 {
692 {
695 PythonQtMemberInfo info = member("hasOwner");
693 PythonQtMemberInfo info = member("hasOwner");
696 if (info._type == PythonQtMemberInfo::Slot) {
694 if (info._type == PythonQtMemberInfo::Slot) {
697 void* obj = object;
695 void* obj = object;
698 bool result = false;
696 bool result = false;
699 void* args[2];
697 void* args[2];
700 args[0] = &result;
698 args[0] = &result;
701 args[1] = &obj;
699 args[1] = &obj;
702 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
700 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
703 return !result;
701 return !result;
704 } else {
702 } else {
705 return false;
703 return false;
706 }
704 }
707 }
705 }
708
706
709 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
707 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
710 {
708 {
711 if (!_polymorphicHandlers.isEmpty()) {
709 if (!_polymorphicHandlers.isEmpty()) {
712 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
710 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
713 void* resultPtr = (*cb)(ptr, resultClassName);
711 void* resultPtr = (*cb)(ptr, resultClassName);
714 if (resultPtr) {
712 if (resultPtr) {
715 return resultPtr;
713 return resultPtr;
716 }
714 }
717 }
715 }
718 }
716 }
719 foreach(const ParentClassInfo& info, _parentClasses) {
717 foreach(const ParentClassInfo& info, _parentClasses) {
720 if (!info._parent->isQObject()) {
718 if (!info._parent->isQObject()) {
721 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
719 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
722 if (resultPtr) {
720 if (resultPtr) {
723 return resultPtr;
721 return resultPtr;
724 }
722 }
725 }
723 }
726 }
724 }
727 return NULL;
725 return NULL;
728 }
726 }
729
727
730 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
728 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
731 {
729 {
732 char* className;
730 char* className;
733 // this would do downcasting recursively...
731 // this would do downcasting recursively...
734 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
732 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
735
733
736 // we only do downcasting on the base object, not on the whole inheritance tree...
734 // we only do downcasting on the base object, not on the whole inheritance tree...
737 void* resultPtr = NULL;
735 void* resultPtr = NULL;
738 if (!_polymorphicHandlers.isEmpty()) {
736 if (!_polymorphicHandlers.isEmpty()) {
739 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
737 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
740 resultPtr = (*cb)(ptr, &className);
738 resultPtr = (*cb)(ptr, &className);
741 if (resultPtr) {
739 if (resultPtr) {
742 break;
740 break;
743 }
741 }
744 }
742 }
745 }
743 }
746 if (resultPtr) {
744 if (resultPtr) {
747 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
745 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
748 } else {
746 } else {
749 *resultClassInfo = this;
747 *resultClassInfo = this;
750 resultPtr = ptr;
748 resultPtr = ptr;
751 }
749 }
752 return resultPtr;
750 return resultPtr;
753 }
751 }
754
752
755 bool PythonQtClassInfo::hasEnum(const QByteArray& name, PythonQtClassInfo* localScope)
753 bool PythonQtClassInfo::hasEnum(const QByteArray& name, PythonQtClassInfo* localScope)
756 {
754 {
757 int scopePos = name.lastIndexOf("::");
755 int scopePos = name.lastIndexOf("::");
758 if (scopePos != -1) {
756 if (scopePos != -1) {
759 // slit into scope and enum name
757 // slit into scope and enum name
760 QByteArray enumScope = name.mid(0,scopePos);
758 QByteArray enumScope = name.mid(0,scopePos);
761 QByteArray enumName = name.mid(scopePos+2);
759 QByteArray enumName = name.mid(scopePos+2);
762 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
760 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
763 if (info) {
761 if (info) {
764 return info->hasEnum(enumName);
762 return info->hasEnum(enumName);
765 } else{
763 } else{
766 return false;
764 return false;
767 }
765 }
768 }
766 }
769 if (localScope) {
767 if (localScope) {
770 return localScope->hasEnum(name);
768 return localScope->hasEnum(name);
771 } else {
769 } else {
772 return false;
770 return false;
773 }
771 }
774 }
772 }
775
773
776 bool PythonQtClassInfo::hasEnum(const QByteArray& name)
774 bool PythonQtClassInfo::hasEnum(const QByteArray& name)
777 {
775 {
778 bool found = false;
776 bool found = false;
779 if (_meta) {
777 if (_meta) {
780 found = _meta->indexOfEnumerator(name)!=-1;
778 found = _meta->indexOfEnumerator(name)!=-1;
781 }
779 }
782 if (!found) {
780 if (!found) {
783 // check enums in the class hierachy of CPP classes
781 // check enums in the class hierachy of CPP classes
784 // look for dynamic decorators in this class and in derived classes
782 // look for dynamic decorators in this class and in derived classes
785 QList<QObject*> decoObjects;
783 QList<QObject*> decoObjects;
786 recursiveCollectDecoratorObjects(decoObjects);
784 recursiveCollectDecoratorObjects(decoObjects);
787 foreach(QObject* deco, decoObjects) {
785 foreach(QObject* deco, decoObjects) {
788 found = deco->metaObject()->indexOfEnumerator(name)!=-1;
786 found = deco->metaObject()->indexOfEnumerator(name)!=-1;
789 if (found) {
787 if (found) {
790 break;
788 break;
791 }
789 }
792 }
790 }
793 }
791 }
794 return found;
792 return found;
795 }
793 }
796
794
797 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
795 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
798 {
796 {
799 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
797 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
800 QMetaEnum e = meta->enumerator(i);
798 QMetaEnum e = meta->enumerator(i);
801 PythonQtObjectPtr p;
799 PythonQtObjectPtr p;
802 p.setNewRef(PythonQt::priv()->createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
800 p.setNewRef(PythonQt::priv()->createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
803 _enumWrappers.append(p);
801 _enumWrappers.append(p);
804 }
802 }
805 }
803 }
806
804
807 void PythonQtClassInfo::createEnumWrappers()
805 void PythonQtClassInfo::createEnumWrappers()
808 {
806 {
809 if (!_enumsCreated) {
807 if (!_enumsCreated) {
810 _enumsCreated = true;
808 _enumsCreated = true;
811 if (_meta) {
809 if (_meta) {
812 createEnumWrappers(_meta);
810 createEnumWrappers(_meta);
813 }
811 }
814 if (decorator()) {
812 if (decorator()) {
815 createEnumWrappers(decorator()->metaObject());
813 createEnumWrappers(decorator()->metaObject());
816 }
814 }
817 foreach(const ParentClassInfo& info, _parentClasses) {
815 foreach(const ParentClassInfo& info, _parentClasses) {
818 info._parent->createEnumWrappers();
816 info._parent->createEnumWrappers();
819 }
817 }
820 }
818 }
821 }
819 }
822
820
823 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
821 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
824 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
822 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
825 const char* className = ((PyTypeObject*)p.object())->tp_name;
823 const char* className = ((PyTypeObject*)p.object())->tp_name;
826 if (qstrcmp(className, name)==0) {
824 if (qstrcmp(className, name)==0) {
827 return p.object();
825 return p.object();
828 }
826 }
829 }
827 }
830 foreach(const ParentClassInfo& info, _parentClasses) {
828 foreach(const ParentClassInfo& info, _parentClasses) {
831 PyObject* p = info._parent->findEnumWrapper(name);
829 PyObject* p = info._parent->findEnumWrapper(name);
832 if (p) return p;
830 if (p) return p;
833 }
831 }
834 return NULL;
832 return NULL;
835 }
833 }
836
834
@@ -1,319 +1,320
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 PythonQtMethodInfo.cpp
35 // \file PythonQtMethodInfo.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 "PythonQtMethodInfo.h"
42 #include "PythonQtMethodInfo.h"
43 #include "PythonQtClassInfo.h"
43 #include <iostream>
44 #include <iostream>
44
45
45 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
46 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
47
48
48 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta)
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
49 {
50 {
50 #ifdef PYTHONQT_DEBUG
51 #ifdef PYTHONQT_DEBUG
51 QByteArray sig(meta.signature());
52 QByteArray sig(meta.signature());
52 sig = sig.mid(sig.indexOf('('));
53 sig = sig.mid(sig.indexOf('('));
53 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
54 std::cout << "caching " << fullSig.data() << std::endl;
55 std::cout << "caching " << fullSig.data() << std::endl;
55 #endif
56 #endif
56
57
57 ParameterInfo type;
58 ParameterInfo type;
58 fillParameterInfo(type, QByteArray(meta.typeName()));
59 fillParameterInfo(type, QByteArray(meta.typeName()));
59 _parameters.append(type);
60 _parameters.append(type);
60 QByteArray name;
61 QByteArray name;
61 QList<QByteArray> names = meta.parameterTypes();
62 QList<QByteArray> names = meta.parameterTypes();
62 foreach (name, names) {
63 foreach (name, names) {
63 fillParameterInfo(type, name);
64 fillParameterInfo(type, name);
64 _parameters.append(type);
65 _parameters.append(type);
65 }
66 }
66 }
67 }
67
68
68 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal)
69 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
69 {
70 {
70 QByteArray sig(signal.signature());
71 QByteArray sig(signal.signature());
71 sig = sig.mid(sig.indexOf('('));
72 sig = sig.mid(sig.indexOf('('));
72 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
73 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
73 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
74 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
74 if (!result) {
75 if (!result) {
75 result = new PythonQtMethodInfo(signal);
76 result = new PythonQtMethodInfo(signal, classInfo);
76 _cachedSignatures.insert(fullSig, result);
77 _cachedSignatures.insert(fullSig, result);
77 }
78 }
78 return result;
79 return result;
79 }
80 }
80
81
81 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromMetaObjectAndSignature(const QMetaObject* metaObject, const char* signature)
82 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromMetaObjectAndSignature(const QMetaObject* metaObject, const char* signature)
82 {
83 {
83 QByteArray sig = QMetaObject::normalizedSignature(signature);
84 QByteArray sig = QMetaObject::normalizedSignature(signature);
84 int idx = metaObject->indexOfMethod(sig);
85 int idx = metaObject->indexOfMethod(sig);
85 QMetaMethod meta = metaObject->method(idx);
86 QMetaMethod meta = metaObject->method(idx);
86 return PythonQtMethodInfo::getCachedMethodInfo(meta);
87 return PythonQtMethodInfo::getCachedMethodInfo(meta, NULL);
87 }
88 }
88
89
89 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName)
90 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName)
90 {
91 {
91 QByteArray name = orgName;
92 QByteArray name = orgName;
92
93
93 int len = name.length();
94 int len = name.length();
94 if (len>0) {
95 if (len>0) {
95 if (strncmp(name.constData(), "const ", 6)==0) {
96 if (strncmp(name.constData(), "const ", 6)==0) {
96 name = name.mid(6);
97 name = name.mid(6);
97 len -= 6;
98 len -= 6;
98 type.isConst = true;
99 type.isConst = true;
99 } else {
100 } else {
100 type.isConst = false;
101 type.isConst = false;
101 }
102 }
102 bool hadPointer = false;
103 bool hadPointer = false;
103 bool hadReference = false;
104 bool hadReference = false;
104 // remove * and & from the end of the string, handle & and * the same way
105 // remove * and & from the end of the string, handle & and * the same way
105 while (name.at(len-1) == '*') {
106 while (name.at(len-1) == '*') {
106 len--;
107 len--;
107 hadPointer = true;
108 hadPointer = true;
108 }
109 }
109 while (name.at(len-1) == '&') {
110 while (name.at(len-1) == '&') {
110 len--;
111 len--;
111 hadReference = true;
112 hadReference = true;
112 }
113 }
113 if (len!=name.length()) {
114 if (len!=name.length()) {
114 name = name.left(len);
115 name = name.left(len);
115 }
116 }
116 type.isPointer = hadPointer;
117 type.isPointer = hadPointer;
117
118
118 QByteArray alias = _parameterNameAliases.value(name);
119 QByteArray alias = _parameterNameAliases.value(name);
119 if (!alias.isEmpty()) {
120 if (!alias.isEmpty()) {
120 name = alias;
121 name = alias;
121 }
122 }
122
123
123 type.typeId = nameToType(name);
124 type.typeId = nameToType(name);
124 if (!type.isPointer && type.typeId == Unknown) {
125 if (!type.isPointer && type.typeId == Unknown) {
125 type.typeId = QMetaType::type(name.constData());
126 type.typeId = QMetaType::type(name.constData());
126 if (type.typeId == QMetaType::Void) {
127 if (type.typeId == QMetaType::Void) {
127 type.typeId = Unknown;
128 type.typeId = Unknown;
128 }
129 }
129 }
130 }
130 type.name = name;
131 type.name = name;
131 } else {
132 } else {
132 type.typeId = QMetaType::Void;
133 type.typeId = QMetaType::Void;
133 type.isPointer = false;
134 type.isPointer = false;
134 type.isConst = false;
135 type.isConst = false;
135 }
136 }
136 }
137 }
137
138
138 int PythonQtMethodInfo::nameToType(const char* name)
139 int PythonQtMethodInfo::nameToType(const char* name)
139 {
140 {
140 if (_parameterTypeDict.isEmpty()) {
141 if (_parameterTypeDict.isEmpty()) {
141 // we could also use QMetaType::nameToType, but that does a string compare search
142 // we could also use QMetaType::nameToType, but that does a string compare search
142 // and does not support QVariant
143 // and does not support QVariant
143
144
144 // QMetaType names
145 // QMetaType names
145 _parameterTypeDict.insert("long", QMetaType::Long);
146 _parameterTypeDict.insert("long", QMetaType::Long);
146 _parameterTypeDict.insert("int", QMetaType::Int);
147 _parameterTypeDict.insert("int", QMetaType::Int);
147 _parameterTypeDict.insert("short", QMetaType::Short);
148 _parameterTypeDict.insert("short", QMetaType::Short);
148 _parameterTypeDict.insert("char", QMetaType::Char);
149 _parameterTypeDict.insert("char", QMetaType::Char);
149 _parameterTypeDict.insert("ulong", QMetaType::ULong);
150 _parameterTypeDict.insert("ulong", QMetaType::ULong);
150 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
151 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
151 _parameterTypeDict.insert("uint", QMetaType::UInt);
152 _parameterTypeDict.insert("uint", QMetaType::UInt);
152 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
153 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
153 _parameterTypeDict.insert("ushort", QMetaType::UShort);
154 _parameterTypeDict.insert("ushort", QMetaType::UShort);
154 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
155 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
155 _parameterTypeDict.insert("uchar", QMetaType::UChar);
156 _parameterTypeDict.insert("uchar", QMetaType::UChar);
156 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
157 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
157 _parameterTypeDict.insert("bool", QMetaType::Bool);
158 _parameterTypeDict.insert("bool", QMetaType::Bool);
158 _parameterTypeDict.insert("float", QMetaType::Float);
159 _parameterTypeDict.insert("float", QMetaType::Float);
159 _parameterTypeDict.insert("double", QMetaType::Double);
160 _parameterTypeDict.insert("double", QMetaType::Double);
160 _parameterTypeDict.insert("qreal", QMetaType::Double);
161 _parameterTypeDict.insert("qreal", QMetaType::Double);
161 _parameterTypeDict.insert("QChar", QMetaType::QChar);
162 _parameterTypeDict.insert("QChar", QMetaType::QChar);
162 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
163 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
163 _parameterTypeDict.insert("Q3CString", QMetaType::QByteArray);
164 _parameterTypeDict.insert("Q3CString", QMetaType::QByteArray);
164 _parameterTypeDict.insert("QString", QMetaType::QString);
165 _parameterTypeDict.insert("QString", QMetaType::QString);
165 _parameterTypeDict.insert("", QMetaType::Void);
166 _parameterTypeDict.insert("", QMetaType::Void);
166 _parameterTypeDict.insert("void", QMetaType::Void);
167 _parameterTypeDict.insert("void", QMetaType::Void);
167 // QVariant names
168 // QVariant names
168 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
169 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
169 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
170 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
170 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
171 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
171 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
172 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
172 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
173 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
173 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
174 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
174 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
175 _parameterTypeDict.insert("QIconSet", QMetaType::QIcon);
175 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
176 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
176 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
177 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
177 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
178 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
178 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
179 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
179 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
180 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
180 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
181 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
181 _parameterTypeDict.insert("QDate", QMetaType::QDate);
182 _parameterTypeDict.insert("QDate", QMetaType::QDate);
182 _parameterTypeDict.insert("QTime", QMetaType::QTime);
183 _parameterTypeDict.insert("QTime", QMetaType::QTime);
183 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
184 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
184 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
185 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
185 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
186 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
186 _parameterTypeDict.insert("QRect", QMetaType::QRect);
187 _parameterTypeDict.insert("QRect", QMetaType::QRect);
187 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
188 _parameterTypeDict.insert("QRectf", QMetaType::QRectF);
188 _parameterTypeDict.insert("QSize", QMetaType::QSize);
189 _parameterTypeDict.insert("QSize", QMetaType::QSize);
189 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
190 _parameterTypeDict.insert("QSizef", QMetaType::QSizeF);
190 _parameterTypeDict.insert("QLine", QMetaType::QLine);
191 _parameterTypeDict.insert("QLine", QMetaType::QLine);
191 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
192 _parameterTypeDict.insert("QLinef", QMetaType::QLineF);
192 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
193 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
193 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
194 _parameterTypeDict.insert("QPointf", QMetaType::QPointF);
194 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
195 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
195 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
196 // _parameterTypeDict.insert("QColorGroup", QMetaType::QColorGroup);
196 _parameterTypeDict.insert("QFont", QMetaType::QFont);
197 _parameterTypeDict.insert("QFont", QMetaType::QFont);
197 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
198 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
198 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
199 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
199 _parameterTypeDict.insert("QColor", QMetaType::QColor);
200 _parameterTypeDict.insert("QColor", QMetaType::QColor);
200 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
201 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
201 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
202 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
202 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
203 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
203 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
204 _parameterTypeDict.insert("QImage", QMetaType::QPolygon);
204 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
205 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
205 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
206 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
206 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
207 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
207 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
208 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
208 _parameterTypeDict.insert("QPen", QMetaType::QPen);
209 _parameterTypeDict.insert("QPen", QMetaType::QPen);
209 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
210 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
210 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
211 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
211 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
212 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
212 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
213 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
213 // own special types... (none so far, could be e.g. ObjectList
214 // own special types... (none so far, could be e.g. ObjectList
214 }
215 }
215 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
216 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
216 if (it!=_parameterTypeDict.end()) {
217 if (it!=_parameterTypeDict.end()) {
217 return it.value();
218 return it.value();
218 } else {
219 } else {
219 return PythonQtMethodInfo::Unknown;
220 return PythonQtMethodInfo::Unknown;
220 }
221 }
221 }
222 }
222
223
223 void PythonQtMethodInfo::cleanupCachedMethodInfos()
224 void PythonQtMethodInfo::cleanupCachedMethodInfos()
224 {
225 {
225 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
226 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
226 while (i.hasNext()) {
227 while (i.hasNext()) {
227 delete i.next().value();
228 delete i.next().value();
228 }
229 }
229 }
230 }
230
231
231 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
232 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
232 {
233 {
233 _parameterNameAliases.insert(alias, name);
234 _parameterNameAliases.insert(alias, name);
234 }
235 }
235
236
236 //-------------------------------------------------------------------------------------------------
237 //-------------------------------------------------------------------------------------------------
237
238
238 void PythonQtSlotInfo::deleteOverloadsAndThis()
239 void PythonQtSlotInfo::deleteOverloadsAndThis()
239 {
240 {
240 PythonQtSlotInfo* cur = this;
241 PythonQtSlotInfo* cur = this;
241 while(cur->nextInfo()) {
242 while(cur->nextInfo()) {
242 PythonQtSlotInfo* next = cur->nextInfo();
243 PythonQtSlotInfo* next = cur->nextInfo();
243 delete cur;
244 delete cur;
244 cur = next;
245 cur = next;
245 }
246 }
246 }
247 }
247
248
248
249
249 QString PythonQtSlotInfo::fullSignature()
250 QString PythonQtSlotInfo::fullSignature()
250 {
251 {
251 bool skipFirstArg = isInstanceDecorator();
252 bool skipFirstArg = isInstanceDecorator();
252 QString result = _meta.typeName();
253 QString result = _meta.typeName();
253 QByteArray sig = slotName();
254 QByteArray sig = slotName();
254 QList<QByteArray> names = _meta.parameterNames();
255 QList<QByteArray> names = _meta.parameterNames();
255
256
256 bool isStatic = false;
257 bool isStatic = false;
257 bool isConstructor = false;
258 bool isConstructor = false;
258 bool isDestructor = false;
259 bool isDestructor = false;
259
260
260 if (_type == ClassDecorator) {
261 if (_type == ClassDecorator) {
261 if (sig.startsWith("new_")) {
262 if (sig.startsWith("new_")) {
262 sig = sig.mid(strlen("new_"));
263 sig = sig.mid(strlen("new_"));
263 isConstructor = true;
264 isConstructor = true;
264 } else if (sig.startsWith("delete_")) {
265 } else if (sig.startsWith("delete_")) {
265 sig = sig.mid(strlen("delete_"));
266 sig = sig.mid(strlen("delete_"));
266 isDestructor = true;
267 isDestructor = true;
267 } else if(sig.startsWith("static_")) {
268 } else if(sig.startsWith("static_")) {
268 isStatic = true;
269 isStatic = true;
269 sig = sig.mid(strlen("static_"));
270 sig = sig.mid(strlen("static_"));
270 int idx = sig.indexOf("_");
271 int idx = sig.indexOf("_");
271 if (idx>=0) {
272 if (idx>=0) {
272 sig = sig.mid(idx+1);
273 sig = sig.mid(idx+1);
273 }
274 }
274 }
275 }
275 }
276 }
276
277
277 result += QByteArray(" ") + sig;
278 result += QByteArray(" ") + sig;
278 result += "(";
279 result += "(";
279
280
280 int lastEntry = _parameters.count()-1;
281 int lastEntry = _parameters.count()-1;
281 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
282 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
282 if (_parameters.at(i).isConst) {
283 if (_parameters.at(i).isConst) {
283 result += "const ";
284 result += "const ";
284 }
285 }
285 result += _parameters.at(i).name;
286 result += _parameters.at(i).name;
286 if (_parameters.at(i).isPointer) {
287 if (_parameters.at(i).isPointer) {
287 result += "*";
288 result += "*";
288 }
289 }
289 if (!names.at(i-1).isEmpty()) {
290 if (!names.at(i-1).isEmpty()) {
290 result += " ";
291 result += " ";
291 result += names.at(i-1);
292 result += names.at(i-1);
292 }
293 }
293 if (i!=lastEntry) {
294 if (i!=lastEntry) {
294 result += ", ";
295 result += ", ";
295 }
296 }
296 }
297 }
297 result += ")";
298 result += ")";
298
299
299 if (isStatic) {
300 if (isStatic) {
300 result = QString("static ") + result;
301 result = QString("static ") + result;
301 }
302 }
302 if (isConstructor) {
303 if (isConstructor) {
303 // result = QString("constructor ") + result;
304 // result = QString("constructor ") + result;
304 }
305 }
305 if (isDestructor) {
306 if (isDestructor) {
306 result = QString("~") + result;
307 result = QString("~") + result;
307 }
308 }
308 return result;
309 return result;
309 }
310 }
310
311
311
312
312 QByteArray PythonQtSlotInfo::slotName()
313 QByteArray PythonQtSlotInfo::slotName()
313 {
314 {
314 QByteArray sig(_meta.signature());
315 QByteArray sig(_meta.signature());
315 int idx = sig.indexOf('(');
316 int idx = sig.indexOf('(');
316 sig = sig.left(idx);
317 sig = sig.left(idx);
317 return sig;
318 return sig;
318 }
319 }
319
320
@@ -1,184 +1,186
1 #ifndef _PYTHONQTMETHODINFO_H
1 #ifndef _PYTHONQTMETHODINFO_H
2 #define _PYTHONQTMETHODINFO_H
2 #define _PYTHONQTMETHODINFO_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 PythonQtMethodInfo.h
38 // \file PythonQtMethodInfo.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
46
47 #include <QByteArray>
47 #include <QByteArray>
48 #include <QHash>
48 #include <QHash>
49 #include <QList>
49 #include <QList>
50 #include <QMetaMethod>
50 #include <QMetaMethod>
51
51
52 class PythonQtClassInfo;
53
52 //! stores information about a specific signal/slot/method
54 //! stores information about a specific signal/slot/method
53 class PYTHONQT_EXPORT PythonQtMethodInfo
55 class PYTHONQT_EXPORT PythonQtMethodInfo
54 {
56 {
55 public:
57 public:
56 enum ParameterType {
58 enum ParameterType {
57 Unknown = -1,
59 Unknown = -1,
58 Variant = -2
60 Variant = -2
59 };
61 };
60
62
61 //! stores the QVariant id (if available) and the name of the type
63 //! stores the QVariant id (if available) and the name of the type
62 struct ParameterInfo {
64 struct ParameterInfo {
63 int typeId; // a mixture from QMetaType and ParameterType
65 int typeId; // a mixture from QMetaType and ParameterType
64 QByteArray name;
66 QByteArray name;
65 bool isPointer;
67 bool isPointer;
66 bool isConst;
68 bool isConst;
67 };
69 };
68
70
69 PythonQtMethodInfo() {};
71 PythonQtMethodInfo() {};
70 ~PythonQtMethodInfo() {};
72 ~PythonQtMethodInfo() {};
71 PythonQtMethodInfo(const QMetaMethod& meta);
73 PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo);
72 PythonQtMethodInfo(const PythonQtMethodInfo& other) {
74 PythonQtMethodInfo(const PythonQtMethodInfo& other) {
73 _parameters = other._parameters;
75 _parameters = other._parameters;
74 }
76 }
75
77
76 //! returns the method info of the signature, uses a cache internally to speed up
78 //! returns the method info of the signature, uses a cache internally to speed up
77 //! multiple requests for the same method
79 //! multiple requests for the same method, classInfo is passed to allow local enum resolution (if NULL is passed, no local enums are recognized)
78 static const PythonQtMethodInfo* getCachedMethodInfo(const QMetaMethod& method);
80 static const PythonQtMethodInfo* getCachedMethodInfo(const QMetaMethod& method, PythonQtClassInfo* classInfo);
79
81
80 //! get the cached method info by finding the meta method on the meta object via its signature
82 //! get the cached method info by finding the meta method on the meta object via its signature, enums are only supported with leading namespace::
81 static const PythonQtMethodInfo* getCachedMethodInfoFromMetaObjectAndSignature(const QMetaObject* metaObject, const char* signature);
83 static const PythonQtMethodInfo* getCachedMethodInfoFromMetaObjectAndSignature(const QMetaObject* metaObject, const char* signature);
82
84
83 //! cleanup the cache
85 //! cleanup the cache
84 static void cleanupCachedMethodInfos();
86 static void cleanupCachedMethodInfos();
85
87
86 //! returns the number of parameters including the return value
88 //! returns the number of parameters including the return value
87 int parameterCount() const { return _parameters.size(); };
89 int parameterCount() const { return _parameters.size(); };
88
90
89 //! returns the id for the given type (using an internal dictionary)
91 //! returns the id for the given type (using an internal dictionary)
90 static int nameToType(const char* name);
92 static int nameToType(const char* name);
91
93
92 //! get the parameter infos
94 //! get the parameter infos
93 const QList<ParameterInfo>& parameters() const { return _parameters; }
95 const QList<ParameterInfo>& parameters() const { return _parameters; }
94
96
95 //! add an alias for a typename, e.g. QObjectList and QList<QObject*>.
97 //! add an alias for a typename, e.g. QObjectList and QList<QObject*>.
96 static void addParameterTypeAlias(const QByteArray& alias, const QByteArray& name);
98 static void addParameterTypeAlias(const QByteArray& alias, const QByteArray& name);
97
99
98 protected:
100 protected:
99 static void fillParameterInfo(ParameterInfo& type, const QByteArray& name);
101 static void fillParameterInfo(ParameterInfo& type, const QByteArray& name);
100
102
101 static QHash<QByteArray, int> _parameterTypeDict;
103 static QHash<QByteArray, int> _parameterTypeDict;
102 static QHash<QByteArray, QByteArray> _parameterNameAliases;
104 static QHash<QByteArray, QByteArray> _parameterNameAliases;
103
105
104 //! stores the cached signatures of methods to speedup mapping from Qt to Python types
106 //! stores the cached signatures of methods to speedup mapping from Qt to Python types
105 static QHash<QByteArray, PythonQtMethodInfo*> _cachedSignatures;
107 static QHash<QByteArray, PythonQtMethodInfo*> _cachedSignatures;
106
108
107 QList<ParameterInfo> _parameters;
109 QList<ParameterInfo> _parameters;
108 };
110 };
109
111
110 //! stores information about a slot, including a next pointer to overloaded slots
112 //! stores information about a slot, including a next pointer to overloaded slots
111 class PythonQtSlotInfo : public PythonQtMethodInfo
113 class PythonQtSlotInfo : public PythonQtMethodInfo
112 {
114 {
113 public:
115 public:
114 enum Type {
116 enum Type {
115 MemberSlot, InstanceDecorator, ClassDecorator
117 MemberSlot, InstanceDecorator, ClassDecorator
116 };
118 };
117
119
118 PythonQtSlotInfo(const PythonQtSlotInfo& info):PythonQtMethodInfo() {
120 PythonQtSlotInfo(const PythonQtSlotInfo& info):PythonQtMethodInfo() {
119 _meta = info._meta;
121 _meta = info._meta;
120 _parameters = info._parameters;
122 _parameters = info._parameters;
121 _slotIndex = info._slotIndex;
123 _slotIndex = info._slotIndex;
122 _next = NULL;
124 _next = NULL;
123 _decorator = info._decorator;
125 _decorator = info._decorator;
124 _type = info._type;
126 _type = info._type;
125 _upcastingOffset = 0;
127 _upcastingOffset = 0;
126 }
128 }
127
129
128 PythonQtSlotInfo(const QMetaMethod& meta, int slotIndex, QObject* decorator = NULL, Type type = MemberSlot ):PythonQtMethodInfo()
130 PythonQtSlotInfo(PythonQtClassInfo* classInfo, const QMetaMethod& meta, int slotIndex, QObject* decorator = NULL, Type type = MemberSlot ):PythonQtMethodInfo()
129 {
131 {
130 const PythonQtMethodInfo* info = getCachedMethodInfo(meta);
132 const PythonQtMethodInfo* info = getCachedMethodInfo(meta, classInfo);
131 _meta = meta;
133 _meta = meta;
132 _parameters = info->parameters();
134 _parameters = info->parameters();
133 _slotIndex = slotIndex;
135 _slotIndex = slotIndex;
134 _next = NULL;
136 _next = NULL;
135 _decorator = decorator;
137 _decorator = decorator;
136 _type = type;
138 _type = type;
137 _upcastingOffset = 0;
139 _upcastingOffset = 0;
138 }
140 }
139
141
140
142
141 public:
143 public:
142
144
143 void deleteOverloadsAndThis();
145 void deleteOverloadsAndThis();
144
146
145 const QMetaMethod* metaMethod() const { return &_meta; }
147 const QMetaMethod* metaMethod() const { return &_meta; }
146
148
147 void setUpcastingOffset(int upcastingOffset) { _upcastingOffset = upcastingOffset; }
149 void setUpcastingOffset(int upcastingOffset) { _upcastingOffset = upcastingOffset; }
148
150
149 int upcastingOffset() const { return _upcastingOffset; }
151 int upcastingOffset() const { return _upcastingOffset; }
150
152
151 //! get the index of the slot (needed for qt_metacall)
153 //! get the index of the slot (needed for qt_metacall)
152 int slotIndex() const { return _slotIndex; }
154 int slotIndex() const { return _slotIndex; }
153
155
154 //! get next overloaded slot (which has the same name)
156 //! get next overloaded slot (which has the same name)
155 PythonQtSlotInfo* nextInfo() const { return _next; }
157 PythonQtSlotInfo* nextInfo() const { return _next; }
156
158
157 //! set the next overloaded slot
159 //! set the next overloaded slot
158 void setNextInfo(PythonQtSlotInfo* next) { _next = next; }
160 void setNextInfo(PythonQtSlotInfo* next) { _next = next; }
159
161
160 //! returns if the slot is a decorator slot
162 //! returns if the slot is a decorator slot
161 bool isInstanceDecorator() { return _decorator!=NULL && _type == InstanceDecorator; }
163 bool isInstanceDecorator() { return _decorator!=NULL && _type == InstanceDecorator; }
162
164
163 //! returns if the slot is a constructor slot
165 //! returns if the slot is a constructor slot
164 bool isClassDecorator() { return _decorator!=NULL && _type == ClassDecorator; }
166 bool isClassDecorator() { return _decorator!=NULL && _type == ClassDecorator; }
165
167
166 QObject* decorator() { return _decorator; }
168 QObject* decorator() { return _decorator; }
167
169
168 //! get the full signature including return type
170 //! get the full signature including return type
169 QString fullSignature();
171 QString fullSignature();
170
172
171 //! get the short slot name
173 //! get the short slot name
172 QByteArray slotName();
174 QByteArray slotName();
173
175
174 private:
176 private:
175 int _slotIndex;
177 int _slotIndex;
176 PythonQtSlotInfo* _next;
178 PythonQtSlotInfo* _next;
177 QObject* _decorator;
179 QObject* _decorator;
178 Type _type;
180 Type _type;
179 QMetaMethod _meta;
181 QMetaMethod _meta;
180 int _upcastingOffset;
182 int _upcastingOffset;
181 };
183 };
182
184
183
185
184 #endif
186 #endif
@@ -1,222 +1,233
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 PythonQtSignalReceiver.cpp
35 // \file PythonQtSignalReceiver.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 "PythonQtSignalReceiver.h"
42 #include "PythonQtSignalReceiver.h"
43 #include "PythonQtClassInfo.h"
43 #include "PythonQtClassInfo.h"
44 #include "PythonQtMethodInfo.h"
44 #include "PythonQtMethodInfo.h"
45 #include "PythonQtConversion.h"
45 #include "PythonQtConversion.h"
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaMethod>
47 #include <QMetaMethod>
48 #include "funcobject.h"
48 #include "funcobject.h"
49
49
50 void PythonQtSignalTarget::call(void **arguments) const {
50 void PythonQtSignalTarget::call(void **arguments) const {
51 PyObject* result = call(_callable, methodInfo(), arguments, false);
51 PyObject* result = call(_callable, methodInfo(), arguments, false);
52 if (result) {
52 if (result) {
53 Py_DECREF(result);
53 Py_DECREF(result);
54 }
54 }
55 }
55 }
56
56
57 PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInfo* methodInfos, void **arguments, bool skipFirstArgumentOfMethodInfo)
57 PyObject* PythonQtSignalTarget::call(PyObject* callable, const PythonQtMethodInfo* methodInfos, void **arguments, bool skipFirstArgumentOfMethodInfo)
58 {
58 {
59 // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments
59 // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments
60 // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal
60 // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal
61
61
62 int numPythonArgs = -1;
62 int numPythonArgs = -1;
63 if (PyFunction_Check(callable)) {
63 if (PyFunction_Check(callable)) {
64 PyObject* o = callable;
64 PyObject* o = callable;
65 PyFunctionObject* func = (PyFunctionObject*)o;
65 PyFunctionObject* func = (PyFunctionObject*)o;
66 PyCodeObject* code = (PyCodeObject*)func->func_code;
66 PyCodeObject* code = (PyCodeObject*)func->func_code;
67 if (!(code->co_flags & 0x04)) {
67 if (!(code->co_flags & 0x04)) {
68 numPythonArgs = code->co_argcount;
68 numPythonArgs = code->co_argcount;
69 } else {
69 } else {
70 // variable numbers of arguments allowed
70 // variable numbers of arguments allowed
71 }
71 }
72 } else if (PyMethod_Check(callable)) {
72 } else if (PyMethod_Check(callable)) {
73 PyObject* o = callable;
73 PyObject* o = callable;
74 PyMethodObject* method = (PyMethodObject*)o;
74 PyMethodObject* method = (PyMethodObject*)o;
75 if (PyFunction_Check(method->im_func)) {
75 if (PyFunction_Check(method->im_func)) {
76 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
76 PyFunctionObject* func = (PyFunctionObject*)method->im_func;
77 PyCodeObject* code = (PyCodeObject*)func->func_code;
77 PyCodeObject* code = (PyCodeObject*)func->func_code;
78 if (!(code->co_flags & 0x04)) {
78 if (!(code->co_flags & 0x04)) {
79 numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self"
79 numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self"
80 } else {
80 } else {
81 // variable numbers of arguments allowed
81 // variable numbers of arguments allowed
82 }
82 }
83 }
83 }
84 }
84 }
85
85
86 const PythonQtMethodInfo* m = methodInfos;
86 const PythonQtMethodInfo* m = methodInfos;
87 // parameterCount includes return value:
87 // parameterCount includes return value:
88 int count = m->parameterCount();
88 int count = m->parameterCount();
89 if (skipFirstArgumentOfMethodInfo) {
89 if (skipFirstArgumentOfMethodInfo) {
90 count--;
90 count--;
91 }
91 }
92 if (numPythonArgs!=-1) {
92 if (numPythonArgs!=-1) {
93 if (count>numPythonArgs+1) {
93 if (count>numPythonArgs+1) {
94 // take less arguments
94 // take less arguments
95 count = numPythonArgs+1;
95 count = numPythonArgs+1;
96 }
96 }
97 }
97 }
98
98
99 PyObject* pargs = NULL;
99 PyObject* pargs = NULL;
100 if (count>1) {
100 if (count>1) {
101 pargs = PyTuple_New(count-1);
101 pargs = PyTuple_New(count-1);
102 }
102 }
103 bool err = false;
103 bool err = false;
104 // transform Qt values to Python
104 // transform Qt values to Python
105 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
105 const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters();
106 int skipFirstOffset = 0;
106 int skipFirstOffset = 0;
107 if (skipFirstArgumentOfMethodInfo) {
107 if (skipFirstArgumentOfMethodInfo) {
108 skipFirstOffset = 1;
108 skipFirstOffset = 1;
109 }
109 }
110 for (int i = 1; i < count; i++) {
110 for (int i = 1; i < count; i++) {
111 const PythonQtMethodInfo::ParameterInfo& param = params.at(i + skipFirstOffset);
111 const PythonQtMethodInfo::ParameterInfo& param = params.at(i + skipFirstOffset);
112 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
112 PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]);
113 if (arg) {
113 if (arg) {
114 // steals reference, no unref
114 // steals reference, no unref
115 PyTuple_SetItem(pargs, i-1,arg);
115 PyTuple_SetItem(pargs, i-1,arg);
116 } else {
116 } else {
117 err = true;
117 err = true;
118 break;
118 break;
119 }
119 }
120 }
120 }
121
121
122 PyObject* result = NULL;
122 PyObject* result = NULL;
123 if (!err) {
123 if (!err) {
124 PyErr_Clear();
124 PyErr_Clear();
125 result = PyObject_CallObject(callable, pargs);
125 result = PyObject_CallObject(callable, pargs);
126 if (result) {
126 if (result) {
127 // ok
127 // ok
128 } else {
128 } else {
129 PythonQt::self()->handleError();
129 PythonQt::self()->handleError();
130 }
130 }
131 }
131 }
132 if (pargs) {
132 if (pargs) {
133 // free the arguments again
133 // free the arguments again
134 Py_DECREF(pargs);
134 Py_DECREF(pargs);
135 }
135 }
136
136
137 return result;
137 return result;
138 }
138 }
139
139
140 //------------------------------------------------------------------------------
140 //------------------------------------------------------------------------------
141
141
142 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
142 PythonQtSignalReceiver::PythonQtSignalReceiver(QObject* obj):PythonQtSignalReceiverBase(obj)
143 {
143 {
144 _obj = obj;
144 _obj = obj;
145
146 // fetch the class info for object, since we will need to for correct enum resolution in
147 // signals
148 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
149 if (!_objClassInfo || !_objClassInfo->isQObject()) {
150 PythonQt::self()->registerClass(obj->metaObject());
151 _objClassInfo = PythonQt::priv()->getClassInfo(obj->metaObject());
152 }
153 // force decorator/enum creation
154 _objClassInfo->decorator();
155
145 _slotCount = staticMetaObject.methodOffset();
156 _slotCount = staticMetaObject.methodOffset();
146 }
157 }
147
158
148 PythonQtSignalReceiver::~PythonQtSignalReceiver()
159 PythonQtSignalReceiver::~PythonQtSignalReceiver()
149 {
160 {
150 PythonQt::priv()->removeSignalEmitter(_obj);
161 PythonQt::priv()->removeSignalEmitter(_obj);
151 }
162 }
152
163
153
164
154 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
165 bool PythonQtSignalReceiver::addSignalHandler(const char* signal, PyObject* callable)
155 {
166 {
156 bool flag = false;
167 bool flag = false;
157 int sigId = getSignalIndex(signal);
168 int sigId = getSignalIndex(signal);
158 if (sigId>=0) {
169 if (sigId>=0) {
159 // create PythonQtMethodInfo from signal
170 // create PythonQtMethodInfo from signal
160 QMetaMethod meta = _obj->metaObject()->method(sigId);
171 QMetaMethod meta = _obj->metaObject()->method(sigId);
161 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta);
172 const PythonQtMethodInfo* signalInfo = PythonQtMethodInfo::getCachedMethodInfo(meta, _objClassInfo);
162 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
173 PythonQtSignalTarget t(sigId, signalInfo, _slotCount, callable);
163 _targets.append(t);
174 _targets.append(t);
164 // now connect to ourselves with the new slot id
175 // now connect to ourselves with the new slot id
165 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
176 QMetaObject::connect(_obj, sigId, this, _slotCount, Qt::AutoConnection, 0);
166
177
167 _slotCount++;
178 _slotCount++;
168 flag = true;
179 flag = true;
169 }
180 }
170 return flag;
181 return flag;
171 }
182 }
172
183
173 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
184 bool PythonQtSignalReceiver::removeSignalHandler(const char* signal, PyObject* callable)
174 {
185 {
175 bool found = false;
186 bool found = false;
176 int sigId = getSignalIndex(signal);
187 int sigId = getSignalIndex(signal);
177 if (sigId>=0) {
188 if (sigId>=0) {
178 QMutableListIterator<PythonQtSignalTarget> i(_targets);
189 QMutableListIterator<PythonQtSignalTarget> i(_targets);
179 while (i.hasNext()) {
190 while (i.hasNext()) {
180 if (i.next().isSame(sigId, callable)) {
191 if (i.next().isSame(sigId, callable)) {
181 i.remove();
192 i.remove();
182 found = true;
193 found = true;
183 break;
194 break;
184 }
195 }
185 }
196 }
186 }
197 }
187 return found;
198 return found;
188 }
199 }
189
200
190 void PythonQtSignalReceiver::removeSignalHandlers()
201 void PythonQtSignalReceiver::removeSignalHandlers()
191 {
202 {
192 _targets.clear();
203 _targets.clear();
193 }
204 }
194
205
195 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
206 int PythonQtSignalReceiver::getSignalIndex(const char* signal)
196 {
207 {
197 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
208 int sigId = _obj->metaObject()->indexOfSignal(signal+1);
198 if (sigId<0) {
209 if (sigId<0) {
199 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
210 QByteArray tmpSig = QMetaObject::normalizedSignature(signal+1);
200 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
211 sigId = _obj->metaObject()->indexOfSignal(tmpSig);
201 }
212 }
202 return sigId;
213 return sigId;
203 }
214 }
204
215
205 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
216 int PythonQtSignalReceiver::qt_metacall(QMetaObject::Call c, int id, void **arguments)
206 {
217 {
207 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
218 // mlabDebugConst("PythonQt", "PythonQtSignalReceiver invoke " << _obj->className() << " " << _obj->name() << " " << id);
208 if (c != QMetaObject::InvokeMetaMethod) {
219 if (c != QMetaObject::InvokeMetaMethod) {
209 QObject::qt_metacall(c, id, arguments);
220 QObject::qt_metacall(c, id, arguments);
210 }
221 }
211
222
212 bool found = false;
223 bool found = false;
213 foreach(const PythonQtSignalTarget& t, _targets) {
224 foreach(const PythonQtSignalTarget& t, _targets) {
214 if (t.slotId() == id) {
225 if (t.slotId() == id) {
215 found = true;
226 found = true;
216 t.call(arguments);
227 t.call(arguments);
217 break;
228 break;
218 }
229 }
219 }
230 }
220 return 0;
231 return 0;
221 }
232 }
222
233
@@ -1,139 +1,141
1 #ifndef _PYTHONQTSIGNALRECEIVER_H
1 #ifndef _PYTHONQTSIGNALRECEIVER_H
2 #define _PYTHONQTSIGNALRECEIVER_H
2 #define _PYTHONQTSIGNALRECEIVER_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 PythonQtSignalReceiver.h
38 // \file PythonQtSignalReceiver.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <Python.h>
45 #include <Python.h>
46 #include "PythonQtSystem.h"
46 #include "PythonQtSystem.h"
47 #include "PythonQtObjectPtr.h"
47 #include "PythonQtObjectPtr.h"
48
48
49 class PythonQtMethodInfo;
49 class PythonQtMethodInfo;
50 class PythonQtClassInfo;
50
51
51 //! stores information about a signal target
52 //! stores information about a signal target
52 /*! copy construction and assignment works fine with the C++ standard behaviour and are thus not implemented
53 /*! copy construction and assignment works fine with the C++ standard behaviour and are thus not implemented
53 */
54 */
54 class PYTHONQT_EXPORT PythonQtSignalTarget {
55 class PYTHONQT_EXPORT PythonQtSignalTarget {
55 public:
56 public:
56 PythonQtSignalTarget() {
57 PythonQtSignalTarget() {
57 _signalId = -1;
58 _signalId = -1;
58 _methodInfo = NULL;
59 _methodInfo = NULL;
59 _slotId = -1;
60 _slotId = -1;
60 }
61 }
61
62
62 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
63 PythonQtSignalTarget(int signalId,const PythonQtMethodInfo* methodInfo, int slotId, PyObject* callable)
63 {
64 {
64 _signalId = signalId;
65 _signalId = signalId;
65 _slotId = slotId;
66 _slotId = slotId;
66 _methodInfo = methodInfo;
67 _methodInfo = methodInfo;
67 _callable = callable;
68 _callable = callable;
68 };
69 };
69
70
70 ~PythonQtSignalTarget() {
71 ~PythonQtSignalTarget() {
71 };
72 };
72
73
73 //! get the id of the original signal
74 //! get the id of the original signal
74 int signalId() const { return _signalId; }
75 int signalId() const { return _signalId; }
75
76
76 //! get the id that was assigned to this simulated slot
77 //! get the id that was assigned to this simulated slot
77 int slotId() const { return _slotId; }
78 int slotId() const { return _slotId; }
78
79
79 //! get the signals parameter info
80 //! get the signals parameter info
80 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
81 const PythonQtMethodInfo* methodInfo() const { return _methodInfo; }
81
82
82 //! call the python callable with the given arguments (as defined in methodInfo)
83 //! call the python callable with the given arguments (as defined in methodInfo)
83 void call(void **arguments) const;
84 void call(void **arguments) const;
84
85
85 //! check if it is the same signal target
86 //! check if it is the same signal target
86 bool isSame(int signalId, PyObject* callable) const { return callable==_callable && signalId==_signalId; }
87 bool isSame(int signalId, PyObject* callable) const { return callable==_callable && signalId==_signalId; }
87
88
88 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
89 //! call the given callable with arguments described by PythonQtMethodInfo, returns a new reference as result value (or NULL)
89 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
90 static PyObject* call(PyObject* callable, const PythonQtMethodInfo* methodInfo, void **arguments, bool skipFirstArgumentOfMethodInfo = false);
90
91
91 private:
92 private:
92 int _signalId;
93 int _signalId;
93 int _slotId;
94 int _slotId;
94 const PythonQtMethodInfo* _methodInfo;
95 const PythonQtMethodInfo* _methodInfo;
95 PythonQtObjectPtr _callable;
96 PythonQtObjectPtr _callable;
96 };
97 };
97
98
98 //! base class for signal receivers
99 //! base class for signal receivers
99 /*!
100 /*!
100 */
101 */
101 class PythonQtSignalReceiverBase : public QObject {
102 class PythonQtSignalReceiverBase : public QObject {
102 Q_OBJECT
103 Q_OBJECT
103 public:
104 public:
104 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
105 PythonQtSignalReceiverBase(QObject* obj):QObject(obj) {};
105 };
106 };
106
107
107 //! receives all signals for one QObject
108 //! receives all signals for one QObject
108 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
109 /*! we derive from our base but do not declare the QObject macro because we want to reimplement qt_metacall only.
109 */
110 */
110 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
111 class PythonQtSignalReceiver : public PythonQtSignalReceiverBase {
111
112
112 public:
113 public:
113 PythonQtSignalReceiver(QObject* obj);
114 PythonQtSignalReceiver(QObject* obj);
114 ~PythonQtSignalReceiver();
115 ~PythonQtSignalReceiver();
115
116
116 //! add a signal handler
117 //! add a signal handler
117 bool addSignalHandler(const char* signal, PyObject* callable);
118 bool addSignalHandler(const char* signal, PyObject* callable);
118
119
119 //! remove a signal handler
120 //! remove a signal handler
120 bool removeSignalHandler(const char* signal, PyObject* callable);
121 bool removeSignalHandler(const char* signal, PyObject* callable);
121
122
122 //! remove all signal handlers
123 //! remove all signal handlers
123 void removeSignalHandlers();
124 void removeSignalHandlers();
124
125
125 //! we implement this method to simulate a number of slots that match the ids in _targets
126 //! we implement this method to simulate a number of slots that match the ids in _targets
126 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
127 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
127
128
128 private:
129 private:
129 //! get the index of the signal
130 //! get the index of the signal
130 int getSignalIndex(const char* signal);
131 int getSignalIndex(const char* signal);
131
132
132 QObject* _obj;
133 QObject* _obj;
134 PythonQtClassInfo* _objClassInfo;
133 int _slotCount;
135 int _slotCount;
134 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
136 // linear list may get slow on multiple targets, but I think typically we have many objects and just a few signals
135 QList<PythonQtSignalTarget> _targets;
137 QList<PythonQtSignalTarget> _targets;
136 };
138 };
137
139
138
140
139 #endif
141 #endif
General Comments 0
You need to be logged in to leave comments. Login now