##// END OF EJS Templates
- removed warnings...
florianlink -
r8:f65f3e118cc5
parent child
Show More
@@ -0,0 +1,80
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 PythonQtQFileImporter.h
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
38 // \date 2009-03
39 */
40 //----------------------------------------------------------------------------------
41
42 #include <QFile>
43 #include <QFileInfo>
44
45 #include "PythonQtQFileImporter.h"
46
47 PythonQtQFileImporter::PythonQtQFileImporter() {
48 }
49
50 PythonQtQFileImporter::~PythonQtQFileImporter() {
51 }
52
53 QByteArray PythonQtQFileImporter::readFileAsBytes (const QString &filename) {
54 QFile f(filename);
55 if (f.open(QIODevice::ReadOnly)) {
56 return f.readAll();
57 } else {
58 return QByteArray();
59 }
60 }
61
62 QByteArray PythonQtQFileImporter::readSourceFile (const QString &filename, bool &ok) {
63 QFile f(filename);
64 if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
65 ok = true;
66 return f.readAll();
67 } else {
68 ok = false;
69 return QByteArray();
70 }
71 }
72
73 bool PythonQtQFileImporter::exists (const QString &filename) {
74 return QFile::exists(filename);
75 }
76
77 QDateTime PythonQtQFileImporter::lastModifiedDate (const QString &filename) {
78 QFileInfo fi(filename);
79 return fi.lastModified();
80 }
@@ -0,0 +1,63
1 #ifndef _PYTHONQTQFILEIMPORTER_H
2 #define _PYTHONQTQFILEIMPORTER_H
3
4 /*
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
24 *
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
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
31 *
32 * http://www.mevis.de
33 *
34 */
35
36 //----------------------------------------------------------------------------------
37 /*!
38 // \file PythonQtQFileImporter.h
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
41 // \date 2009-03
42 */
43 //----------------------------------------------------------------------------------
44
45 #include <PythonQtImportFileInterface.h>
46
47 //! default importer implementation using QFile to load python code
48 class PythonQtQFileImporter : public PythonQtImportFileInterface {
49 public:
50 PythonQtQFileImporter();
51 ~PythonQtQFileImporter();
52
53 QByteArray readFileAsBytes (const QString &filename);
54
55 QByteArray readSourceFile (const QString &filename, bool &ok);
56
57 bool exists (const QString &filename);
58
59 QDateTime lastModifiedDate (const QString &filename);
60
61 };
62
63 #endif
@@ -1,49 +1,46
1 #include <PythonQt.h>
1 #include <PythonQt.h>
2 #include <QtGui>
2 #include <QtGui>
3 #include "QFileImportInterface.h"
4
3
5 int main (int argc, char* argv[]) {
4 int main (int argc, char* argv[]) {
6 QApplication app(argc, argv);
5 QApplication app(argc, argv);
7 PythonQt::init();
6 PythonQt::init();
8 PythonQtObjectPtr mainModule = PythonQt::self()->getMainModule();
7 PythonQtObjectPtr mainModule = PythonQt::self()->getMainModule();
9 mainModule.evalScript(QString("import sys\n"));
8 mainModule.evalScript(QString("import sys\n"));
10 Q_ASSERT(!mainModule.isNull());
9 Q_ASSERT(!mainModule.isNull());
11 {
10 {
12 // evaluate a python file embedded in executable as resource:
11 // evaluate a python file embedded in executable as resource:
13 mainModule.evalFile(":eyed3tagger.py");
12 mainModule.evalFile(":eyed3tagger.py");
14 // create an object, hold onto its reference
13 // create an object, hold onto its reference
15 PythonQtObjectPtr tag = mainModule.evalScript("EyeD3Tagger()\n", Py_eval_input);
14 PythonQtObjectPtr tag = mainModule.evalScript("EyeD3Tagger()\n", Py_eval_input);
16 Q_ASSERT(!tag.isNull());
15 Q_ASSERT(!tag.isNull());
17 tag.call("setFileName", QVariantList() << "t.mp3");
16 tag.call("setFileName", QVariantList() << "t.mp3");
18 QVariant fn = tag.call("fileName", QVariantList());
17 QVariant fn = tag.call("fileName", QVariantList());
19 Q_ASSERT(fn.toString() == QString("t.mp3"));
18 Q_ASSERT(fn.toString() == QString("t.mp3"));
20 // tag goes out of scope, reference count decremented.
19 // tag goes out of scope, reference count decremented.
21 }
20 }
22 qDebug() << "test1";
23 /*
24 {
21 {
25 // Allow the python system path to recognize QFile paths in the sys.path
22 // Allow the python system path to recognize QFile paths in the sys.path
26 QFileImportInterface qfii;
23 //QFileImportInterface qfii;
24 PythonQt::self()->setImporter(NULL);
27 // append the Qt resource root directory to the sys.path
25 // append the Qt resource root directory to the sys.path
28 mainModule.evalScript("sys.path.append(':')\n");
26 mainModule.evalScript("sys.path.append(':')\n");
29 mainModule.evalScript("import eyed3tagger\n");
27 mainModule.evalScript("import eyed3tagger\n");
30 PythonQtObjectPtr tag = mainModule.evalScript("eyed3tagger.EyeD3Tagger()\n", Py_eval_input);
28 PythonQtObjectPtr tag = mainModule.evalScript("eyed3tagger.EyeD3Tagger()\n", Py_eval_input);
31 Q_ASSERT(!tag.isNull());
29 Q_ASSERT(!tag.isNull());
32 tag.call("setFileName", QVariantList() << "t.mp3");
30 tag.call("setFileName", QVariantList() << "t.mp3");
33 QVariant fn = tag.call("fileName", QVariantList());
31 QVariant fn = tag.call("fileName", QVariantList());
34 Q_ASSERT(fn.toString() == QString("t.mp3"));
32 Q_ASSERT(fn.toString() == QString("t.mp3"));
35 }
33 }
36 qDebug() << "test2"; */
37 { // alternative using import and loading it as a real module from sys.path
34 { // alternative using import and loading it as a real module from sys.path
38 // import sys first
35 // import sys first
39 mainModule.evalScript(QString("sys.path.append('%1')\n").arg(QDir::currentPath()));
36 mainModule.evalScript(QString("sys.path.append('%1')\n").arg(QDir::currentPath()));
40 mainModule.evalScript("import eyed3tagger\n");
37 mainModule.evalScript("import eyed3tagger\n");
41 PythonQtObjectPtr tag = mainModule.evalScript("eyed3tagger.EyeD3Tagger()\n", Py_eval_input);
38 PythonQtObjectPtr tag = mainModule.evalScript("eyed3tagger.EyeD3Tagger()\n", Py_eval_input);
42 Q_ASSERT(!tag.isNull());
39 Q_ASSERT(!tag.isNull());
43 tag.call("setFileName", QVariantList() << "t.mp3");
40 tag.call("setFileName", QVariantList() << "t.mp3");
44 QVariant fn = tag.call("fileName", QVariantList());
41 QVariant fn = tag.call("fileName", QVariantList());
45 Q_ASSERT(fn.toString() == QString("t.mp3"));
42 Q_ASSERT(fn.toString() == QString("t.mp3"));
46 }
43 }
47 qDebug() << "finished";
44 qDebug() << "finished";
48 return 0;
45 return 0;
49 }
46 }
@@ -1,11 +1,11
1 CONFIG += debug
1 CONFIG += debug
2 VPATH +=
2 VPATH +=
3 INCLUDEPATH += . $$(PYTHONQT_ROOT)/src /usr/include/python2.5
3 INCLUDEPATH += . $$(PYTHONQT_ROOT)/src /usr/include/python2.5
4
4
5 SOURCES += CPPPyWrapperExample.cpp QFileImportInterface.cpp
5 SOURCES += CPPPyWrapperExample.cpp
6 HEADERS += QFileImportInterface.h
7
6
7 mac { CONFIG -= app_bundle }
8
8
9 LIBS += -L$$(PYTHONQT_ROOT)/lib -lPythonQt -lutil
9 LIBS += -L$$(PYTHONQT_ROOT)/lib -lPythonQt_d -lutil
10
10
11 RESOURCES += CPPPyWrapperExample.qrc
11 RESOURCES += CPPPyWrapperExample.qrc
@@ -1,1011 +1,1029
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 <pydebug.h>
53 #include <pydebug.h>
53
54
54 PythonQt* PythonQt::_self = NULL;
55 PythonQt* PythonQt::_self = NULL;
55 int PythonQt::_uniqueModuleCount = 0;
56 int PythonQt::_uniqueModuleCount = 0;
56
57
57
58
58 void PythonQt::init(int flags)
59 void PythonQt::init(int flags)
59 {
60 {
60 if (!_self) {
61 if (!_self) {
61 _self = new PythonQt(flags);
62 _self = new PythonQt(flags);
62 }
63 }
63
64
64 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
65 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
65 qRegisterMetaType<QList<QObject*> >("QList<void*>");
66 qRegisterMetaType<QList<QObject*> >("QList<void*>");
66
67
67 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
68 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
68
69
69 PythonQt::priv()->addVariantWrapper("QBitArray", new PythonQtQBitArrayWrapper);
70 PythonQt::priv()->addVariantWrapper("QBitArray", new PythonQtQBitArrayWrapper);
70 PythonQt::priv()->addVariantWrapper("QDate", new PythonQtQDateWrapper);
71 PythonQt::priv()->addVariantWrapper("QDate", new PythonQtQDateWrapper);
71 PythonQt::priv()->addVariantWrapper("QTime", new PythonQtQTimeWrapper);
72 PythonQt::priv()->addVariantWrapper("QTime", new PythonQtQTimeWrapper);
72 PythonQt::priv()->addVariantWrapper("QDateTime", new PythonQtQDateTimeWrapper);
73 PythonQt::priv()->addVariantWrapper("QDateTime", new PythonQtQDateTimeWrapper);
73 PythonQt::priv()->addVariantWrapper("QUrl", new PythonQtQUrlWrapper);
74 PythonQt::priv()->addVariantWrapper("QUrl", new PythonQtQUrlWrapper);
74 PythonQt::priv()->addVariantWrapper("QLocale", new PythonQtQLocaleWrapper);
75 PythonQt::priv()->addVariantWrapper("QLocale", new PythonQtQLocaleWrapper);
75 PythonQt::priv()->addVariantWrapper("QRect", new PythonQtQRectWrapper);
76 PythonQt::priv()->addVariantWrapper("QRect", new PythonQtQRectWrapper);
76 PythonQt::priv()->addVariantWrapper("QRectF", new PythonQtQRectFWrapper);
77 PythonQt::priv()->addVariantWrapper("QRectF", new PythonQtQRectFWrapper);
77 PythonQt::priv()->addVariantWrapper("QSize", new PythonQtQSizeWrapper);
78 PythonQt::priv()->addVariantWrapper("QSize", new PythonQtQSizeWrapper);
78 PythonQt::priv()->addVariantWrapper("QSizeF", new PythonQtQSizeFWrapper);
79 PythonQt::priv()->addVariantWrapper("QSizeF", new PythonQtQSizeFWrapper);
79 PythonQt::priv()->addVariantWrapper("QLine", new PythonQtQLineWrapper);
80 PythonQt::priv()->addVariantWrapper("QLine", new PythonQtQLineWrapper);
80 PythonQt::priv()->addVariantWrapper("QLineF", new PythonQtQLineFWrapper);
81 PythonQt::priv()->addVariantWrapper("QLineF", new PythonQtQLineFWrapper);
81 PythonQt::priv()->addVariantWrapper("QPoint", new PythonQtQPointWrapper);
82 PythonQt::priv()->addVariantWrapper("QPoint", new PythonQtQPointWrapper);
82 PythonQt::priv()->addVariantWrapper("QPointF", new PythonQtQPointFWrapper);
83 PythonQt::priv()->addVariantWrapper("QPointF", new PythonQtQPointFWrapper);
83 PythonQt::priv()->addVariantWrapper("QRegExp", new PythonQtQRegExpWrapper);
84 PythonQt::priv()->addVariantWrapper("QRegExp", new PythonQtQRegExpWrapper);
84 PythonQt::priv()->addVariantWrapper("QFont", new PythonQtQFontWrapper);
85 PythonQt::priv()->addVariantWrapper("QFont", new PythonQtQFontWrapper);
85 PythonQt::priv()->addVariantWrapper("QPixmap", new PythonQtQPixmapWrapper);
86 PythonQt::priv()->addVariantWrapper("QPixmap", new PythonQtQPixmapWrapper);
86 PythonQt::priv()->addVariantWrapper("QBrush", new PythonQtQBrushWrapper);
87 PythonQt::priv()->addVariantWrapper("QBrush", new PythonQtQBrushWrapper);
87 PythonQt::priv()->addVariantWrapper("QColor", new PythonQtQColorWrapper);
88 PythonQt::priv()->addVariantWrapper("QColor", new PythonQtQColorWrapper);
88 PythonQt::priv()->addVariantWrapper("QPalette", new PythonQtQPaletteWrapper);
89 PythonQt::priv()->addVariantWrapper("QPalette", new PythonQtQPaletteWrapper);
89 PythonQt::priv()->addVariantWrapper("QIcon", new PythonQtQIconWrapper);
90 PythonQt::priv()->addVariantWrapper("QIcon", new PythonQtQIconWrapper);
90 PythonQt::priv()->addVariantWrapper("QImage", new PythonQtQImageWrapper);
91 PythonQt::priv()->addVariantWrapper("QImage", new PythonQtQImageWrapper);
91 PythonQt::priv()->addVariantWrapper("QPolygon", new PythonQtQPolygonWrapper);
92 PythonQt::priv()->addVariantWrapper("QPolygon", new PythonQtQPolygonWrapper);
92 PythonQt::priv()->addVariantWrapper("QRegion", new PythonQtQRegionWrapper);
93 PythonQt::priv()->addVariantWrapper("QRegion", new PythonQtQRegionWrapper);
93 PythonQt::priv()->addVariantWrapper("QBitmap", new PythonQtQBitmapWrapper);
94 PythonQt::priv()->addVariantWrapper("QBitmap", new PythonQtQBitmapWrapper);
94 PythonQt::priv()->addVariantWrapper("QCursor", new PythonQtQCursorWrapper);
95 PythonQt::priv()->addVariantWrapper("QCursor", new PythonQtQCursorWrapper);
95 PythonQt::priv()->addVariantWrapper("QSizePolicy", new PythonQtQSizePolicyWrapper);
96 PythonQt::priv()->addVariantWrapper("QSizePolicy", new PythonQtQSizePolicyWrapper);
96 PythonQt::priv()->addVariantWrapper("QKeySequence", new PythonQtQKeySequenceWrapper);
97 PythonQt::priv()->addVariantWrapper("QKeySequence", new PythonQtQKeySequenceWrapper);
97 PythonQt::priv()->addVariantWrapper("QPen", new PythonQtQPenWrapper);
98 PythonQt::priv()->addVariantWrapper("QPen", new PythonQtQPenWrapper);
98 PythonQt::priv()->addVariantWrapper("QTextLength", new PythonQtQTextLengthWrapper);
99 PythonQt::priv()->addVariantWrapper("QTextLength", new PythonQtQTextLengthWrapper);
99 PythonQt::priv()->addVariantWrapper("QTextFormat", new PythonQtQTextFormatWrapper);
100 PythonQt::priv()->addVariantWrapper("QTextFormat", new PythonQtQTextFormatWrapper);
100 PythonQt::priv()->addVariantWrapper("QMatrix", new PythonQtQMatrixWrapper);
101 PythonQt::priv()->addVariantWrapper("QMatrix", new PythonQtQMatrixWrapper);
101
102
102 }
103 }
103
104
104 void PythonQt::cleanup()
105 void PythonQt::cleanup()
105 {
106 {
106 if (_self) {
107 if (_self) {
107 delete _self;
108 delete _self;
108 _self = NULL;
109 _self = NULL;
109 }
110 }
110 }
111 }
111
112
112 PythonQt::PythonQt(int flags)
113 PythonQt::PythonQt(int flags)
113 {
114 {
114 _p = new PythonQtPrivate;
115 _p = new PythonQtPrivate;
115 _p->_initFlags = flags;
116 _p->_initFlags = flags;
116
117
117 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
118 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
118
119
119 Py_SetProgramName("PythonQt");
120 Py_SetProgramName("PythonQt");
120 if (flags & IgnoreSiteModule) {
121 if (flags & IgnoreSiteModule) {
121 // this prevents the automatic importing of Python site files
122 // this prevents the automatic importing of Python site files
122 Py_NoSiteFlag = 1;
123 Py_NoSiteFlag = 1;
123 }
124 }
124 Py_Initialize();
125 Py_Initialize();
125
126
126 // add our own python object types for qt object slots
127 // add our own python object types for qt object slots
127 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
128 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
128 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
129 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
129 }
130 }
130 Py_INCREF(&PythonQtSlotFunction_Type);
131 Py_INCREF(&PythonQtSlotFunction_Type);
131
132
132 // add our own python object types for qt objects
133 // add our own python object types for qt objects
133 if (PyType_Ready(&PythonQtWrapper_Type) < 0) {
134 if (PyType_Ready(&PythonQtWrapper_Type) < 0) {
134 std::cerr << "could not initialize PythonQtWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
135 std::cerr << "could not initialize PythonQtWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
135 }
136 }
136 Py_INCREF(&PythonQtWrapper_Type);
137 Py_INCREF(&PythonQtWrapper_Type);
137
138
138 // add our own python object types for qt objects
139 // add our own python object types for qt objects
139 if (PyType_Ready(&PythonQtVariantWrapper_Type) < 0) {
140 if (PyType_Ready(&PythonQtVariantWrapper_Type) < 0) {
140 std::cerr << "could not initialize PythonQtVariantWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
141 std::cerr << "could not initialize PythonQtVariantWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
141 }
142 }
142 Py_INCREF(&PythonQtVariantWrapper_Type);
143 Py_INCREF(&PythonQtVariantWrapper_Type);
143
144
144 // add our own python object types for qt objects
145 // add our own python object types for qt objects
145 if (PyType_Ready(&PythonQtMetaObjectWrapper_Type) < 0) {
146 if (PyType_Ready(&PythonQtMetaObjectWrapper_Type) < 0) {
146 std::cerr << "could not initialize PythonQtMetaObjectWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
147 std::cerr << "could not initialize PythonQtMetaObjectWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
147 }
148 }
148 Py_INCREF(&PythonQtMetaObjectWrapper_Type);
149 Py_INCREF(&PythonQtMetaObjectWrapper_Type);
149
150
150 // add our own python object types for redirection of stdout
151 // add our own python object types for redirection of stdout
151 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
152 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
152 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
153 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
153 }
154 }
154 Py_INCREF(&PythonQtStdOutRedirectType);
155 Py_INCREF(&PythonQtStdOutRedirectType);
155
156
156 initPythonQtModule(flags & RedirectStdOut);
157 initPythonQtModule(flags & RedirectStdOut);
157
158
158 }
159 }
159
160
160 PythonQt::~PythonQt() {
161 PythonQt::~PythonQt() {
161 delete _p;
162 delete _p;
162 _p = NULL;
163 _p = NULL;
163 }
164 }
164
165
165 PythonQtPrivate::~PythonQtPrivate() {
166 PythonQtPrivate::~PythonQtPrivate() {
167 delete _defaultImporter;
168 _defaultImporter = NULL;
169 {
170 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_knownQtDecoratorSlots);
171 while (i.hasNext()) {
172 delete i.next().value();
173 }
174 }
166 {
175 {
167 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownQtClasses);
176 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownQtClasses);
168 while (i.hasNext()) {
177 while (i.hasNext()) {
169 delete i.next().value();
178 delete i.next().value();
170 }
179 }
171 }
180 }
172 {
181 {
173 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownQtWrapperClasses);
182 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownQtWrapperClasses);
174 while (i.hasNext()) {
183 while (i.hasNext()) {
175 delete i.next().value();
184 delete i.next().value();
176 }
185 }
177 }
186 }
178 {
187 {
179 QHashIterator<int , QPair<PythonQtClassInfo*, QObject*> > i(_knownVariantWrappers);
188 QHashIterator<int , QPair<PythonQtClassInfo*, QObject*> > i(_knownVariantWrappers);
180 while (i.hasNext()) {
189 while (i.hasNext()) {
181 delete i.next().value().first;
190 delete i.next().value().first;
182 }
191 }
183 }
192 }
184 {
193 {
185 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_constructorSlots);
194 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_constructorSlots);
186 while (i.hasNext()) {
195 while (i.hasNext()) {
187 delete i.next().value();
196 PythonQtSlotInfo* cur = i.next().value();
197 while(cur->nextInfo()) {
198 PythonQtSlotInfo* next = cur->nextInfo();
199 delete cur;
200 cur = next;
201 }
202 delete cur;
188 }
203 }
189 }
204 }
190 {
205 {
191 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_destructorSlots);
206 QHashIterator<QByteArray, PythonQtSlotInfo *> i(_destructorSlots);
192 while (i.hasNext()) {
207 while (i.hasNext()) {
193 delete i.next().value();
208 PythonQtSlotInfo* cur = i.next().value();
209 while(cur->nextInfo()) {
210 PythonQtSlotInfo* next = cur->nextInfo();
211 delete cur;
212 cur = next;
213 }
214 delete cur;
194 }
215 }
195 }
216 }
196 PythonQtConv::global_valueStorage.clear();
217 PythonQtConv::global_valueStorage.clear();
197 PythonQtConv::global_ptrStorage.clear();
218 PythonQtConv::global_ptrStorage.clear();
198 PythonQtConv::global_variantStorage.clear();
219 PythonQtConv::global_variantStorage.clear();
199
220
200 PythonQtMethodInfo::cleanupCachedMethodInfos();
221 PythonQtMethodInfo::cleanupCachedMethodInfos();
201
222
202 delete _qtNamespace;
223 delete _qtNamespace;
203 }
224 }
204
225
205 PythonQtImportFileInterface* PythonQt::importInterface()
226 PythonQtImportFileInterface* PythonQt::importInterface()
206 {
227 {
207 return _self->_p->_importInterface;
228 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
208 }
229 }
209
230
210 void PythonQt::registerClass(const QMetaObject* metaobject)
231 void PythonQt::registerClass(const QMetaObject* metaobject)
211 {
232 {
212 _p->registerClass(metaobject);
233 _p->registerClass(metaobject);
213 }
234 }
214
235
215 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
236 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
216 {
237 {
217 if (_self->_p->_noLongerWrappedCB) {
238 if (_self->_p->_noLongerWrappedCB) {
218 (*_self->_p->_noLongerWrappedCB)(o);
239 (*_self->_p->_noLongerWrappedCB)(o);
219 };
240 };
220 }
241 }
221
242
222 void PythonQtPrivate::registerClass(const QMetaObject* metaobject)
243 void PythonQtPrivate::registerClass(const QMetaObject* metaobject)
223 {
244 {
224 // we register all classes in the hierarchy
245 // we register all classes in the hierarchy
225 const QMetaObject* m = metaobject;
246 const QMetaObject* m = metaobject;
226 while (m) {
247 while (m) {
227 PythonQtClassInfo* info = _knownQtClasses.value(m->className());
248 PythonQtClassInfo* info = _knownQtClasses.value(m->className());
228 if (!info) {
249 if (!info) {
229 info = new PythonQtClassInfo(m);
250 info = new PythonQtClassInfo(m);
230 _knownQtClasses.insert(m->className(), info);
251 _knownQtClasses.insert(m->className(), info);
231 PyModule_AddObject(_pythonQtModule, m->className(), (PyObject*)createNewPythonQtMetaObjectWrapper(info));
252 PyModule_AddObject(_pythonQtModule, m->className(), (PyObject*)createNewPythonQtMetaObjectWrapper(info));
232 }
253 }
233 m = m->superClass();
254 m = m->superClass();
234 }
255 }
235 }
256 }
236
257
237 bool PythonQtPrivate::isEnumType(const QMetaObject* meta, const QByteArray& name) {
258 bool PythonQtPrivate::isEnumType(const QMetaObject* meta, const QByteArray& name) {
238 int i = meta?meta->indexOfEnumerator(name.constData()):-1;
259 int i = meta?meta->indexOfEnumerator(name.constData()):-1;
239 if (i!=-1) {
260 if (i!=-1) {
240 return true;
261 return true;
241 } else {
262 } else {
242 // look for scope
263 // look for scope
243 int scopePos = name.indexOf("::");
264 int scopePos = name.indexOf("::");
244 if (scopePos != -1) {
265 if (scopePos != -1) {
245 // slit into scope and enum name
266 // slit into scope and enum name
246 QByteArray enumScope = name.mid(0,scopePos);
267 QByteArray enumScope = name.mid(0,scopePos);
247 QByteArray enumName = name.mid(scopePos+2);
268 QByteArray enumName = name.mid(scopePos+2);
248 if (enumScope == "Qt") {
269 if (enumScope == "Qt") {
249 // special qt namespace case
270 // special qt namespace case
250 return isEnumType(&staticQtMetaObject, enumName);
271 return isEnumType(&staticQtMetaObject, enumName);
251 } else {
272 } else {
252 // look for known classes as scope
273 // look for known classes as scope
253 // TODO: Q_GADGETS are not yet handled
274 // TODO: Q_GADGETS are not yet handled
254 PythonQtClassInfo* info = _knownQtClasses.value(enumScope);
275 PythonQtClassInfo* info = _knownQtClasses.value(enumScope);
255 if (info) {
276 if (info) {
256 return isEnumType(info->metaObject(), enumName);
277 return isEnumType(info->metaObject(), enumName);
257 }
278 }
258 }
279 }
259 }
280 }
260 }
281 }
261 return false;
282 return false;
262 }
283 }
263
284
264 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
285 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
265 {
286 {
266 if (!obj) {
287 if (!obj) {
267 Py_INCREF(Py_None);
288 Py_INCREF(Py_None);
268 return Py_None;
289 return Py_None;
269 }
290 }
270 PythonQtWrapper* wrap = findWrapperAndRemoveUnused(obj);
291 PythonQtWrapper* wrap = findWrapperAndRemoveUnused(obj);
271 if (!wrap) {
292 if (!wrap) {
272 // smuggling it in...
293 // smuggling it in...
273 PythonQtClassInfo* classInfo = _knownQtClasses.value(obj->metaObject()->className());
294 PythonQtClassInfo* classInfo = _knownQtClasses.value(obj->metaObject()->className());
274 if (!classInfo) {
295 if (!classInfo) {
275 registerClass(obj->metaObject());
296 registerClass(obj->metaObject());
276 classInfo = _knownQtClasses.value(obj->metaObject()->className());
297 classInfo = _knownQtClasses.value(obj->metaObject()->className());
277 }
298 }
278 wrap = createNewPythonQtWrapper(obj, classInfo);
299 wrap = createNewPythonQtWrapper(obj, classInfo);
279 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
300 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
280 } else {
301 } else {
281 Py_INCREF(wrap);
302 Py_INCREF(wrap);
282 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
303 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
283 }
304 }
284 return (PyObject*)wrap;
305 return (PyObject*)wrap;
285 }
306 }
286
307
287 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
308 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
288 {
309 {
289 if (!ptr) {
310 if (!ptr) {
290 Py_INCREF(Py_None);
311 Py_INCREF(Py_None);
291 return Py_None;
312 return Py_None;
292 }
313 }
293 PythonQtWrapper* wrap = findWrapperAndRemoveUnused(ptr);
314 PythonQtWrapper* wrap = findWrapperAndRemoveUnused(ptr);
294 if (!wrap) {
315 if (!wrap) {
295 PythonQtClassInfo* info = _knownQtClasses.value(name);
316 PythonQtClassInfo* info = _knownQtClasses.value(name);
296 if (!info) {
317 if (!info) {
297 // we do not know the metaobject yet, but we might know it by it's name:
318 // we do not know the metaobject yet, but we might know it by it's name:
298 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
319 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
299 // yes, we know it, so we can convert to QObject
320 // yes, we know it, so we can convert to QObject
300 QObject* qptr = (QObject*)ptr;
321 QObject* qptr = (QObject*)ptr;
301 registerClass(qptr->metaObject());
322 registerClass(qptr->metaObject());
302 info = _knownQtClasses.value(qptr->metaObject()->className());
323 info = _knownQtClasses.value(qptr->metaObject()->className());
303 }
324 }
304 }
325 }
305 if (info) {
326 if (info) {
306 QObject* qptr = (QObject*)ptr;
327 QObject* qptr = (QObject*)ptr;
307 // if the object is a derived object, we want to switch the class info to the one of the derived class:
328 // if the object is a derived object, we want to switch the class info to the one of the derived class:
308 if (name!=(qptr->metaObject()->className())) {
329 if (name!=(qptr->metaObject()->className())) {
309 registerClass(qptr->metaObject());
330 registerClass(qptr->metaObject());
310 info = _knownQtClasses.value(qptr->metaObject()->className());
331 info = _knownQtClasses.value(qptr->metaObject()->className());
311 }
332 }
312 wrap = createNewPythonQtWrapper(qptr, info);
333 wrap = createNewPythonQtWrapper(qptr, info);
313 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
334 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
314 } else {
335 } else {
315 // maybe it is a PyObject, which we can return directly
336 // maybe it is a PyObject, which we can return directly
316 if (name == "PyObject") {
337 if (name == "PyObject") {
317 PyObject* p = (PyObject*)ptr;
338 PyObject* p = (PyObject*)ptr;
318 Py_INCREF(p);
339 Py_INCREF(p);
319 return p;
340 return p;
320 }
341 }
321 // not a known QObject, so try our wrapper factory:
342 // not a known QObject, so try our wrapper factory:
322 QObject* wrapper = NULL;
343 QObject* wrapper = NULL;
323 for (int i=0; i<_cppWrapperFactories.size(); i++) {
344 for (int i=0; i<_cppWrapperFactories.size(); i++) {
324 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
345 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
325 if (wrapper) {
346 if (wrapper) {
326 break;
347 break;
327 }
348 }
328 }
349 }
329 PythonQtClassInfo* info = _knownQtWrapperClasses.value(name);
350 PythonQtClassInfo* info = _knownQtWrapperClasses.value(name);
330 if (!info) {
351 if (!info) {
331 info = new PythonQtClassInfo(wrapper?wrapper->metaObject():&QObject::staticQtMetaObject, name);
352 info = new PythonQtClassInfo(wrapper?wrapper->metaObject():&QObject::staticQtMetaObject, name);
332 _knownQtWrapperClasses.insert(name, info);
353 _knownQtWrapperClasses.insert(name, info);
333 PyModule_AddObject(_pythonQtModule, name, (PyObject*)createNewPythonQtMetaObjectWrapper(info));
354 PyModule_AddObject(_pythonQtModule, name, (PyObject*)createNewPythonQtMetaObjectWrapper(info));
334 } else {
355 } else {
335 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
356 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
336 info->setMetaObject(wrapper->metaObject());
357 info->setMetaObject(wrapper->metaObject());
337 }
358 }
338 }
359 }
339 wrap = createNewPythonQtWrapper(wrapper, info, ptr);
360 wrap = createNewPythonQtWrapper(wrapper, info, ptr);
340 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
361 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
341 }
362 }
342 } else {
363 } else {
343 Py_INCREF(wrap);
364 Py_INCREF(wrap);
344 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
365 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->_info->wrappedClassName().latin1());
345 }
366 }
346 return (PyObject*)wrap;
367 return (PyObject*)wrap;
347 }
368 }
348
369
349 void PythonQt::registerCPPClassNames(const QStringList& names)
370 void PythonQt::registerCPPClassNames(const QStringList& names)
350 {
371 {
351 foreach ( QString n, names) {
372 foreach ( QString n, names) {
352 QByteArray name = n.toLatin1();
373 QByteArray name = n.toLatin1();
353 PythonQtClassInfo* info = _p->_knownQtWrapperClasses.value(name);
374 PythonQtClassInfo* info = _p->_knownQtWrapperClasses.value(name);
354 if (!info) {
375 if (!info) {
355 info = new PythonQtClassInfo(&QObject::staticMetaObject, name);
376 info = new PythonQtClassInfo(&QObject::staticMetaObject, name);
356 _p->_knownQtWrapperClasses.insert(name, info);
377 _p->_knownQtWrapperClasses.insert(name, info);
357 PyModule_AddObject(_p->_pythonQtModule, name.data(), (PyObject*)_p->createNewPythonQtMetaObjectWrapper(info));
378 PyModule_AddObject(_p->_pythonQtModule, name.data(), (PyObject*)_p->createNewPythonQtMetaObjectWrapper(info));
358 }
379 }
359 }
380 }
360 }
381 }
361
382
362 PythonQtWrapper* PythonQtPrivate::createNewPythonQtWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
383 PythonQtWrapper* PythonQtPrivate::createNewPythonQtWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
363 PythonQtWrapper* result;
384 PythonQtWrapper* result;
364 result = (PythonQtWrapper *)PythonQtWrapper_Type.tp_new(&PythonQtWrapper_Type,
385 result = (PythonQtWrapper *)PythonQtWrapper_Type.tp_new(&PythonQtWrapper_Type,
365 NULL, NULL);
386 NULL, NULL);
366
387
367 result->setQObject(obj);
388 result->setQObject(obj);
368 result->_info = info;
389 result->_info = info;
369 result->_wrappedPtr = wrappedPtr;
390 result->_wrappedPtr = wrappedPtr;
370 result->_ownedByPythonQt = false;
391 result->_ownedByPythonQt = false;
371
392
372 if (wrappedPtr) {
393 if (wrappedPtr) {
373 _wrappedObjects.insert(wrappedPtr, result);
394 _wrappedObjects.insert(wrappedPtr, result);
374 } else {
395 } else {
375 _wrappedObjects.insert(obj, result);
396 _wrappedObjects.insert(obj, result);
376 if (obj->parent()== NULL && _wrappedCB) {
397 if (obj->parent()== NULL && _wrappedCB) {
377 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
398 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
378 (*_wrappedCB)(obj);
399 (*_wrappedCB)(obj);
379 }
400 }
380 }
401 }
381 return result;
402 return result;
382 }
403 }
383
404
384 PythonQtVariantWrapper* PythonQtPrivate::createNewPythonQtVariantWrapper(const QVariant& variant) {
405 PythonQtVariantWrapper* PythonQtPrivate::createNewPythonQtVariantWrapper(const QVariant& variant) {
385 PythonQtVariantWrapper* result;
406 PythonQtVariantWrapper* result;
386 result = (PythonQtVariantWrapper *)PythonQtVariantWrapper_Type.tp_new(&PythonQtVariantWrapper_Type,
407 result = (PythonQtVariantWrapper *)PythonQtVariantWrapper_Type.tp_new(&PythonQtVariantWrapper_Type,
387 NULL, NULL);
408 NULL, NULL);
388
409
389 *result->_variant = variant;
410 *result->_variant = variant;
390 QPair<PythonQtClassInfo*, QObject*> pair = _knownVariantWrappers.value(variant.userType());
411 QPair<PythonQtClassInfo*, QObject*> pair = _knownVariantWrappers.value(variant.userType());
391 result->_wrapper = pair.second;
412 result->_wrapper = pair.second;
392 result->_info = pair.first;
413 result->_info = pair.first;
393 return result;
414 return result;
394 }
415 }
395
416
396 PythonQtMetaObjectWrapper* PythonQtPrivate::createNewPythonQtMetaObjectWrapper(PythonQtClassInfo* info) {
417 PythonQtMetaObjectWrapper* PythonQtPrivate::createNewPythonQtMetaObjectWrapper(PythonQtClassInfo* info) {
397 PythonQtMetaObjectWrapper* result;
418 PythonQtMetaObjectWrapper* result;
398 result = (PythonQtMetaObjectWrapper *)PythonQtMetaObjectWrapper_Type.tp_new(&PythonQtMetaObjectWrapper_Type,
419 result = (PythonQtMetaObjectWrapper *)PythonQtMetaObjectWrapper_Type.tp_new(&PythonQtMetaObjectWrapper_Type,
399 NULL, NULL);
420 NULL, NULL);
400 result->_info = info;
421 result->_info = info;
401 return result;
422 return result;
402 }
423 }
403
424
404
425
405 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
426 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
406 {
427 {
407 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
428 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
408 if (!r) {
429 if (!r) {
409 r = new PythonQtSignalReceiver(obj);
430 r = new PythonQtSignalReceiver(obj);
410 _p->_signalReceivers.insert(obj, r);
431 _p->_signalReceivers.insert(obj, r);
411 }
432 }
412 return r;
433 return r;
413 }
434 }
414
435
415 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
436 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
416 {
437 {
417 bool flag = false;
438 bool flag = false;
418 PythonQtObjectPtr callable = lookupCallable(module, objectname);
439 PythonQtObjectPtr callable = lookupCallable(module, objectname);
419 if (callable) {
440 if (callable) {
420 PythonQtSignalReceiver* r = getSignalReceiver(obj);
441 PythonQtSignalReceiver* r = getSignalReceiver(obj);
421 flag = r->addSignalHandler(signal, callable);
442 flag = r->addSignalHandler(signal, callable);
422 if (!flag) {
443 if (!flag) {
423 // signal not found
444 // signal not found
424 }
445 }
425 } else {
446 } else {
426 // callable not found
447 // callable not found
427 }
448 }
428 return flag;
449 return flag;
429 }
450 }
430
451
431 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
452 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
432 {
453 {
433 bool flag = false;
454 bool flag = false;
434 PythonQtSignalReceiver* r = getSignalReceiver(obj);
455 PythonQtSignalReceiver* r = getSignalReceiver(obj);
435 if (r) {
456 if (r) {
436 flag = r->addSignalHandler(signal, receiver);
457 flag = r->addSignalHandler(signal, receiver);
437 }
458 }
438 return flag;
459 return flag;
439 }
460 }
440
461
441 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
462 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
442 {
463 {
443 bool flag = false;
464 bool flag = false;
444 PythonQtObjectPtr callable = lookupCallable(module, objectname);
465 PythonQtObjectPtr callable = lookupCallable(module, objectname);
445 if (callable) {
466 if (callable) {
446 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
467 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
447 if (r) {
468 if (r) {
448 flag = r->removeSignalHandler(signal, callable);
469 flag = r->removeSignalHandler(signal, callable);
449 }
470 }
450 } else {
471 } else {
451 // callable not found
472 // callable not found
452 }
473 }
453 return flag;
474 return flag;
454 }
475 }
455
476
456 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
477 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
457 {
478 {
458 bool flag = false;
479 bool flag = false;
459 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
480 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
460 if (r) {
481 if (r) {
461 flag = r->removeSignalHandler(signal, receiver);
482 flag = r->removeSignalHandler(signal, receiver);
462 }
483 }
463 return flag;
484 return flag;
464 }
485 }
465
486
466 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
487 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
467 {
488 {
468 PythonQtObjectPtr p = lookupObject(module, name);
489 PythonQtObjectPtr p = lookupObject(module, name);
469 if (p) {
490 if (p) {
470 if (PyCallable_Check(p)) {
491 if (PyCallable_Check(p)) {
471 return p;
492 return p;
472 }
493 }
473 }
494 }
474 PyErr_Clear();
495 PyErr_Clear();
475 return NULL;
496 return NULL;
476 }
497 }
477
498
478 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
499 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
479 {
500 {
480 QStringList l = name.split('.');
501 QStringList l = name.split('.');
481 PythonQtObjectPtr p = module;
502 PythonQtObjectPtr p = module;
482 PythonQtObjectPtr prev;
503 PythonQtObjectPtr prev;
483 QString s;
504 QString s;
484 QByteArray b;
505 QByteArray b;
485 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
506 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
486 prev = p;
507 prev = p;
487 b = (*i).toLatin1();
508 b = (*i).toLatin1();
488 p.setNewRef(PyObject_GetAttrString(p, b.data()));
509 p.setNewRef(PyObject_GetAttrString(p, b.data()));
489 }
510 }
490 PyErr_Clear();
511 PyErr_Clear();
491 return p;
512 return p;
492 }
513 }
493
514
494 PythonQtObjectPtr PythonQt::getMainModule() {
515 PythonQtObjectPtr PythonQt::getMainModule() {
495 //both borrowed
516 //both borrowed
496 PythonQtObjectPtr dict = PyImport_GetModuleDict();
517 PythonQtObjectPtr dict = PyImport_GetModuleDict();
497 return PyDict_GetItemString(dict, "__main__");
518 return PyDict_GetItemString(dict, "__main__");
498 }
519 }
499
520
500 QVariant PythonQt::evalCode(PyObject* module, PyObject* pycode) {
521 QVariant PythonQt::evalCode(PyObject* module, PyObject* pycode) {
501 QVariant result;
522 QVariant result;
502 if (pycode) {
523 if (pycode) {
503 PyObject* r = PyEval_EvalCode((PyCodeObject*)pycode, PyModule_GetDict((PyObject*)module) , PyModule_GetDict((PyObject*)module));
524 PyObject* r = PyEval_EvalCode((PyCodeObject*)pycode, PyModule_GetDict((PyObject*)module) , PyModule_GetDict((PyObject*)module));
504 if (r) {
525 if (r) {
505 result = PythonQtConv::PyObjToQVariant(r);
526 result = PythonQtConv::PyObjToQVariant(r);
506 Py_DECREF(r);
527 Py_DECREF(r);
507 } else {
528 } else {
508 handleError();
529 handleError();
509 }
530 }
510 } else {
531 } else {
511 handleError();
532 handleError();
512 }
533 }
513 return result;
534 return result;
514 }
535 }
515
536
516 QVariant PythonQt::evalScript(PyObject* module, const QString& script, int start)
537 QVariant PythonQt::evalScript(PyObject* module, const QString& script, int start)
517 {
538 {
518 QVariant result;
539 QVariant result;
519 PythonQtObjectPtr p;
540 PythonQtObjectPtr p;
520 p.setNewRef(PyRun_String(script.toLatin1().data(), start, PyModule_GetDict(module), PyModule_GetDict(module)));
541 p.setNewRef(PyRun_String(script.toLatin1().data(), start, PyModule_GetDict(module), PyModule_GetDict(module)));
521 if (p) {
542 if (p) {
522 result = PythonQtConv::PyObjToQVariant(p);
543 result = PythonQtConv::PyObjToQVariant(p);
523 } else {
544 } else {
524 handleError();
545 handleError();
525 }
546 }
526 return result;
547 return result;
527 }
548 }
528
549
529 void PythonQt::evalFile(PyObject* module, const QString& filename)
550 void PythonQt::evalFile(PyObject* module, const QString& filename)
530 {
551 {
531 PythonQtObjectPtr code = parseFile(filename);
552 PythonQtObjectPtr code = parseFile(filename);
532 if (code) {
553 if (code) {
533 evalCode(module, code);
554 evalCode(module, code);
534 } else {
555 } else {
535 handleError();
556 handleError();
536 }
557 }
537 }
558 }
538
559
539 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
560 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
540 {
561 {
541 PythonQtObjectPtr p;
562 PythonQtObjectPtr p;
542 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
563 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
543 if (!p) {
564 if (!p) {
544 handleError();
565 handleError();
545 }
566 }
546 return p;
567 return p;
547 }
568 }
548
569
549 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
570 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
550 {
571 {
551 PythonQtObjectPtr code = parseFile(filename);
572 PythonQtObjectPtr code = parseFile(filename);
552 PythonQtObjectPtr module = _p->createModule(name, code);
573 PythonQtObjectPtr module = _p->createModule(name, code);
553 return module;
574 return module;
554 }
575 }
555
576
556 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
577 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
557 {
578 {
558 PyErr_Clear();
579 PyErr_Clear();
559 QString scriptCode = script;
580 QString scriptCode = script;
560 if (scriptCode.isEmpty()) {
581 if (scriptCode.isEmpty()) {
561 // we always need at least a linefeed
582 // we always need at least a linefeed
562 scriptCode = "\n";
583 scriptCode = "\n";
563 }
584 }
564 PythonQtObjectPtr pycode;
585 PythonQtObjectPtr pycode;
565 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
586 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
566 PythonQtObjectPtr module = _p->createModule(name, pycode);
587 PythonQtObjectPtr module = _p->createModule(name, pycode);
567 return module;
588 return module;
568 }
589 }
569
590
570 PythonQtObjectPtr PythonQt::createUniqueModule()
591 PythonQtObjectPtr PythonQt::createUniqueModule()
571 {
592 {
572 static QString pyQtStr("PythonQt_module");
593 static QString pyQtStr("PythonQt_module");
573 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
594 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
574 return createModuleFromScript(moduleName);
595 return createModuleFromScript(moduleName);
575 }
596 }
576
597
577 void PythonQt::addObject(PyObject* module, const QString& name, QObject* object)
598 void PythonQt::addObject(PyObject* module, const QString& name, QObject* object)
578 {
599 {
579 PyModule_AddObject(module, name.toLatin1().data(), _p->wrapQObject(object));
600 PyModule_AddObject(module, name.toLatin1().data(), _p->wrapQObject(object));
580 }
601 }
581
602
582 void PythonQt::addVariable(PyObject* module, const QString& name, const QVariant& v)
603 void PythonQt::addVariable(PyObject* module, const QString& name, const QVariant& v)
583 {
604 {
584 PyModule_AddObject(module, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
605 PyModule_AddObject(module, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
585 }
606 }
586
607
587 void PythonQt::removeVariable(PyObject* module, const QString& name)
608 void PythonQt::removeVariable(PyObject* module, const QString& name)
588 {
609 {
589 PyObject_DelAttrString(module, name.toLatin1().data());
610 PyObject_DelAttrString(module, name.toLatin1().data());
590 }
611 }
591
612
592 QVariant PythonQt::getVariable(PyObject* module, const QString& objectname)
613 QVariant PythonQt::getVariable(PyObject* module, const QString& objectname)
593 {
614 {
594 QVariant result;
615 QVariant result;
595 PythonQtObjectPtr obj = lookupObject(module, objectname);
616 PythonQtObjectPtr obj = lookupObject(module, objectname);
596 if (obj) {
617 if (obj) {
597 result = PythonQtConv::PyObjToQVariant(obj);
618 result = PythonQtConv::PyObjToQVariant(obj);
598 }
619 }
599 return result;
620 return result;
600 }
621 }
601
622
602 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
623 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
603 {
624 {
604 QStringList results;
625 QStringList results;
605
626
606 PythonQtObjectPtr object;
627 PythonQtObjectPtr object;
607 if (objectname.isEmpty()) {
628 if (objectname.isEmpty()) {
608 object = module;
629 object = module;
609 } else {
630 } else {
610 object = lookupObject(module, objectname);
631 object = lookupObject(module, objectname);
611 if (!object && type == CallOverloads) {
632 if (!object && type == CallOverloads) {
612 PyObject* dict = lookupObject(module, "__builtins__");
633 PyObject* dict = lookupObject(module, "__builtins__");
613 if (dict) {
634 if (dict) {
614 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
635 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
615 }
636 }
616 }
637 }
617 }
638 }
618
639
619 if (object) {
640 if (object) {
620 if (type == CallOverloads) {
641 if (type == CallOverloads) {
621 if (PythonQtSlotFunction_Check(object)) {
642 if (PythonQtSlotFunction_Check(object)) {
622 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
643 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
623 PythonQtSlotInfo* info = o->m_ml;
644 PythonQtSlotInfo* info = o->m_ml;
624
645
625 while (info) {
646 while (info) {
626 results << info->fullSignature(info->isInstanceDecorator() || o->m_self->ob_type == &PythonQtVariantWrapper_Type);
647 results << info->fullSignature(info->isInstanceDecorator() || o->m_self->ob_type == &PythonQtVariantWrapper_Type);
627 info = info->nextInfo();
648 info = info->nextInfo();
628 }
649 }
629 } else if (object->ob_type == &PythonQtMetaObjectWrapper_Type) {
650 } else if (object->ob_type == &PythonQtMetaObjectWrapper_Type) {
630 PythonQtMetaObjectWrapper* o = (PythonQtMetaObjectWrapper*)object.object();
651 PythonQtMetaObjectWrapper* o = (PythonQtMetaObjectWrapper*)object.object();
631 PythonQtSlotInfo* info = o->_info->constructors();
652 PythonQtSlotInfo* info = o->_info->constructors();
632
653
633 while (info) {
654 while (info) {
634 results << info->fullSignature(false);
655 results << info->fullSignature(false);
635 info = info->nextInfo();
656 info = info->nextInfo();
636 }
657 }
637 } else {
658 } else {
638 //TODO: use pydoc!
659 //TODO: use pydoc!
639 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
660 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
640 if (doc) {
661 if (doc) {
641 results << PyString_AsString(doc);
662 results << PyString_AsString(doc);
642 Py_DECREF(doc);
663 Py_DECREF(doc);
643 }
664 }
644 }
665 }
645 } else {
666 } else {
646 PyObject* keys = PyObject_Dir(object);
667 PyObject* keys = PyObject_Dir(object);
647 if (keys) {
668 if (keys) {
648 int count = PyList_Size(keys);
669 int count = PyList_Size(keys);
649 PyObject* key;
670 PyObject* key;
650 PyObject* value;
671 PyObject* value;
651 QString keystr;
672 QString keystr;
652 for (int i = 0;i<count;i++) {
673 for (int i = 0;i<count;i++) {
653 key = PyList_GetItem(keys,i);
674 key = PyList_GetItem(keys,i);
654 value = PyObject_GetAttr(object, key);
675 value = PyObject_GetAttr(object, key);
655 if (!value) continue;
676 if (!value) continue;
656 keystr = PyString_AsString(key);
677 keystr = PyString_AsString(key);
657 static const QString underscoreStr("__tmp");
678 static const QString underscoreStr("__tmp");
658 if (!keystr.startsWith(underscoreStr)) {
679 if (!keystr.startsWith(underscoreStr)) {
659 switch (type) {
680 switch (type) {
660 case Anything:
681 case Anything:
661 results << keystr;
682 results << keystr;
662 break;
683 break;
663 case Class:
684 case Class:
664 if (value->ob_type == &PyClass_Type) {
685 if (value->ob_type == &PyClass_Type) {
665 results << keystr;
686 results << keystr;
666 }
687 }
667 break;
688 break;
668 case Variable:
689 case Variable:
669 if (value->ob_type != &PyClass_Type
690 if (value->ob_type != &PyClass_Type
670 && value->ob_type != &PyCFunction_Type
691 && value->ob_type != &PyCFunction_Type
671 && value->ob_type != &PyFunction_Type
692 && value->ob_type != &PyFunction_Type
672 && value->ob_type != &PyModule_Type
693 && value->ob_type != &PyModule_Type
673 ) {
694 ) {
674 results << keystr;
695 results << keystr;
675 }
696 }
676 break;
697 break;
677 case Function:
698 case Function:
678 if (value->ob_type == &PyFunction_Type ||
699 if (value->ob_type == &PyFunction_Type ||
679 value->ob_type == &PyMethod_Type
700 value->ob_type == &PyMethod_Type
680 ) {
701 ) {
681 results << keystr;
702 results << keystr;
682 }
703 }
683 break;
704 break;
684 case Module:
705 case Module:
685 if (value->ob_type == &PyModule_Type) {
706 if (value->ob_type == &PyModule_Type) {
686 results << keystr;
707 results << keystr;
687 }
708 }
688 break;
709 break;
689 default:
710 default:
690 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
711 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
691 }
712 }
692 }
713 }
693 Py_DECREF(value);
714 Py_DECREF(value);
694 }
715 }
695 Py_DECREF(keys);
716 Py_DECREF(keys);
696 }
717 }
697 }
718 }
698 }
719 }
699 return results;
720 return results;
700 }
721 }
701
722
702 QVariant PythonQt::call(PyObject* module, const QString& name, const QVariantList& args)
723 QVariant PythonQt::call(PyObject* module, const QString& name, const QVariantList& args)
703 {
724 {
704 QVariant r;
725 QVariant r;
705
726
706 PythonQtObjectPtr callable = lookupCallable(module, name);
727 PythonQtObjectPtr callable = lookupCallable(module, name);
707 if (callable) {
728 if (callable) {
708 PythonQtObjectPtr pargs;
729 PythonQtObjectPtr pargs;
709 int count = args.size();
730 int count = args.size();
710 if (count>0) {
731 if (count>0) {
711 pargs.setNewRef(PyTuple_New(count));
732 pargs.setNewRef(PyTuple_New(count));
712 }
733 }
713 bool err = false;
734 bool err = false;
714 // transform QVariants to Python
735 // transform QVariants to Python
715 for (int i = 0; i < count; i++) {
736 for (int i = 0; i < count; i++) {
716 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
737 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
717 if (arg) {
738 if (arg) {
718 // steals reference, no unref
739 // steals reference, no unref
719 PyTuple_SetItem(pargs, i,arg);
740 PyTuple_SetItem(pargs, i,arg);
720 } else {
741 } else {
721 err = true;
742 err = true;
722 break;
743 break;
723 }
744 }
724 }
745 }
725
746
726 if (!err) {
747 if (!err) {
727 PyErr_Clear();
748 PyErr_Clear();
728 PythonQtObjectPtr result;
749 PythonQtObjectPtr result;
729 result.setNewRef(PyObject_CallObject(callable, pargs));
750 result.setNewRef(PyObject_CallObject(callable, pargs));
730 if (result) {
751 if (result) {
731 // ok
752 // ok
732 r = PythonQtConv::PyObjToQVariant(result);
753 r = PythonQtConv::PyObjToQVariant(result);
733 } else {
754 } else {
734 PythonQt::self()->handleError();
755 PythonQt::self()->handleError();
735 }
756 }
736 }
757 }
737 }
758 }
738 return r;
759 return r;
739 }
760 }
740
761
741 void PythonQt::addInstanceDecorators(QObject* o)
762 void PythonQt::addInstanceDecorators(QObject* o)
742 {
763 {
743 _p->addDecorators(o, true, false);
764 _p->addDecorators(o, true, false);
744 }
765 }
745
766
746 void PythonQt::addClassDecorators(QObject* o)
767 void PythonQt::addClassDecorators(QObject* o)
747 {
768 {
748 _p->addDecorators(o, false, true);
769 _p->addDecorators(o, false, true);
749 }
770 }
750
771
751 void PythonQt::addDecorators(QObject* o)
772 void PythonQt::addDecorators(QObject* o)
752 {
773 {
753 _p->addDecorators(o, true, true);
774 _p->addDecorators(o, true, true);
754 }
775 }
755
776
756 void PythonQt::registerQObjectClassNames(const QStringList& names)
777 void PythonQt::registerQObjectClassNames(const QStringList& names)
757 {
778 {
758 _p->registerQObjectClassNames(names);
779 _p->registerQObjectClassNames(names);
759 }
780 }
760
781
761 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
782 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
762 {
783 {
763 static bool first = true;
784 PythonQtImport::init();
764 if (first) {
785 _p->_importInterface = importInterface;
765 first = false;
766 _p->_importInterface = importInterface;
767 PythonQtImport::init();
768 }
769 }
786 }
770
787
771 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
788 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
772 {
789 {
773 _p->_importIgnorePaths = paths;
790 _p->_importIgnorePaths = paths;
774 }
791 }
775
792
776 const QStringList& PythonQt::getImporterIgnorePaths()
793 const QStringList& PythonQt::getImporterIgnorePaths()
777 {
794 {
778 return _p->_importIgnorePaths;
795 return _p->_importIgnorePaths;
779 }
796 }
780
797
781 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
798 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
782 {
799 {
783 _p->_cppWrapperFactories.append(factory);
800 _p->_cppWrapperFactories.append(factory);
784 }
801 }
785
802
786 void PythonQt::addConstructorHandler(PythonQtConstructorHandler* factory)
803 void PythonQt::addConstructorHandler(PythonQtConstructorHandler* factory)
787 {
804 {
788 _p->_constructorHandlers.append(factory);
805 _p->_constructorHandlers.append(factory);
789 }
806 }
790
807
791 const QList<PythonQtConstructorHandler*>& PythonQt::constructorHandlers()
808 const QList<PythonQtConstructorHandler*>& PythonQt::constructorHandlers()
792 {
809 {
793 return _p->_constructorHandlers;
810 return _p->_constructorHandlers;
794 };
811 };
795
812
796 //---------------------------------------------------------------------------------------------------
813 //---------------------------------------------------------------------------------------------------
797 PythonQtPrivate::PythonQtPrivate()
814 PythonQtPrivate::PythonQtPrivate()
798 {
815 {
799 _importInterface = NULL;
816 _importInterface = NULL;
817 _defaultImporter = new PythonQtQFileImporter;
800 _noLongerWrappedCB = NULL;
818 _noLongerWrappedCB = NULL;
801 _wrappedCB = NULL;
819 _wrappedCB = NULL;
802 }
820 }
803
821
804 void PythonQtPrivate::addDecorators(QObject* o, bool instanceDeco, bool classDeco)
822 void PythonQtPrivate::addDecorators(QObject* o, bool instanceDeco, bool classDeco)
805 {
823 {
806 o->setParent(this);
824 o->setParent(this);
807 int numMethods = o->metaObject()->methodCount();
825 int numMethods = o->metaObject()->methodCount();
808 for (int i = 0; i < numMethods; i++) {
826 for (int i = 0; i < numMethods; i++) {
809 QMetaMethod m = o->metaObject()->method(i);
827 QMetaMethod m = o->metaObject()->method(i);
810 if ((m.methodType() == QMetaMethod::Method ||
828 if ((m.methodType() == QMetaMethod::Method ||
811 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
829 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
812 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m);
830 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m);
813 if (qstrncmp(m.signature(), "new_", 4)==0) {
831 if (qstrncmp(m.signature(), "new_", 4)==0) {
814 if (!classDeco) continue;
832 if (!classDeco) continue;
815 // either it returns a * or a QVariant and the name starts with "new_"
833 // either it returns a * or a QVariant and the name starts with "new_"
816 bool isVariantReturn = info->parameters().at(0).typeId == PythonQtMethodInfo::Variant;
834 bool isVariantReturn = info->parameters().at(0).typeId == PythonQtMethodInfo::Variant;
817 if ((info->parameters().at(0).isPointer || isVariantReturn)) {
835 if ((info->parameters().at(0).isPointer || isVariantReturn)) {
818 QByteArray signature = m.signature();
836 QByteArray signature = m.signature();
819 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
837 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
820 PythonQtSlotInfo* prev = _constructorSlots.value(nameOfClass);
838 PythonQtSlotInfo* prev = _constructorSlots.value(nameOfClass);
821 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
839 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
822 if (prev) {
840 if (prev) {
823 newSlot->setNextInfo(prev->nextInfo());
841 newSlot->setNextInfo(prev->nextInfo());
824 prev->setNextInfo(newSlot);
842 prev->setNextInfo(newSlot);
825 } else {
843 } else {
826 _constructorSlots.insert(nameOfClass, newSlot);
844 _constructorSlots.insert(nameOfClass, newSlot);
827 }
845 }
828 }
846 }
829 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
847 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
830 if (!classDeco) continue;
848 if (!classDeco) continue;
831 QByteArray signature = m.signature();
849 QByteArray signature = m.signature();
832 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
850 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
833 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
851 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
834 _destructorSlots.insert(nameOfClass, newSlot);
852 _destructorSlots.insert(nameOfClass, newSlot);
835 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
853 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
836 if (!classDeco) continue;
854 if (!classDeco) continue;
837 QByteArray signature = m.signature();
855 QByteArray signature = m.signature();
838 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
856 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
839 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
857 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
840 PythonQtSlotInfo* slotCopy = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
858 PythonQtSlotInfo* slotCopy = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::ClassDecorator);
841 _knownQtDecoratorSlots.insert(nameOfClass, slotCopy);
859 _knownQtDecoratorSlots.insert(nameOfClass, slotCopy);
842 } else {
860 } else {
843 if (!instanceDeco) continue;
861 if (!instanceDeco) continue;
844 if (info->parameters().count()>1) {
862 if (info->parameters().count()>1) {
845 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
863 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
846 if (p.isPointer) {
864 if (p.isPointer) {
847 PythonQtSlotInfo* slotCopy = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::InstanceDecorator);
865 PythonQtSlotInfo* slotCopy = new PythonQtSlotInfo(m, i, o, PythonQtSlotInfo::InstanceDecorator);
848 _knownQtDecoratorSlots.insert(p.name, slotCopy);
866 _knownQtDecoratorSlots.insert(p.name, slotCopy);
849 }
867 }
850 }
868 }
851 }
869 }
852 }
870 }
853 }
871 }
854 }
872 }
855
873
856 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
874 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
857 {
875 {
858 foreach(QString name, names) {
876 foreach(QString name, names) {
859 _knownQObjectClassNames.insert(name.toLatin1(), true);
877 _knownQObjectClassNames.insert(name.toLatin1(), true);
860 }
878 }
861 }
879 }
862
880
863 QList<PythonQtSlotInfo*> PythonQtPrivate::getDecoratorSlots(const QByteArray& className)
881 QList<PythonQtSlotInfo*> PythonQtPrivate::getDecoratorSlots(const QByteArray& className)
864 {
882 {
865 return _knownQtDecoratorSlots.values(className);
883 return _knownQtDecoratorSlots.values(className);
866 }
884 }
867
885
868 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
886 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
869 {
887 {
870 _signalReceivers.remove(obj);
888 _signalReceivers.remove(obj);
871 }
889 }
872
890
873 bool PythonQt::handleError()
891 bool PythonQt::handleError()
874 {
892 {
875 bool flag = false;
893 bool flag = false;
876 if (PyErr_Occurred()) {
894 if (PyErr_Occurred()) {
877
895
878 // currently we just print the error and the stderr handler parses the errors
896 // currently we just print the error and the stderr handler parses the errors
879 PyErr_Print();
897 PyErr_Print();
880
898
881 /*
899 /*
882 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
900 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
883 PyObject *ptype;
901 PyObject *ptype;
884 PyObject *pvalue;
902 PyObject *pvalue;
885 PyObject *ptraceback;
903 PyObject *ptraceback;
886 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
904 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
887
905
888 Py_XDECREF(ptype);
906 Py_XDECREF(ptype);
889 Py_XDECREF(pvalue);
907 Py_XDECREF(pvalue);
890 Py_XDECREF(ptraceback);
908 Py_XDECREF(ptraceback);
891 */
909 */
892 PyErr_Clear();
910 PyErr_Clear();
893 flag = true;
911 flag = true;
894 }
912 }
895 return flag;
913 return flag;
896 }
914 }
897
915
898 void PythonQt::overwriteSysPath(const QStringList& paths)
916 void PythonQt::overwriteSysPath(const QStringList& paths)
899 {
917 {
900 PythonQtObjectPtr sys;
918 PythonQtObjectPtr sys;
901 sys.setNewRef(PyImport_ImportModule("sys"));
919 sys.setNewRef(PyImport_ImportModule("sys"));
902 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
920 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
903 }
921 }
904
922
905 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
923 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
906 {
924 {
907 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
925 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
908 }
926 }
909
927
910 void PythonQt::stdOutRedirectCB(const QString& str)
928 void PythonQt::stdOutRedirectCB(const QString& str)
911 {
929 {
912 emit PythonQt::self()->pythonStdOut(str);
930 emit PythonQt::self()->pythonStdOut(str);
913 }
931 }
914
932
915 void PythonQt::stdErrRedirectCB(const QString& str)
933 void PythonQt::stdErrRedirectCB(const QString& str)
916 {
934 {
917 emit PythonQt::self()->pythonStdErr(str);
935 emit PythonQt::self()->pythonStdErr(str);
918 }
936 }
919
937
920 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
938 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
921 {
939 {
922 _p->_wrappedCB = cb;
940 _p->_wrappedCB = cb;
923 }
941 }
924
942
925 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
943 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
926 {
944 {
927 _p->_noLongerWrappedCB = cb;
945 _p->_noLongerWrappedCB = cb;
928 }
946 }
929
947
930
948
931
949
932 static PyMethodDef PythonQtMethods[] = {
950 static PyMethodDef PythonQtMethods[] = {
933 {NULL, NULL, 0, NULL}
951 {NULL, NULL, 0, NULL}
934 };
952 };
935
953
936 void PythonQt::initPythonQtModule(bool redirectStdOut)
954 void PythonQt::initPythonQtModule(bool redirectStdOut)
937 {
955 {
938 _p->_pythonQtModule.setNewRef(Py_InitModule("PythonQt", PythonQtMethods));
956 _p->_pythonQtModule.setNewRef(Py_InitModule("PythonQt", PythonQtMethods));
939 _p->_qtNamespace = new PythonQtClassInfo(&staticQtMetaObject);
957 _p->_qtNamespace = new PythonQtClassInfo(&staticQtMetaObject);
940 PyModule_AddObject(_p->_pythonQtModule, "Qt", (PyObject*)_p->createNewPythonQtMetaObjectWrapper(_p->_qtNamespace));
958 PyModule_AddObject(_p->_pythonQtModule, "Qt", (PyObject*)_p->createNewPythonQtMetaObjectWrapper(_p->_qtNamespace));
941
959
942 if (redirectStdOut) {
960 if (redirectStdOut) {
943 PythonQtObjectPtr sys;
961 PythonQtObjectPtr sys;
944 PythonQtObjectPtr out;
962 PythonQtObjectPtr out;
945 PythonQtObjectPtr err;
963 PythonQtObjectPtr err;
946 sys.setNewRef(PyImport_ImportModule("sys"));
964 sys.setNewRef(PyImport_ImportModule("sys"));
947 // create a redirection object for stdout and stderr
965 // create a redirection object for stdout and stderr
948 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
966 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
949 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
967 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
950 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
968 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
951 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
969 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
952 // replace the built in file objects with our own objects
970 // replace the built in file objects with our own objects
953 PyModule_AddObject(sys, "stdout", out);
971 PyModule_AddObject(sys, "stdout", out);
954 PyModule_AddObject(sys, "stderr", err);
972 PyModule_AddObject(sys, "stderr", err);
955 }
973 }
956 }
974 }
957
975
958 void PythonQt::addVariantWrapper(const char* typeName, QObject* wrapper)
976 void PythonQt::addVariantWrapper(const char* typeName, QObject* wrapper)
959 {
977 {
960 _p->addVariantWrapper(typeName, wrapper);
978 _p->addVariantWrapper(typeName, wrapper);
961 }
979 }
962
980
963
981
964 void PythonQtPrivate::addVariantWrapper(const char* typeName, QObject* wrapper)
982 void PythonQtPrivate::addVariantWrapper(const char* typeName, QObject* wrapper)
965 {
983 {
966 int type = QMetaType::type(typeName);
984 int type = QMetaType::type(typeName);
967 PythonQtClassInfo* info = new PythonQtClassInfo(wrapper->metaObject(), typeName);
985 PythonQtClassInfo* info = new PythonQtClassInfo(wrapper->metaObject(), typeName);
968 _knownVariantWrappers.insert(type, qMakePair(info, wrapper));
986 _knownVariantWrappers.insert(type, qMakePair(info, wrapper));
969 addDecorators(wrapper, false, true);
987 addDecorators(wrapper, false, true);
970 PyModule_AddObject(_pythonQtModule, typeName, (PyObject*)createNewPythonQtMetaObjectWrapper(info));
988 PyModule_AddObject(_pythonQtModule, typeName, (PyObject*)createNewPythonQtMetaObjectWrapper(info));
971 }
989 }
972
990
973 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
991 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
974 {
992 {
975 if (_p->_initFlags & ExternalHelp) {
993 if (_p->_initFlags & ExternalHelp) {
976 emit pythonHelpRequest(QByteArray(info->className()));
994 emit pythonHelpRequest(QByteArray(info->className()));
977 return Py_BuildValue("");
995 return Py_BuildValue("");
978 } else {
996 } else {
979 return PyString_FromString(info->help().toLatin1().data());
997 return PyString_FromString(info->help().toLatin1().data());
980 }
998 }
981 }
999 }
982
1000
983 void PythonQtPrivate::removeWrapperPointer(void* obj)
1001 void PythonQtPrivate::removeWrapperPointer(void* obj)
984 {
1002 {
985 _wrappedObjects.remove(obj);
1003 _wrappedObjects.remove(obj);
986 }
1004 }
987
1005
988 PythonQtWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1006 PythonQtWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
989 {
1007 {
990 PythonQtWrapper* wrap = _wrappedObjects.value(obj);
1008 PythonQtWrapper* wrap = _wrappedObjects.value(obj);
991 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1009 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
992 // this is a wrapper whose QObject was already removed due to destruction
1010 // this is a wrapper whose QObject was already removed due to destruction
993 // so the obj pointer has to be a new QObject with the same address...
1011 // so the obj pointer has to be a new QObject with the same address...
994 // we remove the old one and set the copy to NULL
1012 // we remove the old one and set the copy to NULL
995 wrap->_objPointerCopy = NULL;
1013 wrap->_objPointerCopy = NULL;
996 removeWrapperPointer(obj);
1014 removeWrapperPointer(obj);
997 wrap = NULL;
1015 wrap = NULL;
998 }
1016 }
999 return wrap;
1017 return wrap;
1000 }
1018 }
1001
1019
1002 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1020 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1003 {
1021 {
1004 PythonQtObjectPtr result;
1022 PythonQtObjectPtr result;
1005 if (pycode) {
1023 if (pycode) {
1006 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1024 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1007 } else {
1025 } else {
1008 PythonQt::self()->handleError();
1026 PythonQt::self()->handleError();
1009 }
1027 }
1010 return result;
1028 return result;
1011 }
1029 }
@@ -1,469 +1,487
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 "PythonQtVariantWrapper.h"
47 #include "PythonQtVariantWrapper.h"
48 #include "PythonQtMetaObjectWrapper.h"
48 #include "PythonQtMetaObjectWrapper.h"
49 #include "PythonQtSlot.h"
49 #include "PythonQtSlot.h"
50 #include "PythonQtObjectPtr.h"
50 #include "PythonQtObjectPtr.h"
51 #include <QObject>
51 #include <QObject>
52 #include <QVariant>
52 #include <QVariant>
53 #include <QList>
53 #include <QList>
54 #include <QHash>
54 #include <QHash>
55 #include <QByteArray>
55 #include <QByteArray>
56 #include <QStringList>
56 #include <QStringList>
57 #include <QtDebug>
57 #include <QtDebug>
58 #include <iostream>
58 #include <iostream>
59
59
60
60
61 class PythonQtClassInfo;
61 class PythonQtClassInfo;
62 class PythonQtPrivate;
62 class PythonQtPrivate;
63 class PythonQtMethodInfo;
63 class PythonQtMethodInfo;
64 class PythonQtSignalReceiver;
64 class PythonQtSignalReceiver;
65 class PythonQtImportFileInterface;
65 class PythonQtImportFileInterface;
66 class PythonQtCppWrapperFactory;
66 class PythonQtCppWrapperFactory;
67 class PythonQtConstructorHandler;
67 class PythonQtConstructorHandler;
68 class PythonQtQFileImporter;
68
69
69 typedef void PythonQtQObjectWrappedCB(QObject* object);
70 typedef void PythonQtQObjectWrappedCB(QObject* object);
70 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
71 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
71
72
72 //! the main interface to the Python Qt binding, realized as a singleton
73 //! the main interface to the Python Qt binding, realized as a singleton
73 class PYTHONQT_EXPORT PythonQt : public QObject {
74 class PYTHONQT_EXPORT PythonQt : public QObject {
74
75
75 Q_OBJECT
76 Q_OBJECT
76
77
77 public:
78 public:
78 enum InitFlags {
79 enum InitFlags {
79 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
80 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
80 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
81 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
81 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
82 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
82 };
83 };
83
84
84 //! initialize the python qt binding (flags are a or combination of InitFlags)
85 //! initialize the python qt binding (flags are a or combination of InitFlags)
85 static void init(int flags = IgnoreSiteModule | RedirectStdOut);
86 static void init(int flags = IgnoreSiteModule | RedirectStdOut);
86
87
87 //! cleanup
88 //! cleanup
88 static void cleanup();
89 static void cleanup();
89
90
90 //! get the singleton instance
91 //! get the singleton instance
91 static PythonQt* self() { return _self; }
92 static PythonQt* self() { return _self; }
92
93
93 //-----------------------------------------------------------------------------
94 //-----------------------------------------------------------------------------
94 // Public API:
95 // Public API:
95
96
96 //! defines the object types for introspection
97 //! defines the object types for introspection
97 enum ObjectType {
98 enum ObjectType {
98 Class,
99 Class,
99 Function,
100 Function,
100 Variable,
101 Variable,
101 Module,
102 Module,
102 Anything,
103 Anything,
103 CallOverloads
104 CallOverloads
104 };
105 };
105
106
106 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
107 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
107 void overwriteSysPath(const QStringList& paths);
108 void overwriteSysPath(const QStringList& paths);
108
109
109 //! sets the __path__ list of a module to the given list (important for local imports)
110 //! sets the __path__ list of a module to the given list (important for local imports)
110 void setModuleImportPath(PyObject* module, const QStringList& paths);
111 void setModuleImportPath(PyObject* module, const QStringList& paths);
111
112
112 //! get the __main__ module of python
113 //! get the __main__ module of python
113 PythonQtObjectPtr getMainModule();
114 PythonQtObjectPtr getMainModule();
114
115
115 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
116 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
116 //! All added metaobjects will be visible under the className in the PythonQt module as MetaObjectWrappers and the enums
117 //! All added metaobjects will be visible under the className in the PythonQt module as MetaObjectWrappers and the enums
117 //! and constructors (added by addConstructors) will be available.
118 //! and constructors (added by addConstructors) will be available.
118 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
119 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
119 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
120 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
120 void registerClass(const QMetaObject* metaobject);
121 void registerClass(const QMetaObject* metaobject);
121
122
122 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
123 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
123 //! and it will register the classes when it first sees a pointer to such a derived class
124 //! and it will register the classes when it first sees a pointer to such a derived class
124 void registerQObjectClassNames(const QStringList& names);
125 void registerQObjectClassNames(const QStringList& names);
125
126
126 //! this will register CPP classnames as known CPP classes (NOT QObjects) and make their MetaObjectWrapper available in
127 //! this will register CPP classnames as known CPP classes (NOT QObjects) and make their MetaObjectWrapper available in
127 //! the PythonQt module. In combination with addConstuctors(), this can be used to create CPP objects from PythonQt
128 //! the PythonQt module. In combination with addConstuctors(), this can be used to create CPP objects from PythonQt
128 void registerCPPClassNames(const QStringList& names);
129 void registerCPPClassNames(const QStringList& names);
129
130
130 //! parses the given file and returns the python code object, this can then be used to call evalCode()
131 //! parses the given file and returns the python code object, this can then be used to call evalCode()
131 PythonQtObjectPtr parseFile(const QString& filename);
132 PythonQtObjectPtr parseFile(const QString& filename);
132
133
133 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
134 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
134 //! If pycode is NULL, a python error is printed.
135 //! If pycode is NULL, a python error is printed.
135 QVariant evalCode(PyObject* module, PyObject* pycode);
136 QVariant evalCode(PyObject* module, PyObject* pycode);
136
137
137 //! evaluates the given script code and returns the result value
138 //! evaluates the given script code and returns the result value
138 QVariant evalScript(PyObject* module, const QString& script, int start = Py_file_input);
139 QVariant evalScript(PyObject* module, const QString& script, int start = Py_file_input);
139
140
140 //! evaluates the given script code from file
141 //! evaluates the given script code from file
141 void evalFile(PyObject* module, const QString& filename);
142 void evalFile(PyObject* module, const QString& filename);
142
143
143 //! creates the new module \c name and evaluates the given file in the context of that module
144 //! creates the new module \c name and evaluates the given file in the context of that module
144 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
145 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
145 //! to a module later on.
146 //! to a module later on.
146 //! The user needs to make sure that the \c name is unique in the python module dictionary.
147 //! The user needs to make sure that the \c name is unique in the python module dictionary.
147 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
148 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
148
149
149 //! creates the new module \c name and evaluates the given script in the context of that module.
150 //! creates the new module \c name and evaluates the given script in the context of that module.
150 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
151 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
151 //! to a module later on.
152 //! to a module later on.
152 //! The user needs to make sure that the \c name is unique in the python module dictionary.
153 //! The user needs to make sure that the \c name is unique in the python module dictionary.
153 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
154 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
154
155
155 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
156 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
156 //! script code
157 //! script code
157 PythonQtObjectPtr createUniqueModule();
158 PythonQtObjectPtr createUniqueModule();
158
159
159 //@{ Signal handlers
160 //@{ Signal handlers
160
161
161 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
162 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
162 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
163 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
163
164
164 //! remove a signal handler from the given \c signal of \c obj
165 //! remove a signal handler from the given \c signal of \c obj
165 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
166 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
166
167
167 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
168 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
168 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
169 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
169
170
170 //! remove a signal handler from the given \c signal of \c obj
171 //! remove a signal handler from the given \c signal of \c obj
171 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
172 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
172
173
173 //@}
174 //@}
174
175
175 //@{ Variable access
176 //@{ Variable access
176
177
177 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
178 //! add the given \c object to the \c module as a variable with \c name (it can be removed via clearVariable)
178 void addObject(PyObject* module, const QString& name, QObject* object);
179 void addObject(PyObject* module, const QString& name, QObject* object);
179
180
180 //! add the given variable to the module
181 //! add the given variable to the module
181 void addVariable(PyObject* module, const QString& name, const QVariant& v);
182 void addVariable(PyObject* module, const QString& name, const QVariant& v);
182
183
183 //! remove the given variable
184 //! remove the given variable
184 void removeVariable(PyObject* module, const QString& name);
185 void removeVariable(PyObject* module, const QString& name);
185
186
186 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
187 //! get the variable with the \c name of the \c module, returns an invalid QVariant on error
187 QVariant getVariable(PyObject* module, const QString& name);
188 QVariant getVariable(PyObject* module, const QString& name);
188
189
189 //! read vars etc. in scope of a module, optional looking inside of an object \c objectname
190 //! read vars etc. in scope of a module, optional looking inside of an object \c objectname
190 QStringList introspection(PyObject* module, const QString& objectname, ObjectType type);
191 QStringList introspection(PyObject* module, const QString& objectname, ObjectType type);
191
192
192 //! returns the found callable object or NULL
193 //! returns the found callable object or NULL
193 //! @return new reference
194 //! @return new reference
194 PythonQtObjectPtr lookupCallable(PyObject* module, const QString& name);
195 PythonQtObjectPtr lookupCallable(PyObject* module, const QString& name);
195
196
196 //@}
197 //@}
197
198
198 //@{ Calling of python callables
199 //@{ Calling of python callables
199
200
200 //! call the given python method, returns the result converted to a QVariant
201 //! call the given python method, returns the result converted to a QVariant
201 QVariant call(PyObject* module, const QString& callable, const QVariantList& args);
202 QVariant call(PyObject* module, const QString& callable, const QVariantList& args);
202
203
203 //@}
204 //@}
204
205
205 //@{ Decorations, constructors, wrappers...
206 //@{ Decorations, constructors, wrappers...
206
207
207
208
208 //! add an object whose slots will be used as decorator slots for
209 //! add an object whose slots will be used as decorator slots for
209 //! other QObjects or CPP classes. The slots need to follow the
210 //! other QObjects or CPP classes. The slots need to follow the
210 //! convention that the first argument is a pointer to the wrapped object.
211 //! convention that the first argument is a pointer to the wrapped object.
211 //! (ownership is passed to PythonQt)
212 //! (ownership is passed to PythonQt)
212 /*!
213 /*!
213 Example:
214 Example:
214
215
215 A slot with the signature
216 A slot with the signature
216
217
217 \code
218 \code
218 bool doSomething(QWidget* w, int a)
219 bool doSomething(QWidget* w, int a)
219 \endcode
220 \endcode
220
221
221 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
222 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
222 that will be called with the concrete instance as first argument.
223 that will be called with the concrete instance as first argument.
223 So in Python you can now e.g. call
224 So in Python you can now e.g. call
224
225
225 \code
226 \code
226 someWidget.doSomething(12)
227 someWidget.doSomething(12)
227 \endcode
228 \endcode
228
229
229 without QWidget really having this method. This allows to easily make normal methods
230 without QWidget really having this method. This allows to easily make normal methods
230 of Qt classes callable by forwarding them with such decorator slots
231 of Qt classes callable by forwarding them with such decorator slots
231 or to make CPP classes (which are not derived from QObject) callable from Python.
232 or to make CPP classes (which are not derived from QObject) callable from Python.
232 */
233 */
233 void addInstanceDecorators(QObject* o);
234 void addInstanceDecorators(QObject* o);
234
235
235 //! add an object whose slots will be used as decorator slots for
236 //! add an object whose slots will be used as decorator slots for
236 //! class objects (ownership is passed to PythonQt)
237 //! class objects (ownership is passed to PythonQt)
237 /*!
238 /*!
238 The slots need to follow the following convention:
239 The slots need to follow the following convention:
239 - SomeClass* new_SomeClass(...)
240 - SomeClass* new_SomeClass(...)
240 - QVariant new_SomeClass(...)
241 - QVariant new_SomeClass(...)
241 - void delete_SomeClass(SomeClass*)
242 - void delete_SomeClass(SomeClass*)
242 - ... static_SomeClass_someName(...)
243 - ... static_SomeClass_someName(...)
243
244
244 This will add:
245 This will add:
245 - a constructor
246 - a constructor
246 - a constructor which generates a QVariant
247 - a constructor which generates a QVariant
247 - a destructor (only useful for CPP objects)
248 - a destructor (only useful for CPP objects)
248 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
249 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
249
250
250 */
251 */
251 void addClassDecorators(QObject* o);
252 void addClassDecorators(QObject* o);
252
253
253 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
254 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
254 void addDecorators(QObject* o);
255 void addDecorators(QObject* o);
255
256
256 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
257 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
257 //! (ownership of wrapper is passed to PythonQt)
258 //! (ownership of wrapper is passed to PythonQt)
258 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
259 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
259
260
260 This will add a wrapper object that is used to make calls to the given classname \c typeName.
261 This will add a wrapper object that is used to make calls to the given classname \c typeName.
261 All slots that take a pointer to typeName as the first argument will be callable from Python on
262 All slots that take a pointer to typeName as the first argument will be callable from Python on
262 a variant object that contains such a type.
263 a variant object that contains such a type.
263 */
264 */
264 void addVariantWrapper(const char* typeName, QObject* wrapper);
265 void addVariantWrapper(const char* typeName, QObject* wrapper);
265
266
266 //! add the given factory to PythonQt (ownership stays with caller)
267 //! add the given factory to PythonQt (ownership stays with caller)
267 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
268 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
268
269
269 //! add the given constructor handler to PythonQt (ownership stays with caller)
270 //! add the given constructor handler to PythonQt (ownership stays with caller)
270 void addConstructorHandler(PythonQtConstructorHandler* handler);
271 void addConstructorHandler(PythonQtConstructorHandler* handler);
271
272
272 //! get list of constructor handlers
273 //! get list of constructor handlers
273 const QList<PythonQtConstructorHandler*>& constructorHandlers();
274 const QList<PythonQtConstructorHandler*>& constructorHandlers();
274
275
275 //@}
276 //@}
276
277
277 //@{ Custom importer (to replace internal import implementation of python)
278 //@{ Custom importer (to replace internal import implementation of python)
278
279
279 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
280 //! 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().
281 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
281 //! It can only be called once, further calls will be ignored silently. (ownership stays with caller)
282 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
283 //! This is not reversible, so even setting setImporter(NULL) afterwards will
284 //! keep the custom PythonQt importer with a QFile default import interface.
285 //! Subsequent python import calls will make use of the passed importInterface
286 //! which forwards all import calls to the given \c importInterface.
287 //! Passing NULL will install a default QFile importer.
288 //! (\c importInterface ownership stays with caller)
282 void setImporter(PythonQtImportFileInterface* importInterface);
289 void setImporter(PythonQtImportFileInterface* importInterface);
283
290
291 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
292 //! (without calling setImporter or installDefaultImporter at least once, the default python import
293 //! mechanism is in place)
294 //! the default importer allows to import files from anywhere QFile can read from,
295 //! including the Qt resource system using ":". Keep in mind that you need to extend
296 //! "sys.path" with ":" to be able to import from the Qt resources.
297 void installDefaultImporter() { setImporter(NULL); }
298
284 //! set paths that the importer should ignore
299 //! set paths that the importer should ignore
285 void setImporterIgnorePaths(const QStringList& paths);
300 void setImporterIgnorePaths(const QStringList& paths);
286
301
287 //! get paths that the importer should ignore
302 //! get paths that the importer should ignore
288 const QStringList& getImporterIgnorePaths();
303 const QStringList& getImporterIgnorePaths();
289
304
290 //@}
305 //@}
291
306
292 //! get access to internal data (should not be used on the public API, but is used by some C functions)
307 //! get access to internal data (should not be used on the public API, but is used by some C functions)
293 static PythonQtPrivate* priv() { return _self->_p; }
308 static PythonQtPrivate* priv() { return _self->_p; }
294
309
295 //! get access to the file importer (if set)
310 //! get access to the file importer (if set)
296 static PythonQtImportFileInterface* importInterface();
311 static PythonQtImportFileInterface* importInterface();
297
312
298 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
313 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
299 //! The error is currently just output to the python stderr, future version might implement better trace printing
314 //! The error is currently just output to the python stderr, future version might implement better trace printing
300 bool handleError();
315 bool handleError();
301
316
302 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
317 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
303 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
318 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
304 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
319 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
305 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
320 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
306
321
307 //! call the callback if it is set
322 //! call the callback if it is set
308 static void qObjectNoLongerWrappedCB(QObject* o);
323 static void qObjectNoLongerWrappedCB(QObject* o);
309
324
310 signals:
325 signals:
311 //! emitted when python outputs something to stdout (and redirection is turned on)
326 //! emitted when python outputs something to stdout (and redirection is turned on)
312 void pythonStdOut(const QString& str);
327 void pythonStdOut(const QString& str);
313 //! emitted when python outputs something to stderr (and redirection is turned on)
328 //! emitted when python outputs something to stderr (and redirection is turned on)
314 void pythonStdErr(const QString& str);
329 void pythonStdErr(const QString& str);
315
330
316 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
331 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
317 void pythonHelpRequest(const QByteArray& cppClassName);
332 void pythonHelpRequest(const QByteArray& cppClassName);
318
333
319
334
320 public:
335 public:
321 //! called by internal help methods
336 //! called by internal help methods
322 PyObject* helpCalled(PythonQtClassInfo* info);
337 PyObject* helpCalled(PythonQtClassInfo* info);
323
338
324 //! returns the found object or NULL
339 //! returns the found object or NULL
325 //! @return new reference
340 //! @return new reference
326 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
341 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
327
342
328 private:
343 private:
329 void initPythonQtModule(bool redirectStdOut);
344 void initPythonQtModule(bool redirectStdOut);
330
345
331 //! callback for stdout redirection, emits pythonStdOut signal
346 //! callback for stdout redirection, emits pythonStdOut signal
332 static void stdOutRedirectCB(const QString& str);
347 static void stdOutRedirectCB(const QString& str);
333 //! callback for stderr redirection, emits pythonStdErr signal
348 //! callback for stderr redirection, emits pythonStdErr signal
334 static void stdErrRedirectCB(const QString& str);
349 static void stdErrRedirectCB(const QString& str);
335
350
336 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
351 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
337 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
352 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
338
353
339 PythonQt(int flags);
354 PythonQt(int flags);
340 ~PythonQt();
355 ~PythonQt();
341
356
342 static PythonQt* _self;
357 static PythonQt* _self;
343 static int _uniqueModuleCount;
358 static int _uniqueModuleCount;
344
359
345 PythonQtPrivate* _p;
360 PythonQtPrivate* _p;
346
361
347 };
362 };
348
363
349 //! internal PythonQt details
364 //! internal PythonQt details
350 class PythonQtPrivate : public QObject {
365 class PythonQtPrivate : public QObject {
351
366
352 Q_OBJECT
367 Q_OBJECT
353
368
354 public:
369 public:
355 PythonQtPrivate();
370 PythonQtPrivate();
356 ~PythonQtPrivate();
371 ~PythonQtPrivate();
357
372
358 //! returns if the id is the id for PythonQtObjectPtr
373 //! returns if the id is the id for PythonQtObjectPtr
359 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
374 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
360
375
361 //! remove the wrapper ptr again
376 //! remove the wrapper ptr again
362 void removeWrapperPointer(void* obj);
377 void removeWrapperPointer(void* obj);
363
378
364 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
379 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
365 void removeSignalEmitter(QObject* obj);
380 void removeSignalEmitter(QObject* obj);
366
381
367 //! wrap the given QObject into a Python object (or return existing wrapper!)
382 //! wrap the given QObject into a Python object (or return existing wrapper!)
368 PyObject* wrapQObject(QObject* obj);
383 PyObject* wrapQObject(QObject* obj);
369
384
370 //! 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
385 //! 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
371 PyObject* wrapPtr(void* ptr, const QByteArray& name);
386 PyObject* wrapPtr(void* ptr, const QByteArray& name);
372
387
373 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
388 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
374 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
389 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
375 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
390 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
376 void registerClass(const QMetaObject* metaobject);
391 void registerClass(const QMetaObject* metaobject);
377
392
378 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
393 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
379 //! and it will register the classes when it first sees a pointer to such a derived class
394 //! and it will register the classes when it first sees a pointer to such a derived class
380 void registerQObjectClassNames(const QStringList& names);
395 void registerQObjectClassNames(const QStringList& names);
381
396
382 //! add a decorator object
397 //! add a decorator object
383 void addDecorators(QObject* o, bool instanceDeco, bool classDeco);
398 void addDecorators(QObject* o, bool instanceDeco, bool classDeco);
384
399
385 //! add a wrapper object for the given qvariant, also does an addConstructors() to add constructors for variants
400 //! add a wrapper object for the given qvariant, also does an addConstructors() to add constructors for variants
386 void addVariantWrapper(const char* typeName, QObject* wrapper);
401 void addVariantWrapper(const char* typeName, QObject* wrapper);
387
402
388 //! get list of all slots that are available as decorator slots
403 //! get list of all slots that are available as decorator slots
389 QList<PythonQtSlotInfo*> getDecoratorSlots(const QByteArray& className);
404 QList<PythonQtSlotInfo*> getDecoratorSlots(const QByteArray& className);
390
405
391 //! check if the enum is either part of the \c meta class or contains a scope and is
406 //! check if the enum is either part of the \c meta class or contains a scope and is
392 //! an enum of another known metaobject (and as last resort, of the Qt namespace)
407 //! an enum of another known metaobject (and as last resort, of the Qt namespace)
393 bool isEnumType(const QMetaObject* meta, const QByteArray& name);
408 bool isEnumType(const QMetaObject* meta, const QByteArray& name);
394
409
395 //! helper method that creates a PythonQtMetaObjectWrapper object
410 //! helper method that creates a PythonQtMetaObjectWrapper object
396 PythonQtMetaObjectWrapper* createNewPythonQtMetaObjectWrapper(PythonQtClassInfo* info);
411 PythonQtMetaObjectWrapper* createNewPythonQtMetaObjectWrapper(PythonQtClassInfo* info);
397
412
398 //! helper method that creates a PythonQtWrapper object and registers it in the object map
413 //! helper method that creates a PythonQtWrapper object and registers it in the object map
399 PythonQtWrapper* createNewPythonQtWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
414 PythonQtWrapper* createNewPythonQtWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
400
415
401 //! helper method that creates a PythonQtVariantWrapper object
416 //! helper method that creates a PythonQtVariantWrapper object
402 PythonQtVariantWrapper* createNewPythonQtVariantWrapper(const QVariant& variant);
417 PythonQtVariantWrapper* createNewPythonQtVariantWrapper(const QVariant& variant);
403
418
404 //! get the class info for a meta object (if available)
419 //! get the class info for a meta object (if available)
405 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownQtClasses.value(meta->className()); }
420 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownQtClasses.value(meta->className()); }
406
421
407 //! get the constructor slot for the given classname
422 //! get the constructor slot for the given classname
408 PythonQtSlotInfo* getConstructorSlot(const QByteArray& className) { return _constructorSlots.value(className); }
423 PythonQtSlotInfo* getConstructorSlot(const QByteArray& className) { return _constructorSlots.value(className); }
409
424
410 //! get the destructor slot for the given classname
425 //! get the destructor slot for the given classname
411 PythonQtSlotInfo* getDestructorSlot(const QByteArray& className) { return _destructorSlots.value(className); }
426 PythonQtSlotInfo* getDestructorSlot(const QByteArray& className) { return _destructorSlots.value(className); }
412
427
413 //! creates the new module from the given pycode
428 //! creates the new module from the given pycode
414 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
429 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
415
430
416 private:
431 private:
417
432
418 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
433 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
419 PythonQtWrapper* findWrapperAndRemoveUnused(void* obj);
434 PythonQtWrapper* findWrapperAndRemoveUnused(void* obj);
420
435
421 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
436 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
422 QHash<void* , PythonQtWrapper *> _wrappedObjects;
437 QHash<void* , PythonQtWrapper *> _wrappedObjects;
423
438
424 //! stores the meta info of known Qt classes
439 //! stores the meta info of known Qt classes
425 QHash<QByteArray, PythonQtClassInfo *> _knownQtClasses;
440 QHash<QByteArray, PythonQtClassInfo *> _knownQtClasses;
426
441
427 //! stores the meta info of known Qt classes
442 //! stores the meta info of known Qt classes
428 QHash<QByteArray, PythonQtClassInfo *> _knownQtWrapperClasses;
443 QHash<QByteArray, PythonQtClassInfo *> _knownQtWrapperClasses;
429
444
430 //! stores the meta info of known Qt C++ wrapper classes
445 //! stores the meta info of known Qt C++ wrapper classes
431 QMultiHash<QByteArray, PythonQtSlotInfo *> _knownQtDecoratorSlots;
446 QMultiHash<QByteArray, PythonQtSlotInfo *> _knownQtDecoratorSlots;
432
447
433 //! names of qobject derived classes that can be casted to qobject savely
448 //! names of qobject derived classes that can be casted to qobject savely
434 QHash<QByteArray, bool> _knownQObjectClassNames;
449 QHash<QByteArray, bool> _knownQObjectClassNames;
435
450
436 //! stores signal receivers for QObjects
451 //! stores signal receivers for QObjects
437 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
452 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
438
453
439 //! the PythonQt python module
454 //! the PythonQt python module
440 PythonQtObjectPtr _pythonQtModule;
455 PythonQtObjectPtr _pythonQtModule;
441
456
442 //! the importer interface (if set)
457 //! the importer interface (if set)
443 PythonQtImportFileInterface* _importInterface;
458 PythonQtImportFileInterface* _importInterface;
444
459
460 //! the default importer
461 PythonQtQFileImporter* _defaultImporter;
462
445 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
463 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
446 PythonQtQObjectWrappedCB* _wrappedCB;
464 PythonQtQObjectWrappedCB* _wrappedCB;
447
465
448 QStringList _importIgnorePaths;
466 QStringList _importIgnorePaths;
449
467
450 //! the cpp object wrapper factories
468 //! the cpp object wrapper factories
451 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
469 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
452
470
453 //! the cpp object wrapper factories
471 //! the cpp object wrapper factories
454 QList<PythonQtConstructorHandler*> _constructorHandlers;
472 QList<PythonQtConstructorHandler*> _constructorHandlers;
455
473
456 QHash<QByteArray , PythonQtSlotInfo *> _constructorSlots;
474 QHash<QByteArray , PythonQtSlotInfo *> _constructorSlots;
457 QHash<QByteArray , PythonQtSlotInfo *> _destructorSlots;
475 QHash<QByteArray , PythonQtSlotInfo *> _destructorSlots;
458
476
459 QHash<int , QPair<PythonQtClassInfo*, QObject*> > _knownVariantWrappers;
477 QHash<int , QPair<PythonQtClassInfo*, QObject*> > _knownVariantWrappers;
460
478
461 PythonQtClassInfo* _qtNamespace;
479 PythonQtClassInfo* _qtNamespace;
462
480
463 int _initFlags;
481 int _initFlags;
464 int _PythonQtObjectPtr_metaId;
482 int _PythonQtObjectPtr_metaId;
465
483
466 friend class PythonQt;
484 friend class PythonQt;
467 };
485 };
468
486
469 #endif
487 #endif
@@ -1,1017 +1,1017
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 PythonQtConversion.cpp
35 // \file PythonQtConversion.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 "PythonQtConversion.h"
42 #include "PythonQtConversion.h"
43 #include "PythonQtVariants.h"
43 #include "PythonQtVariants.h"
44 #include "PythonQtVariantWrapper.h"
44 #include "PythonQtVariantWrapper.h"
45 #include <QDateTime>
45 #include <QDateTime>
46 #include <QTime>
46 #include <QTime>
47 #include <QDate>
47 #include <QDate>
48
48
49 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
49 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
50 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
50 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
51 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
51 PythonQtValueStorage<QVariant, 32> PythonQtConv::global_variantStorage;
52
52
53
53
54 PyObject* PythonQtConv::GetPyBool(bool val)
54 PyObject* PythonQtConv::GetPyBool(bool val)
55 {
55 {
56 PyObject* r = val?Py_True:Py_False;
56 PyObject* r = val?Py_True:Py_False;
57 Py_INCREF(r);
57 Py_INCREF(r);
58 return r;
58 return r;
59 }
59 }
60
60
61 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, void* data) {
61 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, void* data) {
62 if (info.typeId == QMetaType::Void) {
62 if (info.typeId == QMetaType::Void) {
63 Py_INCREF(Py_None);
63 Py_INCREF(Py_None);
64 return Py_None;
64 return Py_None;
65 } else {
65 } else {
66 if (info.isPointer && (info.typeId == PythonQtMethodInfo::Unknown)) {
66 if (info.isPointer && (info.typeId == PythonQtMethodInfo::Unknown)) {
67 // try to convert the pointer to a Python Object
67 // try to convert the pointer to a Python Object
68 PyObject* pyObj = PythonQt::priv()->wrapPtr(*((void**)data), info.name);
68 PyObject* pyObj = PythonQt::priv()->wrapPtr(*((void**)data), info.name);
69 if (pyObj) {
69 if (pyObj) {
70 return pyObj;
70 return pyObj;
71 } else {
71 } else {
72 std::cerr << "unknown pointer type " << info.name.data() << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
72 std::cerr << "unknown pointer type " << info.name.data() << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
73 Py_INCREF(Py_None);
73 Py_INCREF(Py_None);
74 return Py_None;
74 return Py_None;
75 }
75 }
76 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
76 } else if (info.isPointer && (info.typeId == QMetaType::Char)) {
77 // a char ptr will probably be a null terminated string, so we support that:
77 // a char ptr will probably be a null terminated string, so we support that:
78 return PyString_FromString(*((char**)data));
78 return PyString_FromString(*((char**)data));
79 } else {
79 } else {
80 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
80 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
81 if (info.name.startsWith("QList<")) {
81 if (info.name.startsWith("QList<")) {
82 QByteArray innerType = info.name.mid(6,info.name.length()-7);
82 QByteArray innerType = info.name.mid(6,info.name.length()-7);
83 if (innerType.endsWith("*")) {
83 if (innerType.endsWith("*")) {
84 innerType.truncate(innerType.length()-1);
84 innerType.truncate(innerType.length()-1);
85 return ConvertQListWithPointersToPython((QList<void*>*)data, innerType);
85 return ConvertQListWithPointersToPython((QList<void*>*)data, innerType);
86 }
86 }
87 }
87 }
88 }
88 }
89 // handle values that are not yet handled and not pointers
89 // handle values that are not yet handled and not pointers
90 return ConvertQtValueToPythonInternal(info.typeId, data);
90 return ConvertQtValueToPythonInternal(info.typeId, data);
91 }
91 }
92 }
92 }
93 }
93 }
94
94
95 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, void* data) {
95 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, void* data) {
96 switch (type) {
96 switch (type) {
97 case QMetaType::Void:
97 case QMetaType::Void:
98 Py_INCREF(Py_None);
98 Py_INCREF(Py_None);
99 return Py_None;
99 return Py_None;
100 case QMetaType::Char:
100 case QMetaType::Char:
101 return PyInt_FromLong(*((char*)data));
101 return PyInt_FromLong(*((char*)data));
102 case QMetaType::UChar:
102 case QMetaType::UChar:
103 return PyInt_FromLong(*((unsigned char*)data));
103 return PyInt_FromLong(*((unsigned char*)data));
104 case QMetaType::Short:
104 case QMetaType::Short:
105 return PyInt_FromLong(*((short*)data));
105 return PyInt_FromLong(*((short*)data));
106 case QMetaType::UShort:
106 case QMetaType::UShort:
107 return PyInt_FromLong(*((unsigned short*)data));
107 return PyInt_FromLong(*((unsigned short*)data));
108 case QMetaType::Long:
108 case QMetaType::Long:
109 return PyInt_FromLong(*((long*)data));
109 return PyInt_FromLong(*((long*)data));
110 case QMetaType::ULong:
110 case QMetaType::ULong:
111 // does not fit into simple int of python
111 // does not fit into simple int of python
112 return PyLong_FromUnsignedLong(*((unsigned long*)data));
112 return PyLong_FromUnsignedLong(*((unsigned long*)data));
113 case QMetaType::Bool:
113 case QMetaType::Bool:
114 return PythonQtConv::GetPyBool(*((bool*)data));
114 return PythonQtConv::GetPyBool(*((bool*)data));
115 case QMetaType::Int:
115 case QMetaType::Int:
116 return PyInt_FromLong(*((int*)data));
116 return PyInt_FromLong(*((int*)data));
117 case QMetaType::UInt:
117 case QMetaType::UInt:
118 return PyInt_FromLong(*((unsigned int*)data));
118 return PyInt_FromLong(*((unsigned int*)data));
119 case QMetaType::QChar:
119 case QMetaType::QChar:
120 return PyInt_FromLong(*((short*)data));
120 return PyInt_FromLong(*((short*)data));
121 case QMetaType::Float:
121 case QMetaType::Float:
122 return PyFloat_FromDouble(*((float*)data));
122 return PyFloat_FromDouble(*((float*)data));
123 case QMetaType::Double:
123 case QMetaType::Double:
124 return PyFloat_FromDouble(*((double*)data));
124 return PyFloat_FromDouble(*((double*)data));
125 case QMetaType::LongLong:
125 case QMetaType::LongLong:
126 return PyLong_FromLongLong(*((qint64*)data));
126 return PyLong_FromLongLong(*((qint64*)data));
127 case QMetaType::ULongLong:
127 case QMetaType::ULongLong:
128 return PyLong_FromUnsignedLongLong(*((quint64*)data));
128 return PyLong_FromUnsignedLongLong(*((quint64*)data));
129 case QMetaType::QByteArray: {
129 case QMetaType::QByteArray: {
130 QByteArray* v = (QByteArray*) data;
130 QByteArray* v = (QByteArray*) data;
131 return PyString_FromStringAndSize(*v, v->size());
131 return PyString_FromStringAndSize(*v, v->size());
132 }
132 }
133 case QMetaType::QVariantMap:
133 case QMetaType::QVariantMap:
134 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
134 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
135 case QMetaType::QVariantList:
135 case QMetaType::QVariantList:
136 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
136 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
137 case QMetaType::QString:
137 case QMetaType::QString:
138 return PythonQtConv::QStringToPyObject(*((QString*)data));
138 return PythonQtConv::QStringToPyObject(*((QString*)data));
139 case QMetaType::QStringList:
139 case QMetaType::QStringList:
140 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
140 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
141
141
142 case PythonQtMethodInfo::Variant:
142 case PythonQtMethodInfo::Variant:
143 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
143 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
144 case QMetaType::QObjectStar:
144 case QMetaType::QObjectStar:
145 case QMetaType::QWidgetStar:
145 case QMetaType::QWidgetStar:
146 return PythonQt::priv()->wrapQObject(*((QObject**)data));
146 return PythonQt::priv()->wrapQObject(*((QObject**)data));
147
147
148 // the following cases could be handled by the default case, but it is faster to do it with
148 // the following cases could be handled by the default case, but it is faster to do it with
149 // direct casts:
149 // direct casts:
150 case QMetaType::QDate:
150 case QMetaType::QDate:
151 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QDate*)data)));
151 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QDate*)data)));
152 case QMetaType::QTime:
152 case QMetaType::QTime:
153 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QTime*)data)));
153 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QTime*)data)));
154 case QMetaType::QDateTime:
154 case QMetaType::QDateTime:
155 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QDateTime*)data)));
155 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QDateTime*)data)));
156 case QMetaType::QRect:
156 case QMetaType::QRect:
157 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRect*)data)));
157 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRect*)data)));
158 case QMetaType::QSize:
158 case QMetaType::QSize:
159 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSize*)data)));
159 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSize*)data)));
160 case QMetaType::QPoint:
160 case QMetaType::QPoint:
161 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPoint*)data)));
161 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPoint*)data)));
162 case QMetaType::QColor:
162 case QMetaType::QColor:
163 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QColor*)data)));
163 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QColor*)data)));
164 case QMetaType::QPixmap:
164 case QMetaType::QPixmap:
165 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPixmap*)data)));
165 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPixmap*)data)));
166 case QMetaType::QUrl:
166 case QMetaType::QUrl:
167 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QUrl*)data)));
167 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QUrl*)data)));
168 case QMetaType::QRectF:
168 case QMetaType::QRectF:
169 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRectF*)data)));
169 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRectF*)data)));
170 case QMetaType::QSizeF:
170 case QMetaType::QSizeF:
171 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSizeF*)data)));
171 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSizeF*)data)));
172 case QMetaType::QLine:
172 case QMetaType::QLine:
173 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLine*)data)));
173 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLine*)data)));
174 case QMetaType::QLineF:
174 case QMetaType::QLineF:
175 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLineF*)data)));
175 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLineF*)data)));
176 case QMetaType::QPointF:
176 case QMetaType::QPointF:
177 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPointF*)data)));
177 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPointF*)data)));
178 case QMetaType::QRegExp:
178 case QMetaType::QRegExp:
179 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRegExp*)data)));
179 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRegExp*)data)));
180 case QMetaType::QBitArray:
180 case QMetaType::QBitArray:
181 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QBitArray*)data)));
181 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QBitArray*)data)));
182 case QMetaType::QLocale:
182 case QMetaType::QLocale:
183 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLocale*)data)));
183 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QLocale*)data)));
184 case QMetaType::QFont:
184 case QMetaType::QFont:
185 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QFont*)data)));
185 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QFont*)data)));
186 case QMetaType::QBrush:
186 case QMetaType::QBrush:
187 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QBrush*)data)));
187 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QBrush*)data)));
188 case QMetaType::QPalette:
188 case QMetaType::QPalette:
189 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPalette*)data)));
189 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPalette*)data)));
190 case QMetaType::QIcon:
190 case QMetaType::QIcon:
191 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QIcon*)data)));
191 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QIcon*)data)));
192 case QMetaType::QImage:
192 case QMetaType::QImage:
193 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QImage*)data)));
193 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QImage*)data)));
194 case QMetaType::QPolygon:
194 case QMetaType::QPolygon:
195 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPolygon*)data)));
195 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QPolygon*)data)));
196 case QMetaType::QRegion:
196 case QMetaType::QRegion:
197 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRegion*)data)));
197 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QRegion*)data)));
198 case QMetaType::QBitmap:
198 case QMetaType::QBitmap:
199 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QBitmap*)data)));
199 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QBitmap*)data)));
200 case QMetaType::QCursor:
200 case QMetaType::QCursor:
201 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QCursor*)data)));
201 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QCursor*)data)));
202 case QMetaType::QSizePolicy:
202 case QMetaType::QSizePolicy:
203 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSizePolicy*)data)));
203 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(QVariant(*((QSizePolicy*)data)));
204 case QMetaType::QKeySequence:
204 case QMetaType::QKeySequence:
205 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QKeySequence*)data)));
205 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QKeySequence*)data)));
206 case QMetaType::QPen:
206 case QMetaType::QPen:
207 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QPen*)data)));
207 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QPen*)data)));
208 case QMetaType::QTextLength:
208 case QMetaType::QTextLength:
209 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QTextLength*)data)));
209 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QTextLength*)data)));
210 case QMetaType::QTextFormat:
210 case QMetaType::QTextFormat:
211 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QTextFormat*)data)));
211 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QTextFormat*)data)));
212 case QMetaType::QMatrix:
212 case QMetaType::QMatrix:
213 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QMatrix*)data)));
213 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(qVariantFromValue(*((QMatrix*)data)));
214 default:
214 default:
215 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
215 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
216 PyObject* o = ((PythonQtObjectPtr*)data)->object();
216 PyObject* o = ((PythonQtObjectPtr*)data)->object();
217 Py_INCREF(o);
217 Py_INCREF(o);
218 return o;
218 return o;
219 } else {
219 } else {
220 if (type != PythonQtMethodInfo::Unknown) {
220 if (type != PythonQtMethodInfo::Unknown) {
221 QVariant v(type, data);
221 QVariant v(type, data);
222 if (v.isValid()) {
222 if (v.isValid()) {
223 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(v);
223 return (PyObject*)PythonQt::priv()->createNewPythonQtVariantWrapper(v);
224 }
224 }
225 }
225 }
226 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
226 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
227 }
227 }
228 }
228 }
229 Py_INCREF(Py_None);
229 Py_INCREF(Py_None);
230 return Py_None;
230 return Py_None;
231 }
231 }
232
232
233 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
233 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
234 void* ptr = NULL;
234 void* ptr = NULL;
235 if (info.isPointer) {
235 if (info.isPointer) {
236 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
236 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
237 } else {
237 } else {
238 switch (info.typeId) {
238 switch (info.typeId) {
239 case QMetaType::Char:
239 case QMetaType::Char:
240 case QMetaType::UChar:
240 case QMetaType::UChar:
241 case QMetaType::Short:
241 case QMetaType::Short:
242 case QMetaType::UShort:
242 case QMetaType::UShort:
243 case QMetaType::Long:
243 case QMetaType::Long:
244 case QMetaType::ULong:
244 case QMetaType::ULong:
245 case QMetaType::Bool:
245 case QMetaType::Bool:
246 case QMetaType::Int:
246 case QMetaType::Int:
247 case QMetaType::UInt:
247 case QMetaType::UInt:
248 case QMetaType::QChar:
248 case QMetaType::QChar:
249 case QMetaType::Float:
249 case QMetaType::Float:
250 case QMetaType::Double:
250 case QMetaType::Double:
251 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
251 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, 0, ptr);
252 break;
252 break;
253 case PythonQtMethodInfo::Variant:
253 case PythonQtMethodInfo::Variant:
254 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
254 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
255 // return the ptr to the variant
255 // return the ptr to the variant
256 break;
256 break;
257 default:
257 default:
258 if (info.typeId == PythonQtMethodInfo::Unknown) {
258 if (info.typeId == PythonQtMethodInfo::Unknown) {
259 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
259 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
260 if (info.name.startsWith("QList<")) {
260 if (info.name.startsWith("QList<")) {
261 QByteArray innerType = info.name.mid(6,info.name.length()-7);
261 QByteArray innerType = info.name.mid(6,info.name.length()-7);
262 if (innerType.endsWith("*")) {
262 if (innerType.endsWith("*")) {
263 static int id = QMetaType::type("QList<void*>");
263 static int id = QMetaType::type("QList<void*>");
264 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
264 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
265 // return the constData pointer that will be filled with the result value later on
265 // return the constData pointer that will be filled with the result value later on
266 ptr = (void*)((QVariant*)ptr)->constData();
266 ptr = (void*)((QVariant*)ptr)->constData();
267 }
267 }
268 }
268 }
269 }
269 }
270
270
271 if (!ptr) {
271 if (!ptr) {
272 // everything else is stored in a QVariant...
272 // everything else is stored in a QVariant...
273 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
273 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
274 // return the constData pointer that will be filled with the result value later on
274 // return the constData pointer that will be filled with the result value later on
275 ptr = (void*)((QVariant*)ptr)->constData();
275 ptr = (void*)((QVariant*)ptr)->constData();
276 }
276 }
277 }
277 }
278 }
278 }
279 return ptr;
279 return ptr;
280 }
280 }
281
281
282 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, const QMetaObject* meta)
282 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, const QMetaObject* meta)
283 {
283 {
284 bool ok;
284 bool ok;
285 void* ptr = NULL;
285 void* ptr = NULL;
286 if (info.isPointer) {
286 if (info.isPointer) {
287 if (obj->ob_type == &PythonQtWrapper_Type) {
287 if (obj->ob_type == &PythonQtWrapper_Type) {
288 PythonQtWrapper* wrap = (PythonQtWrapper*)obj;
288 PythonQtWrapper* wrap = (PythonQtWrapper*)obj;
289 // c++ wrapper, check if the class names of the c++ objects match
289 // c++ wrapper, check if the class names of the c++ objects match
290 if (wrap->_info->isCPPWrapper()) {
290 if (wrap->_info->isCPPWrapper()) {
291 //TODO: we could support inheritance on cpp wrappers as well
291 //TODO: we could support inheritance on cpp wrappers as well
292 if (wrap->_info->wrappedCPPClassName() == info.name) {
292 if (wrap->_info->wrappedCPPClassName() == info.name) {
293 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, wrap->_wrappedPtr, ptr);
293 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, wrap->_wrappedPtr, ptr);
294 } else {
294 } else {
295 // not matching
295 // not matching
296 }
296 }
297 } else {
297 } else {
298 if (wrap->_info->inherits(info.name)) {
298 if (wrap->_info->inherits(info.name)) {
299 QObject* myObject = wrap->_obj;
299 QObject* myObject = wrap->_obj;
300 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, myObject, ptr);
300 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, myObject, ptr);
301 } else {
301 } else {
302 // not matching
302 // not matching
303 }
303 }
304 }
304 }
305 } else
305 } else
306 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar) {
306 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar) {
307 QString str = PyObjGetString(obj, strict, ok);
307 QString str = PyObjGetString(obj, strict, ok);
308 if (ok) {
308 if (ok) {
309 void* ptr2 = NULL;
309 void* ptr2 = NULL;
310 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
310 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str.toUtf8()), ptr2);
311 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
311 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
312 }
312 }
313 } else if (info.name == "PyObject") {
313 } else if (info.name == "PyObject") {
314 // handle low level PyObject directly
314 // handle low level PyObject directly
315 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, obj, ptr);
315 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, obj, ptr);
316 } else if (obj == Py_None) {
316 } else if (obj == Py_None) {
317 // None is treated as a NULL ptr
317 // None is treated as a NULL ptr
318 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
318 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
319 } else {
319 } else {
320 // if we are not strict, we try if we are passed a 0 integer
320 // if we are not strict, we try if we are passed a 0 integer
321 if (!strict) {
321 if (!strict) {
322 bool ok;
322 bool ok;
323 int value = PyObjGetInt(obj, true, ok);
323 int value = PyObjGetInt(obj, true, ok);
324 if (ok && value==0) {
324 if (ok && value==0) {
325 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
325 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
326 }
326 }
327 }
327 }
328 // EXTRA: we could support pointers to other simple types, but this would not make sense in most situations
328 // EXTRA: we could support pointers to other simple types, but this would not make sense in most situations
329 }
329 }
330
330
331 } else {
331 } else {
332 // not a pointer
332 // not a pointer
333 switch (info.typeId) {
333 switch (info.typeId) {
334 case QMetaType::Char:
334 case QMetaType::Char:
335 {
335 {
336 int val = PyObjGetInt(obj, strict, ok);
336 int val = PyObjGetInt(obj, strict, ok);
337 if (ok) {
337 if (ok) {
338 PythonQtValueStorage_ADD_VALUE(global_valueStorage, char, val, ptr);
338 PythonQtValueStorage_ADD_VALUE(global_valueStorage, char, val, ptr);
339 }
339 }
340 }
340 }
341 break;
341 break;
342 case QMetaType::UChar:
342 case QMetaType::UChar:
343 {
343 {
344 int val = PyObjGetInt(obj, strict, ok);
344 int val = PyObjGetInt(obj, strict, ok);
345 if (ok) {
345 if (ok) {
346 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned char, val, ptr);
346 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned char, val, ptr);
347 }
347 }
348 }
348 }
349 break;
349 break;
350 case QMetaType::Short:
350 case QMetaType::Short:
351 {
351 {
352 int val = PyObjGetInt(obj, strict, ok);
352 int val = PyObjGetInt(obj, strict, ok);
353 if (ok) {
353 if (ok) {
354 PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
354 PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
355 }
355 }
356 }
356 }
357 break;
357 break;
358 case QMetaType::UShort:
358 case QMetaType::UShort:
359 {
359 {
360 int val = PyObjGetInt(obj, strict, ok);
360 int val = PyObjGetInt(obj, strict, ok);
361 if (ok) {
361 if (ok) {
362 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned short, val, ptr);
362 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned short, val, ptr);
363 }
363 }
364 }
364 }
365 break;
365 break;
366 case QMetaType::Long:
366 case QMetaType::Long:
367 {
367 {
368 long val = (long)PyObjGetLongLong(obj, strict, ok);
368 long val = (long)PyObjGetLongLong(obj, strict, ok);
369 if (ok) {
369 if (ok) {
370 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, val, ptr);
370 PythonQtValueStorage_ADD_VALUE(global_valueStorage, long, val, ptr);
371 }
371 }
372 }
372 }
373 break;
373 break;
374 case QMetaType::ULong:
374 case QMetaType::ULong:
375 {
375 {
376 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
376 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
377 if (ok) {
377 if (ok) {
378 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned long, val, ptr);
378 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned long, val, ptr);
379 }
379 }
380 }
380 }
381 break;
381 break;
382 case QMetaType::Bool:
382 case QMetaType::Bool:
383 {
383 {
384 bool val = PyObjGetBool(obj, strict, ok);
384 bool val = PyObjGetBool(obj, strict, ok);
385 if (ok) {
385 if (ok) {
386 PythonQtValueStorage_ADD_VALUE(global_valueStorage, bool, val, ptr);
386 PythonQtValueStorage_ADD_VALUE(global_valueStorage, bool, val, ptr);
387 }
387 }
388 }
388 }
389 break;
389 break;
390 case QMetaType::Int:
390 case QMetaType::Int:
391 {
391 {
392 int val = PyObjGetInt(obj, strict, ok);
392 int val = PyObjGetInt(obj, strict, ok);
393 if (ok) {
393 if (ok) {
394 PythonQtValueStorage_ADD_VALUE(global_valueStorage, int, val, ptr);
394 PythonQtValueStorage_ADD_VALUE(global_valueStorage, int, val, ptr);
395 }
395 }
396 }
396 }
397 break;
397 break;
398 case QMetaType::UInt:
398 case QMetaType::UInt:
399 {
399 {
400 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
400 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
401 if (ok) {
401 if (ok) {
402 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
402 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
403 }
403 }
404 }
404 }
405 break;
405 break;
406 case QMetaType::QChar:
406 case QMetaType::QChar:
407 {
407 {
408 int val = PyObjGetInt(obj, strict, ok);
408 int val = PyObjGetInt(obj, strict, ok);
409 if (ok) {
409 if (ok) {
410 PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
410 PythonQtValueStorage_ADD_VALUE(global_valueStorage, short, val, ptr);
411 }
411 }
412 }
412 }
413 break;
413 break;
414 case QMetaType::Float:
414 case QMetaType::Float:
415 {
415 {
416 float val = (float)PyObjGetDouble(obj, strict, ok);
416 float val = (float)PyObjGetDouble(obj, strict, ok);
417 if (ok) {
417 if (ok) {
418 PythonQtValueStorage_ADD_VALUE(global_valueStorage, float, val, ptr);
418 PythonQtValueStorage_ADD_VALUE(global_valueStorage, float, val, ptr);
419 }
419 }
420 }
420 }
421 break;
421 break;
422 case QMetaType::Double:
422 case QMetaType::Double:
423 {
423 {
424 double val = (double)PyObjGetDouble(obj, strict, ok);
424 double val = (double)PyObjGetDouble(obj, strict, ok);
425 if (ok) {
425 if (ok) {
426 PythonQtValueStorage_ADD_VALUE(global_valueStorage, double, val, ptr);
426 PythonQtValueStorage_ADD_VALUE(global_valueStorage, double, val, ptr);
427 }
427 }
428 }
428 }
429 break;
429 break;
430 case QMetaType::LongLong:
430 case QMetaType::LongLong:
431 {
431 {
432 qint64 val = PyObjGetLongLong(obj, strict, ok);
432 qint64 val = PyObjGetLongLong(obj, strict, ok);
433 if (ok) {
433 if (ok) {
434 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, val, ptr);
434 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, val, ptr);
435 }
435 }
436 }
436 }
437 break;
437 break;
438 case QMetaType::ULongLong:
438 case QMetaType::ULongLong:
439 {
439 {
440 quint64 val = PyObjGetULongLong(obj, strict, ok);
440 quint64 val = PyObjGetULongLong(obj, strict, ok);
441 if (ok) {
441 if (ok) {
442 PythonQtValueStorage_ADD_VALUE(global_valueStorage, quint64, val, ptr);
442 PythonQtValueStorage_ADD_VALUE(global_valueStorage, quint64, val, ptr);
443 }
443 }
444 }
444 }
445 break;
445 break;
446 case QMetaType::QByteArray:
446 case QMetaType::QByteArray:
447 {
447 {
448 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
448 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
449 if (ok) {
449 if (ok) {
450 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(bytes), ptr);
450 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(bytes), ptr);
451 ptr = (void*)((QVariant*)ptr)->constData();
451 ptr = (void*)((QVariant*)ptr)->constData();
452 }
452 }
453 }
453 }
454 break;
454 break;
455 case QMetaType::QString:
455 case QMetaType::QString:
456 {
456 {
457 QString str = PyObjGetString(obj, strict, ok);
457 QString str = PyObjGetString(obj, strict, ok);
458 if (ok) {
458 if (ok) {
459 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str), ptr);
459 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(str), ptr);
460 ptr = (void*)((QVariant*)ptr)->constData();
460 ptr = (void*)((QVariant*)ptr)->constData();
461 }
461 }
462 }
462 }
463 break;
463 break;
464 case QMetaType::QStringList:
464 case QMetaType::QStringList:
465 {
465 {
466 QStringList l = PyObjToStringList(obj, strict, ok);
466 QStringList l = PyObjToStringList(obj, strict, ok);
467 if (ok) {
467 if (ok) {
468 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(l), ptr);
468 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant(l), ptr);
469 ptr = (void*)((QVariant*)ptr)->constData();
469 ptr = (void*)((QVariant*)ptr)->constData();
470 }
470 }
471 }
471 }
472 break;
472 break;
473
473
474 case PythonQtMethodInfo::Variant:
474 case PythonQtMethodInfo::Variant:
475 {
475 {
476 QVariant v = PyObjToQVariant(obj);
476 QVariant v = PyObjToQVariant(obj);
477 if (v.isValid()) {
477 if (v.isValid()) {
478 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
478 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
479 }
479 }
480 }
480 }
481 break;
481 break;
482 default:
482 default:
483 {
483 {
484 if (info.typeId == PythonQtMethodInfo::Unknown) {
484 if (info.typeId == PythonQtMethodInfo::Unknown) {
485 // check for enum case
485 // check for enum case
486 if (PythonQt::priv()->isEnumType(meta, info.name)) {
486 if (PythonQt::priv()->isEnumType(meta, info.name)) {
487 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
487 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
488 if (ok) {
488 if (ok) {
489 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
489 PythonQtValueStorage_ADD_VALUE(global_valueStorage, unsigned int, val, ptr);
490 return ptr;
490 return ptr;
491 } else {
491 } else {
492 return NULL;
492 return NULL;
493 }
493 }
494 }
494 }
495 }
495 }
496 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
496 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
497 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
497 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
498 if (info.name.startsWith("QList<")) {
498 if (info.name.startsWith("QList<")) {
499 QByteArray innerType = info.name.mid(6,info.name.length()-7);
499 QByteArray innerType = info.name.mid(6,info.name.length()-7);
500 if (innerType.endsWith("*")) {
500 if (innerType.endsWith("*")) {
501 innerType.truncate(innerType.length()-1);
501 innerType.truncate(innerType.length()-1);
502 static int id = QMetaType::type("QList<void*>");
502 static int id = QMetaType::type("QList<void*>");
503 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
503 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
504 ptr = (void*)((QVariant*)ptr)->constData();
504 ptr = (void*)((QVariant*)ptr)->constData();
505 ok = ConvertPythonListToQListOfType(obj, (QList<void*>*)ptr, innerType, strict);
505 ok = ConvertPythonListToQListOfType(obj, (QList<void*>*)ptr, innerType, strict);
506 if (ok) {
506 if (ok) {
507 return ptr;
507 return ptr;
508 } else {
508 } else {
509 return NULL;
509 return NULL;
510 }
510 }
511 }
511 }
512 }
512 }
513 }
513 }
514
514
515 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
515 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
516 QVariant v = PyObjToQVariant(obj, info.typeId);
516 QVariant v = PyObjToQVariant(obj, info.typeId);
517 if (v.isValid()) {
517 if (v.isValid()) {
518 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
518 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, v, ptr);
519 ptr = (void*)((QVariant*)ptr)->constData();
519 ptr = (void*)((QVariant*)ptr)->constData();
520 }
520 }
521 }
521 }
522 }
522 }
523 }
523 }
524 return ptr;
524 return ptr;
525 }
525 }
526
526
527
527
528 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
528 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
529 QStringList v;
529 QStringList v;
530 ok = false;
530 ok = false;
531 // if we are strict, we do not want to convert a string to a stringlist
531 // if we are strict, we do not want to convert a string to a stringlist
532 // (strings in python are detected to be sequences)
532 // (strings in python are detected to be sequences)
533 if (strict &&
533 if (strict &&
534 (val->ob_type == &PyString_Type ||
534 (val->ob_type == &PyString_Type ||
535 PyUnicode_Check(val))) {
535 PyUnicode_Check(val))) {
536 ok = false;
536 ok = false;
537 return v;
537 return v;
538 }
538 }
539 if (PySequence_Check(val)) {
539 if (PySequence_Check(val)) {
540 int count = PySequence_Size(val);
540 int count = PySequence_Size(val);
541 for (int i = 0;i<count;i++) {
541 for (int i = 0;i<count;i++) {
542 PyObject* value = PySequence_GetItem(val,i);
542 PyObject* value = PySequence_GetItem(val,i);
543 v.append(PyObjGetString(value,false,ok));
543 v.append(PyObjGetString(value,false,ok));
544 }
544 }
545 ok = true;
545 ok = true;
546 }
546 }
547 return v;
547 return v;
548 }
548 }
549
549
550 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
550 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
551 {
551 {
552 QString r;
552 QString r;
553 PyObject* str = PyObject_Repr(val);
553 PyObject* str = PyObject_Repr(val);
554 if (str) {
554 if (str) {
555 r = QString(PyString_AS_STRING(str));
555 r = QString(PyString_AS_STRING(str));
556 Py_DECREF(str);
556 Py_DECREF(str);
557 }
557 }
558 return r;
558 return r;
559 }
559 }
560
560
561 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
561 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
562 QString r;
562 QString r;
563 ok = true;
563 ok = true;
564 if (val->ob_type == &PyString_Type) {
564 if (val->ob_type == &PyString_Type) {
565 r = QString(PyString_AS_STRING(val));
565 r = QString(PyString_AS_STRING(val));
566 } else if (PyUnicode_Check(val)) {
566 } else if (PyUnicode_Check(val)) {
567 #ifdef WIN32
567 #ifdef WIN32
568 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
568 r = QString::fromUtf16(PyUnicode_AS_UNICODE(val));
569 #else
569 #else
570 PyObject *ptmp = PyUnicode_AsUTF8String(val);
570 PyObject *ptmp = PyUnicode_AsUTF8String(val);
571 if(ptmp) {
571 if(ptmp) {
572 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
572 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
573 Py_DECREF(ptmp);
573 Py_DECREF(ptmp);
574 }
574 }
575 #endif
575 #endif
576 } else if (!strict) {
576 } else if (!strict) {
577 // EXTRA: could also use _Unicode, but why should we?
577 // EXTRA: could also use _Unicode, but why should we?
578 PyObject* str = PyObject_Str(val);
578 PyObject* str = PyObject_Str(val);
579 if (str) {
579 if (str) {
580 r = QString(PyString_AS_STRING(str));
580 r = QString(PyString_AS_STRING(str));
581 Py_DECREF(str);
581 Py_DECREF(str);
582 } else {
582 } else {
583 ok = false;
583 ok = false;
584 }
584 }
585 } else {
585 } else {
586 ok = false;
586 ok = false;
587 }
587 }
588 return r;
588 return r;
589 }
589 }
590
590
591 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool strict, bool& ok) {
591 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
592 QByteArray r;
592 QByteArray r;
593 ok = true;
593 ok = true;
594 if (val->ob_type == &PyString_Type) {
594 if (val->ob_type == &PyString_Type) {
595 long size = PyString_GET_SIZE(val);
595 long size = PyString_GET_SIZE(val);
596 r = QByteArray(PyString_AS_STRING(val), size);
596 r = QByteArray(PyString_AS_STRING(val), size);
597 } else {
597 } else {
598 ok = false;
598 ok = false;
599 }
599 }
600 return r;
600 return r;
601 }
601 }
602
602
603 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
603 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
604 bool d = false;
604 bool d = false;
605 ok = false;
605 ok = false;
606 if (val == Py_False) {
606 if (val == Py_False) {
607 d = false;
607 d = false;
608 ok = true;
608 ok = true;
609 } else if (val == Py_True) {
609 } else if (val == Py_True) {
610 d = true;
610 d = true;
611 ok = true;
611 ok = true;
612 } else if (!strict) {
612 } else if (!strict) {
613 d = PyObjGetInt(val, false, ok)!=0;
613 d = PyObjGetInt(val, false, ok)!=0;
614 ok = true;
614 ok = true;
615 }
615 }
616 return d;
616 return d;
617 }
617 }
618
618
619 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
619 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
620 int d = 0;
620 int d = 0;
621 ok = true;
621 ok = true;
622 if (val->ob_type == &PyInt_Type) {
622 if (val->ob_type == &PyInt_Type) {
623 d = PyInt_AS_LONG(val);
623 d = PyInt_AS_LONG(val);
624 } else if (!strict) {
624 } else if (!strict) {
625 if (val->ob_type == &PyFloat_Type) {
625 if (val->ob_type == &PyFloat_Type) {
626 d = floor(PyFloat_AS_DOUBLE(val));
626 d = floor(PyFloat_AS_DOUBLE(val));
627 } else if (val->ob_type == &PyLong_Type) {
627 } else if (val->ob_type == &PyLong_Type) {
628 // handle error on overflow!
628 // handle error on overflow!
629 d = PyLong_AsLong(val);
629 d = PyLong_AsLong(val);
630 } else if (val == Py_False) {
630 } else if (val == Py_False) {
631 d = 0;
631 d = 0;
632 } else if (val == Py_True) {
632 } else if (val == Py_True) {
633 d = 1;
633 d = 1;
634 } else {
634 } else {
635 ok = false;
635 ok = false;
636 }
636 }
637 } else {
637 } else {
638 ok = false;
638 ok = false;
639 }
639 }
640 return d;
640 return d;
641 }
641 }
642
642
643 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
643 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
644 qint64 d = 0;
644 qint64 d = 0;
645 ok = true;
645 ok = true;
646 if (val->ob_type == &PyInt_Type) {
646 if (val->ob_type == &PyInt_Type) {
647 d = PyInt_AS_LONG(val);
647 d = PyInt_AS_LONG(val);
648 } else if (val->ob_type == &PyLong_Type) {
648 } else if (val->ob_type == &PyLong_Type) {
649 d = PyLong_AsLongLong(val);
649 d = PyLong_AsLongLong(val);
650 } else if (!strict) {
650 } else if (!strict) {
651 if (val->ob_type == &PyFloat_Type) {
651 if (val->ob_type == &PyFloat_Type) {
652 d = floor(PyFloat_AS_DOUBLE(val));
652 d = floor(PyFloat_AS_DOUBLE(val));
653 } else if (val == Py_False) {
653 } else if (val == Py_False) {
654 d = 0;
654 d = 0;
655 } else if (val == Py_True) {
655 } else if (val == Py_True) {
656 d = 1;
656 d = 1;
657 } else {
657 } else {
658 ok = false;
658 ok = false;
659 }
659 }
660 } else {
660 } else {
661 ok = false;
661 ok = false;
662 }
662 }
663 return d;
663 return d;
664 }
664 }
665
665
666 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
666 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
667 quint64 d = 0;
667 quint64 d = 0;
668 ok = true;
668 ok = true;
669 if (val->ob_type == &PyInt_Type) {
669 if (val->ob_type == &PyInt_Type) {
670 d = PyInt_AS_LONG(val);
670 d = PyInt_AS_LONG(val);
671 } else if (val->ob_type == &PyLong_Type) {
671 } else if (val->ob_type == &PyLong_Type) {
672 d = PyLong_AsLongLong(val);
672 d = PyLong_AsLongLong(val);
673 } else if (!strict) {
673 } else if (!strict) {
674 if (val->ob_type == &PyFloat_Type) {
674 if (val->ob_type == &PyFloat_Type) {
675 d = floor(PyFloat_AS_DOUBLE(val));
675 d = floor(PyFloat_AS_DOUBLE(val));
676 } else if (val == Py_False) {
676 } else if (val == Py_False) {
677 d = 0;
677 d = 0;
678 } else if (val == Py_True) {
678 } else if (val == Py_True) {
679 d = 1;
679 d = 1;
680 } else {
680 } else {
681 ok = false;
681 ok = false;
682 }
682 }
683 } else {
683 } else {
684 ok = false;
684 ok = false;
685 }
685 }
686 return d;
686 return d;
687 }
687 }
688
688
689 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
689 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
690 double d = 0;
690 double d = 0;
691 ok = true;
691 ok = true;
692 if (val->ob_type == &PyFloat_Type) {
692 if (val->ob_type == &PyFloat_Type) {
693 d = PyFloat_AS_DOUBLE(val);
693 d = PyFloat_AS_DOUBLE(val);
694 } else if (!strict) {
694 } else if (!strict) {
695 if (val->ob_type == &PyInt_Type) {
695 if (val->ob_type == &PyInt_Type) {
696 d = PyInt_AS_LONG(val);
696 d = PyInt_AS_LONG(val);
697 } else if (val->ob_type == &PyLong_Type) {
697 } else if (val->ob_type == &PyLong_Type) {
698 d = PyLong_AsLong(val);
698 d = PyLong_AsLong(val);
699 } else if (val == Py_False) {
699 } else if (val == Py_False) {
700 d = 0;
700 d = 0;
701 } else if (val == Py_True) {
701 } else if (val == Py_True) {
702 d = 1;
702 d = 1;
703 } else {
703 } else {
704 ok = false;
704 ok = false;
705 }
705 }
706 } else {
706 } else {
707 ok = false;
707 ok = false;
708 }
708 }
709 return d;
709 return d;
710 }
710 }
711
711
712 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
712 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
713 {
713 {
714 QVariant v;
714 QVariant v;
715 bool ok = true;
715 bool ok = true;
716
716
717 if (type==-1) {
717 if (type==-1) {
718 // no special type requested
718 // no special type requested
719 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
719 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
720 type = QVariant::String;
720 type = QVariant::String;
721 } else if (val->ob_type==&PyInt_Type) {
721 } else if (val->ob_type==&PyInt_Type) {
722 type = QVariant::Int;
722 type = QVariant::Int;
723 } else if (val->ob_type==&PyLong_Type) {
723 } else if (val->ob_type==&PyLong_Type) {
724 type = QVariant::LongLong;
724 type = QVariant::LongLong;
725 } else if (val->ob_type==&PyFloat_Type) {
725 } else if (val->ob_type==&PyFloat_Type) {
726 type = QVariant::Double;
726 type = QVariant::Double;
727 } else if (val == Py_False || val == Py_True) {
727 } else if (val == Py_False || val == Py_True) {
728 type = QVariant::Bool;
728 type = QVariant::Bool;
729 } else if (val->ob_type == &PythonQtWrapper_Type) {
729 } else if (val->ob_type == &PythonQtWrapper_Type) {
730 PythonQtWrapper* wrap = (PythonQtWrapper*)val;
730 PythonQtWrapper* wrap = (PythonQtWrapper*)val;
731 // c++ wrapper, check if the class names of the c++ objects match
731 // c++ wrapper, check if the class names of the c++ objects match
732 if (wrap->_info->isCPPWrapper()) {
732 if (wrap->_info->isCPPWrapper()) {
733 // is this worth anything? we loose the knowledge of the cpp object type
733 // is this worth anything? we loose the knowledge of the cpp object type
734 v = qVariantFromValue(wrap->_wrappedPtr);
734 v = qVariantFromValue(wrap->_wrappedPtr);
735 } else {
735 } else {
736 QObject* myObject = wrap->_obj;
736 QObject* myObject = wrap->_obj;
737 v = qVariantFromValue(myObject);
737 v = qVariantFromValue(myObject);
738 }
738 }
739 return v;
739 return v;
740 } else if (val->ob_type==&PyDict_Type) {
740 } else if (val->ob_type==&PyDict_Type) {
741 type = QVariant::Map;
741 type = QVariant::Map;
742 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
742 } else if (val->ob_type==&PyList_Type || val->ob_type==&PyTuple_Type || PySequence_Check(val)) {
743 type = QVariant::List;
743 type = QVariant::List;
744 } else if (val == Py_None) {
744 } else if (val == Py_None) {
745 // none is invalid
745 // none is invalid
746 type = QVariant::Invalid;
746 type = QVariant::Invalid;
747 } else if (val->ob_type == &PythonQtVariantWrapper_Type) {
747 } else if (val->ob_type == &PythonQtVariantWrapper_Type) {
748 PythonQtVariantWrapper* varWrap = (PythonQtVariantWrapper*)val;
748 PythonQtVariantWrapper* varWrap = (PythonQtVariantWrapper*)val;
749 if (varWrap->_variant->userType() == type) {
749 if (varWrap->_variant->userType() == type) {
750 v = *varWrap->_variant;
750 v = *varWrap->_variant;
751 return v;
751 return v;
752 }
752 }
753 } else {
753 } else {
754 // this used to be:
754 // this used to be:
755 // type = QVariant::String;
755 // type = QVariant::String;
756 // but now we want to transport the Python Objects directly:
756 // but now we want to transport the Python Objects directly:
757 PythonQtObjectPtr o(val);
757 PythonQtObjectPtr o(val);
758 v = qVariantFromValue(o);
758 v = qVariantFromValue(o);
759 return v;
759 return v;
760 }
760 }
761 }
761 }
762 // special type request:
762 // special type request:
763 switch (type) {
763 switch (type) {
764 case QVariant::Invalid:
764 case QVariant::Invalid:
765 return v;
765 return v;
766 break;
766 break;
767 case QVariant::Int:
767 case QVariant::Int:
768 {
768 {
769 int d = PyObjGetInt(val, false, ok);
769 int d = PyObjGetInt(val, false, ok);
770 if (ok) return QVariant(d);
770 if (ok) return QVariant(d);
771 }
771 }
772 break;
772 break;
773 case QVariant::UInt:
773 case QVariant::UInt:
774 {
774 {
775 int d = PyObjGetInt(val, false,ok);
775 int d = PyObjGetInt(val, false,ok);
776 if (ok) v = QVariant((unsigned int)d);
776 if (ok) v = QVariant((unsigned int)d);
777 }
777 }
778 break;
778 break;
779 case QVariant::Bool:
779 case QVariant::Bool:
780 {
780 {
781 int d = PyObjGetBool(val,false,ok);
781 int d = PyObjGetBool(val,false,ok);
782 if (ok) v = QVariant((bool)(d!=0));
782 if (ok) v = QVariant((bool)(d!=0));
783 }
783 }
784 break;
784 break;
785 case QVariant::Double:
785 case QVariant::Double:
786 {
786 {
787 double d = PyObjGetDouble(val,false,ok);
787 double d = PyObjGetDouble(val,false,ok);
788 if (ok) v = QVariant(d);
788 if (ok) v = QVariant(d);
789 break;
789 break;
790 }
790 }
791 case QMetaType::Float:
791 case QMetaType::Float:
792 {
792 {
793 float d = (float) PyObjGetDouble(val,false,ok);
793 float d = (float) PyObjGetDouble(val,false,ok);
794 if (ok) v = qVariantFromValue(d);
794 if (ok) v = qVariantFromValue(d);
795 break;
795 break;
796 }
796 }
797 case QMetaType::Long:
797 case QMetaType::Long:
798 {
798 {
799 long d = (long) PyObjGetLongLong(val,false,ok);
799 long d = (long) PyObjGetLongLong(val,false,ok);
800 if (ok) v = qVariantFromValue(d);
800 if (ok) v = qVariantFromValue(d);
801 break;
801 break;
802 }
802 }
803 case QMetaType::ULong:
803 case QMetaType::ULong:
804 {
804 {
805 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
805 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
806 if (ok) v = qVariantFromValue(d);
806 if (ok) v = qVariantFromValue(d);
807 break;
807 break;
808 }
808 }
809 case QMetaType::Short:
809 case QMetaType::Short:
810 {
810 {
811 short d = (short) PyObjGetInt(val,false,ok);
811 short d = (short) PyObjGetInt(val,false,ok);
812 if (ok) v = qVariantFromValue(d);
812 if (ok) v = qVariantFromValue(d);
813 break;
813 break;
814 }
814 }
815 case QMetaType::UShort:
815 case QMetaType::UShort:
816 {
816 {
817 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
817 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
818 if (ok) v = qVariantFromValue(d);
818 if (ok) v = qVariantFromValue(d);
819 break;
819 break;
820 }
820 }
821 case QMetaType::Char:
821 case QMetaType::Char:
822 {
822 {
823 char d = (char) PyObjGetInt(val,false,ok);
823 char d = (char) PyObjGetInt(val,false,ok);
824 if (ok) v = qVariantFromValue(d);
824 if (ok) v = qVariantFromValue(d);
825 break;
825 break;
826 }
826 }
827 case QMetaType::UChar:
827 case QMetaType::UChar:
828 {
828 {
829 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
829 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
830 if (ok) v = qVariantFromValue(d);
830 if (ok) v = qVariantFromValue(d);
831 break;
831 break;
832 }
832 }
833
833
834 case QVariant::ByteArray:
834 case QVariant::ByteArray:
835 case QVariant::String:
835 case QVariant::String:
836 {
836 {
837 bool ok;
837 bool ok;
838 v = QVariant(PyObjGetString(val, false, ok));
838 v = QVariant(PyObjGetString(val, false, ok));
839 }
839 }
840 break;
840 break;
841
841
842 // these are important for MeVisLab
842 // these are important for MeVisLab
843 case QVariant::Map:
843 case QVariant::Map:
844 {
844 {
845 if (PyMapping_Check(val)) {
845 if (PyMapping_Check(val)) {
846 QMap<QString,QVariant> map;
846 QMap<QString,QVariant> map;
847 PyObject* items = PyMapping_Items(val);
847 PyObject* items = PyMapping_Items(val);
848 if (items) {
848 if (items) {
849 int count = PyList_Size(items);
849 int count = PyList_Size(items);
850 PyObject* value;
850 PyObject* value;
851 PyObject* key;
851 PyObject* key;
852 PyObject* tuple;
852 PyObject* tuple;
853 for (int i = 0;i<count;i++) {
853 for (int i = 0;i<count;i++) {
854 tuple = PyList_GetItem(items,i);
854 tuple = PyList_GetItem(items,i);
855 key = PyTuple_GetItem(tuple, 0);
855 key = PyTuple_GetItem(tuple, 0);
856 value = PyTuple_GetItem(tuple, 1);
856 value = PyTuple_GetItem(tuple, 1);
857 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
857 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
858 }
858 }
859 Py_DECREF(items);
859 Py_DECREF(items);
860 v = map;
860 v = map;
861 }
861 }
862 }
862 }
863 }
863 }
864 break;
864 break;
865 case QVariant::List:
865 case QVariant::List:
866 if (PySequence_Check(val)) {
866 if (PySequence_Check(val)) {
867 QVariantList list;
867 QVariantList list;
868 int count = PySequence_Size(val);
868 int count = PySequence_Size(val);
869 PyObject* value;
869 PyObject* value;
870 for (int i = 0;i<count;i++) {
870 for (int i = 0;i<count;i++) {
871 value = PySequence_GetItem(val,i);
871 value = PySequence_GetItem(val,i);
872 list.append(PyObjToQVariant(value, -1));
872 list.append(PyObjToQVariant(value, -1));
873 }
873 }
874 v = list;
874 v = list;
875 }
875 }
876 break;
876 break;
877 case QVariant::StringList:
877 case QVariant::StringList:
878 {
878 {
879 bool ok;
879 bool ok;
880 QStringList l = PyObjToStringList(val, false, ok);
880 QStringList l = PyObjToStringList(val, false, ok);
881 if (ok) {
881 if (ok) {
882 v = l;
882 v = l;
883 }
883 }
884 }
884 }
885 break;
885 break;
886
886
887 default:
887 default:
888 if (val->ob_type == &PythonQtVariantWrapper_Type) {
888 if (val->ob_type == &PythonQtVariantWrapper_Type) {
889 PythonQtVariantWrapper* varWrap = (PythonQtVariantWrapper*)val;
889 PythonQtVariantWrapper* varWrap = (PythonQtVariantWrapper*)val;
890 if (varWrap->_variant->userType() == type) {
890 if (varWrap->_variant->userType() == type) {
891 v = *varWrap->_variant;
891 v = *varWrap->_variant;
892 }
892 }
893 } else {
893 } else {
894 v = QVariant();
894 v = QVariant();
895 }
895 }
896 }
896 }
897 return v;
897 return v;
898 }
898 }
899
899
900 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
900 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
901 {
901 {
902 if (str.isNull()) {
902 if (str.isNull()) {
903 return PyString_FromString("");
903 return PyString_FromString("");
904 } else {
904 } else {
905 #ifdef WIN32
905 #ifdef WIN32
906 // return PyString_FromString(str.toLatin1().data());
906 // return PyString_FromString(str.toLatin1().data());
907 return PyUnicode_FromUnicode(str.utf16(), str.length());
907 return PyUnicode_FromUnicode(str.utf16(), str.length());
908 #else
908 #else
909 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
909 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
910 #endif
910 #endif
911 }
911 }
912 }
912 }
913
913
914 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
914 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
915 {
915 {
916 PyObject* result = PyTuple_New(list.count());
916 PyObject* result = PyTuple_New(list.count());
917 int i = 0;
917 int i = 0;
918 QString str;
918 QString str;
919 foreach (str, list) {
919 foreach (str, list) {
920 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
920 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
921 i++;
921 i++;
922 }
922 }
923 // why is the error state bad after this?
923 // why is the error state bad after this?
924 PyErr_Clear();
924 PyErr_Clear();
925 return result;
925 return result;
926 }
926 }
927
927
928 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
928 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
929 {
929 {
930 PyObject* result = PyList_New(list.count());
930 PyObject* result = PyList_New(list.count());
931 int i = 0;
931 int i = 0;
932 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
932 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
933 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
933 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
934 i++;
934 i++;
935 }
935 }
936 return result;
936 return result;
937 }
937 }
938
938
939 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
939 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
940 {
940 {
941 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
941 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
942 }
942 }
943
943
944 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
944 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
945 PyObject* result = PyDict_New();
945 PyObject* result = PyDict_New();
946 QVariantMap::const_iterator t = m.constBegin();
946 QVariantMap::const_iterator t = m.constBegin();
947 PyObject* key;
947 PyObject* key;
948 PyObject* val;
948 PyObject* val;
949 for (;t!=m.end();t++) {
949 for (;t!=m.end();t++) {
950 key = QStringToPyObject(t.key());
950 key = QStringToPyObject(t.key());
951 val = QVariantToPyObject(t.value());
951 val = QVariantToPyObject(t.value());
952 PyDict_SetItem(result, key, val);
952 PyDict_SetItem(result, key, val);
953 Py_DECREF(key);
953 Py_DECREF(key);
954 Py_DECREF(val);
954 Py_DECREF(val);
955 }
955 }
956 return result;
956 return result;
957 }
957 }
958
958
959 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
959 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
960 PyObject* result = PyTuple_New(l.count());
960 PyObject* result = PyTuple_New(l.count());
961 int i = 0;
961 int i = 0;
962 QVariant v;
962 QVariant v;
963 foreach (v, l) {
963 foreach (v, l) {
964 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
964 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
965 i++;
965 i++;
966 }
966 }
967 // why is the error state bad after this?
967 // why is the error state bad after this?
968 PyErr_Clear();
968 PyErr_Clear();
969 return result;
969 return result;
970 }
970 }
971
971
972 PyObject* PythonQtConv::ConvertQListWithPointersToPython(QList<void*>* list, const QByteArray& type)
972 PyObject* PythonQtConv::ConvertQListWithPointersToPython(QList<void*>* list, const QByteArray& type)
973 {
973 {
974 PyObject* result = PyTuple_New(list->count());
974 PyObject* result = PyTuple_New(list->count());
975 int i = 0;
975 int i = 0;
976 foreach (void* value, *list) {
976 foreach (void* value, *list) {
977 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, type));
977 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, type));
978 i++;
978 i++;
979 }
979 }
980 return result;
980 return result;
981 }
981 }
982
982
983 bool PythonQtConv::ConvertPythonListToQListOfType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool strict)
983 bool PythonQtConv::ConvertPythonListToQListOfType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
984 {
984 {
985 bool result = false;
985 bool result = false;
986 if (PySequence_Check(obj)) {
986 if (PySequence_Check(obj)) {
987 result = true;
987 result = true;
988 int count = PySequence_Size(obj);
988 int count = PySequence_Size(obj);
989 PyObject* value;
989 PyObject* value;
990 for (int i = 0;i<count;i++) {
990 for (int i = 0;i<count;i++) {
991 value = PySequence_GetItem(obj,i);
991 value = PySequence_GetItem(obj,i);
992 if (value->ob_type == &PythonQtWrapper_Type) {
992 if (value->ob_type == &PythonQtWrapper_Type) {
993 PythonQtWrapper* wrap = (PythonQtWrapper*)value;
993 PythonQtWrapper* wrap = (PythonQtWrapper*)value;
994 // c++ wrapper, check if the class names of the c++ objects match
994 // c++ wrapper, check if the class names of the c++ objects match
995 if (wrap->_info->isCPPWrapper()) {
995 if (wrap->_info->isCPPWrapper()) {
996 //TODO: we could support inheritance on cpp wrappers as well
996 //TODO: we could support inheritance on cpp wrappers as well
997 if (wrap->_info->wrappedCPPClassName() == type) {
997 if (wrap->_info->wrappedCPPClassName() == type) {
998 list->append(wrap->_wrappedPtr);
998 list->append(wrap->_wrappedPtr);
999 } else {
999 } else {
1000 result = false;
1000 result = false;
1001 break;
1001 break;
1002 }
1002 }
1003 } else {
1003 } else {
1004 if (wrap->_info->inherits(type)) {
1004 if (wrap->_info->inherits(type)) {
1005 QObject* myObject = wrap->_obj;
1005 QObject* myObject = wrap->_obj;
1006 list->append((void*)myObject);
1006 list->append((void*)myObject);
1007 } else {
1007 } else {
1008 result = false;
1008 result = false;
1009 break;
1009 break;
1010 }
1010 }
1011 }
1011 }
1012 }
1012 }
1013 }
1013 }
1014 }
1014 }
1015 return result;
1015 return result;
1016 }
1016 }
1017
1017
@@ -1,466 +1,462
1 #ifndef _PYTHONQTDOC_H
1 #ifndef _PYTHONQTDOC_H
2 #define _PYTHONQTDOC_H
2 #define _PYTHONQTDOC_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQtDoc.h
38 // \file PythonQtDoc.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-10
41 // \date 2006-10
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 /*!
45 /*!
46 \if USE_GLOBAL_DOXYGEN_DOC
46 \if USE_GLOBAL_DOXYGEN_DOC
47 \page PythonQtPage PythonQt Overview
47 \page PythonQtPage PythonQt Overview
48 \else
48 \else
49 \mainpage PythonQt Overview
49 \mainpage PythonQt Overview
50 \endif
50 \endif
51
51
52 \section Introduction
52 \section Introduction
53
53
54 \b PythonQt is a dynamic Python (http://www.python.org) binding for Qt (http://www.trolltech.com).
54 \b PythonQt is a dynamic Python (http://www.python.org) binding for Qt (http://www.qtsoftware.com).
55 It offers an easy way to embed the Python scripting language into
55 It offers an easy way to embed the Python scripting language into
56 your Qt applications. It makes heavy use of the QMetaObject system and thus requires Qt4.x.
56 your Qt applications. It makes heavy use of the QMetaObject system and thus requires Qt4.x.
57
57
58 In contrast to <a href="http://www.riverbankcomputing.co.uk/pyqt/">PyQt</a> , PythonQt is \b not a complete
58 In contrast to <a href="http://www.riverbankcomputing.co.uk/pyqt/">PyQt</a> , PythonQt is \b not a complete
59 Python wrapper around the complete Qt functionality. So if you are looking for a way to
59 Python wrapper around the complete Qt functionality. So if you are looking for a way to
60 write complete applications in Python using the Qt GUI, you should use PyQt.
60 write complete applications in Python using the Qt GUI, you should use PyQt.
61
61
62 If you are looking for a simple way to embed Python objects into your C++/Qt Application
62 If you are looking for a simple way to embed Python objects into your C++/Qt Application
63 and to script parts of your application via Python, PythonQt is the way to go!
63 and to script parts of your application via Python, PythonQt is the way to go!
64
64
65 PythonQt is a stable library that was developed to make the
65 PythonQt is a stable library that was developed to make the
66 Image Processing and Visualization platform MeVisLab (http://www.mevislab.de)
66 Image Processing and Visualization platform MeVisLab (http://www.mevislab.de)
67 scriptable from Python.
67 scriptable from Python.
68
68
69 \section Licensing
69 \section Licensing
70
70
71 PythonQt is distributed under the LGPL license.
71 PythonQt is distributed under the LGPL license.
72
72
73 \section Download
73 \section Download
74
74
75 PythonQt is hosted on SourceForge at http://sourceforge.net/projects/pythonqt , you can access it via SVN
75 PythonQt is hosted on SourceForge at http://sourceforge.net/projects/pythonqt , you can access it via SVN
76 or download a tarball.
76 or download a tarball.
77
77
78 \section Features
78 \section Features
79
79
80 - Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
80 - Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
81 - Convenient conversions to/from QVariant for PythonQtObjectPtr.
81 - Convenient conversions to/from QVariant for PythonQtObjectPtr.
82 - Access all \b slots, \b properties, children and registered enums of any QObject derived class from Python
82 - Access all \b slots, \b properties, children and registered enums of any QObject derived class from Python
83 - Connecting Qt Signals to Python functions (both from within Python and from C++)
83 - Connecting Qt Signals to Python functions (both from within Python and from C++)
84 - Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
84 - Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
85 - Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
85 - Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
86 - StdOut/Err redirection to Qt signals instead of cout
86 - StdOut/Err redirection to Qt signals instead of cout
87 - Interface for creating your own \c import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
87 - Interface for creating your own \c import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
88 - Mapping of plain-old-datatypes and ALL QVariant types to and from Python
88 - Mapping of plain-old-datatypes and ALL QVariant types to and from Python
89 - Support for wrapping of user QVariant types which are registerd via QMetaType
89 - Support for wrapping of user QVariant types which are registerd via QMetaType
90 - Support for Qt namespace (with all enumerators)
90 - Support for Qt namespace (with all enumerators)
91 - All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
91 - All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
92 - No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the \b moc)
92 - No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the \b moc)
93
93
94 \section Non-Features
94 \section Non-Features
95
95
96 Features that PythonQt does NOT support (and will not support):
96 Features that PythonQt does NOT support (and will not support):
97
97
98 - you can not derive from QObjects inside of Python, this would require wrapper generation like PyQt does
98 - you can not derive from QObjects inside of Python, this would require wrapper generation like PyQt does
99 - you can only script QObject derived classes, for normal C++ classes you need to create a PythonQtCppWrapperFactory and adequate wrapper classes or add decorator slots
99 - you can only script QObject derived classes, for normal C++ classes you need to create a PythonQtCppWrapperFactory and adequate wrapper classes or add decorator slots
100 - you can not access normal member functions of QObjects, only slots and properties, because the \b moc does not store normal member functions in the MetaObject system
100 - you can not access normal member functions of QObjects, only slots and properties, because the \b moc does not store normal member functions in the MetaObject system
101
101
102 \section Interface
102 \section Interface
103
103
104 The main interface to PythonQt is the PythonQt singleton.
104 The main interface to PythonQt is the PythonQt singleton.
105 PythonQt needs to be initialized via PythonQt::init() once.
105 PythonQt needs to be initialized via PythonQt::init() once.
106 Afterwards you communicate with the singleton via PythonQt::self().
106 Afterwards you communicate with the singleton via PythonQt::self().
107 PythonQt offers a default binding for the complete QWidget set, which
107 PythonQt offers a default binding for the complete QWidget set, which
108 needs to be enabled via PythonQtGui::init().
108 needs to be enabled via PythonQtGui::init().
109
109
110
110
111 \section Datatype Datatype Mapping
111 \section Datatype Datatype Mapping
112
112
113 The following table shows the mapping between Python and Qt objects:
113 The following table shows the mapping between Python and Qt objects:
114 <table>
114 <table>
115 <tr><th>Qt/C++</th><th>Python</th></tr>
115 <tr><th>Qt/C++</th><th>Python</th></tr>
116 <tr><td>bool</td><td>bool</td></tr>
116 <tr><td>bool</td><td>bool</td></tr>
117 <tr><td>double</td><td>float</td></tr>
117 <tr><td>double</td><td>float</td></tr>
118 <tr><td>float</td><td>float</td></tr>
118 <tr><td>float</td><td>float</td></tr>
119 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
119 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
120 <tr><td>long</td><td>integer</td></tr>
120 <tr><td>long</td><td>integer</td></tr>
121 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
121 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
122 <tr><td>QString</td><td>unicode string</td></tr>
122 <tr><td>QString</td><td>unicode string</td></tr>
123 <tr><td>QByteArray</td><td>str</td></tr>
123 <tr><td>QByteArray</td><td>str</td></tr>
124 <tr><td>char*</td><td>str</td></tr>
124 <tr><td>char*</td><td>str</td></tr>
125 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
125 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
126 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
126 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
127 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
127 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
128 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
128 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
129 <tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant wrapper that supports complete API of the respective Qt classes</td></tr>
129 <tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant wrapper that supports complete API of the respective Qt classes</td></tr>
130 <tr><td>OwnRegisteredMetaType</td><td>variant wrapper, optionally with a wrapper provided by addVariantWrapper()</td></tr>
130 <tr><td>OwnRegisteredMetaType</td><td>variant wrapper, optionally with a wrapper provided by addVariantWrapper()</td></tr>
131 <tr><td>EnumType</td><td>integer (all enums that are known via the moc and the Qt namespace are supported)</td></tr>
131 <tr><td>EnumType</td><td>integer (all enums that are known via the moc and the Qt namespace are supported)</td></tr>
132 <tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
132 <tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
133 <tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
133 <tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
134 <tr><td>PyObject</td><td>PyObject</td></tr>
134 <tr><td>PyObject</td><td>PyObject</td></tr>
135 </table>
135 </table>
136
136
137 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
137 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
138 a Qt slot.
138 a Qt slot.
139 QVariants are mapped recursively as given above, e.g. a dictionary can
139 QVariants are mapped recursively as given above, e.g. a dictionary can
140 contain lists of dictionaries of doubles.
140 contain lists of dictionaries of doubles.
141 For example a QVariant of type "String" is mapped to a python unicode string.
141 For example a QVariant of type "String" is mapped to a python unicode string.
142 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
142 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
143
143
144 \section QObject QObject Wrapping
144 \section QObject QObject Wrapping
145
145
146 All classes derived from QObject are automatically wrapped with a python wrapper class
146 All classes derived from QObject are automatically wrapped with a python wrapper class
147 when they become visible to the Python interpreter. This can happen via
147 when they become visible to the Python interpreter. This can happen via
148 - the PythonQt::addObject() method
148 - the PythonQt::addObject() method
149 - when a Qt \b slot returns a QObject derived object to python
149 - when a Qt \b slot returns a QObject derived object to python
150 - when a Qt \b signal contains a QObject and is connected to a python function
150 - when a Qt \b signal contains a QObject and is connected to a python function
151
151
152 It is important that you call PythonQt::registerClass() for any QObject derived class
152 It is important that you call PythonQt::registerClass() for any QObject derived class
153 that may become visible to Python, except when you add it via PythonQt::addObject().
153 that may become visible to Python, except when you add it via PythonQt::addObject().
154 This will register the complete parent hierachy of the registered class, so that
154 This will register the complete parent hierachy of the registered class, so that
155 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
155 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
156 parents).
156 parents).
157
157
158 From Python, you can talk to the returned QObjects in a natural way by calling
158 From Python, you can talk to the returned QObjects in a natural way by calling
159 their slots and receiving the return values. You can also read/write all
159 their slots and receiving the return values. You can also read/write all
160 properties of the objects as if they where normal python properties.
160 properties of the objects as if they where normal python properties.
161
161
162 In addition to this, the wrapped objects support
162 In addition to this, the wrapped objects support
163 - className() - returns a string that reprents the classname of the QObject
163 - className() - returns a string that reprents the classname of the QObject
164 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
164 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
165 - connect(signal, function) - connect the signal of the given object to a python function
165 - connect(signal, function) - connect the signal of the given object to a python function
166 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
166 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
167 - disconnect(signal, function) - disconnect the signal of the given object from a python function
167 - disconnect(signal, function) - disconnect the signal of the given object from a python function
168 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
168 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
169 - children() - returns the children of the object
169 - children() - returns the children of the object
170 - setParent(QObject) - set the parent
170 - setParent(QObject) - set the parent
171 - QObject* parent() - get the parent
171 - QObject* parent() - get the parent
172
172
173 The below example shows how to connect signals in Python:
173 The below example shows how to connect signals in Python:
174
174
175 \code
175 \code
176 # define a signal handler function
176 # define a signal handler function
177 def someFunction(flag):
177 def someFunction(flag):
178 print flag
178 print flag
179
179
180 # button1 is a QPushButton that has been added to Python via addObject()
180 # button1 is a QPushButton that has been added to Python via addObject()
181 # connect the clicked signal to a python function:
181 # connect the clicked signal to a python function:
182 button1.connect("clicked(bool)", someFunction)
182 button1.connect("clicked(bool)", someFunction)
183
183
184 \endcode
184 \endcode
185
185
186 \section CPP CPP Wrapping
186 \section CPP CPP Wrapping
187
187
188 You can create dedicated wrapper QObject for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
188 You can create dedicated wrapper QObject for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
189 and adding your factory via addWrapperFactory().
189 and adding your factory via addWrapperFactory().
190 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
190 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
191 and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
191 and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
192 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
192 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
193 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
193 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
194
194
195 \section MetaObject Meta Object/Class access
195 \section MetaObject Meta Object/Class access
196
196
197 For each known CPP class, QObject derived class and QVariant type, PythonQt provides a Meta class. These meta classes are visible
197 For each known CPP class, QObject derived class and QVariant type, PythonQt provides a Meta class. These meta classes are visible
198 inside of the "PythonQt" python module.
198 inside of the "PythonQt" python module.
199
199
200 A Meta class supports:
200 A Meta class supports:
201
201
202 - access to all declared enum values
202 - access to all declared enum values
203 - constructors
203 - constructors
204 - static decorator slots
204 - static decorator slots
205 - help() and className()
205 - help() and className()
206
206
207 From within Python, you can import the module "PythonQt" to access these meta objects and the Qt namespace.
207 From within Python, you can import the module "PythonQt" to access these meta objects and the Qt namespace.
208
208
209 \code
209 \code
210 from PythonQt import *
210 from PythonQt import *
211
211
212 # namespace access:
212 # namespace access:
213 print Qt.AlignLeft
213 print Qt.AlignLeft
214
214
215 # constructors
215 # constructors
216 a = QSize(12,13)
216 a = QSize(12,13)
217 b = QFont()
217 b = QFont()
218
218
219 # static method
219 # static method
220 QDate.currentDate()
220 QDate.currentDate()
221
221
222 # enum value
222 # enum value
223 QFont.UltraCondensed
223 QFont.UltraCondensed
224
224
225 \endcode
225 \endcode
226
226
227 \section Decorators Decorator slots
227 \section Decorators Decorator slots
228
228
229 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
229 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
230
230
231 - constructors
231 - constructors
232 - destructors (for CPP objects)
232 - destructors (for CPP objects)
233 - additional slots
233 - additional slots
234 - static slots (callable on both the Meta object and the instances)
234 - static slots (callable on both the Meta object and the instances)
235
235
236 The idea behind decorators is that we wanted to make it as easy as possible to extend
236 The idea behind decorators is that we wanted to make it as easy as possible to extend
237 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
237 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
238 Python, it looked promising to use this approach for the extension of wrapped objects as well.
238 Python, it looked promising to use this approach for the extension of wrapped objects as well.
239 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
239 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
240 Qt when he wants to create static methods, constructors and additional member functions.
240 Qt when he wants to create static methods, constructors and additional member functions.
241
241
242 The basic idea about decorators is to create a QObject derived class that implements slots
242 The basic idea about decorators is to create a QObject derived class that implements slots
243 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
243 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
244 These slots are then assigned to other classes via the naming convention.
244 These slots are then assigned to other classes via the naming convention.
245
245
246 - QVariant new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a QVariant
246 - QVariant new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a QVariant
247 - SomeClassName* new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a new object of type SomeClassName (where SomeClassName can be any CPP class, not just QObject classes)
247 - SomeClassName* new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a new object of type SomeClassName (where SomeClassName can be any CPP class, not just QObject classes)
248 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
248 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
249 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
249 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
250 - anything someMethodName(SomeClassName* o, ...) - defines a slot that will be available on SomeClassName instances (and derived instances). When such a slot is called the first argument is the pointer to the instance and the rest of the arguments can be used to make a call on the instance.
250 - anything someMethodName(SomeClassName* o, ...) - defines a slot that will be available on SomeClassName instances (and derived instances). When such a slot is called the first argument is the pointer to the instance and the rest of the arguments can be used to make a call on the instance.
251
251
252 The below example shows all kinds of decorators in action:
252 The below example shows all kinds of decorators in action:
253
253
254 \code
254 \code
255
255
256 // an example CPP object
256 // an example CPP object
257 class YourCPPObject {
257 class YourCPPObject {
258 public:
258 public:
259 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
259 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
260
260
261 float doSomething(int arg1) { return arg1*a*b; };
261 float doSomething(int arg1) { return arg1*a*b; };
262
262
263 private:
263 private:
264
264
265 int a;
265 int a;
266 float b;
266 float b;
267 };
267 };
268
268
269 // an example decorator
269 // an example decorator
270 class ExampleDecorator : public QObject
270 class ExampleDecorator : public QObject
271 {
271 {
272 Q_OBJECT
272 Q_OBJECT
273
273
274 public slots:
274 public slots:
275 // add a constructor to QSize variant that takes a QPoint
275 // add a constructor to QSize variant that takes a QPoint
276 QVariant new_QSize(const QPoint& p) { return QSize(p.x(), p.y()); }
276 QVariant new_QSize(const QPoint& p) { return QSize(p.x(), p.y()); }
277
277
278 // add a constructor for QPushButton that takes a text and a parent widget
278 // add a constructor for QPushButton that takes a text and a parent widget
279 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
279 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
280
280
281 // add a constructor for a CPP object
281 // add a constructor for a CPP object
282 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
282 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
283
283
284 // add a destructor for a CPP object
284 // add a destructor for a CPP object
285 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
285 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
286
286
287 // add a static method to QWidget
287 // add a static method to QWidget
288 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
288 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
289
289
290 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
290 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
291 void move(QWidget* w, const QPoint& p) { w->move(p); }
291 void move(QWidget* w, const QPoint& p) { w->move(p); }
292
292
293 // add an additional slot to QWidget, overloading the above move method
293 // add an additional slot to QWidget, overloading the above move method
294 void move(QWidget* w, int x, int y) { w->move(x,y); }
294 void move(QWidget* w, int x, int y) { w->move(x,y); }
295
295
296 // add a method to your own CPP object
296 // add a method to your own CPP object
297 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
297 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
298 };
298 };
299
299
300 ...
300 ...
301
301
302 PythonQt::self()->addDecorators(new ExampleDecorator());
302 PythonQt::self()->addDecorators(new ExampleDecorator());
303 PythonQt::self()->registerClass(&QPushButton::staticMetaObject);
303 PythonQt::self()->registerClass(&QPushButton::staticMetaObject);
304 PythonQt::self()->registerCPPClassNames(QStringList() << "YourCPPObject");
304 PythonQt::self()->registerCPPClassNames(QStringList() << "YourCPPObject");
305
305
306 \endcode
306 \endcode
307
307
308 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
308 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
309 (all these calls are mapped to the above decorator slots):
309 (all these calls are mapped to the above decorator slots):
310
310
311 \code
311 \code
312 from PythonQt import *
312 from PythonQt import *
313
313
314 # call our new constructor of QSize
314 # call our new constructor of QSize
315 size = QSize(QPoint(1,2));
315 size = QSize(QPoint(1,2));
316
316
317 # call our new QPushButton constructor
317 # call our new QPushButton constructor
318 button = QPushButton("sometext");
318 button = QPushButton("sometext");
319
319
320 # call the move slot (overload1)
320 # call the move slot (overload1)
321 button.move(QPoint(0,0))
321 button.move(QPoint(0,0))
322
322
323 # call the move slot (overload2)
323 # call the move slot (overload2)
324 button.move(0,0)
324 button.move(0,0)
325
325
326 # call the static method
326 # call the static method
327 grabber = QWidget.mouseWrapper();
327 grabber = QWidget.mouseWrapper();
328
328
329 # create a CPP object via constructor
329 # create a CPP object via constructor
330 yourCpp = YourCPPObject(1,11.5)
330 yourCpp = YourCPPObject(1,11.5)
331
331
332 # call the wrapped method on CPP object
332 # call the wrapped method on CPP object
333 print yourCpp.doSomething(1);
333 print yourCpp.doSomething(1);
334
334
335 # destructor will be called:
335 # destructor will be called:
336 yourCpp = None
336 yourCpp = None
337
337
338 \endcode
338 \endcode
339
339
340 \section Building
340 \section Building
341
341
342 PythonQt requires at least Qt 4.2.2 (or higher) and Python 2.3, 2.4 or 2.5 on Windows, Linux and MacOS X.
342 PythonQt requires at least Qt 4.2.2 (or higher) and Python 2.3, 2.4, 2.5 or 2.6 on Windows, Linux and MacOS X. It has not yet been tested with Python 3.x, but it should only require minor changes.
343 To compile PythonQt, you will need a python developer installation which includes Python's header files and
343 To compile PythonQt, you will need a python developer installation which includes Python's header files and
344 the python2x.[lib | dll | so | dynlib].
344 the python2x.[lib | dll | so | dynlib].
345 The build scripts a currently set to use Python 2.5.
345 The build scripts a currently set to use Python 2.5.
346 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
346 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
347
347
348 \subsection Windows
348 \subsection Windows
349
349
350 On Windows, the (non-source) Python Windows installer can be used.
350 On Windows, the (non-source) Python Windows installer can be used.
351 Make sure that you use the same compiler, the current Python distribution is built
351 Make sure that you use the same compiler, the current Python distribution is built
352 with Visual Studio 2003. If you want to use another compiler, you will need to build
352 with Visual Studio 2003. If you want to use another compiler, you will need to build
353 Python yourself, using your compiler.
353 Python yourself, using your compiler.
354
354
355 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
355 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
356 dir of the python installation and \b PYTHON_LIB to point to
356 dir of the python installation and \b PYTHON_LIB to point to
357 the directory where the python lib file is located.
357 the directory where the python lib file is located.
358
358
359 When using the prebuild Python installer, this will be:
359 When using the prebuild Python installer, this will be:
360
360
361 \code
361 \code
362 > set PYTHON_PATH = c:\Python25
362 > set PYTHON_PATH = c:\Python25
363 > set PYTHON_LIB = c:\Python25\libs
363 > set PYTHON_LIB = c:\Python25\libs
364 \endcode
364 \endcode
365
365
366 When using the python sources, this will be something like:
366 When using the python sources, this will be something like:
367
367
368 \code
368 \code
369 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
369 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
370 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
370 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
371 \endcode
371 \endcode
372
372
373 To build all, do the following (after setting the above variables):
373 To build all, do the following (after setting the above variables):
374
374
375 \code
375 \code
376 > cd PythonQtRoot
376 > cd PythonQtRoot
377 > vcvars32
377 > vcvars32
378 > qmake
378 > qmake
379 > nmake
379 > nmake
380 \endcode
380 \endcode
381
381
382 This should build everything. If Python can not be linked or include files can not be found,
382 This should build everything. If Python can not be linked or include files can not be found,
383 you probably need to tweak \b build/python.prf
383 you probably need to tweak \b build/python.prf
384
384
385 The tests and examples are located in PythonQt/lib.
385 The tests and examples are located in PythonQt/lib.
386
386
387 \subsection Linux
387 \subsection Linux
388
388
389 On Linux, you need to install a Python-dev package.
389 On Linux, you need to install a Python-dev package.
390 If Python can not be linked or include files can not be found,
390 If Python can not be linked or include files can not be found,
391 you probably need to tweak \b build/python.prf
391 you probably need to tweak \b build/python.prf
392
392
393 To build PythonQt, just do a:
393 To build PythonQt, just do a:
394
394
395 \code
395 \code
396 > cd PythonQtRoot
396 > cd PythonQtRoot
397 > qmake
397 > qmake
398 > make all
398 > make all
399 \endcode
399 \endcode
400
400
401 The tests and examples are located in PythonQt/lib.
401 The tests and examples are located in PythonQt/lib.
402 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
402 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
403 linker can find the *.so files.
403 linker can find the *.so files.
404
404
405 \subsection MacOsX
405 \subsection MacOsX
406
406
407 On Mac, Python is installed as a Framework, so you should not need to install it.
407 On Mac, Python is installed as a Framework, so you should not need to install it.
408 To build PythonQt, just do a:
408 To build PythonQt, just do a:
409
409
410 \code
410 \code
411 > cd PythonQtRoot
411 > cd PythonQtRoot
412 > qmake
412 > qmake
413 > make all
413 > make all
414 \endcode
414 \endcode
415
415
416 \section Tests
416 \section Tests
417
417
418 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
418 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
419
419
420 \section Examples
420 \section Examples
421
421
422 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
422 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
423 interactive scripting console that shows how to script a simple application.
423 interactive scripting console that shows how to script a simple application.
424
424
425 The following shows how to integrate PythonQt into you Qt application:
425 The following shows how to integrate PythonQt into you Qt application:
426
426
427 \code
427 \code
428 #include "PythonQt.h"
428 #include "PythonQt.h"
429 #include <QApplication>
429 #include <QApplication>
430 ...
430 ...
431
431
432 int main( int argc, char **argv )
432 int main( int argc, char **argv )
433 {
433 {
434
434
435 QApplication qapp(argc, argv);
435 QApplication qapp(argc, argv);
436
436
437 // init PythonQt and Python itself
437 // init PythonQt and Python itself
438 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
438 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
439
439
440 // get a smart pointer to the __main__ module of the Python interpreter
440 // get a smart pointer to the __main__ module of the Python interpreter
441 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
441 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
442
442
443 // add a QObject as variable of name "example" to the namespace of the __main__ module
443 // add a QObject as variable of name "example" to the namespace of the __main__ module
444 PyExampleObject example;
444 PyExampleObject example;
445 PythonQt::self()->addObject(mainContext, "example", &example);
445 PythonQt::self()->addObject(mainContext, "example", &example);
446
446
447 // register all other QObjects that you want to script and that are returned by your API
447 // register all other QObjects that you want to script and that are returned by your API
448 PythonQt::self()->registerClass(&QMainWindow::staticMetaObject);
448 PythonQt::self()->registerClass(&QMainWindow::staticMetaObject);
449 PythonQt::self()->registerClass(&QPushButton::staticMetaObject);
449 PythonQt::self()->registerClass(&QPushButton::staticMetaObject);
450 ...
450 ...
451
451
452 // do something
452 // do something
453 PythonQt::self()->runScript(mainContext, "print example\n");
453 PythonQt::self()->runScript(mainContext, "print example\n");
454 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
454 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
455 QVariantList args;
455 QVariantList args;
456 args << 42 << 47;
456 args << 42 << 47;
457 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
457 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
458 ...
458 ...
459 \endcode
459 \endcode
460
460
461
461
462 \section TODOs
463
464 - add more information on how to distribute an application that uses PythonQt, including the Python distribution
465
466 */
462 */
@@ -1,69 +1,72
1 #ifndef _PYTHONQTIMPORTFILEINTERFACE_H
1 #ifndef _PYTHONQTIMPORTFILEINTERFACE_H
2 #define _PYTHONQTIMPORTFILEINTERFACE_H
2 #define _PYTHONQTIMPORTFILEINTERFACE_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 PythonQtImportFileInterface.h
38 // \file PythonQtImportFileInterface.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 <QDateTime>
45 #include <QDateTime>
46 #include <QString>
46 #include <QString>
47 #include <QByteArray>
47 #include <QByteArray>
48
48
49 //! Defines an abstract interface to file access for the Python import statement.
49 //! Defines an abstract interface to file access for the Python import statement.
50 //! see PythonQt::setImporter()
50 //! see PythonQt::setImporter()
51 class PythonQtImportFileInterface {
51 class PythonQtImportFileInterface {
52
52
53 public:
53 public:
54 // get rid of warnings
55 virtual ~PythonQtImportFileInterface() {}
56
54 //! read the given file as byte array, without doing any linefeed translations
57 //! read the given file as byte array, without doing any linefeed translations
55 virtual QByteArray readFileAsBytes(const QString& filename) = 0;
58 virtual QByteArray readFileAsBytes(const QString& filename) = 0;
56
59
57 //! read a source file, expects a readable Python text file with translated line feeds.
60 //! read a source file, expects a readable Python text file with translated line feeds.
58 //! If the file can not be load OR it can not be verified, ok is set to false
61 //! If the file can not be load OR it can not be verified, ok is set to false
59 virtual QByteArray readSourceFile(const QString& filename, bool& ok) = 0;
62 virtual QByteArray readSourceFile(const QString& filename, bool& ok) = 0;
60
63
61 //! returns if the file exists
64 //! returns if the file exists
62 virtual bool exists(const QString& filename) = 0;
65 virtual bool exists(const QString& filename) = 0;
63
66
64 //! get the last modified data of a file
67 //! get the last modified data of a file
65 virtual QDateTime lastModifiedDate(const QString& filename) = 0;
68 virtual QDateTime lastModifiedDate(const QString& filename) = 0;
66
69
67 };
70 };
68
71
69 #endif No newline at end of file
72 #endif
@@ -1,790 +1,781
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 PythonQtImporter.h
35 // \file PythonQtImporter.h
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 // This module was inspired by the zipimport.c module of the original
40 // This module was inspired by the zipimport.c module of the original
41 // Python distribution. Most of the functions are identical or slightly
41 // Python distribution. Most of the functions are identical or slightly
42 // modified to do all the loading of Python files via an external file interface.
42 // modified to do all the loading of Python files via an external file interface.
43 // In contrast to zipimport.c, this module also writes *.pyc files
43 // In contrast to zipimport.c, this module also writes *.pyc files
44 // automatically if it has write access/is not inside of a zip file.
44 // automatically if it has write access/is not inside of a zip file.
45 //----------------------------------------------------------------------------------
45 //----------------------------------------------------------------------------------
46
46
47 #include "PythonQtImporter.h"
47 #include "PythonQtImporter.h"
48 #include "PythonQtImportFileInterface.h"
48 #include "PythonQtImportFileInterface.h"
49 #include "PythonQt.h"
49 #include "PythonQt.h"
50 #include <QFile>
50 #include <QFile>
51 #include <QFileInfo>
51 #include <QFileInfo>
52
52
53 #define IS_SOURCE 0x0
53 #define IS_SOURCE 0x0
54 #define IS_BYTECODE 0x1
54 #define IS_BYTECODE 0x1
55 #define IS_PACKAGE 0x2
55 #define IS_PACKAGE 0x2
56
56
57 struct st_mlab_searchorder {
57 struct st_mlab_searchorder {
58 char suffix[14];
58 char suffix[14];
59 int type;
59 int type;
60 };
60 };
61
61
62 /* mlab_searchorder defines how we search for a module in the Zip
62 /* mlab_searchorder defines how we search for a module in the Zip
63 archive: we first search for a package __init__, then for
63 archive: we first search for a package __init__, then for
64 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
64 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
65 are swapped by initmlabimport() if we run in optimized mode. Also,
65 are swapped by initmlabimport() if we run in optimized mode. Also,
66 '/' is replaced by SEP there. */
66 '/' is replaced by SEP there. */
67 struct st_mlab_searchorder mlab_searchorder[] = {
67 struct st_mlab_searchorder mlab_searchorder[] = {
68 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
68 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
69 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
69 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
70 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
70 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
71 {".pyc", IS_BYTECODE},
71 {".pyc", IS_BYTECODE},
72 {".pyo", IS_BYTECODE},
72 {".pyo", IS_BYTECODE},
73 {".py", IS_SOURCE},
73 {".py", IS_SOURCE},
74 {"", 0}
74 {"", 0}
75 };
75 };
76
76
77 extern PyTypeObject PythonQtImporter_Type;
77 extern PyTypeObject PythonQtImporter_Type;
78 PyObject *PythonQtImportError;
78 PyObject *PythonQtImportError;
79
79
80 QString PythonQtImport::getSubName(const QString& str)
80 QString PythonQtImport::getSubName(const QString& str)
81 {
81 {
82 int idx = str.lastIndexOf('.');
82 int idx = str.lastIndexOf('.');
83 if (idx!=-1) {
83 if (idx!=-1) {
84 return str.mid(idx+1);
84 return str.mid(idx+1);
85 } else {
85 } else {
86 return str;
86 return str;
87 }
87 }
88 }
88 }
89
89
90 PythonQtImport::module_info PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
90 PythonQtImport::module_info PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
91 {
91 {
92 QString subname;
92 QString subname;
93 struct st_mlab_searchorder *zso;
93 struct st_mlab_searchorder *zso;
94
94
95 subname = getSubName(fullname);
95 subname = getSubName(fullname);
96 QString path = *self->_path + "/" + subname;
96 QString path = *self->_path + "/" + subname;
97
97
98 QString test;
98 QString test;
99 for (zso = mlab_searchorder; *zso->suffix; zso++) {
99 for (zso = mlab_searchorder; *zso->suffix; zso++) {
100 test = path + zso->suffix;
100 test = path + zso->suffix;
101 if (PythonQt::importInterface()->exists(test)) {
101 if (PythonQt::importInterface()->exists(test)) {
102 if (zso->type & IS_PACKAGE)
102 if (zso->type & IS_PACKAGE)
103 return MI_PACKAGE;
103 return MI_PACKAGE;
104 else
104 else
105 return MI_MODULE;
105 return MI_MODULE;
106 }
106 }
107 }
107 }
108 return MI_NOT_FOUND;
108 return MI_NOT_FOUND;
109 }
109 }
110
110
111
111
112 /* PythonQtImporter.__init__
112 /* PythonQtImporter.__init__
113 Just store the path argument
113 Just store the path argument
114 */
114 */
115 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject *kwds)
115 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
116 {
116 {
117 self->_path = NULL;
117 self->_path = NULL;
118
118
119 const char* path;
119 const char* path;
120 if (!PyArg_ParseTuple(args, "s",
120 if (!PyArg_ParseTuple(args, "s",
121 &path))
121 &path))
122 return -1;
122 return -1;
123
123
124 if (PythonQt::importInterface()->exists(path)) {
124 if (PythonQt::importInterface()->exists(path)) {
125 //qDebug("path %s", path);
125 //qDebug("path %s", path);
126 QString p(path);
126 QString p(path);
127 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
127 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
128 foreach(QString a, ignorePaths) {
128 foreach(QString a, ignorePaths) {
129 if (a==p) {
129 if (a==p) {
130 PyErr_SetString(PythonQtImportError,
130 PyErr_SetString(PythonQtImportError,
131 "path ignored");
131 "path ignored");
132 return -1;
132 return -1;
133 }
133 }
134 }
134 }
135
135
136 self->_path = new QString(p);
136 self->_path = new QString(p);
137
137
138 //mlabDebugConst("MLABPython", "PythonQtImporter init: " << *self->_path);
138 //mlabDebugConst("MLABPython", "PythonQtImporter init: " << *self->_path);
139
139
140 return 0;
140 return 0;
141 } else {
141 } else {
142 PyErr_SetString(PythonQtImportError,
142 PyErr_SetString(PythonQtImportError,
143 "path does not exist error");
143 "path does not exist error");
144 return -1;
144 return -1;
145 }
145 }
146 }
146 }
147
147
148 void
148 void
149 PythonQtImporter_dealloc(PythonQtImporter *self)
149 PythonQtImporter_dealloc(PythonQtImporter *self)
150 {
150 {
151 // free the stored path
151 // free the stored path
152 if (self->_path) delete self->_path;
152 if (self->_path) delete self->_path;
153 // free ourself
153 // free ourself
154 self->ob_type->tp_free((PyObject *)self);
154 self->ob_type->tp_free((PyObject *)self);
155 }
155 }
156
156
157
157
158 /* Check whether we can satisfy the import of the module named by
158 /* Check whether we can satisfy the import of the module named by
159 'fullname'. Return self if we can, None if we can't. */
159 'fullname'. Return self if we can, None if we can't. */
160 PyObject *
160 PyObject *
161 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
161 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
162 {
162 {
163 PythonQtImporter *self = (PythonQtImporter *)obj;
163 PythonQtImporter *self = (PythonQtImporter *)obj;
164 PyObject *path = NULL;
164 PyObject *path = NULL;
165 char *fullname;
165 char *fullname;
166
166
167 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
167 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
168 &fullname, &path))
168 &fullname, &path))
169 return NULL;
169 return NULL;
170
170
171 // mlabDebugConst("MLABPython", "FindModule " << fullname << " in " << *self->_path);
171 // mlabDebugConst("MLABPython", "FindModule " << fullname << " in " << *self->_path);
172
172
173 PythonQtImport::module_info info = PythonQtImport::getModuleInfo(self, fullname);
173 PythonQtImport::module_info info = PythonQtImport::getModuleInfo(self, fullname);
174 if (info == PythonQtImport::MI_MODULE || info == PythonQtImport::MI_PACKAGE) {
174 if (info == PythonQtImport::MI_MODULE || info == PythonQtImport::MI_PACKAGE) {
175 Py_INCREF(self);
175 Py_INCREF(self);
176 return (PyObject *)self;
176 return (PyObject *)self;
177 } else {
177 } else {
178 Py_INCREF(Py_None);
178 Py_INCREF(Py_None);
179 return Py_None;
179 return Py_None;
180 }
180 }
181 }
181 }
182
182
183 /* Load and return the module named by 'fullname'. */
183 /* Load and return the module named by 'fullname'. */
184 PyObject *
184 PyObject *
185 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
185 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
186 {
186 {
187 PythonQtImporter *self = (PythonQtImporter *)obj;
187 PythonQtImporter *self = (PythonQtImporter *)obj;
188 PyObject *code, *mod, *dict;
188 PyObject *code, *mod, *dict;
189 char *fullname;
189 char *fullname;
190 QString modpath;
190 QString modpath;
191 int ispackage;
191 int ispackage;
192
192
193 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
193 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
194 &fullname))
194 &fullname))
195 return NULL;
195 return NULL;
196
196
197 code = PythonQtImport::getModuleCode(self, fullname, &ispackage, modpath);
197 code = PythonQtImport::getModuleCode(self, fullname, &ispackage, modpath);
198 if (code == NULL)
198 if (code == NULL)
199 return NULL;
199 return NULL;
200
200
201 mod = PyImport_AddModule(fullname);
201 mod = PyImport_AddModule(fullname);
202 if (mod == NULL) {
202 if (mod == NULL) {
203 Py_DECREF(code);
203 Py_DECREF(code);
204 return NULL;
204 return NULL;
205 }
205 }
206 dict = PyModule_GetDict(mod);
206 dict = PyModule_GetDict(mod);
207
207
208 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0)
208 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
209 goto error;
209 Py_DECREF(code);
210 Py_DECREF(mod);
211 return NULL;
212 }
210
213
211 if (ispackage) {
214 if (ispackage) {
212 PyObject *pkgpath, *fullpath;
215 PyObject *pkgpath, *fullpath;
213 QString subname = PythonQtImport::getSubName(fullname);
216 QString subname = PythonQtImport::getSubName(fullname);
214 int err;
217 int err;
215
218
216 fullpath = PyString_FromFormat("%s%c%s",
219 fullpath = PyString_FromFormat("%s%c%s",
217 self->_path->toLatin1().constData(),
220 self->_path->toLatin1().constData(),
218 SEP,
221 SEP,
219 subname.toLatin1().constData());
222 subname.toLatin1().constData());
220 if (fullpath == NULL)
223 if (fullpath == NULL) {
221 goto error;
224 Py_DECREF(code);
225 Py_DECREF(mod);
226 return NULL;
227 }
222
228
223 pkgpath = Py_BuildValue("[O]", fullpath);
229 pkgpath = Py_BuildValue("[O]", fullpath);
224 Py_DECREF(fullpath);
230 Py_DECREF(fullpath);
225 if (pkgpath == NULL)
231 if (pkgpath == NULL) {
226 goto error;
232 Py_DECREF(code);
233 Py_DECREF(mod);
234 return NULL;
235 }
227 err = PyDict_SetItemString(dict, "__path__", pkgpath);
236 err = PyDict_SetItemString(dict, "__path__", pkgpath);
228 Py_DECREF(pkgpath);
237 Py_DECREF(pkgpath);
229 if (err != 0)
238 if (err != 0) {
230 goto error;
239 Py_DECREF(code);
240 Py_DECREF(mod);
241 return NULL;
242 }
231 }
243 }
232 mod = PyImport_ExecCodeModuleEx(fullname, code, (char*)modpath.toLatin1().data());
244 mod = PyImport_ExecCodeModuleEx(fullname, code, (char*)modpath.toLatin1().data());
233 Py_DECREF(code);
245 Py_DECREF(code);
234 if (Py_VerboseFlag)
246 if (Py_VerboseFlag)
235 PySys_WriteStderr("import %s # loaded from %s\n",
247 PySys_WriteStderr("import %s # loaded from %s\n",
236 fullname, modpath);
248 fullname, modpath.toLatin1().constData());
237 return mod;
249 return mod;
238 error:
239 Py_DECREF(code);
240 Py_DECREF(mod);
241 return NULL;
242 }
250 }
243
251
244
252
245 PyObject *
253 PyObject *
246 PythonQtImporter_get_data(PyObject *obj, PyObject *args)
254 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
247 {
255 {
248 // EXTRA, NOT YET IMPLEMENTED
256 // EXTRA, NOT YET IMPLEMENTED
249 return NULL;
257 return NULL;
250 }
258 }
251
259
252 PyObject *
260 PyObject *
253 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
261 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
254 {
262 {
255 PythonQtImporter *self = (PythonQtImporter *)obj;
263 PythonQtImporter *self = (PythonQtImporter *)obj;
256 char *fullname;
264 char *fullname;
257
265
258 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
266 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
259 return NULL;
267 return NULL;
260
268
261 QString notused;
269 QString notused;
262 return PythonQtImport::getModuleCode(self, fullname, NULL, notused);
270 return PythonQtImport::getModuleCode(self, fullname, NULL, notused);
263 }
271 }
264
272
265 PyObject *
273 PyObject *
266 PythonQtImporter_get_source(PyObject *obj, PyObject *args)
274 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
267 {
275 {
268 // EXTRA, NOT YET IMPLEMENTED
276 // EXTRA, NOT YET IMPLEMENTED
269 /*
277 /*
270 PythonQtImporter *self = (PythonQtImporter *)obj;
278 PythonQtImporter *self = (PythonQtImporter *)obj;
271 PyObject *toc_entry;
279 PyObject *toc_entry;
272 char *fullname, *subname, path[MAXPATHLEN+1];
280 char *fullname, *subname, path[MAXPATHLEN+1];
273 int len;
281 int len;
274 enum module_info mi;
282 enum module_info mi;
275
283
276 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_source", &fullname))
284 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_source", &fullname))
277 return NULL;
285 return NULL;
278
286
279 mi = get_module_info(self, fullname);
287 mi = get_module_info(self, fullname);
280 if (mi == MI_ERROR)
288 if (mi == MI_ERROR)
281 return NULL;
289 return NULL;
282 if (mi == MI_NOT_FOUND) {
290 if (mi == MI_NOT_FOUND) {
283 PyErr_Format(PythonQtImportError, "can't find module '%.200s'",
291 PyErr_Format(PythonQtImportError, "can't find module '%.200s'",
284 fullname);
292 fullname);
285 return NULL;
293 return NULL;
286 }
294 }
287 subname = get_subname(fullname);
295 subname = get_subname(fullname);
288
296
289 len = make_filename(PyString_AsString(self->prefix), subname, path);
297 len = make_filename(PyString_AsString(self->prefix), subname, path);
290 if (len < 0)
298 if (len < 0)
291 return NULL;
299 return NULL;
292
300
293 if (mi == MI_PACKAGE) {
301 if (mi == MI_PACKAGE) {
294 path[len] = SEP;
302 path[len] = SEP;
295 strcpy(path + len + 1, "__init__.py");
303 strcpy(path + len + 1, "__init__.py");
296 }
304 }
297 else
305 else
298 strcpy(path + len, ".py");
306 strcpy(path + len, ".py");
299
307
300 toc_entry = PyDict_GetItemString(self->files, path);
308 toc_entry = PyDict_GetItemString(self->files, path);
301 if (toc_entry != NULL)
309 if (toc_entry != NULL)
302 return get_data(PyString_AsString(self->archive), toc_entry);
310 return get_data(PyString_AsString(self->archive), toc_entry);
303
311
304 Py_INCREF(Py_None);
312 Py_INCREF(Py_None);
305 return Py_None;
313 return Py_None;
306 */
314 */
307 return NULL;
315 return NULL;
308 }
316 }
309
317
310 PyDoc_STRVAR(doc_find_module,
318 PyDoc_STRVAR(doc_find_module,
311 "find_module(fullname, path=None) -> self or None.\n\
319 "find_module(fullname, path=None) -> self or None.\n\
312 \n\
320 \n\
313 Search for a module specified by 'fullname'. 'fullname' must be the\n\
321 Search for a module specified by 'fullname'. 'fullname' must be the\n\
314 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
322 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
315 instance itself if the module was found, or None if it wasn't.\n\
323 instance itself if the module was found, or None if it wasn't.\n\
316 The optional 'path' argument is ignored -- it's there for compatibility\n\
324 The optional 'path' argument is ignored -- it's there for compatibility\n\
317 with the importer protocol.");
325 with the importer protocol.");
318
326
319 PyDoc_STRVAR(doc_load_module,
327 PyDoc_STRVAR(doc_load_module,
320 "load_module(fullname) -> module.\n\
328 "load_module(fullname) -> module.\n\
321 \n\
329 \n\
322 Load the module specified by 'fullname'. 'fullname' must be the\n\
330 Load the module specified by 'fullname'. 'fullname' must be the\n\
323 fully qualified (dotted) module name. It returns the imported\n\
331 fully qualified (dotted) module name. It returns the imported\n\
324 module, or raises PythonQtImportError if it wasn't found.");
332 module, or raises PythonQtImportError if it wasn't found.");
325
333
326 PyDoc_STRVAR(doc_get_data,
334 PyDoc_STRVAR(doc_get_data,
327 "get_data(pathname) -> string with file data.\n\
335 "get_data(pathname) -> string with file data.\n\
328 \n\
336 \n\
329 Return the data associated with 'pathname'. Raise IOError if\n\
337 Return the data associated with 'pathname'. Raise IOError if\n\
330 the file wasn't found.");
338 the file wasn't found.");
331
339
332 PyDoc_STRVAR(doc_get_code,
340 PyDoc_STRVAR(doc_get_code,
333 "get_code(fullname) -> code object.\n\
341 "get_code(fullname) -> code object.\n\
334 \n\
342 \n\
335 Return the code object for the specified module. Raise PythonQtImportError\n\
343 Return the code object for the specified module. Raise PythonQtImportError\n\
336 is the module couldn't be found.");
344 is the module couldn't be found.");
337
345
338 PyDoc_STRVAR(doc_get_source,
346 PyDoc_STRVAR(doc_get_source,
339 "get_source(fullname) -> source string.\n\
347 "get_source(fullname) -> source string.\n\
340 \n\
348 \n\
341 Return the source code for the specified module. Raise PythonQtImportError\n\
349 Return the source code for the specified module. Raise PythonQtImportError\n\
342 is the module couldn't be found, return None if the archive does\n\
350 is the module couldn't be found, return None if the archive does\n\
343 contain the module, but has no source for it.");
351 contain the module, but has no source for it.");
344
352
345 PyMethodDef PythonQtImporter_methods[] = {
353 PyMethodDef PythonQtImporter_methods[] = {
346 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
354 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
347 doc_find_module},
355 doc_find_module},
348 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
356 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
349 doc_load_module},
357 doc_load_module},
350 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
358 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
351 doc_get_data},
359 doc_get_data},
352 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
360 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
353 doc_get_code},
361 doc_get_code},
354 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
362 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
355 doc_get_source},
363 doc_get_source},
356 {NULL, NULL} /* sentinel */
364 {NULL, NULL, 0 , NULL} /* sentinel */
357 };
365 };
358
366
359
367
360 PyDoc_STRVAR(PythonQtImporter_doc,
368 PyDoc_STRVAR(PythonQtImporter_doc,
361 "PythonQtImporter(path) -> PythonQtImporter object\n\
369 "PythonQtImporter(path) -> PythonQtImporter object\n\
362 \n\
370 \n\
363 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
371 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
364 . Every path is accepted.");
372 . Every path is accepted.");
365
373
366 #define DEFERRED_ADDRESS(ADDR) 0
374 #define DEFERRED_ADDRESS(ADDR) 0
367
375
368 PyTypeObject PythonQtImporter_Type = {
376 PyTypeObject PythonQtImporter_Type = {
369 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
377 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
370 0,
378 0,
371 "PythonQtImport.PythonQtImporter",
379 "PythonQtImport.PythonQtImporter",
372 sizeof(PythonQtImporter),
380 sizeof(PythonQtImporter),
373 0, /* tp_itemsize */
381 0, /* tp_itemsize */
374 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
382 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
375 0, /* tp_print */
383 0, /* tp_print */
376 0, /* tp_getattr */
384 0, /* tp_getattr */
377 0, /* tp_setattr */
385 0, /* tp_setattr */
378 0, /* tp_compare */
386 0, /* tp_compare */
379 0, /* tp_repr */
387 0, /* tp_repr */
380 0, /* tp_as_number */
388 0, /* tp_as_number */
381 0, /* tp_as_sequence */
389 0, /* tp_as_sequence */
382 0, /* tp_as_mapping */
390 0, /* tp_as_mapping */
383 0, /* tp_hash */
391 0, /* tp_hash */
384 0, /* tp_call */
392 0, /* tp_call */
385 0, /* tp_str */
393 0, /* tp_str */
386 PyObject_GenericGetAttr, /* tp_getattro */
394 PyObject_GenericGetAttr, /* tp_getattro */
387 0, /* tp_setattro */
395 0, /* tp_setattro */
388 0, /* tp_as_buffer */
396 0, /* tp_as_buffer */
389 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
397 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
390 PythonQtImporter_doc, /* tp_doc */
398 PythonQtImporter_doc, /* tp_doc */
391 0, /* tp_traverse */
399 0, /* tp_traverse */
392 0, /* tp_clear */
400 0, /* tp_clear */
393 0, /* tp_richcompare */
401 0, /* tp_richcompare */
394 0, /* tp_weaklistoffset */
402 0, /* tp_weaklistoffset */
395 0, /* tp_iter */
403 0, /* tp_iter */
396 0, /* tp_iternext */
404 0, /* tp_iternext */
397 PythonQtImporter_methods, /* tp_methods */
405 PythonQtImporter_methods, /* tp_methods */
398 0, /* tp_members */
406 0, /* tp_members */
399 0, /* tp_getset */
407 0, /* tp_getset */
400 0, /* tp_base */
408 0, /* tp_base */
401 0, /* tp_dict */
409 0, /* tp_dict */
402 0, /* tp_descr_get */
410 0, /* tp_descr_get */
403 0, /* tp_descr_set */
411 0, /* tp_descr_set */
404 0, /* tp_dictoffset */
412 0, /* tp_dictoffset */
405 (initproc)PythonQtImporter_init, /* tp_init */
413 (initproc)PythonQtImporter_init, /* tp_init */
406 PyType_GenericAlloc, /* tp_alloc */
414 PyType_GenericAlloc, /* tp_alloc */
407 PyType_GenericNew, /* tp_new */
415 PyType_GenericNew, /* tp_new */
408 PyObject_Del, /* tp_free */
416 PyObject_Del, /* tp_free */
409 };
417 };
410
418
411
419
412 /* Given a buffer, return the long that is represented by the first
420 /* Given a buffer, return the long that is represented by the first
413 4 bytes, encoded as little endian. This partially reimplements
421 4 bytes, encoded as little endian. This partially reimplements
414 marshal.c:r_long() */
422 marshal.c:r_long() */
415 long
423 long
416 PythonQtImport::getLong(unsigned char *buf)
424 PythonQtImport::getLong(unsigned char *buf)
417 {
425 {
418 long x;
426 long x;
419 x = buf[0];
427 x = buf[0];
420 x |= (long)buf[1] << 8;
428 x |= (long)buf[1] << 8;
421 x |= (long)buf[2] << 16;
429 x |= (long)buf[2] << 16;
422 x |= (long)buf[3] << 24;
430 x |= (long)buf[3] << 24;
423 #if SIZEOF_LONG > 4
431 #if SIZEOF_LONG > 4
424 /* Sign extension for 64-bit machines */
432 /* Sign extension for 64-bit machines */
425 x |= -(x & 0x80000000L);
433 x |= -(x & 0x80000000L);
426 #endif
434 #endif
427 return x;
435 return x;
428 }
436 }
429
437
430 FILE *
438 FILE *
431 open_exclusive(const QString& filename)
439 open_exclusive(const QString& filename)
432 {
440 {
433 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
441 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
434 /* Use O_EXCL to avoid a race condition when another process tries to
442 /* Use O_EXCL to avoid a race condition when another process tries to
435 write the same file. When that happens, our open() call fails,
443 write the same file. When that happens, our open() call fails,
436 which is just fine (since it's only a cache).
444 which is just fine (since it's only a cache).
437 XXX If the file exists and is writable but the directory is not
445 XXX If the file exists and is writable but the directory is not
438 writable, the file will never be written. Oh well.
446 writable, the file will never be written. Oh well.
439 */
447 */
440 QFile::remove(filename);
448 QFile::remove(filename);
441
449
442 int fd;
450 int fd;
443 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
451 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
444 #ifdef O_BINARY
452 #ifdef O_BINARY
445 flags |= O_BINARY; /* necessary for Windows */
453 flags |= O_BINARY; /* necessary for Windows */
446 #endif
454 #endif
447 #ifdef WIN32
455 #ifdef WIN32
448 fd = _wopen(filename.ucs2(), flags, 0666);
456 fd = _wopen(filename.ucs2(), flags, 0666);
449 #else
457 #else
450 fd = open(filename.local8Bit(), flags, 0666);
458 fd = open(filename.local8Bit(), flags, 0666);
451 #endif
459 #endif
452 if (fd < 0)
460 if (fd < 0)
453 return NULL;
461 return NULL;
454 return fdopen(fd, "wb");
462 return fdopen(fd, "wb");
455 #else
463 #else
456 /* Best we can do -- on Windows this can't happen anyway */
464 /* Best we can do -- on Windows this can't happen anyway */
457 return fopen(filename.toLocal8Bit().constData(), "wb");
465 return fopen(filename.toLocal8Bit().constData(), "wb");
458 #endif
466 #endif
459 }
467 }
460
468
461
469
462 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
470 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
463 {
471 {
464 FILE *fp;
472 FILE *fp;
465
473
466 fp = open_exclusive(filename);
474 fp = open_exclusive(filename);
467 if (fp == NULL) {
475 if (fp == NULL) {
468 if (Py_VerboseFlag)
476 if (Py_VerboseFlag)
469 PySys_WriteStderr(
477 PySys_WriteStderr(
470 "# can't create %s\n", filename.toLatin1().constData());
478 "# can't create %s\n", filename.toLatin1().constData());
471 return;
479 return;
472 }
480 }
473 #if PY_VERSION_HEX < 0x02040000
481 #if PY_VERSION_HEX < 0x02040000
474 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
482 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
475 #else
483 #else
476 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
484 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
477 #endif
485 #endif
478 /* First write a 0 for mtime */
486 /* First write a 0 for mtime */
479 #if PY_VERSION_HEX < 0x02040000
487 #if PY_VERSION_HEX < 0x02040000
480 PyMarshal_WriteLongToFile(0L, fp);
488 PyMarshal_WriteLongToFile(0L, fp);
481 #else
489 #else
482 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
490 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
483 #endif
491 #endif
484 #if PY_VERSION_HEX < 0x02040000
492 #if PY_VERSION_HEX < 0x02040000
485 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
493 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
486 #else
494 #else
487 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
495 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
488 #endif
496 #endif
489 if (ferror(fp)) {
497 if (ferror(fp)) {
490 if (Py_VerboseFlag)
498 if (Py_VerboseFlag)
491 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
499 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
492 /* Don't keep partial file */
500 /* Don't keep partial file */
493 fclose(fp);
501 fclose(fp);
494 QFile::remove(filename);
502 QFile::remove(filename);
495 return;
503 return;
496 }
504 }
497 /* Now write the true mtime */
505 /* Now write the true mtime */
498 fseek(fp, 4L, 0);
506 fseek(fp, 4L, 0);
499 #if PY_VERSION_HEX < 0x02040000
507 #if PY_VERSION_HEX < 0x02040000
500 PyMarshal_WriteLongToFile(mtime, fp);
508 PyMarshal_WriteLongToFile(mtime, fp);
501 #else
509 #else
502 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
510 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
503 #endif
511 #endif
504 fflush(fp);
512 fflush(fp);
505 fclose(fp);
513 fclose(fp);
506 if (Py_VerboseFlag)
514 if (Py_VerboseFlag)
507 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
515 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
508 //#ifdef macintosh
516 //#ifdef macintosh
509 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
517 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
510 //#endif
518 //#endif
511 }
519 }
512
520
513 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
521 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
514 and return the code object. Return None if it the magic word doesn't
522 and return the code object. Return None if it the magic word doesn't
515 match (we do this instead of raising an exception as we fall back
523 match (we do this instead of raising an exception as we fall back
516 to .py if available and we don't want to mask other errors).
524 to .py if available and we don't want to mask other errors).
517 Returns a new reference. */
525 Returns a new reference. */
518 PyObject *
526 PyObject *
519 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
527 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
520 {
528 {
521 PyObject *code;
529 PyObject *code;
522 // ugly cast, but Python API is not const safe
530 // ugly cast, but Python API is not const safe
523 char *buf = (char*) data.constData();
531 char *buf = (char*) data.constData();
524 int size = data.size();
532 int size = data.size();
525
533
526 if (size <= 9) {
534 if (size <= 9) {
527 PySys_WriteStderr("# %s has bad pyc data\n",
535 PySys_WriteStderr("# %s has bad pyc data\n",
528 path.toLatin1().constData());
536 path.toLatin1().constData());
529 Py_INCREF(Py_None);
537 Py_INCREF(Py_None);
530 return Py_None;
538 return Py_None;
531 }
539 }
532
540
533 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
541 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
534 if (Py_VerboseFlag)
542 if (Py_VerboseFlag)
535 PySys_WriteStderr("# %s has bad magic\n",
543 PySys_WriteStderr("# %s has bad magic\n",
536 path.toLatin1().constData());
544 path.toLatin1().constData());
537 Py_INCREF(Py_None);
545 Py_INCREF(Py_None);
538 return Py_None;
546 return Py_None;
539 }
547 }
540
548
541 if (mtime != 0 && !(getLong((unsigned char *)buf + 4) == mtime)) {
549 if (mtime != 0 && !(getLong((unsigned char *)buf + 4) == mtime)) {
542 if (Py_VerboseFlag)
550 if (Py_VerboseFlag)
543 PySys_WriteStderr("# %s has bad mtime\n",
551 PySys_WriteStderr("# %s has bad mtime\n",
544 path.toLatin1().constData());
552 path.toLatin1().constData());
545 Py_INCREF(Py_None);
553 Py_INCREF(Py_None);
546 return Py_None;
554 return Py_None;
547 }
555 }
548
556
549 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
557 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
550 if (code == NULL)
558 if (code == NULL)
551 return NULL;
559 return NULL;
552 if (!PyCode_Check(code)) {
560 if (!PyCode_Check(code)) {
553 Py_DECREF(code);
561 Py_DECREF(code);
554 PyErr_Format(PyExc_TypeError,
562 PyErr_Format(PyExc_TypeError,
555 "compiled module %.200s is not a code object",
563 "compiled module %.200s is not a code object",
556 path.toLatin1().constData());
564 path.toLatin1().constData());
557 return NULL;
565 return NULL;
558 }
566 }
559 return code;
567 return code;
560 }
568 }
561
569
562
570
563 /* Given a string buffer containing Python source code, compile it
571 /* Given a string buffer containing Python source code, compile it
564 return and return a code object as a new reference. */
572 return and return a code object as a new reference. */
565 PyObject *
573 PyObject *
566 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
574 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
567 {
575 {
568 PyObject *code;
576 PyObject *code;
569 QByteArray data1 = data;
577 QByteArray data1 = data;
570 // in qt4, data is null terminated
578 // in qt4, data is null terminated
571 // data1.resize(data.size()+1);
579 // data1.resize(data.size()+1);
572 // data1.data()[data.size()-1] = 0;
580 // data1.data()[data.size()-1] = 0;
573 code = Py_CompileString(data.data(), path.toLatin1().constData(),
581 code = Py_CompileString(data.data(), path.toLatin1().constData(),
574 Py_file_input);
582 Py_file_input);
575 return code;
583 return code;
576 }
584 }
577
585
578
586
579 /* Return the code object for the module named by 'fullname' from the
587 /* Return the code object for the module named by 'fullname' from the
580 Zip archive as a new reference. */
588 Zip archive as a new reference. */
581 PyObject *
589 PyObject *
582 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int ispackage, time_t mtime)
590 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
583 {
591 {
584 bool hasImporter = PythonQt::importInterface()!=NULL;
585
586 PyObject *code;
592 PyObject *code;
587
593
588 QByteArray qdata;
594 QByteArray qdata;
589 if (!hasImporter) {
590 QFile file(path);
591 QIODevice::OpenMode flags = QIODevice::ReadOnly;
592 if (!isbytecode) {
593 flags |= QIODevice::Text;
594 }
595 if (!file.open(flags)) {
596 return NULL;
597 }
598 qdata = file.readAll();
599 } else {
600 if (!isbytecode) {
595 if (!isbytecode) {
601 // mlabDebugConst("MLABPython", "reading source " << path);
596 // mlabDebugConst("MLABPython", "reading source " << path);
602 bool ok;
597 bool ok;
603 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
598 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
604 if (!ok) {
599 if (!ok) {
605 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
600 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
606 return NULL;
601 return NULL;
607 }
602 }
608 if (qdata == " ") {
603 if (qdata == " ") {
609 qdata.clear();
604 qdata.clear();
610 }
605 }
611 } else {
606 } else {
612 qdata = PythonQt::importInterface()->readFileAsBytes(path);
607 qdata = PythonQt::importInterface()->readFileAsBytes(path);
613 }
608 }
614 }
615
609
616 if (isbytecode) {
610 if (isbytecode) {
617 // mlabDebugConst("MLABPython", "reading bytecode " << path);
611 // mlabDebugConst("MLABPython", "reading bytecode " << path);
618 code = unmarshalCode(path, qdata, mtime);
612 code = unmarshalCode(path, qdata, mtime);
619 }
613 }
620 else {
614 else {
621 // mlabDebugConst("MLABPython", "compiling source " << path);
615 // mlabDebugConst("MLABPython", "compiling source " << path);
622 code = compileSource(path, qdata);
616 code = compileSource(path, qdata);
623 if (code) {
617 if (code) {
624 // save a pyc file if possible
618 // save a pyc file if possible
625 QDateTime time;
619 QDateTime time;
626 time = hasImporter?PythonQt::importInterface()->lastModifiedDate(path):QFileInfo(path).lastModified();
620 time = PythonQt::importInterface()->lastModifiedDate(path);
627 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
621 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
628 }
622 }
629 }
623 }
630 return code;
624 return code;
631 }
625 }
632
626
633 time_t
627 time_t
634 PythonQtImport::getMTimeOfSource(const QString& path)
628 PythonQtImport::getMTimeOfSource(const QString& path)
635 {
629 {
636 time_t mtime = 0;
630 time_t mtime = 0;
637 QString path2 = path;
631 QString path2 = path;
638 path2.truncate(path.length()-1);
632 path2.truncate(path.length()-1);
639
633
640 bool hasImporter = PythonQt::importInterface()!=NULL;
634 if (PythonQt::importInterface()->exists(path2)) {
641 if (hasImporter) {
635 mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t();
642 if (PythonQt::importInterface()->exists(path2)) {
643 mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t();
644 }
645 } else {
646 if (QFile::exists(path2)) {
647 mtime = QFileInfo(path2).lastModified().toTime_t();
648 }
649 }
636 }
637
650 return mtime;
638 return mtime;
651 }
639 }
652
640
653 /* Get the code object associated with the module specified by
641 /* Get the code object associated with the module specified by
654 'fullname'. */
642 'fullname'. */
655 PyObject *
643 PyObject *
656 PythonQtImport::getModuleCode(PythonQtImporter *self, char *fullname,
644 PythonQtImport::getModuleCode(PythonQtImporter *self, char *fullname,
657 int *p_ispackage, QString& modpath)
645 int *p_ispackage, QString& modpath)
658 {
646 {
659 QString subname;
647 QString subname;
660 struct st_mlab_searchorder *zso;
648 struct st_mlab_searchorder *zso;
661
649
662 subname = getSubName(fullname);
650 subname = getSubName(fullname);
663 QString path = *self->_path + "/" + subname;
651 QString path = *self->_path + "/" + subname;
664
652
665 QString test;
653 QString test;
666 for (zso = mlab_searchorder; *zso->suffix; zso++) {
654 for (zso = mlab_searchorder; *zso->suffix; zso++) {
667 PyObject *code = NULL;
655 PyObject *code = NULL;
668 test = path + zso->suffix;
656 test = path + zso->suffix;
669
657
670 if (Py_VerboseFlag > 1)
658 if (Py_VerboseFlag > 1)
671 PySys_WriteStderr("# trying %s\n",
659 PySys_WriteStderr("# trying %s\n",
672 test.toLatin1().constData());
660 test.toLatin1().constData());
673 if (PythonQt::importInterface()->exists(test)) {
661 if (PythonQt::importInterface()->exists(test)) {
674 time_t mtime = 0;
662 time_t mtime = 0;
675 int ispackage = zso->type & IS_PACKAGE;
663 int ispackage = zso->type & IS_PACKAGE;
676 int isbytecode = zso->type & IS_BYTECODE;
664 int isbytecode = zso->type & IS_BYTECODE;
677
665
678 if (isbytecode)
666 if (isbytecode)
679 mtime = getMTimeOfSource(test);
667 mtime = getMTimeOfSource(test);
680 if (p_ispackage != NULL)
668 if (p_ispackage != NULL)
681 *p_ispackage = ispackage;
669 *p_ispackage = ispackage;
682 code = getCodeFromData(test, isbytecode, ispackage, mtime);
670 code = getCodeFromData(test, isbytecode, ispackage, mtime);
683 if (code == Py_None) {
671 if (code == Py_None) {
684 Py_DECREF(code);
672 Py_DECREF(code);
685 continue;
673 continue;
686 }
674 }
687 if (code != NULL)
675 if (code != NULL)
688 modpath = test;
676 modpath = test;
689 return code;
677 return code;
690 }
678 }
691 }
679 }
692 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
680 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
693
681
694 return NULL;
682 return NULL;
695 }
683 }
696
684
697 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
685 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
698 {
686 {
699 QString r;
687 QString r;
700 int i = str.lastIndexOf('.');
688 int i = str.lastIndexOf('.');
701 if (i!=-1) {
689 if (i!=-1) {
702 r = str.mid(0,i) + "." + ext;
690 r = str.mid(0,i) + "." + ext;
703 } else {
691 } else {
704 r = str + "." + ext;
692 r = str + "." + ext;
705 }
693 }
706 return r;
694 return r;
707 }
695 }
708
696
709 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
697 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
710 {
698 {
711 bool hasImporter = PythonQt::importInterface()!=NULL;
712
713 PyObject* code;
699 PyObject* code;
714 const static QString pycStr("pyc");
700 const static QString pycStr("pyc");
715 QString pyc = replaceExtension(file, pycStr);
701 QString pyc = replaceExtension(file, pycStr);
716 if ((hasImporter && PythonQt::importInterface()->exists(pyc)) ||
702 if (PythonQt::importInterface()->exists(pyc)) {
717 (!hasImporter && QFile::exists(pyc))) {
718 time_t mtime = 0;
703 time_t mtime = 0;
719 mtime = getMTimeOfSource(pyc);
704 mtime = getMTimeOfSource(pyc);
720 code = getCodeFromData(pyc, true, false, mtime);
705 code = getCodeFromData(pyc, true, false, mtime);
721 if (code != Py_None && code != NULL) {
706 if (code != Py_None && code != NULL) {
722 return code;
707 return code;
723 }
708 }
724 if (code) {
709 if (code) {
725 Py_DECREF(code);
710 Py_DECREF(code);
726 }
711 }
727 }
712 }
728 code = getCodeFromData(file,false,false,0);
713 code = getCodeFromData(file,false,false,0);
729 return code;
714 return code;
730 }
715 }
731
716
732 /* Module init */
717 /* Module init */
733
718
734 PyDoc_STRVAR(mlabimport_doc,
719 PyDoc_STRVAR(mlabimport_doc,
735 "Imports python files into MeVisLab, completely replaces internal python import");
720 "Imports python files into PythonQt, completely replaces internal python import");
736
721
737 void PythonQtImport::init()
722 void PythonQtImport::init()
738 {
723 {
724 static bool first = true;
725 if (!first) {
726 return;
727 }
728 first = false;
729
739 PyObject *mod;
730 PyObject *mod;
740
731
741 if (PyType_Ready(&PythonQtImporter_Type) < 0)
732 if (PyType_Ready(&PythonQtImporter_Type) < 0)
742 return;
733 return;
743
734
744 /* Correct directory separator */
735 /* Correct directory separator */
745 mlab_searchorder[0].suffix[0] = SEP;
736 mlab_searchorder[0].suffix[0] = SEP;
746 mlab_searchorder[1].suffix[0] = SEP;
737 mlab_searchorder[1].suffix[0] = SEP;
747 mlab_searchorder[2].suffix[0] = SEP;
738 mlab_searchorder[2].suffix[0] = SEP;
748 if (Py_OptimizeFlag) {
739 if (Py_OptimizeFlag) {
749 /* Reverse *.pyc and *.pyo */
740 /* Reverse *.pyc and *.pyo */
750 struct st_mlab_searchorder tmp;
741 struct st_mlab_searchorder tmp;
751 tmp = mlab_searchorder[0];
742 tmp = mlab_searchorder[0];
752 mlab_searchorder[0] = mlab_searchorder[1];
743 mlab_searchorder[0] = mlab_searchorder[1];
753 mlab_searchorder[1] = tmp;
744 mlab_searchorder[1] = tmp;
754 tmp = mlab_searchorder[3];
745 tmp = mlab_searchorder[3];
755 mlab_searchorder[3] = mlab_searchorder[4];
746 mlab_searchorder[3] = mlab_searchorder[4];
756 mlab_searchorder[4] = tmp;
747 mlab_searchorder[4] = tmp;
757 }
748 }
758
749
759 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
750 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
760 NULL, PYTHON_API_VERSION);
751 NULL, PYTHON_API_VERSION);
761
752
762 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
753 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
763 PyExc_ImportError, NULL);
754 PyExc_ImportError, NULL);
764 if (PythonQtImportError == NULL)
755 if (PythonQtImportError == NULL)
765 return;
756 return;
766
757
767 Py_INCREF(PythonQtImportError);
758 Py_INCREF(PythonQtImportError);
768 if (PyModule_AddObject(mod, "PythonQtImportError",
759 if (PyModule_AddObject(mod, "PythonQtImportError",
769 PythonQtImportError) < 0)
760 PythonQtImportError) < 0)
770 return;
761 return;
771
762
772 Py_INCREF(&PythonQtImporter_Type);
763 Py_INCREF(&PythonQtImporter_Type);
773 if (PyModule_AddObject(mod, "PythonQtImporter",
764 if (PyModule_AddObject(mod, "PythonQtImporter",
774 (PyObject *)&PythonQtImporter_Type) < 0)
765 (PyObject *)&PythonQtImporter_Type) < 0)
775 return;
766 return;
776
767
777 // set our importer into the path_hooks to handle all path on sys.path
768 // set our importer into the path_hooks to handle all path on sys.path
778 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
769 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
779 PyObject* path_hooks = PySys_GetObject("path_hooks");
770 PyObject* path_hooks = PySys_GetObject("path_hooks");
780 PyList_Append(path_hooks, classobj);
771 PyList_Append(path_hooks, classobj);
781
772
782 #ifndef WIN32
773 #ifndef WIN32
783 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
774 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
784 PyObject* modules = PyImport_GetModuleDict();
775 PyObject* modules = PyImport_GetModuleDict();
785 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
776 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
786 if (encodingsModule != NULL) {
777 if (encodingsModule != NULL) {
787 PyImport_ReloadModule(encodingsModule);
778 PyImport_ReloadModule(encodingsModule);
788 }
779 }
789 #endif
780 #endif
790 }
781 }
@@ -1,245 +1,245
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 PythonQtMetaObjectWrapper.cpp
35 // \file PythonQtMetaObjectWrapper.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 "PythonQtMetaObjectWrapper.h"
42 #include "PythonQtMetaObjectWrapper.h"
43 #include <QObject>
43 #include <QObject>
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include "PythonQtSlot.h"
46 #include "PythonQtSlot.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49
49
50 static void PythonQtMetaObjectWrapper_dealloc(PythonQtMetaObjectWrapper* self)
50 static void PythonQtMetaObjectWrapper_dealloc(PythonQtMetaObjectWrapper* self)
51 {
51 {
52 self->ob_type->tp_free((PyObject*)self);
52 self->ob_type->tp_free((PyObject*)self);
53 }
53 }
54
54
55 static PyObject* PythonQtMetaObjectWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
55 static PyObject* PythonQtMetaObjectWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
56 {
56 {
57 PythonQtMetaObjectWrapper *self;
57 PythonQtMetaObjectWrapper *self;
58
58
59 self = (PythonQtMetaObjectWrapper *)type->tp_alloc(type, 0);
59 self = (PythonQtMetaObjectWrapper *)type->tp_alloc(type, 0);
60 if (self != NULL) {
60 if (self != NULL) {
61 self->_info = NULL;
61 self->_info = NULL;
62 }
62 }
63 return (PyObject *)self;
63 return (PyObject *)self;
64 }
64 }
65
65
66 static int PythonQtMetaObjectWrapper_init(PythonQtMetaObjectWrapper *self, PyObject *args, PyObject *kwds)
66 static int PythonQtMetaObjectWrapper_init(PythonQtMetaObjectWrapper * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
67 {
67 {
68 return 0;
68 return 0;
69 }
69 }
70
70
71 PyObject *PythonQtMetaObjectWrapper_call(PyObject *func, PyObject *args, PyObject *kw) {
71 PyObject *PythonQtMetaObjectWrapper_call(PyObject *func, PyObject *args, PyObject *kw) {
72 PythonQtMetaObjectWrapper* wrapper = (PythonQtMetaObjectWrapper*)func;
72 PythonQtMetaObjectWrapper* wrapper = (PythonQtMetaObjectWrapper*)func;
73 PyObject* result = NULL;
73 PyObject* result = NULL;
74 QString error;
74 QString error;
75 PyObject* err = NULL;
75 PyObject* err = NULL;
76 if (wrapper->_info->constructors()) {
76 if (wrapper->_info->constructors()) {
77 result = PythonQtSlotFunction_CallImpl(NULL, wrapper->_info->constructors(), args, kw);
77 result = PythonQtSlotFunction_CallImpl(NULL, wrapper->_info->constructors(), args, kw);
78 err = PyErr_Occurred();
78 err = PyErr_Occurred();
79 }
79 }
80 if (!result) {
80 if (!result) {
81 QObject* v = NULL;
81 QObject* v = NULL;
82 QListIterator<PythonQtConstructorHandler*> it(PythonQt::self()->constructorHandlers());
82 QListIterator<PythonQtConstructorHandler*> it(PythonQt::self()->constructorHandlers());
83 while (!v && it.hasNext()) {
83 while (!v && it.hasNext()) {
84 v = it.next()->create(wrapper->_info->metaObject(), args, kw, error);
84 v = it.next()->create(wrapper->_info->metaObject(), args, kw, error);
85 }
85 }
86 if (v) {
86 if (v) {
87 result = PythonQt::priv()->wrapQObject(v);
87 result = PythonQt::priv()->wrapQObject(v);
88 }
88 }
89 }
89 }
90 if (result) {
90 if (result) {
91 // change ownershipflag to be owned by PythonQt
91 // change ownershipflag to be owned by PythonQt
92 if (result->ob_type == &PythonQtWrapper_Type) {
92 if (result->ob_type == &PythonQtWrapper_Type) {
93 ((PythonQtWrapper*)result)->_ownedByPythonQt = true;
93 ((PythonQtWrapper*)result)->_ownedByPythonQt = true;
94 }
94 }
95 } else {
95 } else {
96 if (!wrapper->_info->constructors()) {
96 if (!wrapper->_info->constructors()) {
97 if (!err) {
97 if (!err) {
98 if (error.isEmpty()) {
98 if (error.isEmpty()) {
99 error = QString("No constructors available for ") + wrapper->_info->className();
99 error = QString("No constructors available for ") + wrapper->_info->className();
100 }
100 }
101 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
101 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
102 }
102 }
103 }
103 }
104 }
104 }
105 return result;
105 return result;
106 }
106 }
107
107
108 static PyObject *PythonQtMetaObjectWrapper_classname(PythonQtMetaObjectWrapper* type)
108 static PyObject *PythonQtMetaObjectWrapper_classname(PythonQtMetaObjectWrapper* type)
109 {
109 {
110 return PyString_FromString((QString("Meta_") + type->_info->className()).toLatin1().data());
110 return PyString_FromString((QString("Meta_") + type->_info->className()).toLatin1().data());
111 }
111 }
112
112
113 static PyObject *PythonQtMetaObjectWrapper_help(PythonQtMetaObjectWrapper* type)
113 static PyObject *PythonQtMetaObjectWrapper_help(PythonQtMetaObjectWrapper* type)
114 {
114 {
115 return PythonQt::self()->helpCalled(type->_info);
115 return PythonQt::self()->helpCalled(type->_info);
116 }
116 }
117
117
118
118
119 static PyMethodDef PythonQtMetaObjectWrapper_methods[] = {
119 static PyMethodDef PythonQtMetaObjectWrapper_methods[] = {
120 {"className", (PyCFunction)PythonQtMetaObjectWrapper_classname, METH_NOARGS,
120 {"className", (PyCFunction)PythonQtMetaObjectWrapper_classname, METH_NOARGS,
121 "Return the classname of the object"
121 "Return the classname of the object"
122 },
122 },
123 {"help", (PyCFunction)PythonQtMetaObjectWrapper_help, METH_NOARGS,
123 {"help", (PyCFunction)PythonQtMetaObjectWrapper_help, METH_NOARGS,
124 "Shows the help of available methods for this class"
124 "Shows the help of available methods for this class"
125 },
125 },
126 {NULL} /* Sentinel */
126 {NULL, NULL, 0 , NULL} /* Sentinel */
127 };
127 };
128
128
129
129
130 static PyObject *PythonQtMetaObjectWrapper_getattro(PyObject *obj,PyObject *name)
130 static PyObject *PythonQtMetaObjectWrapper_getattro(PyObject *obj,PyObject *name)
131 {
131 {
132 const char *attributeName;
132 const char *attributeName;
133 PythonQtMetaObjectWrapper *wt = (PythonQtMetaObjectWrapper *)obj;
133 PythonQtMetaObjectWrapper *wt = (PythonQtMetaObjectWrapper *)obj;
134
134
135 if ((attributeName = PyString_AsString(name)) == NULL) {
135 if ((attributeName = PyString_AsString(name)) == NULL) {
136 return NULL;
136 return NULL;
137 }
137 }
138
138
139 PythonQtMemberInfo member = wt->_info->member(attributeName);
139 PythonQtMemberInfo member = wt->_info->member(attributeName);
140 if (member._type == PythonQtMemberInfo::EnumValue) {
140 if (member._type == PythonQtMemberInfo::EnumValue) {
141 return PyInt_FromLong(member._enumValue);
141 return PyInt_FromLong(member._enumValue);
142 }
142 }
143 if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) {
143 if (member._type == PythonQtMemberInfo::Slot && member._slot->isClassDecorator()) {
144 return PythonQtSlotFunction_New(member._slot, obj, NULL);
144 return PythonQtSlotFunction_New(member._slot, obj, NULL);
145 }
145 }
146
146
147 // look for the interal methods (className(), help())
147 // look for the interal methods (className(), help())
148 PyObject* internalMethod = Py_FindMethod( PythonQtMetaObjectWrapper_methods, obj, (char*)attributeName);
148 PyObject* internalMethod = Py_FindMethod( PythonQtMetaObjectWrapper_methods, obj, (char*)attributeName);
149 if (internalMethod) {
149 if (internalMethod) {
150 return internalMethod;
150 return internalMethod;
151 }
151 }
152 PyErr_Clear();
152 PyErr_Clear();
153
153
154 if (qstrcmp(attributeName, "__dict__")==0) {
154 if (qstrcmp(attributeName, "__dict__")==0) {
155 QStringList l = wt->_info->memberList(true);
155 QStringList l = wt->_info->memberList(true);
156 PyObject* dict = PyDict_New();
156 PyObject* dict = PyDict_New();
157 foreach (QString name, l) {
157 foreach (QString name, l) {
158 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
158 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
159 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
159 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
160 //Py_DECREF(o);
160 //Py_DECREF(o);
161 }
161 }
162 return dict;
162 return dict;
163 }
163 }
164
164
165 QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
165 QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
166 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
166 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
167 return NULL;
167 return NULL;
168 }
168 }
169
169
170 static PyObject * PythonQtMetaObjectWrapper_repr(PyObject * obj)
170 static PyObject * PythonQtMetaObjectWrapper_repr(PyObject * obj)
171 {
171 {
172 PythonQtMetaObjectWrapper* wt = (PythonQtMetaObjectWrapper*)obj;
172 PythonQtMetaObjectWrapper* wt = (PythonQtMetaObjectWrapper*)obj;
173 if (wt->_info->isCPPWrapper()) {
173 if (wt->_info->isCPPWrapper()) {
174 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wt->_info->className(), wt->_info->metaObject()->className());
174 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wt->_info->className(), wt->_info->metaObject()->className());
175 } else {
175 } else {
176 return PyString_FromFormat("%s Class", wt->_info->className());
176 return PyString_FromFormat("%s Class", wt->_info->className());
177 }
177 }
178 }
178 }
179
179
180 static int PythonQtMetaObjectWrapper_compare(PyObject * obj1, PyObject * obj2)
180 static int PythonQtMetaObjectWrapper_compare(PyObject * obj1, PyObject * obj2)
181 {
181 {
182 if (obj1->ob_type == &PythonQtMetaObjectWrapper_Type &&
182 if (obj1->ob_type == &PythonQtMetaObjectWrapper_Type &&
183 obj2->ob_type == &PythonQtMetaObjectWrapper_Type) {
183 obj2->ob_type == &PythonQtMetaObjectWrapper_Type) {
184
184
185 PythonQtMetaObjectWrapper* w1 = (PythonQtMetaObjectWrapper*)obj1;
185 PythonQtMetaObjectWrapper* w1 = (PythonQtMetaObjectWrapper*)obj1;
186 PythonQtMetaObjectWrapper* w2 = (PythonQtMetaObjectWrapper*)obj2;
186 PythonQtMetaObjectWrapper* w2 = (PythonQtMetaObjectWrapper*)obj2;
187 if (w1->_info == w2->_info) {
187 if (w1->_info == w2->_info) {
188 return 0;
188 return 0;
189 } else {
189 } else {
190 return -1;
190 return -1;
191 }
191 }
192 } else {
192 } else {
193 return -1;
193 return -1;
194 }
194 }
195 }
195 }
196
196
197 static long PythonQtMetaObjectWrapper_hash(PythonQtMetaObjectWrapper *obj)
197 static long PythonQtMetaObjectWrapper_hash(PythonQtMetaObjectWrapper *obj)
198 {
198 {
199 return reinterpret_cast<long>(obj->_info);
199 return reinterpret_cast<long>(obj->_info);
200 }
200 }
201
201
202 PyTypeObject PythonQtMetaObjectWrapper_Type = {
202 PyTypeObject PythonQtMetaObjectWrapper_Type = {
203 PyObject_HEAD_INIT(NULL)
203 PyObject_HEAD_INIT(NULL)
204 0, /*ob_size*/
204 0, /*ob_size*/
205 "PythonQt.PythonQtMetaObjectWrapper", /*tp_name*/
205 "PythonQt.PythonQtMetaObjectWrapper", /*tp_name*/
206 sizeof(PythonQtMetaObjectWrapper), /*tp_basicsize*/
206 sizeof(PythonQtMetaObjectWrapper), /*tp_basicsize*/
207 0, /*tp_itemsize*/
207 0, /*tp_itemsize*/
208 (destructor)PythonQtMetaObjectWrapper_dealloc, /*tp_dealloc*/
208 (destructor)PythonQtMetaObjectWrapper_dealloc, /*tp_dealloc*/
209 0, /*tp_print*/
209 0, /*tp_print*/
210 0, /*tp_getattr*/
210 0, /*tp_getattr*/
211 0, /*tp_setattr*/
211 0, /*tp_setattr*/
212 PythonQtMetaObjectWrapper_compare, /*tp_compare*/
212 PythonQtMetaObjectWrapper_compare, /*tp_compare*/
213 PythonQtMetaObjectWrapper_repr, /*tp_repr*/
213 PythonQtMetaObjectWrapper_repr, /*tp_repr*/
214 0, /*tp_as_number*/
214 0, /*tp_as_number*/
215 0, /*tp_as_sequence*/
215 0, /*tp_as_sequence*/
216 0, /*tp_as_mapping*/
216 0, /*tp_as_mapping*/
217 (hashfunc)PythonQtMetaObjectWrapper_hash, /*tp_hash */
217 (hashfunc)PythonQtMetaObjectWrapper_hash, /*tp_hash */
218 PythonQtMetaObjectWrapper_call, /*tp_call*/
218 PythonQtMetaObjectWrapper_call, /*tp_call*/
219 0, /*tp_str*/
219 0, /*tp_str*/
220 PythonQtMetaObjectWrapper_getattro, /*tp_getattro*/
220 PythonQtMetaObjectWrapper_getattro, /*tp_getattro*/
221 0, /*tp_setattro*/
221 0, /*tp_setattro*/
222 0, /*tp_as_buffer*/
222 0, /*tp_as_buffer*/
223 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
223 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
224 "PythonQtMetaObjectWrapper object", /* tp_doc */
224 "PythonQtMetaObjectWrapper object", /* tp_doc */
225 0, /* tp_traverse */
225 0, /* tp_traverse */
226 0, /* tp_clear */
226 0, /* tp_clear */
227 0, /* tp_richcompare */
227 0, /* tp_richcompare */
228 0, /* tp_weaklistoffset */
228 0, /* tp_weaklistoffset */
229 0, /* tp_iter */
229 0, /* tp_iter */
230 0, /* tp_iternext */
230 0, /* tp_iternext */
231 0, /* tp_methods */
231 0, /* tp_methods */
232 0, /* tp_members */
232 0, /* tp_members */
233 0, /* tp_getset */
233 0, /* tp_getset */
234 0, /* tp_base */
234 0, /* tp_base */
235 0, /* tp_dict */
235 0, /* tp_dict */
236 0, /* tp_descr_get */
236 0, /* tp_descr_get */
237 0, /* tp_descr_set */
237 0, /* tp_descr_set */
238 0, /* tp_dictoffset */
238 0, /* tp_dictoffset */
239 (initproc)PythonQtMetaObjectWrapper_init, /* tp_init */
239 (initproc)PythonQtMetaObjectWrapper_init, /* tp_init */
240 0, /* tp_alloc */
240 0, /* tp_alloc */
241 PythonQtMetaObjectWrapper_new, /* tp_new */
241 PythonQtMetaObjectWrapper_new, /* tp_new */
242 };
242 };
243
243
244 //-------------------------------------------------------
244 //-------------------------------------------------------
245
245
@@ -1,76 +1,79
1 #ifndef _PYTHONQTMETAOBJECTWRAPPER_H
1 #ifndef _PYTHONQTMETAOBJECTWRAPPER_H
2 #define _PYTHONQTMETAOBJECTWRAPPER_H
2 #define _PYTHONQTMETAOBJECTWRAPPER_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 PythonQtMetaObjectWrapper.h
38 // \file PythonQtMetaObjectWrapper.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 <Python.h>
45 #include <Python.h>
46
46
47 #include "structmember.h"
47 #include "structmember.h"
48 #include "methodobject.h"
48 #include "methodobject.h"
49 #include "compile.h"
49 #include "compile.h"
50 #include "eval.h"
50 #include "eval.h"
51 #include <QString>
51 #include <QString>
52
52
53 class PythonQtClassInfo;
53 class PythonQtClassInfo;
54 class QObject;
54 class QObject;
55 struct QMetaObject;
55 struct QMetaObject;
56
56
57 extern PyTypeObject PythonQtMetaObjectWrapper_Type;
57 extern PyTypeObject PythonQtMetaObjectWrapper_Type;
58
58
59 //---------------------------------------------------------------
59 //---------------------------------------------------------------
60 //! a Python wrapper object for Qt meta objects
60 //! a Python wrapper object for Qt meta objects
61 typedef struct {
61 typedef struct {
62 PyObject_HEAD
62 PyObject_HEAD
63
63
64 //! the class information (which contains the meta object as well)
64 //! the class information (which contains the meta object as well)
65 PythonQtClassInfo* _info;
65 PythonQtClassInfo* _info;
66
66
67 } PythonQtMetaObjectWrapper;
67 } PythonQtMetaObjectWrapper;
68
68
69 //---------------------------------------------------------------
69 //---------------------------------------------------------------
70 // an abstact class for handling construction of objects
70 // an abstact class for handling construction of objects
71 class PythonQtConstructorHandler {
71 class PythonQtConstructorHandler {
72 public:
72 public:
73 //! get rid of warnings
74 virtual ~PythonQtConstructorHandler() {}
75
73 virtual QObject* create(const QMetaObject* meta, PyObject *args, PyObject *kw, QString& error) = 0;
76 virtual QObject* create(const QMetaObject* meta, PyObject *args, PyObject *kw, QString& error) = 0;
74 };
77 };
75
78
76 #endif No newline at end of file
79 #endif
@@ -1,134 +1,135
1 #ifndef _PYTHONQTMISC_H
1 #ifndef _PYTHONQTMISC_H
2 #define _PYTHONQTMISC_H
2 #define _PYTHONQTMISC_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 PythonQtMisc.h
38 // \file PythonQtMisc.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
45
46 #include <QList>
46 #include <QList>
47
47
48 #define PythonQtValueStorage_ADD_VALUE(store, type, value, ptr) \
48 #define PythonQtValueStorage_ADD_VALUE(store, type, value, ptr) \
49 { type* item = (type*)store.nextValuePtr(); \
49 { type* item = (type*)store.nextValuePtr(); \
50 *item = value; \
50 *item = value; \
51 ptr = (void*)item; \
51 ptr = (void*)item; \
52 }
52 }
53
53
54 //! stores a position in the PythonQtValueStorage
54 //! stores a position in the PythonQtValueStorage
55 class PythonQtValueStoragePosition {
55 class PythonQtValueStoragePosition {
56
56
57 public:
57 public:
58 PythonQtValueStoragePosition() { chunkIdx = 0; chunkOffset = 0; }
58 PythonQtValueStoragePosition() { chunkIdx = 0; chunkOffset = 0; }
59
59
60 int chunkIdx;
60 int chunkIdx;
61 int chunkOffset;
61 int chunkOffset;
62
62
63 };
63 };
64
64
65 //! a helper class that stores basic C++ value types in chunks
65 //! a helper class that stores basic C++ value types in chunks
66 template <typename T, int chunkEntries> class PythonQtValueStorage
66 template <typename T, int chunkEntries> class PythonQtValueStorage
67 {
67 {
68 public:
68 public:
69 PythonQtValueStorage() {
69 PythonQtValueStorage() {
70 _chunkIdx = 0;
70 _chunkIdx = 0;
71 _chunkOffset = 0;
71 _chunkOffset = 0;
72 _currentChunk = new T[chunkEntries];
72 _currentChunk = new T[chunkEntries];
73 _chunks.append(_currentChunk);
73 _chunks.append(_currentChunk);
74 };
74 };
75
75
76 //! clear all memory
76 //! clear all memory
77 void clear() {
77 void clear() {
78 T* chunk;
78 T* chunk;
79 foreach(chunk, _chunks) {
79 foreach(chunk, _chunks) {
80 delete[]chunk;
80 delete[]chunk;
81 }
81 }
82 _chunks.clear();
82 }
83 }
83
84
84 //! reset the storage to 0 (without freeing memory, thus caching old entries for reuse)
85 //! reset the storage to 0 (without freeing memory, thus caching old entries for reuse)
85 void reset() {
86 void reset() {
86 _chunkIdx = 0;
87 _chunkIdx = 0;
87 _chunkOffset = 0;
88 _chunkOffset = 0;
88 _currentChunk = _chunks.at(0);
89 _currentChunk = _chunks.at(0);
89 }
90 }
90
91
91 //! get the current position to be restored with setPos
92 //! get the current position to be restored with setPos
92 void getPos(PythonQtValueStoragePosition & pos) {
93 void getPos(PythonQtValueStoragePosition & pos) {
93 pos.chunkIdx = _chunkIdx;
94 pos.chunkIdx = _chunkIdx;
94 pos.chunkOffset = _chunkOffset;
95 pos.chunkOffset = _chunkOffset;
95 }
96 }
96
97
97 //! set the current position (without freeing memory, thus caching old entries for reuse)
98 //! set the current position (without freeing memory, thus caching old entries for reuse)
98 void setPos(const PythonQtValueStoragePosition& pos) {
99 void setPos(const PythonQtValueStoragePosition& pos) {
99 _chunkOffset = pos.chunkOffset;
100 _chunkOffset = pos.chunkOffset;
100 if (_chunkIdx != pos.chunkIdx) {
101 if (_chunkIdx != pos.chunkIdx) {
101 _chunkIdx = pos.chunkIdx;
102 _chunkIdx = pos.chunkIdx;
102 _currentChunk = _chunks.at(_chunkIdx);
103 _currentChunk = _chunks.at(_chunkIdx);
103 }
104 }
104 }
105 }
105
106
106 //! add one default constructed value and return the pointer to it
107 //! add one default constructed value and return the pointer to it
107 T* nextValuePtr() {
108 T* nextValuePtr() {
108 if (_chunkOffset>=chunkEntries) {
109 if (_chunkOffset>=chunkEntries) {
109 _chunkIdx++;
110 _chunkIdx++;
110 if (_chunkIdx >= _chunks.size()) {
111 if (_chunkIdx >= _chunks.size()) {
111 T* newChunk = new T[chunkEntries];
112 T* newChunk = new T[chunkEntries];
112 _chunks.append(newChunk);
113 _chunks.append(newChunk);
113 _currentChunk = newChunk;
114 _currentChunk = newChunk;
114 } else {
115 } else {
115 _currentChunk = _chunks.at(_chunkIdx);
116 _currentChunk = _chunks.at(_chunkIdx);
116 }
117 }
117 _chunkOffset = 0;
118 _chunkOffset = 0;
118 }
119 }
119 T* newEntry = _currentChunk + _chunkOffset;
120 T* newEntry = _currentChunk + _chunkOffset;
120 _chunkOffset++;
121 _chunkOffset++;
121 return newEntry;
122 return newEntry;
122 };
123 };
123
124
124 private:
125 private:
125 QList<T*> _chunks;
126 QList<T*> _chunks;
126
127
127 int _chunkIdx;
128 int _chunkIdx;
128 int _chunkOffset;
129 int _chunkOffset;
129 T* _currentChunk;
130 T* _currentChunk;
130
131
131 };
132 };
132
133
133
134
134 #endif
135 #endif
@@ -1,450 +1,454
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtSlot.cpp
35 // \file PythonQtSlot.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtSlot.h"
43 #include "PythonQtSlot.h"
44 #include "PythonQtWrapper.h"
44 #include "PythonQtWrapper.h"
45 #include "PythonQtClassInfo.h"
45 #include "PythonQtClassInfo.h"
46 #include "PythonQtMisc.h"
46 #include "PythonQtMisc.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include <iostream>
48 #include <iostream>
49
49
50 #define PYTHONQT_MAX_ARGS 32
50 #define PYTHONQT_MAX_ARGS 32
51
51
52
52
53 PyObject* PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, bool isVariantCall, void* firstArgument)
53 PyObject* PythonQtCallSlot(QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, bool isVariantCall, void* firstArgument)
54 {
54 {
55 if (isVariantCall && info->isInstanceDecorator()) return NULL;
55 if (isVariantCall && info->isInstanceDecorator()) return NULL;
56
56
57 static unsigned int recursiveEntry = 0;
57 static unsigned int recursiveEntry = 0;
58
58
59 // store the current storage position, so that we can get back to this state after a slot is called
59 // store the current storage position, so that we can get back to this state after a slot is called
60 // (do this locally, so that we have all positions on the stack
60 // (do this locally, so that we have all positions on the stack
61 PythonQtValueStoragePosition globalValueStoragePos;
61 PythonQtValueStoragePosition globalValueStoragePos;
62 PythonQtValueStoragePosition globalPtrStoragePos;
62 PythonQtValueStoragePosition globalPtrStoragePos;
63 PythonQtValueStoragePosition globalVariantStoragePos;
63 PythonQtValueStoragePosition globalVariantStoragePos;
64 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
64 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
65 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
65 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
66 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
66 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
67
67
68 recursiveEntry++;
68 recursiveEntry++;
69
69
70 // the arguments that are passed to qt_metacall
70 // the arguments that are passed to qt_metacall
71 void* argList[PYTHONQT_MAX_ARGS];
71 void* argList[PYTHONQT_MAX_ARGS];
72 PyObject* result = NULL;
72 PyObject* result = NULL;
73 int argc = info->parameterCount();
73 int argc = info->parameterCount();
74 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
74 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
75
75
76 bool returnValueIsEnum = false;
76 bool returnValueIsEnum = false;
77 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
77 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
78 // set return argument to NULL
78 // set return argument to NULL
79 argList[0] = NULL;
79 argList[0] = NULL;
80
80
81 if (returnValueParam.typeId != QMetaType::Void) {
81 if (returnValueParam.typeId != QMetaType::Void) {
82 // extra handling of enum return value
82 // extra handling of enum return value
83 if (!returnValueParam.isPointer && returnValueParam.typeId == PythonQtMethodInfo::Unknown) {
83 if (!returnValueParam.isPointer && returnValueParam.typeId == PythonQtMethodInfo::Unknown) {
84 returnValueIsEnum = PythonQt::priv()->isEnumType(objectToCall->metaObject(), returnValueParam.name);
84 returnValueIsEnum = PythonQt::priv()->isEnumType(objectToCall->metaObject(), returnValueParam.name);
85 if (returnValueIsEnum) {
85 if (returnValueIsEnum) {
86 // create enum return value
86 // create enum return value
87 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
87 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, argList[0]);
88 }
88 }
89 }
89 }
90 if (argList[0]==NULL) {
90 if (argList[0]==NULL) {
91 // create empty default value for the return value
91 // create empty default value for the return value
92 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
92 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
93 }
93 }
94 }
94 }
95
95
96 const QMetaObject* meta = objectToCall?objectToCall->metaObject():NULL;
96 const QMetaObject* meta = objectToCall?objectToCall->metaObject():NULL;
97 bool ok = true;
97 bool ok = true;
98 bool skipFirst = false;
98 bool skipFirst = false;
99 if (info->isInstanceDecorator() || isVariantCall) {
99 if (info->isInstanceDecorator() || isVariantCall) {
100 skipFirst = true;
100 skipFirst = true;
101 if (!firstArgument) {
101 if (!firstArgument) {
102 argList[1] = &objectToCall;
102 argList[1] = &objectToCall;
103 } else {
103 } else {
104 // for the variant call we take the ptr to the variant data, for decorators on CPP objects, we take the cpp ptr
104 // for the variant call we take the ptr to the variant data, for decorators on CPP objects, we take the cpp ptr
105 argList[1] = &firstArgument;
105 argList[1] = &firstArgument;
106 }
106 }
107 if (ok) {
107 if (ok) {
108 for (int i = 2; i<argc && ok; i++) {
108 for (int i = 2; i<argc && ok; i++) {
109 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
109 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
110 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
110 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
111 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, meta);
111 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, meta);
112 if (argList[i]==NULL) {
112 if (argList[i]==NULL) {
113 ok = false;
113 ok = false;
114 break;
114 break;
115 }
115 }
116 }
116 }
117 }
117 }
118 } else {
118 } else {
119 for (int i = 1; i<argc && ok; i++) {
119 for (int i = 1; i<argc && ok; i++) {
120 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
120 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
121 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
121 //std::cout << param.name.data() << " " << param.typeId << (param.isPointer?"*":"") << (param.isConst?" const":"") << std::endl;
122 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, meta);
122 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, meta);
123 if (argList[i]==NULL) {
123 if (argList[i]==NULL) {
124 ok = false;
124 ok = false;
125 break;
125 break;
126 }
126 }
127 }
127 }
128 }
128 }
129
129
130 if (ok) {
130 if (ok) {
131 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
131 (info->decorator()?info->decorator():objectToCall)->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
132
132
133 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
133 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
134 if (!returnValueIsEnum) {
134 if (!returnValueIsEnum) {
135 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
135 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
136 } else {
136 } else {
137 result = PyInt_FromLong(*((unsigned int*)argList[0]));
137 result = PyInt_FromLong(*((unsigned int*)argList[0]));
138 }
138 }
139 } else {
139 } else {
140 QString e = QString("Called ") + info->fullSignature(skipFirst) + ", return type is ignored because it is unknown to PythonQt.";
140 QString e = QString("Called ") + info->fullSignature(skipFirst) + ", return type is ignored because it is unknown to PythonQt.";
141 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
141 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
142 result = NULL;
142 result = NULL;
143 }
143 }
144 }
144 }
145 recursiveEntry--;
145 recursiveEntry--;
146
146
147 // reset the parameter storage position to the stored pos to "pop" the parameter stack
147 // reset the parameter storage position to the stored pos to "pop" the parameter stack
148 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
148 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
149 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
149 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
150 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
150 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
151
151
152 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
152 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
153 return result;
153 return result;
154 }
154 }
155
155
156 //-----------------------------------------------------------------------------------
156 //-----------------------------------------------------------------------------------
157
157
158 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
158 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
159
159
160 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
160 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
161 {
161 {
162 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
162 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
163 PythonQtSlotInfo* info = f->m_ml;
163 PythonQtSlotInfo* info = f->m_ml;
164 if (f->m_self->ob_type == &PythonQtWrapper_Type) {
164 if (f->m_self->ob_type == &PythonQtWrapper_Type) {
165 PythonQtWrapper* self = (PythonQtWrapper*) f->m_self;
165 PythonQtWrapper* self = (PythonQtWrapper*) f->m_self;
166 return PythonQtSlotFunction_CallImpl(self->_obj, info, args, kw, false, self->_wrappedPtr);
166 return PythonQtSlotFunction_CallImpl(self->_obj, info, args, kw, false, self->_wrappedPtr);
167 } else if (f->m_self->ob_type == &PythonQtVariantWrapper_Type) {
167 } else if (f->m_self->ob_type == &PythonQtVariantWrapper_Type) {
168 PythonQtVariantWrapper* self = (PythonQtVariantWrapper*) f->m_self;
168 PythonQtVariantWrapper* self = (PythonQtVariantWrapper*) f->m_self;
169 if (!info->isClassDecorator()) {
169 if (!info->isClassDecorator()) {
170 return PythonQtSlotFunction_CallImpl(self->_wrapper, info, args, kw, true, (void*)self->_variant->constData());
170 return PythonQtSlotFunction_CallImpl(self->_wrapper, info, args, kw, true, (void*)self->_variant->constData());
171 } else {
171 } else {
172 return PythonQtSlotFunction_CallImpl(NULL, info, args, kw);
172 return PythonQtSlotFunction_CallImpl(NULL, info, args, kw);
173 }
173 }
174 } else if (f->m_self->ob_type == &PythonQtMetaObjectWrapper_Type) {
174 } else if (f->m_self->ob_type == &PythonQtMetaObjectWrapper_Type) {
175 return PythonQtSlotFunction_CallImpl(NULL, info, args, kw);
175 return PythonQtSlotFunction_CallImpl(NULL, info, args, kw);
176 } else {
176 } else {
177 return NULL;
177 return NULL;
178 }
178 }
179 }
179 }
180
180
181 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject *kw, bool isVariantCall, void* firstArg)
181 PyObject *PythonQtSlotFunction_CallImpl(QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, bool isVariantCall, void* firstArg)
182 {
182 {
183 int argc = PyTuple_Size(args);
183 int argc = PyTuple_Size(args);
184
184
185 #ifdef PYTHONQT_DEBUG
185 #ifdef PYTHONQT_DEBUG
186 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
186 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
187 #endif
187 #endif
188
188
189 PyObject* r = NULL;
189 PyObject* r = NULL;
190
190
191 if (info->nextInfo()) {
191 if (info->nextInfo()) {
192 // overloaded slot call, try on all slots with strict conversion first
192 // overloaded slot call, try on all slots with strict conversion first
193 PythonQtSlotInfo* i = info;
193 PythonQtSlotInfo* i = info;
194 while (i && r==NULL) {
194 while (i && r==NULL) {
195 bool skipFirst = (i->isInstanceDecorator() || isVariantCall);
195 bool skipFirst = (i->isInstanceDecorator() || isVariantCall);
196 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
196 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
197 PyErr_Clear();
197 PyErr_Clear();
198 r = PythonQtCallSlot(objectToCall, args, true, i, isVariantCall, firstArg);
198 r = PythonQtCallSlot(objectToCall, args, true, i, isVariantCall, firstArg);
199 if (PyErr_Occurred()) break;
199 if (PyErr_Occurred()) break;
200 }
200 }
201 i = i->nextInfo();
201 i = i->nextInfo();
202 }
202 }
203 if (!r) {
203 if (!r) {
204 // try on all slots with non-strict conversion
204 // try on all slots with non-strict conversion
205 i = info;
205 i = info;
206 while (i && r==NULL) {
206 while (i && r==NULL) {
207 bool skipFirst = (i->isInstanceDecorator() || isVariantCall);
207 bool skipFirst = (i->isInstanceDecorator() || isVariantCall);
208 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
208 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
209 PyErr_Clear();
209 PyErr_Clear();
210 r = PythonQtCallSlot(objectToCall, args, false, i, isVariantCall, firstArg);
210 r = PythonQtCallSlot(objectToCall, args, false, i, isVariantCall, firstArg);
211 if (PyErr_Occurred()) break;
211 if (PyErr_Occurred()) break;
212 }
212 }
213 i = i->nextInfo();
213 i = i->nextInfo();
214 }
214 }
215 }
215 }
216 if (r==NULL && !PyErr_Occurred()) {
216 if (r==NULL && !PyErr_Occurred()) {
217 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
217 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
218 PythonQtSlotInfo* i = info;
218 PythonQtSlotInfo* i = info;
219 while (i) {
219 while (i) {
220 bool skipFirst = (i->isInstanceDecorator() || isVariantCall);
220 bool skipFirst = (i->isInstanceDecorator() || isVariantCall);
221 e += QString(i->fullSignature(skipFirst)) + "\n";
221 e += QString(i->fullSignature(skipFirst)) + "\n";
222 i = i->nextInfo();
222 i = i->nextInfo();
223 }
223 }
224 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
224 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
225 }
225 }
226 } else {
226 } else {
227 // simple (non-overloaded) slot call
227 // simple (non-overloaded) slot call
228 bool skipFirst = (info->isInstanceDecorator() || isVariantCall);
228 bool skipFirst = (info->isInstanceDecorator() || isVariantCall);
229 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
229 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
230 PyErr_Clear();
230 PyErr_Clear();
231 r = PythonQtCallSlot(objectToCall, args, false, info, isVariantCall, firstArg);
231 r = PythonQtCallSlot(objectToCall, args, false, info, isVariantCall, firstArg);
232 if (r==NULL && !PyErr_Occurred()) {
232 if (r==NULL && !PyErr_Occurred()) {
233 QString e = QString("Called ") + info->fullSignature(skipFirst) + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
233 QString e = QString("Called ") + info->fullSignature(skipFirst) + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
234 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
234 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
235 }
235 }
236 } else {
236 } else {
237 QString e = QString("Called ") + info->fullSignature(skipFirst) + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
237 QString e = QString("Called ") + info->fullSignature(skipFirst) + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
238 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
238 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
239 }
239 }
240 }
240 }
241
241
242 return r;
242 return r;
243 }
243 }
244
244
245 PyObject *
245 PyObject *
246 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
246 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
247 {
247 {
248 PythonQtSlotFunctionObject *op;
248 PythonQtSlotFunctionObject *op;
249 op = pythonqtslot_free_list;
249 op = pythonqtslot_free_list;
250 if (op != NULL) {
250 if (op != NULL) {
251 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
251 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
252 PyObject_INIT(op, &PythonQtSlotFunction_Type);
252 PyObject_INIT(op, &PythonQtSlotFunction_Type);
253 }
253 }
254 else {
254 else {
255 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
255 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
256 if (op == NULL)
256 if (op == NULL)
257 return NULL;
257 return NULL;
258 }
258 }
259 op->m_ml = ml;
259 op->m_ml = ml;
260 Py_XINCREF(self);
260 Py_XINCREF(self);
261 op->m_self = self;
261 op->m_self = self;
262 Py_XINCREF(module);
262 Py_XINCREF(module);
263 op->m_module = module;
263 op->m_module = module;
264 PyObject_GC_Track(op);
264 PyObject_GC_Track(op);
265 return (PyObject *)op;
265 return (PyObject *)op;
266 }
266 }
267
267
268 PythonQtSlotInfo*
268 PythonQtSlotInfo*
269 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
269 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
270 {
270 {
271 if (!PythonQtSlotFunction_Check(op)) {
271 if (!PythonQtSlotFunction_Check(op)) {
272 PyErr_BadInternalCall();
272 PyErr_BadInternalCall();
273 return NULL;
273 return NULL;
274 }
274 }
275 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
275 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
276 }
276 }
277
277
278 PyObject *
278 PyObject *
279 PythonQtSlotFunction_GetSelf(PyObject *op)
279 PythonQtSlotFunction_GetSelf(PyObject *op)
280 {
280 {
281 if (!PythonQtSlotFunction_Check(op)) {
281 if (!PythonQtSlotFunction_Check(op)) {
282 PyErr_BadInternalCall();
282 PyErr_BadInternalCall();
283 return NULL;
283 return NULL;
284 }
284 }
285 return ((PythonQtSlotFunctionObject *)op) -> m_self;
285 return ((PythonQtSlotFunctionObject *)op) -> m_self;
286 }
286 }
287
287
288 /* Methods (the standard built-in methods, that is) */
288 /* Methods (the standard built-in methods, that is) */
289
289
290 static void
290 static void
291 meth_dealloc(PythonQtSlotFunctionObject *m)
291 meth_dealloc(PythonQtSlotFunctionObject *m)
292 {
292 {
293 PyObject_GC_UnTrack(m);
293 PyObject_GC_UnTrack(m);
294 Py_XDECREF(m->m_self);
294 Py_XDECREF(m->m_self);
295 Py_XDECREF(m->m_module);
295 Py_XDECREF(m->m_module);
296 m->m_self = (PyObject *)pythonqtslot_free_list;
296 m->m_self = (PyObject *)pythonqtslot_free_list;
297 pythonqtslot_free_list = m;
297 pythonqtslot_free_list = m;
298 }
298 }
299
299
300 static PyObject *
300 static PyObject *
301 meth_get__doc__(PythonQtSlotFunctionObject *m, void *closure)
301 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
302 {
302 {
303 Py_INCREF(Py_None);
303 Py_INCREF(Py_None);
304 return Py_None;
304 return Py_None;
305 }
305 }
306
306
307 static PyObject *
307 static PyObject *
308 meth_get__name__(PythonQtSlotFunctionObject *m, void *closure)
308 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
309 {
309 {
310 return PyString_FromString(m->m_ml->metaMethod()->signature());
310 return PyString_FromString(m->m_ml->metaMethod()->signature());
311 }
311 }
312
312
313 static int
313 static int
314 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
314 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
315 {
315 {
316 int err;
316 int err;
317 if (m->m_self != NULL) {
317 if (m->m_self != NULL) {
318 err = visit(m->m_self, arg);
318 err = visit(m->m_self, arg);
319 if (err)
319 if (err)
320 return err;
320 return err;
321 }
321 }
322 if (m->m_module != NULL) {
322 if (m->m_module != NULL) {
323 err = visit(m->m_module, arg);
323 err = visit(m->m_module, arg);
324 if (err)
324 if (err)
325 return err;
325 return err;
326 }
326 }
327 return 0;
327 return 0;
328 }
328 }
329
329
330 static PyObject *
330 static PyObject *
331 meth_get__self__(PythonQtSlotFunctionObject *m, void *closure)
331 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
332 {
332 {
333 PyObject *self;
333 PyObject *self;
334 if (PyEval_GetRestricted()) {
334 if (PyEval_GetRestricted()) {
335 PyErr_SetString(PyExc_RuntimeError,
335 PyErr_SetString(PyExc_RuntimeError,
336 "method.__self__ not accessible in restricted mode");
336 "method.__self__ not accessible in restricted mode");
337 return NULL;
337 return NULL;
338 }
338 }
339 self = m->m_self;
339 self = m->m_self;
340 if (self == NULL)
340 if (self == NULL)
341 self = Py_None;
341 self = Py_None;
342 Py_INCREF(self);
342 Py_INCREF(self);
343 return self;
343 return self;
344 }
344 }
345
345
346 static PyGetSetDef meth_getsets [] = {
346 static PyGetSetDef meth_getsets [] = {
347 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
347 {"__doc__", (getter)meth_get__doc__, NULL, NULL},
348 {"__name__", (getter)meth_get__name__, NULL, NULL},
348 {"__name__", (getter)meth_get__name__, NULL, NULL},
349 {"__self__", (getter)meth_get__self__, NULL, NULL},
349 {"__self__", (getter)meth_get__self__, NULL, NULL},
350 {0}
350 {NULL, NULL, NULL,NULL},
351 };
351 };
352
352
353 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
354 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
355 #endif
356
353 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
357 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
354
358
355 static PyMemberDef meth_members[] = {
359 static PyMemberDef meth_members[] = {
356 {"__module__", T_OBJECT, OFF(m_module), WRITE_RESTRICTED},
360 {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
357 {NULL}
361 {NULL}
358 };
362 };
359
363
360 static PyObject *
364 static PyObject *
361 meth_repr(PythonQtSlotFunctionObject *m)
365 meth_repr(PythonQtSlotFunctionObject *m)
362 {
366 {
363 return PyString_FromFormat("<built-in qt slot %s of %s object at %p>",
367 return PyString_FromFormat("<built-in qt slot %s of %s object at %p>",
364 m->m_ml->metaMethod()->signature(),
368 m->m_ml->metaMethod()->signature(),
365 m->m_self->ob_type->tp_name,
369 m->m_self->ob_type->tp_name,
366 m->m_self);
370 m->m_self);
367 }
371 }
368
372
369 static int
373 static int
370 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
374 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
371 {
375 {
372 if (a->m_self != b->m_self)
376 if (a->m_self != b->m_self)
373 return (a->m_self < b->m_self) ? -1 : 1;
377 return (a->m_self < b->m_self) ? -1 : 1;
374 if (a->m_ml == b->m_ml)
378 if (a->m_ml == b->m_ml)
375 return 0;
379 return 0;
376 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
380 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
377 return -1;
381 return -1;
378 else
382 else
379 return 1;
383 return 1;
380 }
384 }
381
385
382 static long
386 static long
383 meth_hash(PythonQtSlotFunctionObject *a)
387 meth_hash(PythonQtSlotFunctionObject *a)
384 {
388 {
385 long x,y;
389 long x,y;
386 if (a->m_self == NULL)
390 if (a->m_self == NULL)
387 x = 0;
391 x = 0;
388 else {
392 else {
389 x = PyObject_Hash(a->m_self);
393 x = PyObject_Hash(a->m_self);
390 if (x == -1)
394 if (x == -1)
391 return -1;
395 return -1;
392 }
396 }
393 y = _Py_HashPointer((void*)(a->m_ml));
397 y = _Py_HashPointer((void*)(a->m_ml));
394 if (y == -1)
398 if (y == -1)
395 return -1;
399 return -1;
396 x ^= y;
400 x ^= y;
397 if (x == -1)
401 if (x == -1)
398 x = -2;
402 x = -2;
399 return x;
403 return x;
400 }
404 }
401
405
402
406
403 PyTypeObject PythonQtSlotFunction_Type = {
407 PyTypeObject PythonQtSlotFunction_Type = {
404 PyObject_HEAD_INIT(&PyType_Type)
408 PyObject_HEAD_INIT(&PyType_Type)
405 0,
409 0,
406 "builtin_qt_slot",
410 "builtin_qt_slot",
407 sizeof(PythonQtSlotFunctionObject),
411 sizeof(PythonQtSlotFunctionObject),
408 0,
412 0,
409 (destructor)meth_dealloc, /* tp_dealloc */
413 (destructor)meth_dealloc, /* tp_dealloc */
410 0, /* tp_print */
414 0, /* tp_print */
411 0, /* tp_getattr */
415 0, /* tp_getattr */
412 0, /* tp_setattr */
416 0, /* tp_setattr */
413 (cmpfunc)meth_compare, /* tp_compare */
417 (cmpfunc)meth_compare, /* tp_compare */
414 (reprfunc)meth_repr, /* tp_repr */
418 (reprfunc)meth_repr, /* tp_repr */
415 0, /* tp_as_number */
419 0, /* tp_as_number */
416 0, /* tp_as_sequence */
420 0, /* tp_as_sequence */
417 0, /* tp_as_mapping */
421 0, /* tp_as_mapping */
418 (hashfunc)meth_hash, /* tp_hash */
422 (hashfunc)meth_hash, /* tp_hash */
419 PythonQtSlotFunction_Call, /* tp_call */
423 PythonQtSlotFunction_Call, /* tp_call */
420 0, /* tp_str */
424 0, /* tp_str */
421 PyObject_GenericGetAttr, /* tp_getattro */
425 PyObject_GenericGetAttr, /* tp_getattro */
422 0, /* tp_setattro */
426 0, /* tp_setattro */
423 0, /* tp_as_buffer */
427 0, /* tp_as_buffer */
424 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
428 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
425 0, /* tp_doc */
429 0, /* tp_doc */
426 (traverseproc)meth_traverse, /* tp_traverse */
430 (traverseproc)meth_traverse, /* tp_traverse */
427 0, /* tp_clear */
431 0, /* tp_clear */
428 0, /* tp_richcompare */
432 0, /* tp_richcompare */
429 0, /* tp_weaklistoffset */
433 0, /* tp_weaklistoffset */
430 0, /* tp_iter */
434 0, /* tp_iter */
431 0, /* tp_iternext */
435 0, /* tp_iternext */
432 0, /* tp_methods */
436 0, /* tp_methods */
433 meth_members, /* tp_members */
437 meth_members, /* tp_members */
434 meth_getsets, /* tp_getset */
438 meth_getsets, /* tp_getset */
435 0, /* tp_base */
439 0, /* tp_base */
436 0, /* tp_dict */
440 0, /* tp_dict */
437 };
441 };
438
442
439 /* Clear out the free list */
443 /* Clear out the free list */
440
444
441 void
445 void
442 PythonQtSlotFunction_Fini(void)
446 PythonQtSlotFunction_Fini(void)
443 {
447 {
444 while (pythonqtslot_free_list) {
448 while (pythonqtslot_free_list) {
445 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
449 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
446 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
450 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
447 PyObject_GC_Del(v);
451 PyObject_GC_Del(v);
448 }
452 }
449 }
453 }
450
454
@@ -1,136 +1,136
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 PythonQtStdOut.cpp
35 // \file PythonQtStdOut.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 "PythonQtStdOut.h"
42 #include "PythonQtStdOut.h"
43
43
44 static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
44 static PyObject *PythonQtStdOutRedirect_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
45 {
45 {
46 PythonQtStdOutRedirect *self;
46 PythonQtStdOutRedirect *self;
47 self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
47 self = (PythonQtStdOutRedirect *)type->tp_alloc(type, 0);
48
48
49 self->softspace = 0;
49 self->softspace = 0;
50 self->_cb = NULL;
50 self->_cb = NULL;
51
51
52 return (PyObject *)self;
52 return (PyObject *)self;
53 }
53 }
54
54
55 static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args)
55 static PyObject *PythonQtStdOutRedirect_write(PyObject *self, PyObject *args)
56 {
56 {
57 PythonQtStdOutRedirect* s = (PythonQtStdOutRedirect*)self;
57 PythonQtStdOutRedirect* s = (PythonQtStdOutRedirect*)self;
58 if (s->_cb) {
58 if (s->_cb) {
59 char *string;
59 char *string;
60 if (!PyArg_ParseTuple(args, "s", &string))
60 if (!PyArg_ParseTuple(args, "s", &string))
61 return NULL;
61 return NULL;
62
62
63 if (s->softspace > 0) {
63 if (s->softspace > 0) {
64 (*s->_cb)(QString(""));
64 (*s->_cb)(QString(""));
65 s->softspace = 0;
65 s->softspace = 0;
66 }
66 }
67
67
68 (*s->_cb)(QString(string));
68 (*s->_cb)(QString(string));
69 }
69 }
70 return Py_BuildValue("");
70 return Py_BuildValue("");
71 }
71 }
72
72
73 static PyObject *PythonQtStdOutRedirect_flush(PyObject *self, PyObject *args)
73 static PyObject *PythonQtStdOutRedirect_flush(PyObject * /*self*/, PyObject * /*args*/)
74 {
74 {
75 return Py_BuildValue("");
75 return Py_BuildValue("");
76 }
76 }
77
77
78
78
79
79
80 static PyMethodDef PythonQtStdOutRedirect_methods[] = {
80 static PyMethodDef PythonQtStdOutRedirect_methods[] = {
81 {"write", (PyCFunction)PythonQtStdOutRedirect_write, METH_VARARGS,
81 {"write", (PyCFunction)PythonQtStdOutRedirect_write, METH_VARARGS,
82 "redirect the writing to a callback"},
82 "redirect the writing to a callback"},
83 {"flush", (PyCFunction)PythonQtStdOutRedirect_flush, METH_VARARGS,
83 {"flush", (PyCFunction)PythonQtStdOutRedirect_flush, METH_VARARGS,
84 "flush the output, currently not implemented but needed for logging framework"
84 "flush the output, currently not implemented but needed for logging framework"
85 },
85 },
86 {NULL} /* Sentinel */
86 {NULL, NULL, 0 , NULL} /* sentinel */
87 };
87 };
88
88
89 static PyMemberDef PythonQtStdOutRedirect_members[] = {
89 static PyMemberDef PythonQtStdOutRedirect_members[] = {
90 {"softspace", T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
90 {"softspace", T_INT, offsetof(PythonQtStdOutRedirect, softspace), 0,
91 "soft space flag"
91 "soft space flag"
92 },
92 },
93 {NULL} /* Sentinel */
93 {NULL} /* Sentinel */
94 };
94 };
95
95
96 PyTypeObject PythonQtStdOutRedirectType = {
96 PyTypeObject PythonQtStdOutRedirectType = {
97 PyObject_HEAD_INIT(NULL)
97 PyObject_HEAD_INIT(NULL)
98 0, /*ob_size*/
98 0, /*ob_size*/
99 "PythonQtStdOutRedirect", /*tp_name*/
99 "PythonQtStdOutRedirect", /*tp_name*/
100 sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/
100 sizeof(PythonQtStdOutRedirect), /*tp_basicsize*/
101 0, /*tp_itemsize*/
101 0, /*tp_itemsize*/
102 0, /*tp_dealloc*/
102 0, /*tp_dealloc*/
103 0, /*tp_print*/
103 0, /*tp_print*/
104 0, /*tp_getattr*/
104 0, /*tp_getattr*/
105 0, /*tp_setattr*/
105 0, /*tp_setattr*/
106 0, /*tp_compare*/
106 0, /*tp_compare*/
107 0, /*tp_repr*/
107 0, /*tp_repr*/
108 0, /*tp_as_number*/
108 0, /*tp_as_number*/
109 0, /*tp_as_sequence*/
109 0, /*tp_as_sequence*/
110 0, /*tp_as_mapping*/
110 0, /*tp_as_mapping*/
111 0, /*tp_hash */
111 0, /*tp_hash */
112 0, /*tp_call*/
112 0, /*tp_call*/
113 0, /*tp_str*/
113 0, /*tp_str*/
114 0, /*tp_getattro*/
114 0, /*tp_getattro*/
115 0, /*tp_setattro*/
115 0, /*tp_setattro*/
116 0, /*tp_as_buffer*/
116 0, /*tp_as_buffer*/
117 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
117 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
118 "PythonQtStdOutRedirect", /* tp_doc */
118 "PythonQtStdOutRedirect", /* tp_doc */
119 0, /* tp_traverse */
119 0, /* tp_traverse */
120 0, /* tp_clear */
120 0, /* tp_clear */
121 0, /* tp_richcompare */
121 0, /* tp_richcompare */
122 0, /* tp_weaklistoffset */
122 0, /* tp_weaklistoffset */
123 0, /* tp_iter */
123 0, /* tp_iter */
124 0, /* tp_iternext */
124 0, /* tp_iternext */
125 PythonQtStdOutRedirect_methods, /* tp_methods */
125 PythonQtStdOutRedirect_methods, /* tp_methods */
126 PythonQtStdOutRedirect_members, /* tp_members */
126 PythonQtStdOutRedirect_members, /* tp_members */
127 0, /* tp_getset */
127 0, /* tp_getset */
128 0, /* tp_base */
128 0, /* tp_base */
129 0, /* tp_dict */
129 0, /* tp_dict */
130 0, /* tp_descr_get */
130 0, /* tp_descr_get */
131 0, /* tp_descr_set */
131 0, /* tp_descr_set */
132 0, /* tp_dictoffset */
132 0, /* tp_dictoffset */
133 0, /* tp_init */
133 0, /* tp_init */
134 0, /* tp_alloc */
134 0, /* tp_alloc */
135 PythonQtStdOutRedirect_new, /* tp_new */
135 PythonQtStdOutRedirect_new, /* tp_new */
136 };
136 };
@@ -1,271 +1,271
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 PythonQtVariantWrapper.cpp
35 // \file PythonQtVariantWrapper.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 "PythonQtVariantWrapper.h"
42 #include "PythonQtVariantWrapper.h"
43 #include <QObject>
43 #include <QObject>
44 #include <QDate>
44 #include <QDate>
45 #include <QDateTime>
45 #include <QDateTime>
46 #include <QTime>
46 #include <QTime>
47 #include "PythonQt.h"
47 #include "PythonQt.h"
48 #include "PythonQtSlot.h"
48 #include "PythonQtSlot.h"
49 #include "PythonQtClassInfo.h"
49 #include "PythonQtClassInfo.h"
50 #include "PythonQtConversion.h"
50 #include "PythonQtConversion.h"
51
51
52 static void PythonQtVariantWrapper_dealloc(PythonQtVariantWrapper* self)
52 static void PythonQtVariantWrapper_dealloc(PythonQtVariantWrapper* self)
53 {
53 {
54 if (self->_variant) {
54 if (self->_variant) {
55 delete self->_variant;
55 delete self->_variant;
56 self->_variant = NULL;
56 self->_variant = NULL;
57 }
57 }
58 self->ob_type->tp_free((PyObject*)self);
58 self->ob_type->tp_free((PyObject*)self);
59 }
59 }
60
60
61 static PyObject* PythonQtVariantWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
61 static PyObject* PythonQtVariantWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
62 {
62 {
63 PythonQtVariantWrapper *self;
63 PythonQtVariantWrapper *self;
64
64
65 self = (PythonQtVariantWrapper *)type->tp_alloc(type, 0);
65 self = (PythonQtVariantWrapper *)type->tp_alloc(type, 0);
66 if (self != NULL) {
66 if (self != NULL) {
67 self->_variant = new QVariant();
67 self->_variant = new QVariant();
68 self->_info = NULL;
68 self->_info = NULL;
69 }
69 }
70 return (PyObject *)self;
70 return (PyObject *)self;
71 }
71 }
72
72
73 static int PythonQtVariantWrapper_init(PythonQtVariantWrapper *self, PyObject *args, PyObject *kwds)
73 static int PythonQtVariantWrapper_init(PythonQtVariantWrapper * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
74 {
74 {
75 return 0;
75 return 0;
76 }
76 }
77
77
78 static PyObject *PythonQtVariantWrapper_classname(PythonQtVariantWrapper* type)
78 static PyObject *PythonQtVariantWrapper_classname(PythonQtVariantWrapper* type)
79 {
79 {
80 return PyString_FromString(type->_info->className());
80 return PyString_FromString(type->_info->className());
81 }
81 }
82
82
83 static PyObject *PythonQtVariantWrapper_help(PythonQtVariantWrapper* type)
83 static PyObject *PythonQtVariantWrapper_help(PythonQtVariantWrapper* type)
84 {
84 {
85 return PythonQt::self()->helpCalled(type->_info);
85 return PythonQt::self()->helpCalled(type->_info);
86 }
86 }
87
87
88
88
89 static PyMethodDef PythonQtVariantWrapper_methods[] = {
89 static PyMethodDef PythonQtVariantWrapper_methods[] = {
90 {"className", (PyCFunction)PythonQtVariantWrapper_classname, METH_NOARGS,
90 {"className", (PyCFunction)PythonQtVariantWrapper_classname, METH_NOARGS,
91 "Return the classname of the object"
91 "Return the classname of the object"
92 },
92 },
93 {"help", (PyCFunction)PythonQtVariantWrapper_help, METH_NOARGS,
93 {"help", (PyCFunction)PythonQtVariantWrapper_help, METH_NOARGS,
94 "Shows the help of available methods for this class"
94 "Shows the help of available methods for this class"
95 },
95 },
96 {NULL} /* Sentinel */
96 {NULL,NULL,0,NULL} /* Sentinel */
97 };
97 };
98
98
99
99
100 static PyObject *PythonQtVariantWrapper_getattro(PyObject *obj,PyObject *name)
100 static PyObject *PythonQtVariantWrapper_getattro(PyObject *obj,PyObject *name)
101 {
101 {
102 const char *attributeName;
102 const char *attributeName;
103 PythonQtVariantWrapper *wt = (PythonQtVariantWrapper *)obj;
103 PythonQtVariantWrapper *wt = (PythonQtVariantWrapper *)obj;
104
104
105 if ((attributeName = PyString_AsString(name)) == NULL) {
105 if ((attributeName = PyString_AsString(name)) == NULL) {
106 return NULL;
106 return NULL;
107 }
107 }
108
108
109 if (wt->_wrapper && wt->_info) {
109 if (wt->_wrapper && wt->_info) {
110 PythonQtMemberInfo member = wt->_info->member(attributeName);
110 PythonQtMemberInfo member = wt->_info->member(attributeName);
111 if (member._type == PythonQtMemberInfo::Slot) {
111 if (member._type == PythonQtMemberInfo::Slot) {
112 return PythonQtSlotFunction_New(member._slot, obj, NULL);
112 return PythonQtSlotFunction_New(member._slot, obj, NULL);
113 } else if (member._type == PythonQtMemberInfo::EnumValue) {
113 } else if (member._type == PythonQtMemberInfo::EnumValue) {
114 return PyInt_FromLong(member._enumValue);
114 return PyInt_FromLong(member._enumValue);
115 }
115 }
116 }
116 }
117
117
118 // look for the interal methods (className(), help())
118 // look for the interal methods (className(), help())
119 PyObject* internalMethod = Py_FindMethod( PythonQtVariantWrapper_methods, obj, (char*)attributeName);
119 PyObject* internalMethod = Py_FindMethod( PythonQtVariantWrapper_methods, obj, (char*)attributeName);
120 if (internalMethod) {
120 if (internalMethod) {
121 return internalMethod;
121 return internalMethod;
122 }
122 }
123 PyErr_Clear();
123 PyErr_Clear();
124
124
125 if (qstrcmp(attributeName, "__dict__")==0) {
125 if (qstrcmp(attributeName, "__dict__")==0) {
126 QStringList l = wt->_info->memberList(false);
126 QStringList l = wt->_info->memberList(false);
127 PyObject* dict = PyDict_New();
127 PyObject* dict = PyDict_New();
128 foreach (QString name, l) {
128 foreach (QString name, l) {
129 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
129 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
130 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
130 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
131 //Py_DECREF(o);
131 //Py_DECREF(o);
132 }
132 }
133 return dict;
133 return dict;
134 }
134 }
135
135
136 QString error = QString(wt->_variant->typeName()) + " has no attribute named '" + QString(attributeName) + "'";
136 QString error = QString(wt->_variant->typeName()) + " has no attribute named '" + QString(attributeName) + "'";
137 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
137 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
138
138
139 return NULL;
139 return NULL;
140 }
140 }
141
141
142 QString qVariantToString(const QVariant& v) {
142 QString qVariantToString(const QVariant& v) {
143 QString r;
143 QString r;
144 switch (v.type()) {
144 switch (v.type()) {
145 case QVariant::Size:
145 case QVariant::Size:
146 r = QString::number(v.toSize().width()) + ", " + QString::number(v.toSize().height());
146 r = QString::number(v.toSize().width()) + ", " + QString::number(v.toSize().height());
147 break;
147 break;
148 case QVariant::SizeF:
148 case QVariant::SizeF:
149 r = QString::number(v.toSizeF().width()) + ", " + QString::number(v.toSizeF().height());
149 r = QString::number(v.toSizeF().width()) + ", " + QString::number(v.toSizeF().height());
150 break;
150 break;
151 case QVariant::Point:
151 case QVariant::Point:
152 r = QString::number(v.toPoint().x()) + ", " + QString::number(v.toPoint().y());
152 r = QString::number(v.toPoint().x()) + ", " + QString::number(v.toPoint().y());
153 break;
153 break;
154 case QVariant::PointF:
154 case QVariant::PointF:
155 r = QString::number(v.toPointF().x()) + ", " + QString::number(v.toPointF().y());
155 r = QString::number(v.toPointF().x()) + ", " + QString::number(v.toPointF().y());
156 break;
156 break;
157 case QVariant::Rect:
157 case QVariant::Rect:
158 r = QString::number(v.toRect().x()) + ", " + QString::number(v.toRect().y());
158 r = QString::number(v.toRect().x()) + ", " + QString::number(v.toRect().y());
159 r += ", " + QString::number(v.toRect().width()) + ", " + QString::number(v.toRect().height());
159 r += ", " + QString::number(v.toRect().width()) + ", " + QString::number(v.toRect().height());
160 break;
160 break;
161 case QVariant::RectF:
161 case QVariant::RectF:
162 r = QString::number(v.toRectF().x()) + ", " + QString::number(v.toRectF().y());
162 r = QString::number(v.toRectF().x()) + ", " + QString::number(v.toRectF().y());
163 r += ", " + QString::number(v.toRectF().width()) + ", " + QString::number(v.toRectF().height());
163 r += ", " + QString::number(v.toRectF().width()) + ", " + QString::number(v.toRectF().height());
164 break;
164 break;
165 case QVariant::Date:
165 case QVariant::Date:
166 r = v.toDate().toString(Qt::ISODate);
166 r = v.toDate().toString(Qt::ISODate);
167 break;
167 break;
168 case QVariant::DateTime:
168 case QVariant::DateTime:
169 r = v.toDateTime().toString(Qt::ISODate);
169 r = v.toDateTime().toString(Qt::ISODate);
170 break;
170 break;
171 case QVariant::Time:
171 case QVariant::Time:
172 r = v.toTime().toString(Qt::ISODate);
172 r = v.toTime().toString(Qt::ISODate);
173 break;
173 break;
174 case QVariant::Pixmap:
174 case QVariant::Pixmap:
175 {
175 {
176 QPixmap p = qvariant_cast<QPixmap>(v);
176 QPixmap p = qvariant_cast<QPixmap>(v);
177 r = QString("Pixmap ") + QString::number(p.width()) + ", " + QString::number(p.height());
177 r = QString("Pixmap ") + QString::number(p.width()) + ", " + QString::number(p.height());
178 }
178 }
179 break;
179 break;
180 case QVariant::Image:
180 case QVariant::Image:
181 {
181 {
182 QImage img = qvariant_cast<QImage>(v);
182 QImage img = qvariant_cast<QImage>(v);
183 r = QString("Image ") + QString::number(img.width()) + ", " + QString::number(img.height());
183 r = QString("Image ") + QString::number(img.width()) + ", " + QString::number(img.height());
184 }
184 }
185 break;
185 break;
186 //TODO: add more printing for other variant types
186 //TODO: add more printing for other variant types
187 default:
187 default:
188 r = v.toString();
188 r = v.toString();
189 }
189 }
190 return r;
190 return r;
191 }
191 }
192
192
193 static PyObject * PythonQtVariantWrapper_str(PyObject * obj)
193 static PyObject * PythonQtVariantWrapper_str(PyObject * obj)
194 {
194 {
195 PythonQtVariantWrapper* wt = (PythonQtVariantWrapper*)obj;
195 PythonQtVariantWrapper* wt = (PythonQtVariantWrapper*)obj;
196 QString val = qVariantToString(*wt->_variant);
196 QString val = qVariantToString(*wt->_variant);
197 if (val.isEmpty()) {
197 if (val.isEmpty()) {
198 val = wt->_variant->typeName();
198 val = wt->_variant->typeName();
199 }
199 }
200 return PyString_FromFormat("%s", val.toLatin1().constData());
200 return PyString_FromFormat("%s", val.toLatin1().constData());
201 }
201 }
202
202
203 static PyObject * PythonQtVariantWrapper_repr(PyObject * obj)
203 static PyObject * PythonQtVariantWrapper_repr(PyObject * obj)
204 {
204 {
205 PythonQtVariantWrapper* wt = (PythonQtVariantWrapper*)obj;
205 PythonQtVariantWrapper* wt = (PythonQtVariantWrapper*)obj;
206 QString val = qVariantToString(*wt->_variant);
206 QString val = qVariantToString(*wt->_variant);
207 return PyString_FromFormat("%s(%s)", wt->_variant->typeName(), val.toLatin1().constData());
207 return PyString_FromFormat("%s(%s)", wt->_variant->typeName(), val.toLatin1().constData());
208 }
208 }
209
209
210 static int PythonQtVariantWrapper_compare(PyObject * obj1, PyObject * obj2)
210 static int PythonQtVariantWrapper_compare(PyObject * obj1, PyObject * obj2)
211 {
211 {
212 if (obj1->ob_type == &PythonQtVariantWrapper_Type &&
212 if (obj1->ob_type == &PythonQtVariantWrapper_Type &&
213 obj2->ob_type == &PythonQtVariantWrapper_Type) {
213 obj2->ob_type == &PythonQtVariantWrapper_Type) {
214
214
215 PythonQtVariantWrapper* w1 = (PythonQtVariantWrapper*)obj1;
215 PythonQtVariantWrapper* w1 = (PythonQtVariantWrapper*)obj1;
216 PythonQtVariantWrapper* w2 = (PythonQtVariantWrapper*)obj2;
216 PythonQtVariantWrapper* w2 = (PythonQtVariantWrapper*)obj2;
217 if (*w1->_variant == *w2->_variant) {
217 if (*w1->_variant == *w2->_variant) {
218 return 0;
218 return 0;
219 } else {
219 } else {
220 return -1;
220 return -1;
221 }
221 }
222 } else {
222 } else {
223 return -1;
223 return -1;
224 }
224 }
225 }
225 }
226
226
227
227
228 PyTypeObject PythonQtVariantWrapper_Type = {
228 PyTypeObject PythonQtVariantWrapper_Type = {
229 PyObject_HEAD_INIT(NULL)
229 PyObject_HEAD_INIT(NULL)
230 0, /*ob_size*/
230 0, /*ob_size*/
231 "PythonQt.PythonQtVariantWrapper", /*tp_name*/
231 "PythonQt.PythonQtVariantWrapper", /*tp_name*/
232 sizeof(PythonQtVariantWrapper), /*tp_basicsize*/
232 sizeof(PythonQtVariantWrapper), /*tp_basicsize*/
233 0, /*tp_itemsize*/
233 0, /*tp_itemsize*/
234 (destructor)PythonQtVariantWrapper_dealloc, /*tp_dealloc*/
234 (destructor)PythonQtVariantWrapper_dealloc, /*tp_dealloc*/
235 0, /*tp_print*/
235 0, /*tp_print*/
236 0, /*tp_getattr*/
236 0, /*tp_getattr*/
237 0, /*tp_setattr*/
237 0, /*tp_setattr*/
238 PythonQtVariantWrapper_compare, /*tp_compare*/
238 PythonQtVariantWrapper_compare, /*tp_compare*/
239 PythonQtVariantWrapper_repr, /*tp_repr*/
239 PythonQtVariantWrapper_repr, /*tp_repr*/
240 0, /*tp_as_number*/
240 0, /*tp_as_number*/
241 0, /*tp_as_sequence*/
241 0, /*tp_as_sequence*/
242 0, /*tp_as_mapping*/
242 0, /*tp_as_mapping*/
243 0, /*tp_hash */
243 0, /*tp_hash */
244 0, /*tp_call*/
244 0, /*tp_call*/
245 PythonQtVariantWrapper_str, /*tp_str*/
245 PythonQtVariantWrapper_str, /*tp_str*/
246 PythonQtVariantWrapper_getattro, /*tp_getattro*/
246 PythonQtVariantWrapper_getattro, /*tp_getattro*/
247 0, /*tp_setattro*/
247 0, /*tp_setattro*/
248 0, /*tp_as_buffer*/
248 0, /*tp_as_buffer*/
249 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
249 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
250 "PythonQtVariantWrapper object", /* tp_doc */
250 "PythonQtVariantWrapper object", /* tp_doc */
251 0, /* tp_traverse */
251 0, /* tp_traverse */
252 0, /* tp_clear */
252 0, /* tp_clear */
253 0, /* tp_richcompare */
253 0, /* tp_richcompare */
254 0, /* tp_weaklistoffset */
254 0, /* tp_weaklistoffset */
255 0, /* tp_iter */
255 0, /* tp_iter */
256 0, /* tp_iternext */
256 0, /* tp_iternext */
257 0, /* tp_methods */
257 0, /* tp_methods */
258 0, /* tp_members */
258 0, /* tp_members */
259 0, /* tp_getset */
259 0, /* tp_getset */
260 0, /* tp_base */
260 0, /* tp_base */
261 0, /* tp_dict */
261 0, /* tp_dict */
262 0, /* tp_descr_get */
262 0, /* tp_descr_get */
263 0, /* tp_descr_set */
263 0, /* tp_descr_set */
264 0, /* tp_dictoffset */
264 0, /* tp_dictoffset */
265 (initproc)PythonQtVariantWrapper_init, /* tp_init */
265 (initproc)PythonQtVariantWrapper_init, /* tp_init */
266 0, /* tp_alloc */
266 0, /* tp_alloc */
267 PythonQtVariantWrapper_new, /* tp_new */
267 PythonQtVariantWrapper_new, /* tp_new */
268 };
268 };
269
269
270 //-------------------------------------------------------
270 //-------------------------------------------------------
271
271
@@ -1,400 +1,403
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 PythonQtWrapper.cpp
35 // \file PythonQtWrapper.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 "PythonQtWrapper.h"
42 #include "PythonQtWrapper.h"
43 #include <QObject>
43 #include <QObject>
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include "PythonQtSlot.h"
45 #include "PythonQtSlot.h"
46 #include "PythonQtClassInfo.h"
46 #include "PythonQtClassInfo.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48
48
49 static void PythonQtWrapper_dealloc(PythonQtWrapper* self)
49 static void PythonQtWrapper_dealloc(PythonQtWrapper* self)
50 {
50 {
51 if (self->_wrappedPtr) {
51 if (self->_wrappedPtr) {
52
52
53 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
53 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
54
54
55 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
55 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
56 // we own our qobject, so we delete it now:
56 // we own our qobject, so we delete it now:
57 delete self->_obj;
57 delete self->_obj;
58 self->_obj = NULL;
58 self->_obj = NULL;
59 if (self->_ownedByPythonQt) {
59 if (self->_ownedByPythonQt) {
60 PythonQtSlotInfo* slot = PythonQt::priv()->getDestructorSlot(self->_info->wrappedCPPClassName());
60 PythonQtSlotInfo* slot = PythonQt::priv()->getDestructorSlot(self->_info->wrappedCPPClassName());
61 if (slot) {
61 if (slot) {
62 void* args[2];
62 void* args[2];
63 args[0] = NULL;
63 args[0] = NULL;
64 args[1] = &self->_wrappedPtr;
64 args[1] = &self->_wrappedPtr;
65 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
65 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
66 self->_wrappedPtr = NULL;
66 self->_wrappedPtr = NULL;
67 } else {
67 } else {
68 // TODO: print a warning? we can not destroy that object
68 // TODO: print a warning? we can not destroy that object
69 }
69 }
70 }
70 }
71 } else {
71 } else {
72 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
72 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
73 if (self->_objPointerCopy) {
73 if (self->_objPointerCopy) {
74 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
74 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
75 }
75 }
76 if (self->_obj) {
76 if (self->_obj) {
77 if (self->_ownedByPythonQt) {
77 if (self->_ownedByPythonQt) {
78 if (!self->_obj->parent()) {
78 if (!self->_obj->parent()) {
79 delete self->_obj;
79 delete self->_obj;
80 }
80 }
81 } else {
81 } else {
82 if (self->_obj->parent()==NULL) {
82 if (self->_obj->parent()==NULL) {
83 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
83 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
84 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
84 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
85 }
85 }
86 }
86 }
87 }
87 }
88 }
88 }
89 self->_obj = NULL;
89 self->_obj = NULL;
90 self->_obj.~QPointer<QObject>();
90 self->_obj.~QPointer<QObject>();
91 self->ob_type->tp_free((PyObject*)self);
91 self->ob_type->tp_free((PyObject*)self);
92 }
92 }
93
93
94 static PyObject* PythonQtWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
94 static PyObject* PythonQtWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
95 {
95 {
96 PythonQtWrapper *self;
96 PythonQtWrapper *self;
97
97
98 self = (PythonQtWrapper *)type->tp_alloc(type, 0);
98 self = (PythonQtWrapper *)type->tp_alloc(type, 0);
99 if (self != NULL) {
99 if (self != NULL) {
100 self->_info = NULL;
100 self->_info = NULL;
101 new (&self->_obj) QPointer<QObject>();
101 new (&self->_obj) QPointer<QObject>();
102 self->_wrappedPtr = NULL;
102 self->_wrappedPtr = NULL;
103 self->_ownedByPythonQt = false;
103 self->_ownedByPythonQt = false;
104 }
104 }
105 return (PyObject *)self;
105 return (PyObject *)self;
106 }
106 }
107
107
108 static int PythonQtWrapper_init(PythonQtWrapper *self, PyObject *args, PyObject *kwds)
108 static int PythonQtWrapper_init(PythonQtWrapper * /*self*/, PyObject * /*args*/, PyObject * /*kwds*/)
109 {
109 {
110 return 0;
110 return 0;
111 }
111 }
112
112
113 static PyObject *PythonQtWrapper_classname(PythonQtWrapper* type)
113 static PyObject *PythonQtWrapper_classname(PythonQtWrapper* type)
114 {
114 {
115 return PyString_FromString(type->_info->className());
115 return PyString_FromString(type->_info->className());
116 }
116 }
117
117
118 static PyObject *PythonQtWrapper_help(PythonQtWrapper* type)
118 static PyObject *PythonQtWrapper_help(PythonQtWrapper* type)
119 {
119 {
120 return PythonQt::self()->helpCalled(type->_info);
120 return PythonQt::self()->helpCalled(type->_info);
121 }
121 }
122
122
123
123
124 static PyMethodDef PythonQtWrapper_methods[] = {
124 static PyMethodDef PythonQtWrapper_methods[] = {
125 {"className", (PyCFunction)PythonQtWrapper_classname, METH_NOARGS,
125 {"className", (PyCFunction)PythonQtWrapper_classname, METH_NOARGS,
126 "Return the classname of the object"
126 "Return the classname of the object"
127 },
127 },
128 {"help", (PyCFunction)PythonQtWrapper_help, METH_NOARGS,
128 {"help", (PyCFunction)PythonQtWrapper_help, METH_NOARGS,
129 "Shows the help of available methods for this class"
129 "Shows the help of available methods for this class"
130 },
130 },
131 {NULL} /* Sentinel */
131 {NULL, NULL, 0, NULL} /* Sentinel */
132 };
132 };
133
133
134
134
135 static PyObject *PythonQtWrapper_getattro(PyObject *obj,PyObject *name)
135 static PyObject *PythonQtWrapper_getattro(PyObject *obj,PyObject *name)
136 {
136 {
137 const char *attributeName;
137 const char *attributeName;
138 PythonQtWrapper *wt = (PythonQtWrapper *)obj;
138 PythonQtWrapper *wt = (PythonQtWrapper *)obj;
139
139
140 if ((attributeName = PyString_AsString(name)) == NULL) {
140 if ((attributeName = PyString_AsString(name)) == NULL) {
141 return NULL;
141 return NULL;
142 }
142 }
143
143
144 if (!wt->_obj && !wt->_wrappedPtr) {
144 if (!wt->_obj && !wt->_wrappedPtr) {
145 QString error = QString("Trying to read attribute '") + attributeName + "' from a destroyed " + wt->_info->className() + " object";
145 QString error = QString("Trying to read attribute '") + attributeName + "' from a destroyed " + wt->_info->className() + " object";
146 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
146 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
147 return NULL;
147 return NULL;
148 }
148 }
149
149
150 // mlabDebugConst("Python","get " << attributeName);
150 // mlabDebugConst("Python","get " << attributeName);
151
151
152 // TODO: dynamic properties are missing
152 // TODO: dynamic properties are missing
153
153
154 PythonQtMemberInfo member = wt->_info->member(attributeName);
154 PythonQtMemberInfo member = wt->_info->member(attributeName);
155 switch (member._type) {
155 switch (member._type) {
156 case PythonQtMemberInfo::Property:
156 case PythonQtMemberInfo::Property:
157 if (wt->_obj) {
157 if (wt->_obj) {
158 return PythonQtConv::QVariantToPyObject(member._property.read(wt->_obj));
158 return PythonQtConv::QVariantToPyObject(member._property.read(wt->_obj));
159 }
159 }
160 break;
160 break;
161 case PythonQtMemberInfo::Slot:
161 case PythonQtMemberInfo::Slot:
162 return PythonQtSlotFunction_New(member._slot, obj, NULL);
162 return PythonQtSlotFunction_New(member._slot, obj, NULL);
163 break;
163 break;
164 case PythonQtMemberInfo::EnumValue:
164 case PythonQtMemberInfo::EnumValue:
165 return PyInt_FromLong(member._enumValue);
165 return PyInt_FromLong(member._enumValue);
166 break;
166 break;
167 default:
168 // is an invalid type, go on
169 break;
167 }
170 }
168
171
169 // look for the interal methods (className(), help())
172 // look for the interal methods (className(), help())
170 PyObject* internalMethod = Py_FindMethod( PythonQtWrapper_methods, obj, (char*)attributeName);
173 PyObject* internalMethod = Py_FindMethod( PythonQtWrapper_methods, obj, (char*)attributeName);
171 if (internalMethod) {
174 if (internalMethod) {
172 return internalMethod;
175 return internalMethod;
173 }
176 }
174 PyErr_Clear();
177 PyErr_Clear();
175
178
176 if (wt->_obj) {
179 if (wt->_obj) {
177 // look for a child
180 // look for a child
178 QObjectList children = wt->_obj->children();
181 QObjectList children = wt->_obj->children();
179 for (int i = 0; i < children.count(); i++) {
182 for (int i = 0; i < children.count(); i++) {
180 QObject *child = children.at(i);
183 QObject *child = children.at(i);
181 if (child->objectName() == attributeName) {
184 if (child->objectName() == attributeName) {
182 return PythonQt::self()->priv()->wrapQObject(child);
185 return PythonQt::self()->priv()->wrapQObject(child);
183 }
186 }
184 }
187 }
185 }
188 }
186
189
187 if (qstrcmp(attributeName, "__dict__")==0) {
190 if (qstrcmp(attributeName, "__dict__")==0) {
188 QStringList l = wt->_info->memberList(false);
191 QStringList l = wt->_info->memberList(false);
189 PyObject* dict = PyDict_New();
192 PyObject* dict = PyDict_New();
190 foreach (QString name, l) {
193 foreach (QString name, l) {
191 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
194 //PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
192 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
195 PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
193 //Py_DECREF(o);
196 //Py_DECREF(o);
194 }
197 }
195 // Note: we do not put children into the dict, is would look confusing?!
198 // Note: we do not put children into the dict, is would look confusing?!
196 return dict;
199 return dict;
197 }
200 }
198
201
199
202
200 QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
203 QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
201 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
204 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
202 return NULL;
205 return NULL;
203 }
206 }
204
207
205 static int PythonQtWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
208 static int PythonQtWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
206 {
209 {
207 QString error;
210 QString error;
208 char *attributeName;
211 char *attributeName;
209 PythonQtWrapper *wt = (PythonQtWrapper *)obj;
212 PythonQtWrapper *wt = (PythonQtWrapper *)obj;
210
213
211 if ((attributeName = PyString_AsString(name)) == NULL)
214 if ((attributeName = PyString_AsString(name)) == NULL)
212 return -1;
215 return -1;
213
216
214 if (!wt->_obj) {
217 if (!wt->_obj) {
215 error = QString("Trying to set attribute '") + attributeName + "' on a destroyed " + wt->_info->className() + " object";
218 error = QString("Trying to set attribute '") + attributeName + "' on a destroyed " + wt->_info->className() + " object";
216 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
219 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
217 return -1;
220 return -1;
218 }
221 }
219
222
220 PythonQtMemberInfo member = wt->_info->member(attributeName);
223 PythonQtMemberInfo member = wt->_info->member(attributeName);
221 if (member._type == PythonQtMemberInfo::Property) {
224 if (member._type == PythonQtMemberInfo::Property) {
222 QMetaProperty prop = member._property;
225 QMetaProperty prop = member._property;
223 if (prop.isWritable()) {
226 if (prop.isWritable()) {
224 QVariant v;
227 QVariant v;
225 if (prop.isEnumType()) {
228 if (prop.isEnumType()) {
226 // this will give us either a string or an int, everything else will probably be an error
229 // this will give us either a string or an int, everything else will probably be an error
227 v = PythonQtConv::PyObjToQVariant(value);
230 v = PythonQtConv::PyObjToQVariant(value);
228 } else {
231 } else {
229 int t = prop.userType();
232 int t = prop.userType();
230 v = PythonQtConv::PyObjToQVariant(value, t);
233 v = PythonQtConv::PyObjToQVariant(value, t);
231 }
234 }
232 bool success = false;
235 bool success = false;
233 if (v.isValid()) {
236 if (v.isValid()) {
234 success = prop.write(wt->_obj, v);
237 success = prop.write(wt->_obj, v);
235 }
238 }
236 if (success) {
239 if (success) {
237 return 0;
240 return 0;
238 } else {
241 } else {
239 error = QString("Property '") + attributeName + "' of type '" +
242 error = QString("Property '") + attributeName + "' of type '" +
240 prop.typeName() + "' does not accept an object of type "
243 prop.typeName() + "' does not accept an object of type "
241 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
244 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
242 }
245 }
243 } else {
246 } else {
244 error = QString("Property '") + attributeName + "' of " + wt->_info->className() + " object is not writable";
247 error = QString("Property '") + attributeName + "' of " + wt->_info->className() + " object is not writable";
245 }
248 }
246 } else {
249 } else {
247 if (member._type == PythonQtMemberInfo::Slot) {
250 if (member._type == PythonQtMemberInfo::Slot) {
248 error = QString("Slot '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
251 error = QString("Slot '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
249 } else if (member._type == PythonQtMemberInfo::EnumValue) {
252 } else if (member._type == PythonQtMemberInfo::EnumValue) {
250 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
253 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
251 }
254 }
252 }
255 }
253
256
254 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
257 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
255 return -1;
258 return -1;
256 }
259 }
257
260
258 static PyObject * PythonQtWrapper_repr(PyObject * obj)
261 static PyObject * PythonQtWrapper_repr(PyObject * obj)
259 {
262 {
260 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
263 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
261 QObject *qobj = wt->_obj;
264 QObject *qobj = wt->_obj;
262 if (wt->_wrappedPtr) {
265 if (wt->_wrappedPtr) {
263 if (wt->_obj) {
266 if (wt->_obj) {
264 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wt->_info->className(), wt->_wrappedPtr, wt->_obj->metaObject()->className(), qobj);
267 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", wt->_info->className(), wt->_wrappedPtr, wt->_obj->metaObject()->className(), qobj);
265 } else {
268 } else {
266 return PyString_FromFormat("%s (C++ Object %p unwrapped)", wt->_info->className(), wt->_wrappedPtr);
269 return PyString_FromFormat("%s (C++ Object %p unwrapped)", wt->_info->className(), wt->_wrappedPtr);
267 }
270 }
268 } else {
271 } else {
269 return PyString_FromFormat("%s (QObject %p)", wt->_info->className(), qobj);
272 return PyString_FromFormat("%s (QObject %p)", wt->_info->className(), qobj);
270 }
273 }
271 }
274 }
272
275
273 static int PythonQtWrapper_compare(PyObject * obj1, PyObject * obj2)
276 static int PythonQtWrapper_compare(PyObject * obj1, PyObject * obj2)
274 {
277 {
275 if (obj1->ob_type == &PythonQtWrapper_Type &&
278 if (obj1->ob_type == &PythonQtWrapper_Type &&
276 obj2->ob_type == &PythonQtWrapper_Type) {
279 obj2->ob_type == &PythonQtWrapper_Type) {
277
280
278 PythonQtWrapper* w1 = (PythonQtWrapper*)obj1;
281 PythonQtWrapper* w1 = (PythonQtWrapper*)obj1;
279 PythonQtWrapper* w2 = (PythonQtWrapper*)obj2;
282 PythonQtWrapper* w2 = (PythonQtWrapper*)obj2;
280 if (w1->_wrappedPtr != NULL) {
283 if (w1->_wrappedPtr != NULL) {
281 if (w1->_wrappedPtr == w1->_wrappedPtr) {
284 if (w1->_wrappedPtr == w1->_wrappedPtr) {
282 return 0;
285 return 0;
283 } else {
286 } else {
284 return -1;
287 return -1;
285 }
288 }
286 } else if (w1->_obj == w2->_obj) {
289 } else if (w1->_obj == w2->_obj) {
287 return 0;
290 return 0;
288 } else {
291 } else {
289 return -1;
292 return -1;
290 }
293 }
291 } else {
294 } else {
292 return -1;
295 return -1;
293 }
296 }
294 }
297 }
295
298
296 static int PythonQtWrapper_nonzero(PyObject *obj)
299 static int PythonQtWrapper_nonzero(PyObject *obj)
297 {
300 {
298 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
301 PythonQtWrapper* wt = (PythonQtWrapper*)obj;
299 return (wt->_wrappedPtr == NULL && wt->_obj == NULL)?0:1;
302 return (wt->_wrappedPtr == NULL && wt->_obj == NULL)?0:1;
300 }
303 }
301
304
302
305
303 static long PythonQtWrapper_hash(PythonQtWrapper *obj)
306 static long PythonQtWrapper_hash(PythonQtWrapper *obj)
304 {
307 {
305 if (obj->_wrappedPtr != NULL) {
308 if (obj->_wrappedPtr != NULL) {
306 return reinterpret_cast<long>(obj->_wrappedPtr);
309 return reinterpret_cast<long>(obj->_wrappedPtr);
307 } else {
310 } else {
308 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
311 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
309 return reinterpret_cast<long>(qobj);
312 return reinterpret_cast<long>(qobj);
310 }
313 }
311 }
314 }
312
315
313
316
314
317
315 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
318 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
316 static PyNumberMethods PythonQtWrapper_as_number = {
319 static PyNumberMethods PythonQtWrapper_as_number = {
317 0, /* nb_add */
320 0, /* nb_add */
318 0, /* nb_subtract */
321 0, /* nb_subtract */
319 0, /* nb_multiply */
322 0, /* nb_multiply */
320 0, /* nb_divide */
323 0, /* nb_divide */
321 0, /* nb_remainder */
324 0, /* nb_remainder */
322 0, /* nb_divmod */
325 0, /* nb_divmod */
323 0, /* nb_power */
326 0, /* nb_power */
324 0, /* nb_negative */
327 0, /* nb_negative */
325 0, /* nb_positive */
328 0, /* nb_positive */
326 0, /* nb_absolute */
329 0, /* nb_absolute */
327 PythonQtWrapper_nonzero, /* nb_nonzero */
330 PythonQtWrapper_nonzero, /* nb_nonzero */
328 0, /* nb_invert */
331 0, /* nb_invert */
329 0, /* nb_lshift */
332 0, /* nb_lshift */
330 0, /* nb_rshift */
333 0, /* nb_rshift */
331 0, /* nb_and */
334 0, /* nb_and */
332 0, /* nb_xor */
335 0, /* nb_xor */
333 0, /* nb_or */
336 0, /* nb_or */
334 0, /* nb_coerce */
337 0, /* nb_coerce */
335 0, /* nb_int */
338 0, /* nb_int */
336 0, /* nb_long */
339 0, /* nb_long */
337 0, /* nb_float */
340 0, /* nb_float */
338 0, /* nb_oct */
341 0, /* nb_oct */
339 0, /* nb_hex */
342 0, /* nb_hex */
340 0, /* nb_inplace_add */
343 0, /* nb_inplace_add */
341 0, /* nb_inplace_subtract */
344 0, /* nb_inplace_subtract */
342 0, /* nb_inplace_multiply */
345 0, /* nb_inplace_multiply */
343 0, /* nb_inplace_divide */
346 0, /* nb_inplace_divide */
344 0, /* nb_inplace_remainder */
347 0, /* nb_inplace_remainder */
345 0, /* nb_inplace_power */
348 0, /* nb_inplace_power */
346 0, /* nb_inplace_lshift */
349 0, /* nb_inplace_lshift */
347 0, /* nb_inplace_rshift */
350 0, /* nb_inplace_rshift */
348 0, /* nb_inplace_and */
351 0, /* nb_inplace_and */
349 0, /* nb_inplace_xor */
352 0, /* nb_inplace_xor */
350 0, /* nb_inplace_or */
353 0, /* nb_inplace_or */
351 0, /* nb_floor_divide */
354 0, /* nb_floor_divide */
352 0, /* nb_true_divide */
355 0, /* nb_true_divide */
353 0, /* nb_inplace_floor_divide */
356 0, /* nb_inplace_floor_divide */
354 0, /* nb_inplace_true_divide */
357 0, /* nb_inplace_true_divide */
355 };
358 };
356
359
357 PyTypeObject PythonQtWrapper_Type = {
360 PyTypeObject PythonQtWrapper_Type = {
358 PyObject_HEAD_INIT(NULL)
361 PyObject_HEAD_INIT(NULL)
359 0, /*ob_size*/
362 0, /*ob_size*/
360 "PythonQt.PythonQtWrapper", /*tp_name*/
363 "PythonQt.PythonQtWrapper", /*tp_name*/
361 sizeof(PythonQtWrapper), /*tp_basicsize*/
364 sizeof(PythonQtWrapper), /*tp_basicsize*/
362 0, /*tp_itemsize*/
365 0, /*tp_itemsize*/
363 (destructor)PythonQtWrapper_dealloc, /*tp_dealloc*/
366 (destructor)PythonQtWrapper_dealloc, /*tp_dealloc*/
364 0, /*tp_print*/
367 0, /*tp_print*/
365 0, /*tp_getattr*/
368 0, /*tp_getattr*/
366 0, /*tp_setattr*/
369 0, /*tp_setattr*/
367 PythonQtWrapper_compare, /*tp_compare*/
370 PythonQtWrapper_compare, /*tp_compare*/
368 PythonQtWrapper_repr, /*tp_repr*/
371 PythonQtWrapper_repr, /*tp_repr*/
369 &PythonQtWrapper_as_number, /*tp_as_number*/
372 &PythonQtWrapper_as_number, /*tp_as_number*/
370 0, /*tp_as_sequence*/
373 0, /*tp_as_sequence*/
371 0, /*tp_as_mapping*/
374 0, /*tp_as_mapping*/
372 (hashfunc)PythonQtWrapper_hash, /*tp_hash */
375 (hashfunc)PythonQtWrapper_hash, /*tp_hash */
373 0, /*tp_call*/
376 0, /*tp_call*/
374 0, /*tp_str*/
377 0, /*tp_str*/
375 PythonQtWrapper_getattro, /*tp_getattro*/
378 PythonQtWrapper_getattro, /*tp_getattro*/
376 PythonQtWrapper_setattro, /*tp_setattro*/
379 PythonQtWrapper_setattro, /*tp_setattro*/
377 0, /*tp_as_buffer*/
380 0, /*tp_as_buffer*/
378 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
381 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
379 "PythonQtWrapper object", /* tp_doc */
382 "PythonQtWrapper object", /* tp_doc */
380 0, /* tp_traverse */
383 0, /* tp_traverse */
381 0, /* tp_clear */
384 0, /* tp_clear */
382 0, /* tp_richcompare */
385 0, /* tp_richcompare */
383 0, /* tp_weaklistoffset */
386 0, /* tp_weaklistoffset */
384 0, /* tp_iter */
387 0, /* tp_iter */
385 0, /* tp_iternext */
388 0, /* tp_iternext */
386 0, /* tp_methods */
389 0, /* tp_methods */
387 0, /* tp_members */
390 0, /* tp_members */
388 0, /* tp_getset */
391 0, /* tp_getset */
389 0, /* tp_base */
392 0, /* tp_base */
390 0, /* tp_dict */
393 0, /* tp_dict */
391 0, /* tp_descr_get */
394 0, /* tp_descr_get */
392 0, /* tp_descr_set */
395 0, /* tp_descr_set */
393 0, /* tp_dictoffset */
396 0, /* tp_dictoffset */
394 (initproc)PythonQtWrapper_init, /* tp_init */
397 (initproc)PythonQtWrapper_init, /* tp_init */
395 0, /* tp_alloc */
398 0, /* tp_alloc */
396 PythonQtWrapper_new, /* tp_new */
399 PythonQtWrapper_new, /* tp_new */
397 };
400 };
398
401
399 //-------------------------------------------------------
402 //-------------------------------------------------------
400
403
@@ -1,42 +1,44
1 DEFINES += PYTHONQT_EXPORTS
1 DEFINES += PYTHONQT_EXPORTS
2
2
3 HEADERS += \
3 HEADERS += \
4 $$PWD/PythonQt.h \
4 $$PWD/PythonQt.h \
5 $$PWD/PythonQtStdDecorators.h \
5 $$PWD/PythonQtStdDecorators.h \
6 $$PWD/PythonQtClassInfo.h \
6 $$PWD/PythonQtClassInfo.h \
7 $$PWD/PythonQtImporter.h \
7 $$PWD/PythonQtImporter.h \
8 $$PWD/PythonQtObjectPtr.h \
8 $$PWD/PythonQtObjectPtr.h \
9 $$PWD/PythonQtSlot.h \
9 $$PWD/PythonQtSlot.h \
10 $$PWD/PythonQtStdOut.h \
10 $$PWD/PythonQtStdOut.h \
11 $$PWD/PythonQtMisc.h \
11 $$PWD/PythonQtMisc.h \
12 $$PWD/PythonQtMethodInfo.h \
12 $$PWD/PythonQtMethodInfo.h \
13 $$PWD/PythonQtImportFileInterface.h \
13 $$PWD/PythonQtImportFileInterface.h \
14 $$PWD/PythonQtConversion.h \
14 $$PWD/PythonQtConversion.h \
15 $$PWD/PythonQtSignalReceiver.h \
15 $$PWD/PythonQtSignalReceiver.h \
16 $$PWD/PythonQtWrapper.h \
16 $$PWD/PythonQtWrapper.h \
17 $$PWD/PythonQtMetaObjectWrapper.h \
17 $$PWD/PythonQtMetaObjectWrapper.h \
18 $$PWD/PythonQtCppWrapperFactory.h \
18 $$PWD/PythonQtCppWrapperFactory.h \
19 $$PWD/PythonQtVariants.h \
19 $$PWD/PythonQtVariants.h \
20 $$PWD/PythonQtVariantWrapper.h \
20 $$PWD/PythonQtVariantWrapper.h \
21 $$PWD/PythonQtQFileImporter.h \
21 $$PWD/wrapper/PythonQtWrappedVariants.h \
22 $$PWD/wrapper/PythonQtWrappedVariants.h \
22 $$PWD/gui/PythonQtScriptingConsole.h \
23 $$PWD/gui/PythonQtScriptingConsole.h \
23 $$PWD/PythonQtSystem.h
24 $$PWD/PythonQtSystem.h
24
25
25 SOURCES += \
26 SOURCES += \
26 $$PWD/PythonQtStdDecorators.cpp \
27 $$PWD/PythonQtStdDecorators.cpp \
27 $$PWD/PythonQt.cpp \
28 $$PWD/PythonQt.cpp \
28 $$PWD/PythonQtClassInfo.cpp \
29 $$PWD/PythonQtClassInfo.cpp \
29 $$PWD/PythonQtImporter.cpp \
30 $$PWD/PythonQtImporter.cpp \
30 $$PWD/PythonQtObjectPtr.cpp \
31 $$PWD/PythonQtObjectPtr.cpp \
31 $$PWD/PythonQtStdOut.cpp \
32 $$PWD/PythonQtStdOut.cpp \
32 $$PWD/PythonQtSlot.cpp \
33 $$PWD/PythonQtSlot.cpp \
33 $$PWD/PythonQtMisc.cpp \
34 $$PWD/PythonQtMisc.cpp \
34 $$PWD/PythonQtMethodInfo.cpp \
35 $$PWD/PythonQtMethodInfo.cpp \
35 $$PWD/PythonQtConversion.cpp \
36 $$PWD/PythonQtConversion.cpp \
36 $$PWD/PythonQtSignalReceiver.cpp \
37 $$PWD/PythonQtSignalReceiver.cpp \
37 $$PWD/PythonQtVariants.cpp \
38 $$PWD/PythonQtVariants.cpp \
38 $$PWD/PythonQtVariantWrapper.cpp \
39 $$PWD/PythonQtVariantWrapper.cpp \
39 $$PWD/PythonQtWrapper.cpp \
40 $$PWD/PythonQtWrapper.cpp \
41 $$PWD/PythonQtQFileImporter.cpp \
40 $$PWD/PythonQtMetaObjectWrapper.cpp \
42 $$PWD/PythonQtMetaObjectWrapper.cpp \
41 $$PWD/gui/PythonQtScriptingConsole.cpp
43 $$PWD/gui/PythonQtScriptingConsole.cpp
42
44
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now