##// END OF EJS Templates
added static connect/disconnect and dummy emit implementation, added dummy SIGNAL/SLOT functions to namespace...
florianlink -
r61:d314d06796c4
parent child
Show More
@@ -1,1193 +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)
1134 {
1135 const char* value;
1136 if (!PyArg_ParseTuple(args, "s", &value)) {
1137 return NULL;
1138 }
1139 // we do not prepend 0,1 or 2, why should we?
1140 return PyString_FromString(value);
1141 }
1142
1143 static PyObject *PythonQt_SLOT(PyObject * /*type*/, PyObject *args)
1144 {
1145 const char* value;
1146 if (!PyArg_ParseTuple(args, "s", &value)) {
1147 return NULL;
1148 }
1149 // we do not prepend 0,1 or 2, why should we?
1150 return PyString_FromString(value);
1151 }
1152
1153 static PyMethodDef PythonQt_Qt_methods[] = {
1154 {"SIGNAL", (PyCFunction)PythonQt_SIGNAL, METH_VARARGS,
1155 "Returns a signal string"
1156 },
1157 {"SLOT", (PyCFunction)PythonQt_SLOT, METH_VARARGS,
1158 "Returns a slot string"
1159 }
1160 };
1161
1133 PyObject* PythonQtPrivate::packageByName(const char* name)
1162 PyObject* PythonQtPrivate::packageByName(const char* name)
1134 {
1163 {
1135 if (name==NULL || name[0]==0) {
1164 if (name==NULL || name[0]==0) {
1136 return _pythonQtModule;
1165 return _pythonQtModule;
1137 }
1166 }
1138 PyObject* v = _packages.value(name);
1167 PyObject* v = _packages.value(name);
1139 if (!v) {
1168 if (!v) {
1140 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) {
1171 // add SIGNAL and SLOT functions
1172 PyModule_AddObject(v, "SIGNAL", PyCFunction_New(PythonQt_Qt_methods, v));
1173 PyModule_AddObject(v, "SLOT", PyCFunction_New(PythonQt_Qt_methods+1, v));
1174 }
1141 _packages.insert(name, v);
1175 _packages.insert(name, v);
1142 // AddObject steals the reference, so increment it!
1176 // AddObject steals the reference, so increment it!
1143 Py_INCREF(v);
1177 Py_INCREF(v);
1144 PyModule_AddObject(_pythonQtModule, name, v);
1178 PyModule_AddObject(_pythonQtModule, name, v);
1145 }
1179 }
1146 return v;
1180 return v;
1147 }
1181 }
1148
1182
1149
1183
1150 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1184 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1151 {
1185 {
1152 if (_p->_initFlags & ExternalHelp) {
1186 if (_p->_initFlags & ExternalHelp) {
1153 emit pythonHelpRequest(QByteArray(info->className()));
1187 emit pythonHelpRequest(QByteArray(info->className()));
1154 return Py_BuildValue("");
1188 return Py_BuildValue("");
1155 } else {
1189 } else {
1156 return PyString_FromString(info->help().toLatin1().data());
1190 return PyString_FromString(info->help().toLatin1().data());
1157 }
1191 }
1158 }
1192 }
1159
1193
1160 void PythonQtPrivate::removeWrapperPointer(void* obj)
1194 void PythonQtPrivate::removeWrapperPointer(void* obj)
1161 {
1195 {
1162 _wrappedObjects.remove(obj);
1196 _wrappedObjects.remove(obj);
1163 }
1197 }
1164
1198
1165 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1199 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1166 {
1200 {
1167 _wrappedObjects.insert(obj, wrapper);
1201 _wrappedObjects.insert(obj, wrapper);
1168 }
1202 }
1169
1203
1170 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1204 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1171 {
1205 {
1172 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1206 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1173 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1207 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1174 // 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
1175 // 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...
1176 // we remove the old one and set the copy to NULL
1210 // we remove the old one and set the copy to NULL
1177 wrap->_objPointerCopy = NULL;
1211 wrap->_objPointerCopy = NULL;
1178 removeWrapperPointer(obj);
1212 removeWrapperPointer(obj);
1179 wrap = NULL;
1213 wrap = NULL;
1180 }
1214 }
1181 return wrap;
1215 return wrap;
1182 }
1216 }
1183
1217
1184 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1218 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1185 {
1219 {
1186 PythonQtObjectPtr result;
1220 PythonQtObjectPtr result;
1187 if (pycode) {
1221 if (pycode) {
1188 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1222 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1189 } else {
1223 } else {
1190 PythonQt::self()->handleError();
1224 PythonQt::self()->handleError();
1191 }
1225 }
1192 return result;
1226 return result;
1193 }
1227 }
@@ -1,509 +1,511
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 maily 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 does not (yet?) offer QtCore.SIGNAL() and QtCore.SLOT() methods, connect and disconnect just take strings for signals and slots
146 - PythonQt offer QtCore.SIGNAL() and QtCore.SLOT() methods for compability, but no 0/1/3 is prepended
147 - QObject.emit to emit Qt signals from Python is not yet possible
147 - 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
149 - PythonQt does not offer to add new signals to Python/C++ objects
148 - 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)
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 - Probably there are lots of details that differ, I do not know PyQt that well to list them all.
151 - Probably there are lots of details that differ, I do not know PyQt that well to list them all.
150
152
151
153
152 \section Interface
154 \section Interface
153
155
154 The main interface to PythonQt is the PythonQt singleton.
156 The main interface to PythonQt is the PythonQt singleton.
155 PythonQt needs to be initialized via PythonQt::init() once.
157 PythonQt needs to be initialized via PythonQt::init() once.
156 Afterwards you communicate with the singleton via PythonQt::self().
158 Afterwards you communicate with the singleton via PythonQt::self().
157 PythonQt offers a complete Qt binding, which
159 PythonQt offers a complete Qt binding, which
158 needs to be enabled via PythonQt_QtAll::init().
160 needs to be enabled via PythonQt_QtAll::init().
159
161
160
162
161 \section Datatype Datatype Mapping
163 \section Datatype Datatype Mapping
162
164
163 The following table shows the mapping between Python and Qt objects:
165 The following table shows the mapping between Python and Qt objects:
164 <table>
166 <table>
165 <tr><th>Qt/C++</th><th>Python</th></tr>
167 <tr><th>Qt/C++</th><th>Python</th></tr>
166 <tr><td>bool</td><td>bool</td></tr>
168 <tr><td>bool</td><td>bool</td></tr>
167 <tr><td>double</td><td>float</td></tr>
169 <tr><td>double</td><td>float</td></tr>
168 <tr><td>float</td><td>float</td></tr>
170 <tr><td>float</td><td>float</td></tr>
169 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
171 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
170 <tr><td>long</td><td>integer</td></tr>
172 <tr><td>long</td><td>integer</td></tr>
171 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
173 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
172 <tr><td>QString</td><td>unicode string</td></tr>
174 <tr><td>QString</td><td>unicode string</td></tr>
173 <tr><td>QByteArray</td><td>str</td></tr>
175 <tr><td>QByteArray</td><td>str</td></tr>
174 <tr><td>char*</td><td>str</td></tr>
176 <tr><td>char*</td><td>str</td></tr>
175 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
177 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
176 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
178 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
177 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
179 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
178 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
180 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
179 <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>
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>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional information/wrapping provided by registerCPPClass()</td></tr>
182 <tr><td>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional information/wrapping provided by registerCPPClass()</td></tr>
181 <tr><td>QList<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
183 <tr><td>QList<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
182 <tr><td>EnumType</td><td>integer (all enums that are known via the moc and the Qt namespace are supported)</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>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
185 <tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
184 <tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</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>PyObject</td><td>PyObject</td></tr>
187 <tr><td>PyObject</td><td>PyObject</td></tr>
186 </table>
188 </table>
187
189
188 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
190 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
189 a Qt slot.
191 a Qt slot.
190 QVariants are mapped recursively as given above, e.g. a dictionary can
192 QVariants are mapped recursively as given above, e.g. a dictionary can
191 contain lists of dictionaries of doubles.
193 contain lists of dictionaries of doubles.
192 For example a QVariant of type "String" is mapped to a python unicode string.
194 For example a QVariant of type "String" is mapped to a python unicode string.
193 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
195 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
194
196
195 \section QObject QObject Wrapping
197 \section QObject QObject Wrapping
196
198
197 All classes derived from QObject are automatically wrapped with a python wrapper class
199 All classes derived from QObject are automatically wrapped with a python wrapper class
198 when they become visible to the Python interpreter. This can happen via
200 when they become visible to the Python interpreter. This can happen via
199 - the PythonQt::addObject() method
201 - the PythonQt::addObject() method
200 - when a Qt \b slot returns a QObject derived object to python
202 - when a Qt \b slot returns a QObject derived object to python
201 - when a Qt \b signal contains a QObject and is connected to a python function
203 - when a Qt \b signal contains a QObject and is connected to a python function
202
204
203 It is important that you call PythonQt::registerClass() for any QObject derived class
205 It is important that you call PythonQt::registerClass() for any QObject derived class
204 that may become visible to Python, except when you add it via PythonQt::addObject().
206 that may become visible to Python, except when you add it via PythonQt::addObject().
205 This will register the complete parent hierachy of the registered class, so that
207 This will register the complete parent hierachy of the registered class, so that
206 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
208 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
207 parents).
209 parents).
208
210
209 From Python, you can talk to the returned QObjects in a natural way by calling
211 From Python, you can talk to the returned QObjects in a natural way by calling
210 their slots and receiving the return values. You can also read/write all
212 their slots and receiving the return values. You can also read/write all
211 properties of the objects as if they where normal python properties.
213 properties of the objects as if they where normal python properties.
212
214
213 In addition to this, the wrapped objects support
215 In addition to this, the wrapped objects support
214 - className() - returns a string that reprents the classname of the QObject
216 - className() - returns a string that reprents the classname of the QObject
215 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
217 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
216 - delete() - deletes the object (use with care, especially if you passed the ownership to C++)
218 - delete() - deletes the object (use with care, especially if you passed the ownership to C++)
217 - connect(signal, function) - connect the signal of the given object to a python function
219 - connect(signal, function) - connect the signal of the given object to a python function
218 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
220 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
219 - disconnect(signal, function) - disconnect the signal of the given object from a python function
221 - disconnect(signal, function) - disconnect the signal of the given object from a python function
220 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
222 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
221 - children() - returns the children of the object
223 - children() - returns the children of the object
222 - setParent(QObject) - set the parent
224 - setParent(QObject) - set the parent
223 - QObject* parent() - get the parent
225 - QObject* parent() - get the parent
224
226
225 The below example shows how to connect signals in Python:
227 The below example shows how to connect signals in Python:
226
228
227 \code
229 \code
228 # define a signal handler function
230 # define a signal handler function
229 def someFunction(flag):
231 def someFunction(flag):
230 print flag
232 print flag
231
233
232 # button1 is a QPushButton that has been added to Python via addObject()
234 # button1 is a QPushButton that has been added to Python via addObject()
233 # connect the clicked signal to a python function:
235 # connect the clicked signal to a python function:
234 button1.connect("clicked(bool)", someFunction)
236 button1.connect("clicked(bool)", someFunction)
235
237
236 \endcode
238 \endcode
237
239
238 \section CPP CPP Wrapping
240 \section CPP CPP Wrapping
239
241
240 You can create dedicated wrapper QObjects for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
242 You can create dedicated wrapper QObjects for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
241 and adding your factory via addWrapperFactory().
243 and adding your factory via addWrapperFactory().
242 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
244 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
243 and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
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 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
246 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
245 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
247 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
246
248
247 \section MetaObject Meta Object/Class access
249 \section MetaObject Meta Object/Class access
248
250
249 For each known C++ class, PythonQt provides a Python class. These classes are visible
251 For each known C++ class, PythonQt provides a Python class. These classes are visible
250 inside of the "PythonQt" python module or in subpackages if a package is given when the class is registered.
252 inside of the "PythonQt" python module or in subpackages if a package is given when the class is registered.
251
253
252 A Meta class supports:
254 A Meta class supports:
253
255
254 - access to all declared enum values
256 - access to all declared enum values
255 - constructors
257 - constructors
256 - static methods
258 - static methods
257 - unbound non-static methods
259 - unbound non-static methods
258 - help() and className()
260 - help() and className()
259
261
260 From within Python, you can import the module "PythonQt" to access these classes and the Qt namespace.
262 From within Python, you can import the module "PythonQt" to access these classes and the Qt namespace.
261
263
262 \code
264 \code
263 from PythonQt import QtCore
265 from PythonQt import QtCore
264
266
265 # namespace access:
267 # namespace access:
266 print QtCore.Qt.AlignLeft
268 print QtCore.Qt.AlignLeft
267
269
268 # constructors
270 # constructors
269 a = QtCore.QSize(12,13)
271 a = QtCore.QSize(12,13)
270 b = QtCore.QFont()
272 b = QtCore.QFont()
271
273
272 # static method
274 # static method
273 QtCore.QDate.currentDate()
275 QtCore.QDate.currentDate()
274
276
275 # enum value
277 # enum value
276 QtCore.QFont.UltraCondensed
278 QtCore.QFont.UltraCondensed
277
279
278 \endcode
280 \endcode
279
281
280 \section Decorators Decorator slots
282 \section Decorators Decorator slots
281
283
282 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
284 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
283
285
284 - constructors
286 - constructors
285 - destructors (for CPP objects)
287 - destructors (for CPP objects)
286 - additional slots
288 - additional slots
287 - static slots (callable on both the Meta object and the instances)
289 - static slots (callable on both the Meta object and the instances)
288
290
289 The idea behind decorators is that we wanted to make it as easy as possible to extend
291 The idea behind decorators is that we wanted to make it as easy as possible to extend
290 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
292 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
291 Python, it looked promising to use this approach for the extension of wrapped objects as well.
293 Python, it looked promising to use this approach for the extension of wrapped objects as well.
292 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
294 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
293 Qt when he wants to create static methods, constructors and additional member functions.
295 Qt when he wants to create static methods, constructors and additional member functions.
294
296
295 The basic idea about decorators is to create a QObject derived class that implements slots
297 The basic idea about decorators is to create a QObject derived class that implements slots
296 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
298 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
297 These slots are then assigned to other classes via the naming convention.
299 These slots are then assigned to other classes via the naming convention.
298
300
299 - 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)
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 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
302 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
301 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
303 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
302 - 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.
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
305
304 The below example shows all kinds of decorators in action:
306 The below example shows all kinds of decorators in action:
305
307
306 \code
308 \code
307
309
308 // an example CPP object
310 // an example CPP object
309 class YourCPPObject {
311 class YourCPPObject {
310 public:
312 public:
311 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
313 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
312
314
313 float doSomething(int arg1) { return arg1*a*b; };
315 float doSomething(int arg1) { return arg1*a*b; };
314
316
315 private:
317 private:
316
318
317 int a;
319 int a;
318 float b;
320 float b;
319 };
321 };
320
322
321 // an example decorator
323 // an example decorator
322 class ExampleDecorator : public QObject
324 class ExampleDecorator : public QObject
323 {
325 {
324 Q_OBJECT
326 Q_OBJECT
325
327
326 public slots:
328 public slots:
327 // add a constructor to QSize that takes a QPoint
329 // add a constructor to QSize that takes a QPoint
328 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
330 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
329
331
330 // add a constructor for QPushButton that takes a text and a parent widget
332 // add a constructor for QPushButton that takes a text and a parent widget
331 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
333 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
332
334
333 // add a constructor for a CPP object
335 // add a constructor for a CPP object
334 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
336 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
335
337
336 // add a destructor for a CPP object
338 // add a destructor for a CPP object
337 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
339 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
338
340
339 // add a static method to QWidget
341 // add a static method to QWidget
340 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
342 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
341
343
342 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
344 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
343 void move(QWidget* w, const QPoint& p) { w->move(p); }
345 void move(QWidget* w, const QPoint& p) { w->move(p); }
344
346
345 // add an additional slot to QWidget, overloading the above move method
347 // add an additional slot to QWidget, overloading the above move method
346 void move(QWidget* w, int x, int y) { w->move(x,y); }
348 void move(QWidget* w, int x, int y) { w->move(x,y); }
347
349
348 // add a method to your own CPP object
350 // add a method to your own CPP object
349 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
351 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
350 };
352 };
351
353
352 ...
354 ...
353
355
354 PythonQt::self()->addDecorators(new ExampleDecorator());
356 PythonQt::self()->addDecorators(new ExampleDecorator());
355 PythonQt::self()->registerCPPClass("YourCPPObject");
357 PythonQt::self()->registerCPPClass("YourCPPObject");
356
358
357 \endcode
359 \endcode
358
360
359 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
361 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
360 (all these calls are mapped to the above decorator slots):
362 (all these calls are mapped to the above decorator slots):
361
363
362 \code
364 \code
363 from PythonQt import QtCore, QtGui, YourCPPObject
365 from PythonQt import QtCore, QtGui, YourCPPObject
364
366
365 # call our new constructor of QSize
367 # call our new constructor of QSize
366 size = QtCore.QSize(QPoint(1,2));
368 size = QtCore.QSize(QPoint(1,2));
367
369
368 # call our new QPushButton constructor
370 # call our new QPushButton constructor
369 button = QtGui.QPushButton("sometext");
371 button = QtGui.QPushButton("sometext");
370
372
371 # call the move slot (overload1)
373 # call the move slot (overload1)
372 button.move(QPoint(0,0))
374 button.move(QPoint(0,0))
373
375
374 # call the move slot (overload2)
376 # call the move slot (overload2)
375 button.move(0,0)
377 button.move(0,0)
376
378
377 # call the static method
379 # call the static method
378 grabber = QtGui.QWidget.mouseWrapper();
380 grabber = QtGui.QWidget.mouseWrapper();
379
381
380 # create a CPP object via constructor
382 # create a CPP object via constructor
381 yourCpp = YourCPPObject(1,11.5)
383 yourCpp = YourCPPObject(1,11.5)
382
384
383 # call the wrapped method on CPP object
385 # call the wrapped method on CPP object
384 print yourCpp.doSomething(1);
386 print yourCpp.doSomething(1);
385
387
386 # destructor will be called:
388 # destructor will be called:
387 yourCpp = None
389 yourCpp = None
388
390
389 \endcode
391 \endcode
390
392
391 \section Building
393 \section Building
392
394
393 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.
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 To compile PythonQt, you will need a python developer installation which includes Python's header files and
396 To compile PythonQt, you will need a python developer installation which includes Python's header files and
395 the python2x.[lib | dll | so | dynlib].
397 the python2x.[lib | dll | so | dynlib].
396 The build scripts a currently set to use Python 2.5.
398 The build scripts a currently set to use Python 2.5.
397 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
399 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
398
400
399 \subsection Windows
401 \subsection Windows
400
402
401 On Windows, the (non-source) Python Windows installer can be used.
403 On Windows, the (non-source) Python Windows installer can be used.
402 Make sure that you use the same compiler, the current Python distribution is built
404 Make sure that you use the same compiler, the current Python distribution is built
403 with Visual Studio 2003. If you want to use another compiler, you will need to build
405 with Visual Studio 2003. If you want to use another compiler, you will need to build
404 Python yourself, using your compiler.
406 Python yourself, using your compiler.
405
407
406 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
408 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
407 dir of the python installation and \b PYTHON_LIB to point to
409 dir of the python installation and \b PYTHON_LIB to point to
408 the directory where the python lib file is located.
410 the directory where the python lib file is located.
409
411
410 When using the prebuild Python installer, this will be:
412 When using the prebuild Python installer, this will be:
411
413
412 \code
414 \code
413 > set PYTHON_PATH = c:\Python25
415 > set PYTHON_PATH = c:\Python25
414 > set PYTHON_LIB = c:\Python25\libs
416 > set PYTHON_LIB = c:\Python25\libs
415 \endcode
417 \endcode
416
418
417 When using the python sources, this will be something like:
419 When using the python sources, this will be something like:
418
420
419 \code
421 \code
420 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
422 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
421 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
423 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
422 \endcode
424 \endcode
423
425
424 To build all, do the following (after setting the above variables):
426 To build all, do the following (after setting the above variables):
425
427
426 \code
428 \code
427 > cd PythonQtRoot
429 > cd PythonQtRoot
428 > vcvars32
430 > vcvars32
429 > qmake
431 > qmake
430 > nmake
432 > nmake
431 \endcode
433 \endcode
432
434
433 This should build everything. If Python can not be linked or include files can not be found,
435 This should build everything. If Python can not be linked or include files can not be found,
434 you probably need to tweak \b build/python.prf
436 you probably need to tweak \b build/python.prf
435
437
436 The tests and examples are located in PythonQt/lib.
438 The tests and examples are located in PythonQt/lib.
437
439
438 \subsection Linux
440 \subsection Linux
439
441
440 On Linux, you need to install a Python-dev package.
442 On Linux, you need to install a Python-dev package.
441 If Python can not be linked or include files can not be found,
443 If Python can not be linked or include files can not be found,
442 you probably need to tweak \b build/python.prf
444 you probably need to tweak \b build/python.prf
443
445
444 To build PythonQt, just do a:
446 To build PythonQt, just do a:
445
447
446 \code
448 \code
447 > cd PythonQtRoot
449 > cd PythonQtRoot
448 > qmake
450 > qmake
449 > make all
451 > make all
450 \endcode
452 \endcode
451
453
452 The tests and examples are located in PythonQt/lib.
454 The tests and examples are located in PythonQt/lib.
453 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
455 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
454 linker can find the *.so files.
456 linker can find the *.so files.
455
457
456 \subsection MacOsX
458 \subsection MacOsX
457
459
458 On Mac, Python is installed as a Framework, so you should not need to install it.
460 On Mac, Python is installed as a Framework, so you should not need to install it.
459 To build PythonQt, just do a:
461 To build PythonQt, just do a:
460
462
461 \code
463 \code
462 > cd PythonQtRoot
464 > cd PythonQtRoot
463 > qmake
465 > qmake
464 > make all
466 > make all
465 \endcode
467 \endcode
466
468
467 \section Tests
469 \section Tests
468
470
469 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
471 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
470
472
471 \section Examples
473 \section Examples
472
474
473 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
475 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
474 interactive scripting console that shows how to script a simple application.
476 interactive scripting console that shows how to script a simple application.
475
477
476 The following shows how to integrate PythonQt into you Qt application:
478 The following shows how to integrate PythonQt into you Qt application:
477
479
478 \code
480 \code
479 #include "PythonQt.h"
481 #include "PythonQt.h"
480 #include <QApplication>
482 #include <QApplication>
481 ...
483 ...
482
484
483 int main( int argc, char **argv )
485 int main( int argc, char **argv )
484 {
486 {
485
487
486 QApplication qapp(argc, argv);
488 QApplication qapp(argc, argv);
487
489
488 // init PythonQt and Python itself
490 // init PythonQt and Python itself
489 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
491 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
490
492
491
493
492 // get a smart pointer to the __main__ module of the Python interpreter
494 // get a smart pointer to the __main__ module of the Python interpreter
493 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
495 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
494
496
495 // add a QObject as variable of name "example" to the namespace of the __main__ module
497 // add a QObject as variable of name "example" to the namespace of the __main__ module
496 PyExampleObject example;
498 PyExampleObject example;
497 PythonQt::self()->addObject(mainContext, "example", &example);
499 PythonQt::self()->addObject(mainContext, "example", &example);
498
500
499 // do something
501 // do something
500 PythonQt::self()->runScript(mainContext, "print example\n");
502 PythonQt::self()->runScript(mainContext, "print example\n");
501 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
503 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
502 QVariantList args;
504 QVariantList args;
503 args << 42 << 47;
505 args << 42 << 47;
504 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
506 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
505 ...
507 ...
506 \endcode
508 \endcode
507
509
508
510
509 */
511 */
@@ -1,116 +1,125
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("2");
50 signalTmp += signal;
50 signalTmp += signal;
51 if (sender) {
51 if (sender) {
52 return PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
52 return PythonQt::self()->addSignalHandler(sender, signalTmp, callable);
53 } else {
53 } else {
54 return false;
54 return false;
55 }
55 }
56 }
56 }
57
57
58 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
58 bool PythonQtStdDecorators::connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
59 {
59 {
60 bool r = false;
60 bool r = false;
61 if (sender && receiver) {
61 if (sender && receiver) {
62 QByteArray signalTmp("2");
62 QByteArray signalTmp("2");
63 signalTmp += signal;
63 signalTmp += signal;
64 QByteArray slotTmp("1");
64 QByteArray slotTmp("1");
65 slotTmp += slot;
65 slotTmp += slot;
66 if (receiver) {
66 if (receiver) {
67 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
67 r = QObject::connect(sender, signalTmp, receiver, slotTmp);
68 }
68 }
69 }
69 }
70 return r;
70 return r;
71 }
71 }
72
72
73 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
73 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, PyObject* callable)
74 {
74 {
75 QByteArray signalTmp("2");
75 QByteArray signalTmp("2");
76 signalTmp += signal;
76 signalTmp += signal;
77 if (sender) {
77 if (sender) {
78 return PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
78 return PythonQt::self()->removeSignalHandler(sender, signalTmp, callable);
79 } else {
79 } else {
80 return false;
80 return false;
81 }
81 }
82 }
82 }
83
83
84 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
84 bool PythonQtStdDecorators::disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot)
85 {
85 {
86 bool r = false;
86 bool r = false;
87 if (sender && receiver) {
87 if (sender && receiver) {
88 QByteArray signalTmp("2");
88 QByteArray signalTmp("2");
89 signalTmp += signal;
89 signalTmp += signal;
90 QByteArray slotTmp("1");
90 QByteArray slotTmp("1");
91 slotTmp += slot;
91 slotTmp += slot;
92 if (receiver) {
92 if (receiver) {
93 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
93 r = QObject::disconnect(sender, signalTmp, receiver, slotTmp);
94 }
94 }
95 }
95 }
96 return r;
96 return r;
97 }
97 }
98
98
99 #undef emit
100 void PythonQtStdDecorators::emit(QObject* sender, const QByteArray& signal, PyObject* arg1 ,PyObject* arg2 ,
101 PyObject* arg3 ,PyObject* arg4 ,PyObject* arg5 ,PyObject* arg6 ,PyObject* arg7 )
102 {
103 // TODO xxx
104 // use normal PythonQtSlot calling code, add "allowSignal" to member lookup?!
105 }
106 #define emit
107
99 QObject* PythonQtStdDecorators::parent(QObject* o) {
108 QObject* PythonQtStdDecorators::parent(QObject* o) {
100 return o->parent();
109 return o->parent();
101 }
110 }
102
111
103 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
112 void PythonQtStdDecorators::setParent(QObject* o, QObject* parent)
104 {
113 {
105 o->setParent(parent);
114 o->setParent(parent);
106 }
115 }
107
116
108 QVariantList PythonQtStdDecorators::children(QObject* o)
117 QVariantList PythonQtStdDecorators::children(QObject* o)
109 {
118 {
110 QVariantList v;
119 QVariantList v;
111 QListIterator<QObject*> it(o->children());
120 QListIterator<QObject*> it(o->children());
112 while (it.hasNext()) {
121 while (it.hasNext()) {
113 v << qVariantFromValue(it.next());
122 v << qVariantFromValue(it.next());
114 }
123 }
115 return v;
124 return v;
116 }
125 }
@@ -1,79 +1,84
1 #ifndef _PYTHONQTSTDDECORATORS_H
1 #ifndef _PYTHONQTSTDDECORATORS_H
2 #define _PYTHONQTSTDDECORATORS_H
2 #define _PYTHONQTSTDDECORATORS_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 PythonQtStdDecorators.h
38 // \file PythonQtStdDecorators.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 2007-04
41 // \date 2007-04
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include <Python.h>
46 #include <Python.h>
47 #include <QObject>
47 #include <QObject>
48 #include <QVariantList>
48 #include <QVariantList>
49 #include <QTextDocument>
49 #include <QTextDocument>
50 #include <QColor>
50 #include <QColor>
51 #include <QDateTime>
51 #include <QDateTime>
52 #include <QDate>
52 #include <QDate>
53 #include <QTime>
53 #include <QTime>
54
54
55 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
55 class PYTHONQT_EXPORT PythonQtStdDecorators : public QObject
56 {
56 {
57 Q_OBJECT
57 Q_OBJECT
58
58
59 public slots:
59 public slots:
60 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
60 bool connect(QObject* sender, const QByteArray& signal, PyObject* callable);
61 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
61 bool connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
62 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
62 bool disconnect(QObject* sender, const QByteArray& signal, PyObject* callable);
63 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
63 bool disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot);
64
64
65 #undef emit
66 void emit(QObject* sender, const QByteArray& signal, PyObject* arg1 = NULL,PyObject* arg2 = NULL,
67 PyObject* arg3 = NULL,PyObject* arg4 = NULL,PyObject* arg5 = NULL,PyObject* arg6 = NULL,PyObject* arg7 = NULL);
68 #define emit
69
65 bool static_QObject_connect(QObject* sender, const QByteArray& signal, PyObject* callable) { return connect(sender, signal, callable); }
70 bool static_QObject_connect(QObject* sender, const QByteArray& signal, PyObject* callable) { return connect(sender, signal, callable); }
66 bool static_QObject_connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot) { return connect(sender, signal, receiver, slot); }
71 bool static_QObject_connect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot) { return connect(sender, signal, receiver, slot); }
67 bool static_QObject_disconnect(QObject* sender, const QByteArray& signal, PyObject* callable) { return disconnect(sender, signal, callable); }
72 bool static_QObject_disconnect(QObject* sender, const QByteArray& signal, PyObject* callable) { return disconnect(sender, signal, callable); }
68 bool static_QObject_disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot) { return disconnect(sender, signal, receiver, slot); };
73 bool static_QObject_disconnect(QObject* sender, const QByteArray& signal, QObject* receiver, const QByteArray& slot) { return disconnect(sender, signal, receiver, slot); };
69
74
70 QObject* parent(QObject* o);
75 QObject* parent(QObject* o);
71 void setParent(QObject* o, QObject* parent);
76 void setParent(QObject* o, QObject* parent);
72
77
73 QVariantList children(QObject* o);
78 QVariantList children(QObject* o);
74
79
75 //TODO: add findChild/findChildren/children/...
80 //TODO: add findChild/findChildren/children/...
76 };
81 };
77
82
78
83
79 #endif
84 #endif
General Comments 0
You need to be logged in to leave comments. Login now