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