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