##// END OF EJS Templates
SIGNAL/SLOT methods improved and supported in connect/disconnect...
florianlink -
r62:b7a51b352089
parent child
Show More
@@ -1,1227 +1,1227
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtImporter.h"
43 #include "PythonQtImporter.h"
44 #include "PythonQtClassInfo.h"
44 #include "PythonQtClassInfo.h"
45 #include "PythonQtMethodInfo.h"
45 #include "PythonQtMethodInfo.h"
46 #include "PythonQtSignalReceiver.h"
46 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtStdOut.h"
48 #include "PythonQtStdOut.h"
49 #include "PythonQtCppWrapperFactory.h"
49 #include "PythonQtCppWrapperFactory.h"
50 #include "PythonQtVariants.h"
50 #include "PythonQtVariants.h"
51 #include "PythonQtStdDecorators.h"
51 #include "PythonQtStdDecorators.h"
52 #include "PythonQtQFileImporter.h"
52 #include "PythonQtQFileImporter.h"
53 #include <pydebug.h>
53 #include <pydebug.h>
54 #include <vector>
54 #include <vector>
55
55
56 PythonQt* PythonQt::_self = NULL;
56 PythonQt* PythonQt::_self = NULL;
57 int PythonQt::_uniqueModuleCount = 0;
57 int PythonQt::_uniqueModuleCount = 0;
58
58
59 void PythonQt::init(int flags)
59 void PythonQt::init(int flags)
60 {
60 {
61 if (!_self) {
61 if (!_self) {
62 _self = new PythonQt(flags);
62 _self = new PythonQt(flags);
63 }
63 }
64
64
65 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
65 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
66 qRegisterMetaType<QList<QObject*> >("QList<void*>");
66 qRegisterMetaType<QList<QObject*> >("QList<void*>");
67
67
68 PythonQtRegisterToolClassesTemplateConverter(int);
68 PythonQtRegisterToolClassesTemplateConverter(int);
69 PythonQtRegisterToolClassesTemplateConverter(float);
69 PythonQtRegisterToolClassesTemplateConverter(float);
70 PythonQtRegisterToolClassesTemplateConverter(double);
70 PythonQtRegisterToolClassesTemplateConverter(double);
71 // TODO: which other POD types should be available for QList etc.
71 // TODO: which other POD types should be available for QList etc.
72
72
73 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
73 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
74
74
75 PythonQt::self()->registerCPPClass("Qt", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_Qt>);
75 PythonQt::self()->registerCPPClass("Qt", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_Qt>);
76 PythonQt::self()->registerCPPClass("QBitArray", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QBitArray>);
76 PythonQt::self()->registerCPPClass("QBitArray", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QBitArray>);
77 PythonQt::self()->registerCPPClass("QDate", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QDate>);
77 PythonQt::self()->registerCPPClass("QDate", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QDate>);
78 PythonQt::self()->registerCPPClass("QTime", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QTime>);
78 PythonQt::self()->registerCPPClass("QTime", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QTime>);
79 PythonQt::self()->registerCPPClass("QDateTime", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QDateTime>);
79 PythonQt::self()->registerCPPClass("QDateTime", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QDateTime>);
80 PythonQt::self()->registerCPPClass("QUrl", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QUrl>);
80 PythonQt::self()->registerCPPClass("QUrl", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QUrl>);
81 PythonQt::self()->registerCPPClass("QLocale", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLocale>);
81 PythonQt::self()->registerCPPClass("QLocale", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLocale>);
82 PythonQt::self()->registerCPPClass("QRect", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRect>);
82 PythonQt::self()->registerCPPClass("QRect", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRect>);
83 PythonQt::self()->registerCPPClass("QRectF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRectF>);
83 PythonQt::self()->registerCPPClass("QRectF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRectF>);
84 PythonQt::self()->registerCPPClass("QSize", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QSize>);
84 PythonQt::self()->registerCPPClass("QSize", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QSize>);
85 PythonQt::self()->registerCPPClass("QSizeF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QSizeF>);
85 PythonQt::self()->registerCPPClass("QSizeF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QSizeF>);
86 PythonQt::self()->registerCPPClass("QLine", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLine>);
86 PythonQt::self()->registerCPPClass("QLine", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLine>);
87 PythonQt::self()->registerCPPClass("QLineF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLineF>);
87 PythonQt::self()->registerCPPClass("QLineF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QLineF>);
88 PythonQt::self()->registerCPPClass("QPoint", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QPoint>);
88 PythonQt::self()->registerCPPClass("QPoint", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QPoint>);
89 PythonQt::self()->registerCPPClass("QPointF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QPointF>);
89 PythonQt::self()->registerCPPClass("QPointF", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QPointF>);
90 PythonQt::self()->registerCPPClass("QRegExp", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRegExp>);
90 PythonQt::self()->registerCPPClass("QRegExp", "", "QtCore", PythonQtCreateObject<PythonQtWrapper_QRegExp>);
91
91
92 PythonQtRegisterToolClassesTemplateConverter(QDate);
92 PythonQtRegisterToolClassesTemplateConverter(QDate);
93 PythonQtRegisterToolClassesTemplateConverter(QTime);
93 PythonQtRegisterToolClassesTemplateConverter(QTime);
94 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
94 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
95 PythonQtRegisterToolClassesTemplateConverter(QUrl);
95 PythonQtRegisterToolClassesTemplateConverter(QUrl);
96 PythonQtRegisterToolClassesTemplateConverter(QLocale);
96 PythonQtRegisterToolClassesTemplateConverter(QLocale);
97 PythonQtRegisterToolClassesTemplateConverter(QRect);
97 PythonQtRegisterToolClassesTemplateConverter(QRect);
98 PythonQtRegisterToolClassesTemplateConverter(QRectF);
98 PythonQtRegisterToolClassesTemplateConverter(QRectF);
99 PythonQtRegisterToolClassesTemplateConverter(QSize);
99 PythonQtRegisterToolClassesTemplateConverter(QSize);
100 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
100 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
101 PythonQtRegisterToolClassesTemplateConverter(QLine);
101 PythonQtRegisterToolClassesTemplateConverter(QLine);
102 PythonQtRegisterToolClassesTemplateConverter(QLineF);
102 PythonQtRegisterToolClassesTemplateConverter(QLineF);
103 PythonQtRegisterToolClassesTemplateConverter(QPoint);
103 PythonQtRegisterToolClassesTemplateConverter(QPoint);
104 PythonQtRegisterToolClassesTemplateConverter(QPointF);
104 PythonQtRegisterToolClassesTemplateConverter(QPointF);
105 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
105 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
106
106
107 PythonQt::self()->registerCPPClass("QFont", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QFont>);
107 PythonQt::self()->registerCPPClass("QFont", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QFont>);
108 PythonQt::self()->registerCPPClass("QPixmap", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPixmap>);
108 PythonQt::self()->registerCPPClass("QPixmap", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPixmap>);
109 PythonQt::self()->registerCPPClass("QBrush", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QBrush>);
109 PythonQt::self()->registerCPPClass("QBrush", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QBrush>);
110 PythonQt::self()->registerCPPClass("QColor", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QColor>);
110 PythonQt::self()->registerCPPClass("QColor", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QColor>);
111 PythonQt::self()->registerCPPClass("QPalette", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPalette>);
111 PythonQt::self()->registerCPPClass("QPalette", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPalette>);
112 PythonQt::self()->registerCPPClass("QIcon", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QIcon>);
112 PythonQt::self()->registerCPPClass("QIcon", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QIcon>);
113 PythonQt::self()->registerCPPClass("QImage", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QImage>);
113 PythonQt::self()->registerCPPClass("QImage", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QImage>);
114 PythonQt::self()->registerCPPClass("QPolygon", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPolygon>);
114 PythonQt::self()->registerCPPClass("QPolygon", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPolygon>);
115 PythonQt::self()->registerCPPClass("QRegion", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QRegion>);
115 PythonQt::self()->registerCPPClass("QRegion", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QRegion>);
116 PythonQt::self()->registerCPPClass("QBitmap", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QBitmap>);
116 PythonQt::self()->registerCPPClass("QBitmap", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QBitmap>);
117 PythonQt::self()->registerCPPClass("QCursor", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QCursor>);
117 PythonQt::self()->registerCPPClass("QCursor", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QCursor>);
118 PythonQt::self()->registerCPPClass("QSizePolicy", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QSizePolicy>);
118 PythonQt::self()->registerCPPClass("QSizePolicy", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QSizePolicy>);
119 PythonQt::self()->registerCPPClass("QKeySequence", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QKeySequence>);
119 PythonQt::self()->registerCPPClass("QKeySequence", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QKeySequence>);
120 PythonQt::self()->registerCPPClass("QPen", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPen>);
120 PythonQt::self()->registerCPPClass("QPen", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QPen>);
121 PythonQt::self()->registerCPPClass("QTextLength", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QTextLength>);
121 PythonQt::self()->registerCPPClass("QTextLength", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QTextLength>);
122 PythonQt::self()->registerCPPClass("QTextFormat", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QTextFormat>);
122 PythonQt::self()->registerCPPClass("QTextFormat", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QTextFormat>);
123 PythonQt::self()->registerCPPClass("QMatrix", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QMatrix>);
123 PythonQt::self()->registerCPPClass("QMatrix", "", "QtGui", PythonQtCreateObject<PythonQtWrapper_QMatrix>);
124
124
125 PythonQtRegisterToolClassesTemplateConverter(QFont);
125 PythonQtRegisterToolClassesTemplateConverter(QFont);
126 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
126 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
127 PythonQtRegisterToolClassesTemplateConverter(QBrush);
127 PythonQtRegisterToolClassesTemplateConverter(QBrush);
128 PythonQtRegisterToolClassesTemplateConverter(QColor);
128 PythonQtRegisterToolClassesTemplateConverter(QColor);
129 PythonQtRegisterToolClassesTemplateConverter(QPalette);
129 PythonQtRegisterToolClassesTemplateConverter(QPalette);
130 PythonQtRegisterToolClassesTemplateConverter(QIcon);
130 PythonQtRegisterToolClassesTemplateConverter(QIcon);
131 PythonQtRegisterToolClassesTemplateConverter(QImage);
131 PythonQtRegisterToolClassesTemplateConverter(QImage);
132 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
132 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
133 PythonQtRegisterToolClassesTemplateConverter(QRegion);
133 PythonQtRegisterToolClassesTemplateConverter(QRegion);
134 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
134 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
135 PythonQtRegisterToolClassesTemplateConverter(QCursor);
135 PythonQtRegisterToolClassesTemplateConverter(QCursor);
136 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
136 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
137 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
137 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
138 PythonQtRegisterToolClassesTemplateConverter(QPen);
138 PythonQtRegisterToolClassesTemplateConverter(QPen);
139 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
139 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
140 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
140 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
141 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
141 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
142
142
143 }
143 }
144
144
145 void PythonQt::cleanup()
145 void PythonQt::cleanup()
146 {
146 {
147 if (_self) {
147 if (_self) {
148 delete _self;
148 delete _self;
149 _self = NULL;
149 _self = NULL;
150 }
150 }
151 }
151 }
152
152
153 PythonQt::PythonQt(int flags)
153 PythonQt::PythonQt(int flags)
154 {
154 {
155 _p = new PythonQtPrivate;
155 _p = new PythonQtPrivate;
156 _p->_initFlags = flags;
156 _p->_initFlags = flags;
157
157
158 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
158 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
159
159
160 Py_SetProgramName("PythonQt");
160 Py_SetProgramName("PythonQt");
161 if (flags & IgnoreSiteModule) {
161 if (flags & IgnoreSiteModule) {
162 // this prevents the automatic importing of Python site files
162 // this prevents the automatic importing of Python site files
163 Py_NoSiteFlag = 1;
163 Py_NoSiteFlag = 1;
164 }
164 }
165 Py_Initialize();
165 Py_Initialize();
166
166
167 // add our own python object types for qt object slots
167 // add our own python object types for qt object slots
168 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
168 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
169 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
169 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
170 }
170 }
171 Py_INCREF(&PythonQtSlotFunction_Type);
171 Py_INCREF(&PythonQtSlotFunction_Type);
172
172
173 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
173 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
174 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
174 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
175 // add our own python object types for classes
175 // add our own python object types for classes
176 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
176 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
177 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
177 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
178 }
178 }
179 Py_INCREF(&PythonQtClassWrapper_Type);
179 Py_INCREF(&PythonQtClassWrapper_Type);
180
180
181 // add our own python object types for CPP instances
181 // add our own python object types for CPP instances
182 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
182 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
183 PythonQt::handleError();
183 PythonQt::handleError();
184 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
184 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
185 }
185 }
186 Py_INCREF(&PythonQtInstanceWrapper_Type);
186 Py_INCREF(&PythonQtInstanceWrapper_Type);
187
187
188 // add our own python object types for redirection of stdout
188 // add our own python object types for redirection of stdout
189 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
189 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
190 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
190 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
191 }
191 }
192 Py_INCREF(&PythonQtStdOutRedirectType);
192 Py_INCREF(&PythonQtStdOutRedirectType);
193
193
194 initPythonQtModule(flags & RedirectStdOut);
194 initPythonQtModule(flags & RedirectStdOut);
195
195
196 }
196 }
197
197
198 PythonQt::~PythonQt() {
198 PythonQt::~PythonQt() {
199 delete _p;
199 delete _p;
200 _p = NULL;
200 _p = NULL;
201 }
201 }
202
202
203 PythonQtPrivate::~PythonQtPrivate() {
203 PythonQtPrivate::~PythonQtPrivate() {
204 delete _defaultImporter;
204 delete _defaultImporter;
205 _defaultImporter = NULL;
205 _defaultImporter = NULL;
206
206
207 {
207 {
208 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
208 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
209 while (i.hasNext()) {
209 while (i.hasNext()) {
210 delete i.next().value();
210 delete i.next().value();
211 }
211 }
212 }
212 }
213 PythonQtConv::global_valueStorage.clear();
213 PythonQtConv::global_valueStorage.clear();
214 PythonQtConv::global_ptrStorage.clear();
214 PythonQtConv::global_ptrStorage.clear();
215 PythonQtConv::global_variantStorage.clear();
215 PythonQtConv::global_variantStorage.clear();
216
216
217 PythonQtMethodInfo::cleanupCachedMethodInfos();
217 PythonQtMethodInfo::cleanupCachedMethodInfos();
218 }
218 }
219
219
220 PythonQtImportFileInterface* PythonQt::importInterface()
220 PythonQtImportFileInterface* PythonQt::importInterface()
221 {
221 {
222 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
222 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
223 }
223 }
224
224
225 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
225 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
226 {
226 {
227 if (_self->_p->_noLongerWrappedCB) {
227 if (_self->_p->_noLongerWrappedCB) {
228 (*_self->_p->_noLongerWrappedCB)(o);
228 (*_self->_p->_noLongerWrappedCB)(o);
229 };
229 };
230 }
230 }
231
231
232 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
232 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
233 {
233 {
234 _p->registerClass(metaobject, package, wrapperCreator, shell);
234 _p->registerClass(metaobject, package, wrapperCreator, shell);
235 }
235 }
236
236
237 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
237 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
238 {
238 {
239 // we register all classes in the hierarchy
239 // we register all classes in the hierarchy
240 const QMetaObject* m = metaobject;
240 const QMetaObject* m = metaobject;
241 bool first = true;
241 bool first = true;
242 while (m) {
242 while (m) {
243 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
243 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
244 if (!info->pythonQtClassWrapper()) {
244 if (!info->pythonQtClassWrapper()) {
245 info->setupQObject(m);
245 info->setupQObject(m);
246 createPythonQtClassWrapper(info, package);
246 createPythonQtClassWrapper(info, package);
247 if (m->superClass()) {
247 if (m->superClass()) {
248 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
248 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
249 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
249 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
250 }
250 }
251 }
251 }
252 if (first) {
252 if (first) {
253 first = false;
253 first = false;
254 if (wrapperCreator) {
254 if (wrapperCreator) {
255 info->setDecoratorProvider(wrapperCreator);
255 info->setDecoratorProvider(wrapperCreator);
256 }
256 }
257 if (shell) {
257 if (shell) {
258 info->setShellSetInstanceWrapperCB(shell);
258 info->setShellSetInstanceWrapperCB(shell);
259 }
259 }
260 }
260 }
261 m = m->superClass();
261 m = m->superClass();
262 }
262 }
263 }
263 }
264
264
265 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package)
265 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package)
266 {
266 {
267 PyObject* pack = packageByName(package);
267 PyObject* pack = packageByName(package);
268 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, package);
268 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, package);
269 PyModule_AddObject(pack, info->className(), pyobj);
269 PyModule_AddObject(pack, info->className(), pyobj);
270 if (package && strncmp(package,"Qt",2)==0) {
270 if (package && strncmp(package,"Qt",2)==0) {
271 // since PyModule_AddObject steals the reference, we need a incref once more...
271 // since PyModule_AddObject steals the reference, we need a incref once more...
272 Py_INCREF(pyobj);
272 Py_INCREF(pyobj);
273 // put all qt objects into Qt as well
273 // put all qt objects into Qt as well
274 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
274 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
275 }
275 }
276 info->setPythonQtClassWrapper(pyobj);
276 info->setPythonQtClassWrapper(pyobj);
277 }
277 }
278
278
279 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
279 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
280 {
280 {
281 if (!obj) {
281 if (!obj) {
282 Py_INCREF(Py_None);
282 Py_INCREF(Py_None);
283 return Py_None;
283 return Py_None;
284 }
284 }
285 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
285 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
286 if (!wrap) {
286 if (!wrap) {
287 // smuggling it in...
287 // smuggling it in...
288 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
288 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
289 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
289 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
290 registerClass(obj->metaObject());
290 registerClass(obj->metaObject());
291 classInfo = _knownClassInfos.value(obj->metaObject()->className());
291 classInfo = _knownClassInfos.value(obj->metaObject()->className());
292 }
292 }
293 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
293 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
294 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
294 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
295 } else {
295 } else {
296 Py_INCREF(wrap);
296 Py_INCREF(wrap);
297 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
297 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
298 }
298 }
299 return (PyObject*)wrap;
299 return (PyObject*)wrap;
300 }
300 }
301
301
302 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
302 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
303 {
303 {
304 if (!ptr) {
304 if (!ptr) {
305 Py_INCREF(Py_None);
305 Py_INCREF(Py_None);
306 return Py_None;
306 return Py_None;
307 }
307 }
308
308
309 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
309 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
310 if (!wrap) {
310 if (!wrap) {
311 PythonQtClassInfo* info = _knownClassInfos.value(name);
311 PythonQtClassInfo* info = _knownClassInfos.value(name);
312 if (!info) {
312 if (!info) {
313 // maybe it is a PyObject, which we can return directly
313 // maybe it is a PyObject, which we can return directly
314 if (name == "PyObject") {
314 if (name == "PyObject") {
315 PyObject* p = (PyObject*)ptr;
315 PyObject* p = (PyObject*)ptr;
316 Py_INCREF(p);
316 Py_INCREF(p);
317 return p;
317 return p;
318 }
318 }
319
319
320 // we do not know the metaobject yet, but we might know it by it's name:
320 // we do not know the metaobject yet, but we might know it by it's name:
321 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
321 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
322 // yes, we know it, so we can convert to QObject
322 // yes, we know it, so we can convert to QObject
323 QObject* qptr = (QObject*)ptr;
323 QObject* qptr = (QObject*)ptr;
324 registerClass(qptr->metaObject());
324 registerClass(qptr->metaObject());
325 info = _knownClassInfos.value(qptr->metaObject()->className());
325 info = _knownClassInfos.value(qptr->metaObject()->className());
326 }
326 }
327 }
327 }
328 if (info && info->isQObject()) {
328 if (info && info->isQObject()) {
329 QObject* qptr = (QObject*)ptr;
329 QObject* qptr = (QObject*)ptr;
330 // if the object is a derived object, we want to switch the class info to the one of the derived class:
330 // if the object is a derived object, we want to switch the class info to the one of the derived class:
331 if (name!=(qptr->metaObject()->className())) {
331 if (name!=(qptr->metaObject()->className())) {
332 registerClass(qptr->metaObject());
332 registerClass(qptr->metaObject());
333 info = _knownClassInfos.value(qptr->metaObject()->className());
333 info = _knownClassInfos.value(qptr->metaObject()->className());
334 }
334 }
335 wrap = createNewPythonQtInstanceWrapper(qptr, info);
335 wrap = createNewPythonQtInstanceWrapper(qptr, info);
336 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
336 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
337 return (PyObject*)wrap;
337 return (PyObject*)wrap;
338 }
338 }
339
339
340 // not a known QObject, so try our wrapper factory:
340 // not a known QObject, so try our wrapper factory:
341 QObject* wrapper = NULL;
341 QObject* wrapper = NULL;
342 for (int i=0; i<_cppWrapperFactories.size(); i++) {
342 for (int i=0; i<_cppWrapperFactories.size(); i++) {
343 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
343 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
344 if (wrapper) {
344 if (wrapper) {
345 break;
345 break;
346 }
346 }
347 }
347 }
348
348
349 if (info) {
349 if (info) {
350 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
350 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
351 ptr = info->castDownIfPossible(ptr, &info);
351 ptr = info->castDownIfPossible(ptr, &info);
352 }
352 }
353
353
354 if (!info || info->pythonQtClassWrapper()==NULL) {
354 if (!info || info->pythonQtClassWrapper()==NULL) {
355 // still unknown, register as CPP class
355 // still unknown, register as CPP class
356 registerCPPClass(name.constData());
356 registerCPPClass(name.constData());
357 info = _knownClassInfos.value(name);
357 info = _knownClassInfos.value(name);
358 }
358 }
359 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
359 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
360 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
360 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
361 info->setMetaObject(wrapper->metaObject());
361 info->setMetaObject(wrapper->metaObject());
362 }
362 }
363 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
363 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
364 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
364 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
365 } else {
365 } else {
366 Py_INCREF(wrap);
366 Py_INCREF(wrap);
367 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
367 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
368 }
368 }
369 return (PyObject*)wrap;
369 return (PyObject*)wrap;
370 }
370 }
371
371
372 PyObject* PythonQtPrivate::dummyTuple() {
372 PyObject* PythonQtPrivate::dummyTuple() {
373 static PyObject* dummyTuple = NULL;
373 static PyObject* dummyTuple = NULL;
374 if (dummyTuple==NULL) {
374 if (dummyTuple==NULL) {
375 dummyTuple = PyTuple_New(1);
375 dummyTuple = PyTuple_New(1);
376 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
376 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
377 }
377 }
378 return dummyTuple;
378 return dummyTuple;
379 }
379 }
380
380
381
381
382 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
382 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
383 // call the associated class type to create a new instance...
383 // call the associated class type to create a new instance...
384 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
384 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
385
385
386 result->setQObject(obj);
386 result->setQObject(obj);
387 result->_wrappedPtr = wrappedPtr;
387 result->_wrappedPtr = wrappedPtr;
388 result->_ownedByPythonQt = false;
388 result->_ownedByPythonQt = false;
389 result->_useQMetaTypeDestroy = false;
389 result->_useQMetaTypeDestroy = false;
390
390
391 if (wrappedPtr) {
391 if (wrappedPtr) {
392 _wrappedObjects.insert(wrappedPtr, result);
392 _wrappedObjects.insert(wrappedPtr, result);
393 } else {
393 } else {
394 _wrappedObjects.insert(obj, result);
394 _wrappedObjects.insert(obj, result);
395 if (obj->parent()== NULL && _wrappedCB) {
395 if (obj->parent()== NULL && _wrappedCB) {
396 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
396 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
397 (*_wrappedCB)(obj);
397 (*_wrappedCB)(obj);
398 }
398 }
399 }
399 }
400 return result;
400 return result;
401 }
401 }
402
402
403 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) {
403 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) {
404 PythonQtClassWrapper* result;
404 PythonQtClassWrapper* result;
405
405
406 PyObject* className = PyString_FromString(info->className());
406 PyObject* className = PyString_FromString(info->className());
407
407
408 PyObject* baseClasses = PyTuple_New(1);
408 PyObject* baseClasses = PyTuple_New(1);
409 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
409 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
410
410
411 PyObject* typeDict = PyDict_New();
411 PyObject* typeDict = PyDict_New();
412 QByteArray moduleName("PythonQt");
412 QByteArray moduleName("PythonQt");
413 if (package && strcmp(package, "")!=0) {
413 if (package && strcmp(package, "")!=0) {
414 moduleName += ".";
414 moduleName += ".";
415 moduleName += package;
415 moduleName += package;
416 }
416 }
417 PyDict_SetItemString(typeDict, "__module__", PyString_FromString(moduleName.constData()));
417 PyDict_SetItemString(typeDict, "__module__", PyString_FromString(moduleName.constData()));
418
418
419 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
419 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
420
420
421 // set the class info so that PythonQtClassWrapper_new can read it
421 // set the class info so that PythonQtClassWrapper_new can read it
422 _currentClassInfoForClassWrapperCreation = info;
422 _currentClassInfoForClassWrapperCreation = info;
423 // create the new type object by calling the type
423 // create the new type object by calling the type
424 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
424 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
425
425
426 Py_DECREF(baseClasses);
426 Py_DECREF(baseClasses);
427 Py_DECREF(typeDict);
427 Py_DECREF(typeDict);
428 Py_DECREF(args);
428 Py_DECREF(args);
429 Py_DECREF(className);
429 Py_DECREF(className);
430
430
431 return result;
431 return result;
432 }
432 }
433
433
434 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
434 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
435 {
435 {
436 PyObject* args = Py_BuildValue("(i)", enumValue);
436 PyObject* args = Py_BuildValue("(i)", enumValue);
437 PyObject* result = PyObject_Call(enumType, args, NULL);
437 PyObject* result = PyObject_Call(enumType, args, NULL);
438 Py_DECREF(args);
438 Py_DECREF(args);
439 return result;
439 return result;
440 }
440 }
441
441
442 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
442 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
443 PyObject* result;
443 PyObject* result;
444
444
445 PyObject* className = PyString_FromString(enumName);
445 PyObject* className = PyString_FromString(enumName);
446
446
447 PyObject* baseClasses = PyTuple_New(1);
447 PyObject* baseClasses = PyTuple_New(1);
448 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
448 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
449
449
450 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
450 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
451 PyObject* typeDict = PyDict_New();
451 PyObject* typeDict = PyDict_New();
452 PyDict_SetItemString(typeDict, "__module__", module);
452 PyDict_SetItemString(typeDict, "__module__", module);
453
453
454 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
454 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
455
455
456 // create the new int derived type object by calling the core type
456 // create the new int derived type object by calling the core type
457 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
457 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
458
458
459 Py_DECREF(baseClasses);
459 Py_DECREF(baseClasses);
460 Py_DECREF(typeDict);
460 Py_DECREF(typeDict);
461 Py_DECREF(args);
461 Py_DECREF(args);
462 Py_DECREF(className);
462 Py_DECREF(className);
463
463
464 return result;
464 return result;
465 }
465 }
466
466
467 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
467 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
468 {
468 {
469 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
469 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
470 if (!r) {
470 if (!r) {
471 r = new PythonQtSignalReceiver(obj);
471 r = new PythonQtSignalReceiver(obj);
472 _p->_signalReceivers.insert(obj, r);
472 _p->_signalReceivers.insert(obj, r);
473 }
473 }
474 return r;
474 return r;
475 }
475 }
476
476
477 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
477 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
478 {
478 {
479 bool flag = false;
479 bool flag = false;
480 PythonQtObjectPtr callable = lookupCallable(module, objectname);
480 PythonQtObjectPtr callable = lookupCallable(module, objectname);
481 if (callable) {
481 if (callable) {
482 PythonQtSignalReceiver* r = getSignalReceiver(obj);
482 PythonQtSignalReceiver* r = getSignalReceiver(obj);
483 flag = r->addSignalHandler(signal, callable);
483 flag = r->addSignalHandler(signal, callable);
484 if (!flag) {
484 if (!flag) {
485 // signal not found
485 // signal not found
486 }
486 }
487 } else {
487 } else {
488 // callable not found
488 // callable not found
489 }
489 }
490 return flag;
490 return flag;
491 }
491 }
492
492
493 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
493 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
494 {
494 {
495 bool flag = false;
495 bool flag = false;
496 PythonQtSignalReceiver* r = getSignalReceiver(obj);
496 PythonQtSignalReceiver* r = getSignalReceiver(obj);
497 if (r) {
497 if (r) {
498 flag = r->addSignalHandler(signal, receiver);
498 flag = r->addSignalHandler(signal, receiver);
499 }
499 }
500 return flag;
500 return flag;
501 }
501 }
502
502
503 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
503 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
504 {
504 {
505 bool flag = false;
505 bool flag = false;
506 PythonQtObjectPtr callable = lookupCallable(module, objectname);
506 PythonQtObjectPtr callable = lookupCallable(module, objectname);
507 if (callable) {
507 if (callable) {
508 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
508 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
509 if (r) {
509 if (r) {
510 flag = r->removeSignalHandler(signal, callable);
510 flag = r->removeSignalHandler(signal, callable);
511 }
511 }
512 } else {
512 } else {
513 // callable not found
513 // callable not found
514 }
514 }
515 return flag;
515 return flag;
516 }
516 }
517
517
518 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
518 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
519 {
519 {
520 bool flag = false;
520 bool flag = false;
521 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
521 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
522 if (r) {
522 if (r) {
523 flag = r->removeSignalHandler(signal, receiver);
523 flag = r->removeSignalHandler(signal, receiver);
524 }
524 }
525 return flag;
525 return flag;
526 }
526 }
527
527
528 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
528 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
529 {
529 {
530 PythonQtObjectPtr p = lookupObject(module, name);
530 PythonQtObjectPtr p = lookupObject(module, name);
531 if (p) {
531 if (p) {
532 if (PyCallable_Check(p)) {
532 if (PyCallable_Check(p)) {
533 return p;
533 return p;
534 }
534 }
535 }
535 }
536 PyErr_Clear();
536 PyErr_Clear();
537 return NULL;
537 return NULL;
538 }
538 }
539
539
540 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
540 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
541 {
541 {
542 QStringList l = name.split('.');
542 QStringList l = name.split('.');
543 PythonQtObjectPtr p = module;
543 PythonQtObjectPtr p = module;
544 PythonQtObjectPtr prev;
544 PythonQtObjectPtr prev;
545 QString s;
545 QString s;
546 QByteArray b;
546 QByteArray b;
547 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
547 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
548 prev = p;
548 prev = p;
549 b = (*i).toLatin1();
549 b = (*i).toLatin1();
550 if (PyDict_Check(p)) {
550 if (PyDict_Check(p)) {
551 p = PyDict_GetItemString(p, b.data());
551 p = PyDict_GetItemString(p, b.data());
552 } else {
552 } else {
553 p.setNewRef(PyObject_GetAttrString(p, b.data()));
553 p.setNewRef(PyObject_GetAttrString(p, b.data()));
554 }
554 }
555 }
555 }
556 PyErr_Clear();
556 PyErr_Clear();
557 return p;
557 return p;
558 }
558 }
559
559
560 PythonQtObjectPtr PythonQt::getMainModule() {
560 PythonQtObjectPtr PythonQt::getMainModule() {
561 //both borrowed
561 //both borrowed
562 PythonQtObjectPtr dict = PyImport_GetModuleDict();
562 PythonQtObjectPtr dict = PyImport_GetModuleDict();
563 return PyDict_GetItemString(dict, "__main__");
563 return PyDict_GetItemString(dict, "__main__");
564 }
564 }
565
565
566 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
566 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
567 QVariant result;
567 QVariant result;
568 if (pycode) {
568 if (pycode) {
569 PyObject* dict = NULL;
569 PyObject* dict = NULL;
570 if (PyModule_Check(object)) {
570 if (PyModule_Check(object)) {
571 dict = PyModule_GetDict(object);
571 dict = PyModule_GetDict(object);
572 } else if (PyDict_Check(object)) {
572 } else if (PyDict_Check(object)) {
573 dict = object;
573 dict = object;
574 }
574 }
575 PyObject* r = NULL;
575 PyObject* r = NULL;
576 if (dict) {
576 if (dict) {
577 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
577 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
578 }
578 }
579 if (r) {
579 if (r) {
580 result = PythonQtConv::PyObjToQVariant(r);
580 result = PythonQtConv::PyObjToQVariant(r);
581 Py_DECREF(r);
581 Py_DECREF(r);
582 } else {
582 } else {
583 handleError();
583 handleError();
584 }
584 }
585 } else {
585 } else {
586 handleError();
586 handleError();
587 }
587 }
588 return result;
588 return result;
589 }
589 }
590
590
591 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
591 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
592 {
592 {
593 QVariant result;
593 QVariant result;
594 PythonQtObjectPtr p;
594 PythonQtObjectPtr p;
595 PyObject* dict = NULL;
595 PyObject* dict = NULL;
596 if (PyModule_Check(object)) {
596 if (PyModule_Check(object)) {
597 dict = PyModule_GetDict(object);
597 dict = PyModule_GetDict(object);
598 } else if (PyDict_Check(object)) {
598 } else if (PyDict_Check(object)) {
599 dict = object;
599 dict = object;
600 }
600 }
601 if (dict) {
601 if (dict) {
602 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
602 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
603 }
603 }
604 if (p) {
604 if (p) {
605 result = PythonQtConv::PyObjToQVariant(p);
605 result = PythonQtConv::PyObjToQVariant(p);
606 } else {
606 } else {
607 handleError();
607 handleError();
608 }
608 }
609 return result;
609 return result;
610 }
610 }
611
611
612 void PythonQt::evalFile(PyObject* module, const QString& filename)
612 void PythonQt::evalFile(PyObject* module, const QString& filename)
613 {
613 {
614 PythonQtObjectPtr code = parseFile(filename);
614 PythonQtObjectPtr code = parseFile(filename);
615 if (code) {
615 if (code) {
616 evalCode(module, code);
616 evalCode(module, code);
617 } else {
617 } else {
618 handleError();
618 handleError();
619 }
619 }
620 }
620 }
621
621
622 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
622 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
623 {
623 {
624 PythonQtObjectPtr p;
624 PythonQtObjectPtr p;
625 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
625 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
626 if (!p) {
626 if (!p) {
627 handleError();
627 handleError();
628 }
628 }
629 return p;
629 return p;
630 }
630 }
631
631
632 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
632 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
633 {
633 {
634 PythonQtObjectPtr code = parseFile(filename);
634 PythonQtObjectPtr code = parseFile(filename);
635 PythonQtObjectPtr module = _p->createModule(name, code);
635 PythonQtObjectPtr module = _p->createModule(name, code);
636 return module;
636 return module;
637 }
637 }
638
638
639 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
639 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
640 {
640 {
641 PyErr_Clear();
641 PyErr_Clear();
642 QString scriptCode = script;
642 QString scriptCode = script;
643 if (scriptCode.isEmpty()) {
643 if (scriptCode.isEmpty()) {
644 // we always need at least a linefeed
644 // we always need at least a linefeed
645 scriptCode = "\n";
645 scriptCode = "\n";
646 }
646 }
647 PythonQtObjectPtr pycode;
647 PythonQtObjectPtr pycode;
648 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
648 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
649 PythonQtObjectPtr module = _p->createModule(name, pycode);
649 PythonQtObjectPtr module = _p->createModule(name, pycode);
650 return module;
650 return module;
651 }
651 }
652
652
653 PythonQtObjectPtr PythonQt::createUniqueModule()
653 PythonQtObjectPtr PythonQt::createUniqueModule()
654 {
654 {
655 static QString pyQtStr("PythonQt_module");
655 static QString pyQtStr("PythonQt_module");
656 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
656 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
657 return createModuleFromScript(moduleName);
657 return createModuleFromScript(moduleName);
658 }
658 }
659
659
660 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
660 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
661 {
661 {
662 if (PyModule_Check(object)) {
662 if (PyModule_Check(object)) {
663 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
663 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
664 } else if (PyDict_Check(object)) {
664 } else if (PyDict_Check(object)) {
665 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
665 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
666 } else {
666 } else {
667 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
667 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
668 }
668 }
669 }
669 }
670
670
671 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
671 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
672 {
672 {
673 if (PyModule_Check(object)) {
673 if (PyModule_Check(object)) {
674 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
674 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
675 } else if (PyDict_Check(object)) {
675 } else if (PyDict_Check(object)) {
676 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
676 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
677 } else {
677 } else {
678 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
678 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
679 }
679 }
680 }
680 }
681
681
682 void PythonQt::removeVariable(PyObject* object, const QString& name)
682 void PythonQt::removeVariable(PyObject* object, const QString& name)
683 {
683 {
684 if (PyDict_Check(object)) {
684 if (PyDict_Check(object)) {
685 PyDict_DelItemString(object, name.toLatin1().data());
685 PyDict_DelItemString(object, name.toLatin1().data());
686 } else {
686 } else {
687 PyObject_DelAttrString(object, name.toLatin1().data());
687 PyObject_DelAttrString(object, name.toLatin1().data());
688 }
688 }
689 }
689 }
690
690
691 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
691 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
692 {
692 {
693 QVariant result;
693 QVariant result;
694 PythonQtObjectPtr obj = lookupObject(object, objectname);
694 PythonQtObjectPtr obj = lookupObject(object, objectname);
695 if (obj) {
695 if (obj) {
696 result = PythonQtConv::PyObjToQVariant(obj);
696 result = PythonQtConv::PyObjToQVariant(obj);
697 }
697 }
698 return result;
698 return result;
699 }
699 }
700
700
701 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
701 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
702 {
702 {
703 QStringList results;
703 QStringList results;
704
704
705 PythonQtObjectPtr object;
705 PythonQtObjectPtr object;
706 if (objectname.isEmpty()) {
706 if (objectname.isEmpty()) {
707 object = module;
707 object = module;
708 } else {
708 } else {
709 object = lookupObject(module, objectname);
709 object = lookupObject(module, objectname);
710 if (!object && type == CallOverloads) {
710 if (!object && type == CallOverloads) {
711 PyObject* dict = lookupObject(module, "__builtins__");
711 PyObject* dict = lookupObject(module, "__builtins__");
712 if (dict) {
712 if (dict) {
713 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
713 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
714 }
714 }
715 }
715 }
716 }
716 }
717
717
718 if (object) {
718 if (object) {
719 if (type == CallOverloads) {
719 if (type == CallOverloads) {
720 if (PythonQtSlotFunction_Check(object)) {
720 if (PythonQtSlotFunction_Check(object)) {
721 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
721 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
722 PythonQtSlotInfo* info = o->m_ml;
722 PythonQtSlotInfo* info = o->m_ml;
723
723
724 while (info) {
724 while (info) {
725 results << info->fullSignature();
725 results << info->fullSignature();
726 info = info->nextInfo();
726 info = info->nextInfo();
727 }
727 }
728 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
728 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
729 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
729 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
730 PythonQtSlotInfo* info = o->classInfo()->constructors();
730 PythonQtSlotInfo* info = o->classInfo()->constructors();
731
731
732 while (info) {
732 while (info) {
733 results << info->fullSignature();
733 results << info->fullSignature();
734 info = info->nextInfo();
734 info = info->nextInfo();
735 }
735 }
736 } else {
736 } else {
737 //TODO: use pydoc!
737 //TODO: use pydoc!
738 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
738 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
739 if (doc) {
739 if (doc) {
740 results << PyString_AsString(doc);
740 results << PyString_AsString(doc);
741 Py_DECREF(doc);
741 Py_DECREF(doc);
742 }
742 }
743 }
743 }
744 } else {
744 } else {
745 PyObject* keys = NULL;
745 PyObject* keys = NULL;
746 bool isDict = false;
746 bool isDict = false;
747 if (PyDict_Check(object)) {
747 if (PyDict_Check(object)) {
748 keys = PyDict_Keys(object);
748 keys = PyDict_Keys(object);
749 isDict = true;
749 isDict = true;
750 } else {
750 } else {
751 keys = PyObject_Dir(object);
751 keys = PyObject_Dir(object);
752 }
752 }
753 if (keys) {
753 if (keys) {
754 int count = PyList_Size(keys);
754 int count = PyList_Size(keys);
755 PyObject* key;
755 PyObject* key;
756 PyObject* value;
756 PyObject* value;
757 QString keystr;
757 QString keystr;
758 for (int i = 0;i<count;i++) {
758 for (int i = 0;i<count;i++) {
759 key = PyList_GetItem(keys,i);
759 key = PyList_GetItem(keys,i);
760 if (isDict) {
760 if (isDict) {
761 value = PyDict_GetItem(object, key);
761 value = PyDict_GetItem(object, key);
762 Py_INCREF(value);
762 Py_INCREF(value);
763 } else {
763 } else {
764 value = PyObject_GetAttr(object, key);
764 value = PyObject_GetAttr(object, key);
765 }
765 }
766 if (!value) continue;
766 if (!value) continue;
767 keystr = PyString_AsString(key);
767 keystr = PyString_AsString(key);
768 static const QString underscoreStr("__tmp");
768 static const QString underscoreStr("__tmp");
769 if (!keystr.startsWith(underscoreStr)) {
769 if (!keystr.startsWith(underscoreStr)) {
770 switch (type) {
770 switch (type) {
771 case Anything:
771 case Anything:
772 results << keystr;
772 results << keystr;
773 break;
773 break;
774 case Class:
774 case Class:
775 if (value->ob_type == &PyClass_Type) {
775 if (value->ob_type == &PyClass_Type) {
776 results << keystr;
776 results << keystr;
777 }
777 }
778 break;
778 break;
779 case Variable:
779 case Variable:
780 if (value->ob_type != &PyClass_Type
780 if (value->ob_type != &PyClass_Type
781 && value->ob_type != &PyCFunction_Type
781 && value->ob_type != &PyCFunction_Type
782 && value->ob_type != &PyFunction_Type
782 && value->ob_type != &PyFunction_Type
783 && value->ob_type != &PyModule_Type
783 && value->ob_type != &PyModule_Type
784 ) {
784 ) {
785 results << keystr;
785 results << keystr;
786 }
786 }
787 break;
787 break;
788 case Function:
788 case Function:
789 if (value->ob_type == &PyFunction_Type ||
789 if (value->ob_type == &PyFunction_Type ||
790 value->ob_type == &PyMethod_Type
790 value->ob_type == &PyMethod_Type
791 ) {
791 ) {
792 results << keystr;
792 results << keystr;
793 }
793 }
794 break;
794 break;
795 case Module:
795 case Module:
796 if (value->ob_type == &PyModule_Type) {
796 if (value->ob_type == &PyModule_Type) {
797 results << keystr;
797 results << keystr;
798 }
798 }
799 break;
799 break;
800 default:
800 default:
801 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
801 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
802 }
802 }
803 }
803 }
804 Py_DECREF(value);
804 Py_DECREF(value);
805 }
805 }
806 Py_DECREF(keys);
806 Py_DECREF(keys);
807 }
807 }
808 }
808 }
809 }
809 }
810 return results;
810 return results;
811 }
811 }
812
812
813 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
813 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
814 {
814 {
815 PythonQtObjectPtr callable = lookupCallable(object, name);
815 PythonQtObjectPtr callable = lookupCallable(object, name);
816 if (callable) {
816 if (callable) {
817 return call(callable, args);
817 return call(callable, args);
818 } else {
818 } else {
819 return QVariant();
819 return QVariant();
820 }
820 }
821 }
821 }
822
822
823 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
823 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
824 {
824 {
825 QVariant r;
825 QVariant r;
826 if (callable) {
826 if (callable) {
827 PythonQtObjectPtr pargs;
827 PythonQtObjectPtr pargs;
828 int count = args.size();
828 int count = args.size();
829 if (count>0) {
829 if (count>0) {
830 pargs.setNewRef(PyTuple_New(count));
830 pargs.setNewRef(PyTuple_New(count));
831 }
831 }
832 bool err = false;
832 bool err = false;
833 // transform QVariants to Python
833 // transform QVariants to Python
834 for (int i = 0; i < count; i++) {
834 for (int i = 0; i < count; i++) {
835 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
835 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
836 if (arg) {
836 if (arg) {
837 // steals reference, no unref
837 // steals reference, no unref
838 PyTuple_SetItem(pargs, i,arg);
838 PyTuple_SetItem(pargs, i,arg);
839 } else {
839 } else {
840 err = true;
840 err = true;
841 break;
841 break;
842 }
842 }
843 }
843 }
844
844
845 if (!err) {
845 if (!err) {
846 PyErr_Clear();
846 PyErr_Clear();
847 PythonQtObjectPtr result;
847 PythonQtObjectPtr result;
848 result.setNewRef(PyObject_CallObject(callable, pargs));
848 result.setNewRef(PyObject_CallObject(callable, pargs));
849 if (result) {
849 if (result) {
850 // ok
850 // ok
851 r = PythonQtConv::PyObjToQVariant(result);
851 r = PythonQtConv::PyObjToQVariant(result);
852 } else {
852 } else {
853 PythonQt::self()->handleError();
853 PythonQt::self()->handleError();
854 }
854 }
855 }
855 }
856 }
856 }
857 return r;
857 return r;
858 }
858 }
859
859
860 void PythonQt::addInstanceDecorators(QObject* o)
860 void PythonQt::addInstanceDecorators(QObject* o)
861 {
861 {
862 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
862 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
863 }
863 }
864
864
865 void PythonQt::addClassDecorators(QObject* o)
865 void PythonQt::addClassDecorators(QObject* o)
866 {
866 {
867 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
867 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
868 }
868 }
869
869
870 void PythonQt::addDecorators(QObject* o)
870 void PythonQt::addDecorators(QObject* o)
871 {
871 {
872 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
872 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
873 }
873 }
874
874
875 void PythonQt::registerQObjectClassNames(const QStringList& names)
875 void PythonQt::registerQObjectClassNames(const QStringList& names)
876 {
876 {
877 _p->registerQObjectClassNames(names);
877 _p->registerQObjectClassNames(names);
878 }
878 }
879
879
880 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
880 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
881 {
881 {
882 PythonQtImport::init();
882 PythonQtImport::init();
883 _p->_importInterface = importInterface;
883 _p->_importInterface = importInterface;
884 }
884 }
885
885
886 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
886 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
887 {
887 {
888 _p->_importIgnorePaths = paths;
888 _p->_importIgnorePaths = paths;
889 }
889 }
890
890
891 const QStringList& PythonQt::getImporterIgnorePaths()
891 const QStringList& PythonQt::getImporterIgnorePaths()
892 {
892 {
893 return _p->_importIgnorePaths;
893 return _p->_importIgnorePaths;
894 }
894 }
895
895
896 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
896 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
897 {
897 {
898 _p->_cppWrapperFactories.append(factory);
898 _p->_cppWrapperFactories.append(factory);
899 }
899 }
900
900
901 //---------------------------------------------------------------------------------------------------
901 //---------------------------------------------------------------------------------------------------
902 PythonQtPrivate::PythonQtPrivate()
902 PythonQtPrivate::PythonQtPrivate()
903 {
903 {
904 _importInterface = NULL;
904 _importInterface = NULL;
905 _defaultImporter = new PythonQtQFileImporter;
905 _defaultImporter = new PythonQtQFileImporter;
906 _noLongerWrappedCB = NULL;
906 _noLongerWrappedCB = NULL;
907 _wrappedCB = NULL;
907 _wrappedCB = NULL;
908 _currentClassInfoForClassWrapperCreation = NULL;
908 _currentClassInfoForClassWrapperCreation = NULL;
909 }
909 }
910
910
911 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
911 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
912 {
912 {
913 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
913 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
914 _currentClassInfoForClassWrapperCreation = NULL;
914 _currentClassInfoForClassWrapperCreation = NULL;
915 return info;
915 return info;
916 }
916 }
917
917
918 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
918 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
919 {
919 {
920 o->setParent(this);
920 o->setParent(this);
921 int numMethods = o->metaObject()->methodCount();
921 int numMethods = o->metaObject()->methodCount();
922 for (int i = 0; i < numMethods; i++) {
922 for (int i = 0; i < numMethods; i++) {
923 QMetaMethod m = o->metaObject()->method(i);
923 QMetaMethod m = o->metaObject()->method(i);
924 if ((m.methodType() == QMetaMethod::Method ||
924 if ((m.methodType() == QMetaMethod::Method ||
925 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
925 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
926 if (qstrncmp(m.signature(), "new_", 4)==0) {
926 if (qstrncmp(m.signature(), "new_", 4)==0) {
927 if ((decoTypes & ConstructorDecorator) == 0) continue;
927 if ((decoTypes & ConstructorDecorator) == 0) continue;
928 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
928 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
929 if (info->parameters().at(0).isPointer) {
929 if (info->parameters().at(0).isPointer) {
930 QByteArray signature = m.signature();
930 QByteArray signature = m.signature();
931 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
931 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
932 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
932 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
933 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
933 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
934 classInfo->addConstructor(newSlot);
934 classInfo->addConstructor(newSlot);
935 }
935 }
936 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
936 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
937 if ((decoTypes & DestructorDecorator) == 0) continue;
937 if ((decoTypes & DestructorDecorator) == 0) continue;
938 QByteArray signature = m.signature();
938 QByteArray signature = m.signature();
939 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
939 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
940 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
940 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
941 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
941 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
942 classInfo->setDestructor(newSlot);
942 classInfo->setDestructor(newSlot);
943 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
943 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
944 if ((decoTypes & StaticDecorator) == 0) continue;
944 if ((decoTypes & StaticDecorator) == 0) continue;
945 QByteArray signature = m.signature();
945 QByteArray signature = m.signature();
946 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
946 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
947 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
947 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
948 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
948 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
949 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
949 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
950 classInfo->addDecoratorSlot(newSlot);
950 classInfo->addDecoratorSlot(newSlot);
951 } else {
951 } else {
952 if ((decoTypes & InstanceDecorator) == 0) continue;
952 if ((decoTypes & InstanceDecorator) == 0) continue;
953 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
953 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
954 if (info->parameters().count()>1) {
954 if (info->parameters().count()>1) {
955 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
955 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
956 if (p.isPointer) {
956 if (p.isPointer) {
957 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
957 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
958 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
958 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
959 classInfo->addDecoratorSlot(newSlot);
959 classInfo->addDecoratorSlot(newSlot);
960 }
960 }
961 }
961 }
962 }
962 }
963 }
963 }
964 }
964 }
965 }
965 }
966
966
967 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
967 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
968 {
968 {
969 foreach(QString name, names) {
969 foreach(QString name, names) {
970 _knownQObjectClassNames.insert(name.toLatin1(), true);
970 _knownQObjectClassNames.insert(name.toLatin1(), true);
971 }
971 }
972 }
972 }
973
973
974 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
974 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
975 {
975 {
976 _signalReceivers.remove(obj);
976 _signalReceivers.remove(obj);
977 }
977 }
978
978
979 bool PythonQt::handleError()
979 bool PythonQt::handleError()
980 {
980 {
981 bool flag = false;
981 bool flag = false;
982 if (PyErr_Occurred()) {
982 if (PyErr_Occurred()) {
983
983
984 // currently we just print the error and the stderr handler parses the errors
984 // currently we just print the error and the stderr handler parses the errors
985 PyErr_Print();
985 PyErr_Print();
986
986
987 /*
987 /*
988 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
988 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
989 PyObject *ptype;
989 PyObject *ptype;
990 PyObject *pvalue;
990 PyObject *pvalue;
991 PyObject *ptraceback;
991 PyObject *ptraceback;
992 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
992 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
993
993
994 Py_XDECREF(ptype);
994 Py_XDECREF(ptype);
995 Py_XDECREF(pvalue);
995 Py_XDECREF(pvalue);
996 Py_XDECREF(ptraceback);
996 Py_XDECREF(ptraceback);
997 */
997 */
998 PyErr_Clear();
998 PyErr_Clear();
999 flag = true;
999 flag = true;
1000 }
1000 }
1001 return flag;
1001 return flag;
1002 }
1002 }
1003
1003
1004 void PythonQt::addSysPath(const QString& path)
1004 void PythonQt::addSysPath(const QString& path)
1005 {
1005 {
1006 PythonQtObjectPtr sys;
1006 PythonQtObjectPtr sys;
1007 sys.setNewRef(PyImport_ImportModule("sys"));
1007 sys.setNewRef(PyImport_ImportModule("sys"));
1008 PythonQtObjectPtr obj = lookupObject(sys, "path");
1008 PythonQtObjectPtr obj = lookupObject(sys, "path");
1009 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1009 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1010 }
1010 }
1011
1011
1012 void PythonQt::overwriteSysPath(const QStringList& paths)
1012 void PythonQt::overwriteSysPath(const QStringList& paths)
1013 {
1013 {
1014 PythonQtObjectPtr sys;
1014 PythonQtObjectPtr sys;
1015 sys.setNewRef(PyImport_ImportModule("sys"));
1015 sys.setNewRef(PyImport_ImportModule("sys"));
1016 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1016 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1017 }
1017 }
1018
1018
1019 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1019 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1020 {
1020 {
1021 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1021 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1022 }
1022 }
1023
1023
1024 void PythonQt::stdOutRedirectCB(const QString& str)
1024 void PythonQt::stdOutRedirectCB(const QString& str)
1025 {
1025 {
1026 emit PythonQt::self()->pythonStdOut(str);
1026 emit PythonQt::self()->pythonStdOut(str);
1027 }
1027 }
1028
1028
1029 void PythonQt::stdErrRedirectCB(const QString& str)
1029 void PythonQt::stdErrRedirectCB(const QString& str)
1030 {
1030 {
1031 emit PythonQt::self()->pythonStdErr(str);
1031 emit PythonQt::self()->pythonStdErr(str);
1032 }
1032 }
1033
1033
1034 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1034 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1035 {
1035 {
1036 _p->_wrappedCB = cb;
1036 _p->_wrappedCB = cb;
1037 }
1037 }
1038
1038
1039 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1039 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1040 {
1040 {
1041 _p->_noLongerWrappedCB = cb;
1041 _p->_noLongerWrappedCB = cb;
1042 }
1042 }
1043
1043
1044
1044
1045
1045
1046 static PyMethodDef PythonQtMethods[] = {
1046 static PyMethodDef PythonQtMethods[] = {
1047 {NULL, NULL, 0, NULL}
1047 {NULL, NULL, 0, NULL}
1048 };
1048 };
1049
1049
1050 void PythonQt::initPythonQtModule(bool redirectStdOut)
1050 void PythonQt::initPythonQtModule(bool redirectStdOut)
1051 {
1051 {
1052 _p->_pythonQtModule = Py_InitModule("PythonQt", PythonQtMethods);
1052 _p->_pythonQtModule = Py_InitModule("PythonQt", PythonQtMethods);
1053
1053
1054 if (redirectStdOut) {
1054 if (redirectStdOut) {
1055 PythonQtObjectPtr sys;
1055 PythonQtObjectPtr sys;
1056 PythonQtObjectPtr out;
1056 PythonQtObjectPtr out;
1057 PythonQtObjectPtr err;
1057 PythonQtObjectPtr err;
1058 sys.setNewRef(PyImport_ImportModule("sys"));
1058 sys.setNewRef(PyImport_ImportModule("sys"));
1059 // create a redirection object for stdout and stderr
1059 // create a redirection object for stdout and stderr
1060 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1060 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1061 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1061 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1062 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1062 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1063 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1063 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1064 // replace the built in file objects with our own objects
1064 // replace the built in file objects with our own objects
1065 PyModule_AddObject(sys, "stdout", out);
1065 PyModule_AddObject(sys, "stdout", out);
1066 PyModule_AddObject(sys, "stderr", err);
1066 PyModule_AddObject(sys, "stderr", err);
1067 }
1067 }
1068 }
1068 }
1069
1069
1070 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1070 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1071 {
1071 {
1072 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1072 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1073 }
1073 }
1074
1074
1075
1075
1076 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1076 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1077 {
1077 {
1078 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1078 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1079 if (!info) {
1079 if (!info) {
1080 info = new PythonQtClassInfo();
1080 info = new PythonQtClassInfo();
1081 info->setupCPPObject(typeName);
1081 info->setupCPPObject(typeName);
1082 _knownClassInfos.insert(typeName, info);
1082 _knownClassInfos.insert(typeName, info);
1083 }
1083 }
1084 return info;
1084 return info;
1085 }
1085 }
1086
1086
1087 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1087 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1088 {
1088 {
1089 _p->addPolymorphicHandler(typeName, cb);
1089 _p->addPolymorphicHandler(typeName, cb);
1090 }
1090 }
1091
1091
1092 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1092 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1093 {
1093 {
1094 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1094 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1095 info->addPolymorphicHandler(cb);
1095 info->addPolymorphicHandler(cb);
1096 }
1096 }
1097
1097
1098 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1098 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1099 {
1099 {
1100 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1100 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1101 }
1101 }
1102
1102
1103 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1103 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1104 {
1104 {
1105 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1105 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1106 if (info) {
1106 if (info) {
1107 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1107 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1108 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1108 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1109 return true;
1109 return true;
1110 } else {
1110 } else {
1111 return false;
1111 return false;
1112 }
1112 }
1113 }
1113 }
1114
1114
1115 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1115 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1116 {
1116 {
1117 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1117 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1118 if (!info->pythonQtClassWrapper()) {
1118 if (!info->pythonQtClassWrapper()) {
1119 info->setupCPPObject(typeName);
1119 info->setupCPPObject(typeName);
1120 createPythonQtClassWrapper(info, package);
1120 createPythonQtClassWrapper(info, package);
1121 }
1121 }
1122 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1122 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1123 addParentClass(typeName, parentTypeName, 0);
1123 addParentClass(typeName, parentTypeName, 0);
1124 }
1124 }
1125 if (wrapperCreator) {
1125 if (wrapperCreator) {
1126 info->setDecoratorProvider(wrapperCreator);
1126 info->setDecoratorProvider(wrapperCreator);
1127 }
1127 }
1128 if (shell) {
1128 if (shell) {
1129 info->setShellSetInstanceWrapperCB(shell);
1129 info->setShellSetInstanceWrapperCB(shell);
1130 }
1130 }
1131 }
1131 }
1132
1132
1133 static PyObject *PythonQt_SIGNAL(PyObject * /*type*/, PyObject *args)
1133 static PyObject *PythonQt_SIGNAL(PyObject * /*type*/, PyObject *args)
1134 {
1134 {
1135 const char* value;
1135 const char* value;
1136 if (!PyArg_ParseTuple(args, "s", &value)) {
1136 if (!PyArg_ParseTuple(args, "s", &value)) {
1137 return NULL;
1137 return NULL;
1138 }
1138 }
1139 // we do not prepend 0,1 or 2, why should we?
1139 // we do not prepend 0,1 or 2, why should we?
1140 return PyString_FromString(value);
1140 return PyString_FromString(QByteArray("2") + value);
1141 }
1141 }
1142
1142
1143 static PyObject *PythonQt_SLOT(PyObject * /*type*/, PyObject *args)
1143 static PyObject *PythonQt_SLOT(PyObject * /*type*/, PyObject *args)
1144 {
1144 {
1145 const char* value;
1145 const char* value;
1146 if (!PyArg_ParseTuple(args, "s", &value)) {
1146 if (!PyArg_ParseTuple(args, "s", &value)) {
1147 return NULL;
1147 return NULL;
1148 }
1148 }
1149 // we do not prepend 0,1 or 2, why should we?
1149 // we do not prepend 0,1 or 2, why should we?
1150 return PyString_FromString(value);
1150 return PyString_FromString(QByteArray("1") + value);
1151 }
1151 }
1152
1152
1153 static PyMethodDef PythonQt_Qt_methods[] = {
1153 static PyMethodDef PythonQt_Qt_methods[] = {
1154 {"SIGNAL", (PyCFunction)PythonQt_SIGNAL, METH_VARARGS,
1154 {"SIGNAL", (PyCFunction)PythonQt_SIGNAL, METH_VARARGS,
1155 "Returns a signal string"
1155 "Returns a signal string"
1156 },
1156 },
1157 {"SLOT", (PyCFunction)PythonQt_SLOT, METH_VARARGS,
1157 {"SLOT", (PyCFunction)PythonQt_SLOT, METH_VARARGS,
1158 "Returns a slot string"
1158 "Returns a slot string"
1159 }
1159 }
1160 };
1160 };
1161
1161
1162 PyObject* PythonQtPrivate::packageByName(const char* name)
1162 PyObject* PythonQtPrivate::packageByName(const char* name)
1163 {
1163 {
1164 if (name==NULL || name[0]==0) {
1164 if (name==NULL || name[0]==0) {
1165 return _pythonQtModule;
1165 return _pythonQtModule;
1166 }
1166 }
1167 PyObject* v = _packages.value(name);
1167 PyObject* v = _packages.value(name);
1168 if (!v) {
1168 if (!v) {
1169 v = PyImport_AddModule((QByteArray("PythonQt.") + name).constData());
1169 v = PyImport_AddModule((QByteArray("PythonQt.") + name).constData());
1170 if (strcmp(name,"Qt")==0 || strcmp(name,"QtCore")==0) {
1170 if (strcmp(name,"Qt")==0 || strcmp(name,"QtCore")==0) {
1171 // add SIGNAL and SLOT functions
1171 // add SIGNAL and SLOT functions
1172 PyModule_AddObject(v, "SIGNAL", PyCFunction_New(PythonQt_Qt_methods, v));
1172 PyModule_AddObject(v, "SIGNAL", PyCFunction_New(PythonQt_Qt_methods, v));
1173 PyModule_AddObject(v, "SLOT", PyCFunction_New(PythonQt_Qt_methods+1, v));
1173 PyModule_AddObject(v, "SLOT", PyCFunction_New(PythonQt_Qt_methods+1, v));
1174 }
1174 }
1175 _packages.insert(name, v);
1175 _packages.insert(name, v);
1176 // AddObject steals the reference, so increment it!
1176 // AddObject steals the reference, so increment it!
1177 Py_INCREF(v);
1177 Py_INCREF(v);
1178 PyModule_AddObject(_pythonQtModule, name, v);
1178 PyModule_AddObject(_pythonQtModule, name, v);
1179 }
1179 }
1180 return v;
1180 return v;
1181 }
1181 }
1182
1182
1183
1183
1184 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1184 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1185 {
1185 {
1186 if (_p->_initFlags & ExternalHelp) {
1186 if (_p->_initFlags & ExternalHelp) {
1187 emit pythonHelpRequest(QByteArray(info->className()));
1187 emit pythonHelpRequest(QByteArray(info->className()));
1188 return Py_BuildValue("");
1188 return Py_BuildValue("");
1189 } else {
1189 } else {
1190 return PyString_FromString(info->help().toLatin1().data());
1190 return PyString_FromString(info->help().toLatin1().data());
1191 }
1191 }
1192 }
1192 }
1193
1193
1194 void PythonQtPrivate::removeWrapperPointer(void* obj)
1194 void PythonQtPrivate::removeWrapperPointer(void* obj)
1195 {
1195 {
1196 _wrappedObjects.remove(obj);
1196 _wrappedObjects.remove(obj);
1197 }
1197 }
1198
1198
1199 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1199 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1200 {
1200 {
1201 _wrappedObjects.insert(obj, wrapper);
1201 _wrappedObjects.insert(obj, wrapper);
1202 }
1202 }
1203
1203
1204 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1204 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1205 {
1205 {
1206 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1206 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1207 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1207 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1208 // this is a wrapper whose QObject was already removed due to destruction
1208 // this is a wrapper whose QObject was already removed due to destruction
1209 // so the obj pointer has to be a new QObject with the same address...
1209 // so the obj pointer has to be a new QObject with the same address...
1210 // we remove the old one and set the copy to NULL
1210 // we remove the old one and set the copy to NULL
1211 wrap->_objPointerCopy = NULL;
1211 wrap->_objPointerCopy = NULL;
1212 removeWrapperPointer(obj);
1212 removeWrapperPointer(obj);
1213 wrap = NULL;
1213 wrap = NULL;
1214 }
1214 }
1215 return wrap;
1215 return wrap;
1216 }
1216 }
1217
1217
1218 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1218 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1219 {
1219 {
1220 PythonQtObjectPtr result;
1220 PythonQtObjectPtr result;
1221 if (pycode) {
1221 if (pycode) {
1222 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1222 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1223 } else {
1223 } else {
1224 PythonQt::self()->handleError();
1224 PythonQt::self()->handleError();
1225 }
1225 }
1226 return result;
1226 return result;
1227 }
1227 }
@@ -1,511 +1,510
1 #ifndef _PYTHONQTDOC_H
1 #ifndef _PYTHONQTDOC_H
2 #define _PYTHONQTDOC_H
2 #define _PYTHONQTDOC_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 PythonQtDoc.h
38 // \file PythonQtDoc.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-10
41 // \date 2006-10
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 /*!
45 /*!
46 \if USE_GLOBAL_DOXYGEN_DOC
46 \if USE_GLOBAL_DOXYGEN_DOC
47 \page PythonQtPage PythonQt Overview
47 \page PythonQtPage PythonQt Overview
48 \else
48 \else
49 \mainpage PythonQt Overview
49 \mainpage PythonQt Overview
50 \endif
50 \endif
51
51
52 \section Introduction
52 \section Introduction
53
53
54 \b PythonQt is a dynamic Python (http://www.python.org) binding for Qt (http://www.qtsoftware.com).
54 \b PythonQt is a dynamic Python (http://www.python.org) binding for Qt (http://www.qtsoftware.com).
55 It offers an easy way to embed the Python scripting language into
55 It offers an easy way to embed the Python scripting language into
56 your Qt applications. It makes heavy use of the QMetaObject system and thus requires Qt4.x.
56 your Qt applications. It makes heavy use of the QMetaObject system and thus requires Qt4.x.
57
57
58 The focus of PythonQt is on embedding Python into an existing C++ application, not on writing the whole
58 The focus of PythonQt is on embedding Python into an existing C++ application, not on writing the whole
59 application completely in Python. If you want to write your whole application in Python,
59 application completely in Python. If you want to write your whole application in Python,
60 you should use <a href="http://www.riverbankcomputing.co.uk/pyqt/">PyQt</a> instead.
60 you should use <a href="http://www.riverbankcomputing.co.uk/pyqt/">PyQt</a> instead.
61
61
62 If you are looking for a simple way to embed Python objects into your C++/Qt Application
62 If you are looking for a simple way to embed Python objects into your C++/Qt Application
63 and to script parts of your application via Python, PythonQt is the way to go!
63 and to script parts of your application via Python, PythonQt is the way to go!
64
64
65 PythonQt is a stable library that was developed to make the
65 PythonQt is a stable library that was developed to make the
66 Image Processing and Visualization platform MeVisLab (http://www.mevislab.de)
66 Image Processing and Visualization platform MeVisLab (http://www.mevislab.de)
67 scriptable from Python.
67 scriptable from Python.
68
68
69 \section Download
69 \section Download
70
70
71 PythonQt is hosted on SourceForge at http://sourceforge.net/projects/pythonqt , you can access it via SVN
71 PythonQt is hosted on SourceForge at http://sourceforge.net/projects/pythonqt , you can access it via SVN
72 or download a tarball.
72 or download a tarball.
73
73
74 \section Licensing
74 \section Licensing
75
75
76 PythonQt is distributed under the LGPL license, so it pairs well with the LGPL of the Qt 4.5 release and allows
76 PythonQt is distributed under the LGPL license, so it pairs well with the LGPL of the Qt 4.5 release and allows
77 to be used in commercial applications when following the LGPL 2.1 obligations.
77 to be used in commercial applications when following the LGPL 2.1 obligations.
78
78
79 \section LicensingWrapper Licensing of Wrapper Generator
79 \section LicensingWrapper Licensing of Wrapper Generator
80
80
81 The build system of PythonQt makes use of a modified version of the GPL'ed QtScript generator,
81 The build system of PythonQt makes use of a modified version of the GPL'ed QtScript generator,
82 located in the "generator" directory.
82 located in the "generator" directory.
83
83
84 See http://labs.trolltech.com/page/Projects/QtScript/Generator for details on the original project.
84 See http://labs.trolltech.com/page/Projects/QtScript/Generator for details on the original project.
85 Thanks a lot to the QtJambi guys and the QtScript Generator project for the C++ parser and
85 Thanks a lot to the QtJambi guys and the QtScript Generator project for the C++ parser and
86 Qt typesystem files!
86 Qt typesystem files!
87
87
88 The PythonQt wrappers generated by the generator located in the "generated_cpp" directory are distributed under the LGPL,
88 The PythonQt wrappers generated by the generator located in the "generated_cpp" directory are distributed under the LGPL,
89 they are not restriced by the GPL.
89 they are not restriced by the GPL.
90
90
91 The generated wrappers are pre-generated and checked-in for Qt 4.4.3, so you only need to build and run the
91 The generated wrappers are pre-generated and checked-in for Qt 4.4.3, so you only need to build and run the
92 generator when you want to build additional wrappers or you want to upgrade/downgrade to an newer Qt version.
92 generator when you want to build additional wrappers or you want to upgrade/downgrade to an newer Qt version.
93 You may use the generator to generate C++ bindings for your own C++ classes (e.g. to make them deriveable in Python),
93 You may use the generator to generate C++ bindings for your own C++ classes (e.g. to make them deriveable in Python),
94 , but this is currently not documented and involves creating your own typesystem files.
94 , but this is currently not documented and involves creating your own typesystem files.
95
95
96 \section Features
96 \section Features
97
97
98 The following are the built-in features of the PythonQt library:
98 The following are the built-in features of the PythonQt library:
99
99
100 - Access all \b slots, \b properties, children and registered enums of any QObject derived class from Python
100 - Access all \b slots, \b properties, children and registered enums of any QObject derived class from Python
101 - Connecting Qt Signals to Python functions (both from within Python and from C++)
101 - Connecting Qt Signals to Python functions (both from within Python and from C++)
102 - Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
102 - Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
103 - Convenient conversions to/from QVariant for PythonQtObjectPtr.
103 - Convenient conversions to/from QVariant for PythonQtObjectPtr.
104 - Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
104 - Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
105 - Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
105 - Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
106 - StdOut/Err redirection to Qt signals instead of cout
106 - StdOut/Err redirection to Qt signals instead of cout
107 - Interface for creating your own \c import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
107 - Interface for creating your own \c import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
108 - Mapping of plain-old-datatypes and ALL QVariant types to and from Python
108 - Mapping of plain-old-datatypes and ALL QVariant types to and from Python
109 - Support for wrapping of user QVariant types which are registerd via QMetaType
109 - Support for wrapping of user QVariant types which are registerd via QMetaType
110 - Support for Qt namespace (with all enumerators)
110 - Support for Qt namespace (with all enumerators)
111 - All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
111 - All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
112 - No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the \b moc)
112 - No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the \b moc)
113 - Multiple inheritance for C++ objects (e.g. a QWidget is derived from QObject and QPaintDevice, PythonQt will automatically cast a QWidget to a QPaintDevice when needed)
113 - Multiple inheritance for C++ objects (e.g. a QWidget is derived from QObject and QPaintDevice, PythonQt will automatically cast a QWidget to a QPaintDevice when needed)
114 - Polymorphic downcasting (if e.g. PythonQt sees a QEvent, it can downcast it depending on the type(), so the Python e.g. sees a QPaintEvent instead of a plain QEvent)
114 - Polymorphic downcasting (if e.g. PythonQt sees a QEvent, it can downcast it depending on the type(), so the Python e.g. sees a QPaintEvent instead of a plain QEvent)
115 - Deriving C++ objects from Python and overwriting virtual method with a Python implementation (requires usage of wrapper generator or manual work!)
115 - Deriving C++ objects from Python and overwriting virtual method with a Python implementation (requires usage of wrapper generator or manual work!)
116 - Extensible handler for Python/C++ conversion of complex types, e.g. mapping of QVector<SomeObject> to/from a Python array
116 - Extensible handler for Python/C++ conversion of complex types, e.g. mapping of QVector<SomeObject> to/from a Python array
117
117
118 \section FeaturesQtAll Features (with PythonQt_QtAll linked in)
118 \section FeaturesQtAll Features (with PythonQt_QtAll linked in)
119
119
120 Thanks to the new wrapper generator, PythonQt now offers the additional PythonQt_QtAll library which wraps the complete Qt API, including all C++ classes and all non-slots on QObject derived classes.
120 Thanks to the new wrapper generator, PythonQt now offers the additional PythonQt_QtAll library which wraps the complete Qt API, including all C++ classes and all non-slots on QObject derived classes.
121 This offers the following features:
121 This offers the following features:
122
122
123 - Complete Qt API wrapped and accessible
123 - Complete Qt API wrapped and accessible
124 - The following modules are available as submodule of the PythonQt module:
124 - The following modules are available as submodule of the PythonQt module:
125 - QtCore
125 - QtCore
126 - QtGui
126 - QtGui
127 - QtNetwork
127 - QtNetwork
128 - QtOpenGL
128 - QtOpenGL
129 - QtSql
129 - QtSql
130 - QtSvg
130 - QtSvg
131 - QtUiTools
131 - QtUiTools
132 - QtWebKit
132 - QtWebKit
133 - QtXml
133 - QtXml
134 - QtXmlPatterns
134 - QtXmlPatterns
135 - (phonon, QtHelp, assistant, designer are currently not supported, this would require some additional effort on the code generator)
135 - (phonon, QtHelp, assistant, designer are currently not supported, this would require some additional effort on the code generator)
136 - For convenience, all classes are also available in the PythonQt.Qt module, for people who do not care in which module a class is located
136 - For convenience, all classes are also available in the PythonQt.Qt module, for people who do not care in which module a class is located
137 - Any Qt class that has virtual methods can be easily derived from Python and the virtual methods can be reimplemented in Python
137 - Any Qt class that has virtual methods can be easily derived from Python and the virtual methods can be reimplemented in Python
138 - Polymorphic downcasting on QEvent, QGraphicsItem, QStyleOption, ...
138 - Polymorphic downcasting on QEvent, QGraphicsItem, QStyleOption, ...
139 - Multiple inheritance support (e.g. QGraphicsTextItem is a QObject AND a QGraphicsItem, PythonQt will handle this well)
139 - Multiple inheritance support (e.g. QGraphicsTextItem is a QObject AND a QGraphicsItem, PythonQt will handle this well)
140
140
141 \section Comparision Comparision with PyQt
141 \section Comparision Comparision with PyQt
142
142
143 - PythonQt is not as Pythonic as PyQt in many details (e.g. operator mapping, pickling, translation support, ...) and it is mainly thought for embedding and intercommunication between Qt/Cpp and Python
143 - PythonQt is not as Pythonic as PyQt in many details (e.g. operator mapping, pickling, translation support, ...) and it is mainly thought for embedding and intercommunication between Qt/Cpp and Python
144 - PythonQt allows to communicate in both directions, e.g. calling a Python object from C++ AND calling a C++ method from Python, while PyQt only handles the Python->C++ direction
144 - PythonQt allows to communicate in both directions, e.g. calling a Python object from C++ AND calling a C++ method from Python, while PyQt only handles the Python->C++ direction
145 - PythonQt offers properties as Python attributes, while PyQt offers them as setter/getter methods (e.g. QWidget.width is a property in PythonQt and a method in PyQt)
145 - PythonQt offers properties as Python attributes, while PyQt offers them as setter/getter methods (e.g. QWidget.width is a property in PythonQt and a method in PyQt)
146 - PythonQt offer QtCore.SIGNAL() and QtCore.SLOT() methods for compability, but no 0/1/3 is prepended
147 - PythonQt does not support instanceof checks for Qt classes, except for the exact match and derived Python classes
146 - PythonQt does not support instanceof checks for Qt classes, except for the exact match and derived Python classes
148 - QObject.emit to emit Qt signals from Python is not yet implemented
147 - QObject.emit to emit Qt signals from Python is not yet implemented
149 - PythonQt does not offer to add new signals to Python/C++ objects
148 - PythonQt does not offer to add new signals to Python/C++ objects
150 - Ownership of objects is a bit different in PythonQt, currently Python classes derived from a C++ class need to be manually references in PythonQt to not get deleted too early (this will be fixed)
149 - Ownership of objects is a bit different in PythonQt, currently Python classes derived from a C++ class need to be manually references in PythonQt to not get deleted too early (this will be fixed)
151 - Probably there are lots of details that differ, I do not know PyQt that well to list them all.
150 - Probably there are lots of details that differ, I do not know PyQt that well to list them all.
152
151
153
152
154 \section Interface
153 \section Interface
155
154
156 The main interface to PythonQt is the PythonQt singleton.
155 The main interface to PythonQt is the PythonQt singleton.
157 PythonQt needs to be initialized via PythonQt::init() once.
156 PythonQt needs to be initialized via PythonQt::init() once.
158 Afterwards you communicate with the singleton via PythonQt::self().
157 Afterwards you communicate with the singleton via PythonQt::self().
159 PythonQt offers a complete Qt binding, which
158 PythonQt offers a complete Qt binding, which
160 needs to be enabled via PythonQt_QtAll::init().
159 needs to be enabled via PythonQt_QtAll::init().
161
160
162
161
163 \section Datatype Datatype Mapping
162 \section Datatype Datatype Mapping
164
163
165 The following table shows the mapping between Python and Qt objects:
164 The following table shows the mapping between Python and Qt objects:
166 <table>
165 <table>
167 <tr><th>Qt/C++</th><th>Python</th></tr>
166 <tr><th>Qt/C++</th><th>Python</th></tr>
168 <tr><td>bool</td><td>bool</td></tr>
167 <tr><td>bool</td><td>bool</td></tr>
169 <tr><td>double</td><td>float</td></tr>
168 <tr><td>double</td><td>float</td></tr>
170 <tr><td>float</td><td>float</td></tr>
169 <tr><td>float</td><td>float</td></tr>
171 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
170 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
172 <tr><td>long</td><td>integer</td></tr>
171 <tr><td>long</td><td>integer</td></tr>
173 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
172 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
174 <tr><td>QString</td><td>unicode string</td></tr>
173 <tr><td>QString</td><td>unicode string</td></tr>
175 <tr><td>QByteArray</td><td>str</td></tr>
174 <tr><td>QByteArray</td><td>str</td></tr>
176 <tr><td>char*</td><td>str</td></tr>
175 <tr><td>char*</td><td>str</td></tr>
177 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
176 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
178 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
177 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
179 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
178 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
180 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
179 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
181 <tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant wrapper that supports complete API of the respective Qt classes</td></tr>
180 <tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant wrapper that supports complete API of the respective Qt classes</td></tr>
182 <tr><td>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional information/wrapping provided by registerCPPClass()</td></tr>
181 <tr><td>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional information/wrapping provided by registerCPPClass()</td></tr>
183 <tr><td>QList<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
182 <tr><td>QList<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
184 <tr><td>EnumType</td><td>integer (all enums that are known via the moc and the Qt namespace are supported)</td></tr>
183 <tr><td>EnumType</td><td>integer (all enums that are known via the moc and the Qt namespace are supported)</td></tr>
185 <tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
184 <tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
186 <tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
185 <tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
187 <tr><td>PyObject</td><td>PyObject</td></tr>
186 <tr><td>PyObject</td><td>PyObject</td></tr>
188 </table>
187 </table>
189
188
190 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
189 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
191 a Qt slot.
190 a Qt slot.
192 QVariants are mapped recursively as given above, e.g. a dictionary can
191 QVariants are mapped recursively as given above, e.g. a dictionary can
193 contain lists of dictionaries of doubles.
192 contain lists of dictionaries of doubles.
194 For example a QVariant of type "String" is mapped to a python unicode string.
193 For example a QVariant of type "String" is mapped to a python unicode string.
195 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
194 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
196
195
197 \section QObject QObject Wrapping
196 \section QObject QObject Wrapping
198
197
199 All classes derived from QObject are automatically wrapped with a python wrapper class
198 All classes derived from QObject are automatically wrapped with a python wrapper class
200 when they become visible to the Python interpreter. This can happen via
199 when they become visible to the Python interpreter. This can happen via
201 - the PythonQt::addObject() method
200 - the PythonQt::addObject() method
202 - when a Qt \b slot returns a QObject derived object to python
201 - when a Qt \b slot returns a QObject derived object to python
203 - when a Qt \b signal contains a QObject and is connected to a python function
202 - when a Qt \b signal contains a QObject and is connected to a python function
204
203
205 It is important that you call PythonQt::registerClass() for any QObject derived class
204 It is important that you call PythonQt::registerClass() for any QObject derived class
206 that may become visible to Python, except when you add it via PythonQt::addObject().
205 that may become visible to Python, except when you add it via PythonQt::addObject().
207 This will register the complete parent hierachy of the registered class, so that
206 This will register the complete parent hierachy of the registered class, so that
208 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
207 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
209 parents).
208 parents).
210
209
211 From Python, you can talk to the returned QObjects in a natural way by calling
210 From Python, you can talk to the returned QObjects in a natural way by calling
212 their slots and receiving the return values. You can also read/write all
211 their slots and receiving the return values. You can also read/write all
213 properties of the objects as if they where normal python properties.
212 properties of the objects as if they where normal python properties.
214
213
215 In addition to this, the wrapped objects support
214 In addition to this, the wrapped objects support
216 - className() - returns a string that reprents the classname of the QObject
215 - className() - returns a string that reprents the classname of the QObject
217 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
216 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
218 - delete() - deletes the object (use with care, especially if you passed the ownership to C++)
217 - delete() - deletes the object (use with care, especially if you passed the ownership to C++)
219 - connect(signal, function) - connect the signal of the given object to a python function
218 - connect(signal, function) - connect the signal of the given object to a python function
220 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
219 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
221 - disconnect(signal, function) - disconnect the signal of the given object from a python function
220 - disconnect(signal, function) - disconnect the signal of the given object from a python function
222 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
221 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
223 - children() - returns the children of the object
222 - children() - returns the children of the object
224 - setParent(QObject) - set the parent
223 - setParent(QObject) - set the parent
225 - QObject* parent() - get the parent
224 - QObject* parent() - get the parent
226
225
227 The below example shows how to connect signals in Python:
226 The below example shows how to connect signals in Python:
228
227
229 \code
228 \code
230 # define a signal handler function
229 # define a signal handler function
231 def someFunction(flag):
230 def someFunction(flag):
232 print flag
231 print flag
233
232
234 # button1 is a QPushButton that has been added to Python via addObject()
233 # button1 is a QPushButton that has been added to Python via addObject()
235 # connect the clicked signal to a python function:
234 # connect the clicked signal to a python function:
236 button1.connect("clicked(bool)", someFunction)
235 button1.connect("clicked(bool)", someFunction)
237
236
238 \endcode
237 \endcode
239
238
240 \section CPP CPP Wrapping
239 \section CPP CPP Wrapping
241
240
242 You can create dedicated wrapper QObjects for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
241 You can create dedicated wrapper QObjects for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
243 and adding your factory via addWrapperFactory().
242 and adding your factory via addWrapperFactory().
244 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
243 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
245 and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
244 and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
246 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
245 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
247 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
246 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
248
247
249 \section MetaObject Meta Object/Class access
248 \section MetaObject Meta Object/Class access
250
249
251 For each known C++ class, PythonQt provides a Python class. These classes are visible
250 For each known C++ class, PythonQt provides a Python class. These classes are visible
252 inside of the "PythonQt" python module or in subpackages if a package is given when the class is registered.
251 inside of the "PythonQt" python module or in subpackages if a package is given when the class is registered.
253
252
254 A Meta class supports:
253 A Meta class supports:
255
254
256 - access to all declared enum values
255 - access to all declared enum values
257 - constructors
256 - constructors
258 - static methods
257 - static methods
259 - unbound non-static methods
258 - unbound non-static methods
260 - help() and className()
259 - help() and className()
261
260
262 From within Python, you can import the module "PythonQt" to access these classes and the Qt namespace.
261 From within Python, you can import the module "PythonQt" to access these classes and the Qt namespace.
263
262
264 \code
263 \code
265 from PythonQt import QtCore
264 from PythonQt import QtCore
266
265
267 # namespace access:
266 # namespace access:
268 print QtCore.Qt.AlignLeft
267 print QtCore.Qt.AlignLeft
269
268
270 # constructors
269 # constructors
271 a = QtCore.QSize(12,13)
270 a = QtCore.QSize(12,13)
272 b = QtCore.QFont()
271 b = QtCore.QFont()
273
272
274 # static method
273 # static method
275 QtCore.QDate.currentDate()
274 QtCore.QDate.currentDate()
276
275
277 # enum value
276 # enum value
278 QtCore.QFont.UltraCondensed
277 QtCore.QFont.UltraCondensed
279
278
280 \endcode
279 \endcode
281
280
282 \section Decorators Decorator slots
281 \section Decorators Decorator slots
283
282
284 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
283 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
285
284
286 - constructors
285 - constructors
287 - destructors (for CPP objects)
286 - destructors (for CPP objects)
288 - additional slots
287 - additional slots
289 - static slots (callable on both the Meta object and the instances)
288 - static slots (callable on both the Meta object and the instances)
290
289
291 The idea behind decorators is that we wanted to make it as easy as possible to extend
290 The idea behind decorators is that we wanted to make it as easy as possible to extend
292 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
291 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
293 Python, it looked promising to use this approach for the extension of wrapped objects as well.
292 Python, it looked promising to use this approach for the extension of wrapped objects as well.
294 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
293 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
295 Qt when he wants to create static methods, constructors and additional member functions.
294 Qt when he wants to create static methods, constructors and additional member functions.
296
295
297 The basic idea about decorators is to create a QObject derived class that implements slots
296 The basic idea about decorators is to create a QObject derived class that implements slots
298 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
297 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
299 These slots are then assigned to other classes via the naming convention.
298 These slots are then assigned to other classes via the naming convention.
300
299
301 - SomeClassName* new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a new object of type SomeClassName (where SomeClassName can be any CPP class, not just QObject classes)
300 - SomeClassName* new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a new object of type SomeClassName (where SomeClassName can be any CPP class, not just QObject classes)
302 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
301 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
303 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
302 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
304 - anything someMethodName(SomeClassName* o, ...) - defines a slot that will be available on SomeClassName instances (and derived instances). When such a slot is called the first argument is the pointer to the instance and the rest of the arguments can be used to make a call on the instance.
303 - anything someMethodName(SomeClassName* o, ...) - defines a slot that will be available on SomeClassName instances (and derived instances). When such a slot is called the first argument is the pointer to the instance and the rest of the arguments can be used to make a call on the instance.
305
304
306 The below example shows all kinds of decorators in action:
305 The below example shows all kinds of decorators in action:
307
306
308 \code
307 \code
309
308
310 // an example CPP object
309 // an example CPP object
311 class YourCPPObject {
310 class YourCPPObject {
312 public:
311 public:
313 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
312 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
314
313
315 float doSomething(int arg1) { return arg1*a*b; };
314 float doSomething(int arg1) { return arg1*a*b; };
316
315
317 private:
316 private:
318
317
319 int a;
318 int a;
320 float b;
319 float b;
321 };
320 };
322
321
323 // an example decorator
322 // an example decorator
324 class ExampleDecorator : public QObject
323 class ExampleDecorator : public QObject
325 {
324 {
326 Q_OBJECT
325 Q_OBJECT
327
326
328 public slots:
327 public slots:
329 // add a constructor to QSize that takes a QPoint
328 // add a constructor to QSize that takes a QPoint
330 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
329 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
331
330
332 // add a constructor for QPushButton that takes a text and a parent widget
331 // add a constructor for QPushButton that takes a text and a parent widget
333 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
332 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
334
333
335 // add a constructor for a CPP object
334 // add a constructor for a CPP object
336 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
335 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
337
336
338 // add a destructor for a CPP object
337 // add a destructor for a CPP object
339 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
338 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
340
339
341 // add a static method to QWidget
340 // add a static method to QWidget
342 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
341 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
343
342
344 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
343 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
345 void move(QWidget* w, const QPoint& p) { w->move(p); }
344 void move(QWidget* w, const QPoint& p) { w->move(p); }
346
345
347 // add an additional slot to QWidget, overloading the above move method
346 // add an additional slot to QWidget, overloading the above move method
348 void move(QWidget* w, int x, int y) { w->move(x,y); }
347 void move(QWidget* w, int x, int y) { w->move(x,y); }
349
348
350 // add a method to your own CPP object
349 // add a method to your own CPP object
351 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
350 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
352 };
351 };
353
352
354 ...
353 ...
355
354
356 PythonQt::self()->addDecorators(new ExampleDecorator());
355 PythonQt::self()->addDecorators(new ExampleDecorator());
357 PythonQt::self()->registerCPPClass("YourCPPObject");
356 PythonQt::self()->registerCPPClass("YourCPPObject");
358
357
359 \endcode
358 \endcode
360
359
361 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
360 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
362 (all these calls are mapped to the above decorator slots):
361 (all these calls are mapped to the above decorator slots):
363
362
364 \code
363 \code
365 from PythonQt import QtCore, QtGui, YourCPPObject
364 from PythonQt import QtCore, QtGui, YourCPPObject
366
365
367 # call our new constructor of QSize
366 # call our new constructor of QSize
368 size = QtCore.QSize(QPoint(1,2));
367 size = QtCore.QSize(QPoint(1,2));
369
368
370 # call our new QPushButton constructor
369 # call our new QPushButton constructor
371 button = QtGui.QPushButton("sometext");
370 button = QtGui.QPushButton("sometext");
372
371
373 # call the move slot (overload1)
372 # call the move slot (overload1)
374 button.move(QPoint(0,0))
373 button.move(QPoint(0,0))
375
374
376 # call the move slot (overload2)
375 # call the move slot (overload2)
377 button.move(0,0)
376 button.move(0,0)
378
377
379 # call the static method
378 # call the static method
380 grabber = QtGui.QWidget.mouseWrapper();
379 grabber = QtGui.QWidget.mouseWrapper();
381
380
382 # create a CPP object via constructor
381 # create a CPP object via constructor
383 yourCpp = YourCPPObject(1,11.5)
382 yourCpp = YourCPPObject(1,11.5)
384
383
385 # call the wrapped method on CPP object
384 # call the wrapped method on CPP object
386 print yourCpp.doSomething(1);
385 print yourCpp.doSomething(1);
387
386
388 # destructor will be called:
387 # destructor will be called:
389 yourCpp = None
388 yourCpp = None
390
389
391 \endcode
390 \endcode
392
391
393 \section Building
392 \section Building
394
393
395 PythonQt requires at least Qt 4.2.2 (or higher) and Python 2.3, 2.4, 2.5 or 2.6 on Windows, Linux and MacOS X. It has not yet been tested with Python 3.x, but it should only require minor changes.
394 PythonQt requires at least Qt 4.2.2 (or higher) and Python 2.3, 2.4, 2.5 or 2.6 on Windows, Linux and MacOS X. It has not yet been tested with Python 3.x, but it should only require minor changes.
396 To compile PythonQt, you will need a python developer installation which includes Python's header files and
395 To compile PythonQt, you will need a python developer installation which includes Python's header files and
397 the python2x.[lib | dll | so | dynlib].
396 the python2x.[lib | dll | so | dynlib].
398 The build scripts a currently set to use Python 2.5.
397 The build scripts a currently set to use Python 2.5.
399 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
398 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
400
399
401 \subsection Windows
400 \subsection Windows
402
401
403 On Windows, the (non-source) Python Windows installer can be used.
402 On Windows, the (non-source) Python Windows installer can be used.
404 Make sure that you use the same compiler, the current Python distribution is built
403 Make sure that you use the same compiler, the current Python distribution is built
405 with Visual Studio 2003. If you want to use another compiler, you will need to build
404 with Visual Studio 2003. If you want to use another compiler, you will need to build
406 Python yourself, using your compiler.
405 Python yourself, using your compiler.
407
406
408 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
407 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
409 dir of the python installation and \b PYTHON_LIB to point to
408 dir of the python installation and \b PYTHON_LIB to point to
410 the directory where the python lib file is located.
409 the directory where the python lib file is located.
411
410
412 When using the prebuild Python installer, this will be:
411 When using the prebuild Python installer, this will be:
413
412
414 \code
413 \code
415 > set PYTHON_PATH = c:\Python25
414 > set PYTHON_PATH = c:\Python25
416 > set PYTHON_LIB = c:\Python25\libs
415 > set PYTHON_LIB = c:\Python25\libs
417 \endcode
416 \endcode
418
417
419 When using the python sources, this will be something like:
418 When using the python sources, this will be something like:
420
419
421 \code
420 \code
422 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
421 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
423 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
422 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
424 \endcode
423 \endcode
425
424
426 To build all, do the following (after setting the above variables):
425 To build all, do the following (after setting the above variables):
427
426
428 \code
427 \code
429 > cd PythonQtRoot
428 > cd PythonQtRoot
430 > vcvars32
429 > vcvars32
431 > qmake
430 > qmake
432 > nmake
431 > nmake
433 \endcode
432 \endcode
434
433
435 This should build everything. If Python can not be linked or include files can not be found,
434 This should build everything. If Python can not be linked or include files can not be found,
436 you probably need to tweak \b build/python.prf
435 you probably need to tweak \b build/python.prf
437
436
438 The tests and examples are located in PythonQt/lib.
437 The tests and examples are located in PythonQt/lib.
439
438
440 \subsection Linux
439 \subsection Linux
441
440
442 On Linux, you need to install a Python-dev package.
441 On Linux, you need to install a Python-dev package.
443 If Python can not be linked or include files can not be found,
442 If Python can not be linked or include files can not be found,
444 you probably need to tweak \b build/python.prf
443 you probably need to tweak \b build/python.prf
445
444
446 To build PythonQt, just do a:
445 To build PythonQt, just do a:
447
446
448 \code
447 \code
449 > cd PythonQtRoot
448 > cd PythonQtRoot
450 > qmake
449 > qmake
451 > make all
450 > make all
452 \endcode
451 \endcode
453
452
454 The tests and examples are located in PythonQt/lib.
453 The tests and examples are located in PythonQt/lib.
455 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
454 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
456 linker can find the *.so files.
455 linker can find the *.so files.
457
456
458 \subsection MacOsX
457 \subsection MacOsX
459
458
460 On Mac, Python is installed as a Framework, so you should not need to install it.
459 On Mac, Python is installed as a Framework, so you should not need to install it.
461 To build PythonQt, just do a:
460 To build PythonQt, just do a:
462
461
463 \code
462 \code
464 > cd PythonQtRoot
463 > cd PythonQtRoot
465 > qmake
464 > qmake
466 > make all
465 > make all
467 \endcode
466 \endcode
468
467
469 \section Tests
468 \section Tests
470
469
471 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
470 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
472
471
473 \section Examples
472 \section Examples
474
473
475 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
474 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
476 interactive scripting console that shows how to script a simple application.
475 interactive scripting console that shows how to script a simple application.
477
476
478 The following shows how to integrate PythonQt into you Qt application:
477 The following shows how to integrate PythonQt into you Qt application:
479
478
480 \code
479 \code
481 #include "PythonQt.h"
480 #include "PythonQt.h"
482 #include <QApplication>
481 #include <QApplication>
483 ...
482 ...
484
483
485 int main( int argc, char **argv )
484 int main( int argc, char **argv )
486 {
485 {
487
486
488 QApplication qapp(argc, argv);
487 QApplication qapp(argc, argv);
489
488
490 // init PythonQt and Python itself
489 // init PythonQt and Python itself
491 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
490 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
492
491
493
492
494 // get a smart pointer to the __main__ module of the Python interpreter
493 // get a smart pointer to the __main__ module of the Python interpreter
495 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
494 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
496
495
497 // add a QObject as variable of name "example" to the namespace of the __main__ module
496 // add a QObject as variable of name "example" to the namespace of the __main__ module
498 PyExampleObject example;
497 PyExampleObject example;
499 PythonQt::self()->addObject(mainContext, "example", &example);
498 PythonQt::self()->addObject(mainContext, "example", &example);
500
499
501 // do something
500 // do something
502 PythonQt::self()->runScript(mainContext, "print example\n");
501 PythonQt::self()->runScript(mainContext, "print example\n");
503 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
502 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
504 QVariantList args;
503 QVariantList args;
505 args << 42 << 47;
504 args << 42 << 47;
506 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
505 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
507 ...
506 ...
508 \endcode
507 \endcode
509
508
510
509
511 */
510 */
@@ -1,125 +1,155
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 PythonQtStdDecorators.cpp
35 // \file PythonQtStdDecorators.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 2007-04
38 // \date 2007-04
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtStdDecorators.h"
42 #include "PythonQtStdDecorators.h"
43 #include "PythonQt.h"
43 #include "PythonQt.h"
44 #include "PythonQtClassInfo.h"
44 #include "PythonQtClassInfo.h"
45
45
46
46
47 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, PyObject* callable)
47 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, PyObject* callable)
48 {
48 {
49 QByteArray signalTmp("2");
49 QByteArray signalTmp;
50 signalTmp += signal;
50 char first = signal.at(0);
51 if (first>='0' && first<='9') {
52 signalTmp = signal;
53 } else {
54 signalTmp = "2" + signal;
55 }
56
51 if (sender) {
57 if (sender) {
52 return PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
58 return PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
53 } else {
59 } else {
54 return false;
60 return false;
55 }
61 }
56 }
62 }
57
63
58 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
64 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
59 {
65 {
60 bool r = false;
66 bool r = false;
61 if (sender && receiver) {
67 if (sender && receiver) {
62 QByteArray signalTmp("2");
68 QByteArray signalTmp;
63 signalTmp += signal;
69 char first = signal.at(0);
64 QByteArray slotTmp("1");
70 if (first>='0' && first<='9') {
65 slotTmp += slot;
71 signalTmp = signal;
66 if (receiver) {
72 } else {
67 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
73 signalTmp = "2" + signal;
68 }
74 }
75
76 QByteArray slotTmp;
77 first = slot.at(0);
78 if (first>='0' && first<='9') {
79 slotTmp = slot;
80 } else {
81 slotTmp = "1" + slot;
82 }
83 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
69 }
84 }
70 return r;
85 return r;
71 }
86 }
72
87
73 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
88 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
74 {
89 {
75 QByteArray signalTmp("2");
90 QByteArray signalTmp;
76 signalTmp += signal;
91 char first = signal.at(0);
92 if (first>='0' && first<='9') {
93 signalTmp = signal;
94 } else {
95 signalTmp = "2" + signal;
96 }
77 if (sender) {
97 if (sender) {
78 return PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
98 return PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
79 } else {
99 } else {
80 return false;
100 return false;
81 }
101 }
82 }
102 }
83
103
84 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
104 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
85 {
105 {
86 bool r = false;
106 bool r = false;
87 if (sender && receiver) {
107 if (sender && receiver) {
88 QByteArray signalTmp("2");
108 QByteArray signalTmp;
89 signalTmp += signal;
109 char first = signal.at(0);
90 QByteArray slotTmp("1");
110 if (first>='0' && first<='9') {
91 slotTmp += slot;
111 signalTmp = signal;
92 if (receiver) {
112 } else {
93 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
113 signalTmp = "2" + signal;
94 }
114 }
115
116 QByteArray slotTmp;
117 first = slot.at(0);
118 if (first>='0' && first<='9') {
119 slotTmp = slot;
120 } else {
121 slotTmp = "1" + slot;
122 }
123
124 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
95 }
125 }
96 return r;
126 return r;
97 }
127 }
98
128
99 #undef emit
129 #undef emit
100 void PythonQtStdDecorators::emit(QObject* sender, const QByteArray& signal, PyObject* arg1 ,PyObject* arg2 ,
130 void PythonQtStdDecorators::emit(QObject* sender, const QByteArray& signal, PyObject* arg1 ,PyObject* arg2 ,
101 PyObject* arg3 ,PyObject* arg4 ,PyObject* arg5 ,PyObject* arg6 ,PyObject* arg7 )
131 PyObject* arg3 ,PyObject* arg4 ,PyObject* arg5 ,PyObject* arg6 ,PyObject* arg7 )
102 {
132 {
103 // TODO xxx
133 // TODO xxx
104 // use normal PythonQtSlot calling code, add "allowSignal" to member lookup?!
134 // use normal PythonQtSlot calling code, add "allowSignal" to member lookup?!
105 }
135 }
106 #define emit
136 #define emit
107
137
108 QObject* PythonQtStdDecorators::parent(QObject* o) {
138 QObject* PythonQtStdDecorators::parent(QObject* o) {
109 return o->parent();
139 return o->parent();
110 }
140 }
111
141
112 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
142 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
113 {
143 {
114 o->setParent(parent);
144 o->setParent(parent);
115 }
145 }
116
146
117 QVariantList PythonQtStdDecorators::children(QObject* o)
147 QVariantList PythonQtStdDecorators::children(QObject* o)
118 {
148 {
119 QVariantList v;
149 QVariantList v;
120 QListIterator<QObject*> it(o->children());
150 QListIterator<QObject*> it(o->children());
121 while (it.hasNext()) {
151 while (it.hasNext()) {
122 v << qVariantFromValue(it.next());
152 v << qVariantFromValue(it.next());
123 }
153 }
124 return v;
154 return v;
125 }
155 }
General Comments 0
You need to be logged in to leave comments. Login now