@@ -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 |
|
|
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 |
|
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 |
|
|
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 |
|
|
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; |
|
|||
764 | if (first) { |
|
|||
765 | first = false; |
|
|||
766 | _p->_importInterface = importInterface; |
|
|||
767 |
|
|
784 | PythonQtImport::init(); | |
768 | } |
|
785 | _p->_importInterface = importInterface; | |
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 |
|
|
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. |
|
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. |
|
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 = |
|
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; |
|
|||
641 | if (hasImporter) { |
|
|||
642 |
|
|
634 | if (PythonQt::importInterface()->exists(path2)) { | |
643 |
|
|
635 | mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t(); | |
644 |
|
|
636 | } | |
645 | } else { |
|
637 | ||
646 | if (QFile::exists(path2)) { |
|
|||
647 | mtime = QFileInfo(path2).lastModified().toTime_t(); |
|
|||
648 | } |
|
|||
649 | } |
|
|||
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 ( |
|
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 |
|
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} |
|
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