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