##// END OF EJS Templates
Fix __getattr__ problems.
Orochimarufan -
r207:99eb8a233276
parent child
Show More
@@ -1,138 +1,142
1 project(PythonQt)
1 project(PythonQt)
2 cmake_minimum_required(VERSION 2.8.10)
2 cmake_minimum_required(VERSION 2.8.10)
3
3
4 include(CTestUseLaunchers OPTIONAL)
4 include(CTestUseLaunchers OPTIONAL)
5
5
6 set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
6 set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH})
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Debug
9 # Debug
10 option(PythonQt_DEBUG "Enable/Disable PythonQt debug output" OFF)
10 option(PythonQt_DEBUG "Enable/Disable PythonQt debug output" OFF)
11 if(PythonQt_DEBUG)
11 if(PythonQt_DEBUG)
12 add_definitions(-DPYTHONQT_DEBUG)
12 add_definitions(-DPYTHONQT_DEBUG)
13 else()
13 else()
14 remove_definitions(-DPYTHONQT_DEBUG)
14 remove_definitions(-DPYTHONQT_DEBUG)
15 endif()
15 endif()
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Qt
18 # Qt
19 option(PythonQt_Qt5 "Use Qt 5.x (5.1+)" OFF)
19 option(PythonQt_Qt5 "Use Qt 5.x (5.1+)" OFF)
20 if(PythonQt_Qt5)
20 if(PythonQt_Qt5)
21 include(PythonQt_Qt_5x)
21 include(PythonQt_Qt_5x)
22 else(PythonQt_Qt5)
22 else(PythonQt_Qt5)
23 include(PythonQt_Qt_4x)
23 include(PythonQt_Qt_4x)
24 endif(PythonQt_Qt5)
24 endif(PythonQt_Qt5)
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 # The variable "generated_cpp_suffix" allows to conditionnally compile the generated wrappers
27 # The variable "generated_cpp_suffix" allows to conditionnally compile the generated wrappers
28 # associated with the Qt version being used.
28 # associated with the Qt version being used.
29 if(PythonQt_Qt5)
29 if(PythonQt_Qt5)
30 set(generated_cpp_suffix "_${Qt5Core_VERSION_MAJOR}${Qt5Core_VERSION_MINOR}")
30 set(generated_cpp_suffix "_${Qt5Core_VERSION_MAJOR}${Qt5Core_VERSION_MINOR}")
31 else()
31 else()
32 set(generated_cpp_suffix "_${QT_VERSION_MAJOR}${QT_VERSION_MINOR}")
32 set(generated_cpp_suffix "_${QT_VERSION_MAJOR}${QT_VERSION_MINOR}")
33 endif()
33 endif()
34
34
35 if("${generated_cpp_suffix}" STREQUAL "_48")
35 if("${generated_cpp_suffix}" STREQUAL "_48")
36 set(generated_cpp_suffix "")
36 set(generated_cpp_suffix "")
37 endif()
37 endif()
38 if("${generated_cpp_suffix}" STREQUAL "_46")
38 if("${generated_cpp_suffix}" STREQUAL "_46")
39 set(generated_cpp_suffix "_47") # Also use 4.7 wrappers for 4.6.x version
39 set(generated_cpp_suffix "_47") # Also use 4.7 wrappers for 4.6.x version
40 endif()
40 endif()
41 if("${generated_cpp_suffix}" STREQUAL "_51")
41 if("${generated_cpp_suffix}" STREQUAL "_51")
42 set(generated_cpp_suffix "_50")
42 set(generated_cpp_suffix "_50")
43 endif()
43 endif()
44
44
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46 # Generator
46 # Generator
47 if(PythonQt_Qt5)
47 if(PythonQt_Qt5)
48 add_subdirectory(generator_50 EXCLUDE_FROM_ALL)
48 add_subdirectory(generator_50 EXCLUDE_FROM_ALL)
49 add_custom_target(generator)
49 add_custom_target(generator)
50 add_dependencies(generator pythonqt_generator)
50 add_dependencies(generator pythonqt_generator)
51 endif()
51 endif()
52
52
53 # TODO
53 # TODO
54
54
55 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
56 # Build options
56 # Build options
57
57
58 #option(PythonQt_Wrap_QtAll "Make all Qt components available in python" OFF)
58 #option(PythonQt_Wrap_QtAll "Make all Qt components available in python" OFF)
59 #
59 #
60 #set(qtlibs core gui network opengl sql svg uitools webkit xml xmlpatterns)
60 #set(qtlibs core gui network opengl sql svg uitools webkit xml xmlpatterns)
61 #foreach(qtlib ${qtlibs})
61 #foreach(qtlib ${qtlibs})
62 # OPTION(PythonQt_Wrap_Qt${qtlib} "Make all of Qt${qtlib} available in python" OFF)
62 # OPTION(PythonQt_Wrap_Qt${qtlib} "Make all of Qt${qtlib} available in python" OFF)
63 #endforeach()
63 #endforeach()
64
64
65 # Force option if it applies
65 # Force option if it applies
66 #if(PythonQt_Wrap_QtAll)
66 #if(PythonQt_Wrap_QtAll)
67 # list(REMOVE_ITEM qtlibs xmlpatterns) # xmlpatterns wrapper does *NOT* build at all :(
67 # list(REMOVE_ITEM qtlibs xmlpatterns) # xmlpatterns wrapper does *NOT* build at all :(
68 # foreach(qtlib ${qtlibs})
68 # foreach(qtlib ${qtlibs})
69 # if(NOT ${PythonQt_Wrap_Qt${qtlib}})
69 # if(NOT ${PythonQt_Wrap_Qt${qtlib}})
70 # set(PythonQt_Wrap_Qt${qtlib} ON CACHE BOOL "Make all of Qt${qtlib} available in python" FORCE)
70 # set(PythonQt_Wrap_Qt${qtlib} ON CACHE BOOL "Make all of Qt${qtlib} available in python" FORCE)
71 # message(STATUS "Enabling [PythonQt_Wrap_Qt${qtlib}] because of [PythonQt_Wrap_QtAll] evaluates to True")
71 # message(STATUS "Enabling [PythonQt_Wrap_Qt${qtlib}] because of [PythonQt_Wrap_QtAll] evaluates to True")
72 # endif()
72 # endif()
73 # endforeach()
73 # endforeach()
74 #endif()
74 #endif()
75
75
76 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
77 # Add extra sources
77 # Add extra sources
78 #foreach(qtlib core gui network opengl sql svg uitools webkit xml xmlpatterns)
78 #foreach(qtlib core gui network opengl sql svg uitools webkit xml xmlpatterns)
79 #
79 #
80 # if (${PythonQt_Wrap_Qt${qtlib}})
80 # if (${PythonQt_Wrap_Qt${qtlib}})
81 #
81 #
82 # ADD_DEFINITIONS(-DPYTHONQT_WRAP_Qt${qtlib})
82 # ADD_DEFINITIONS(-DPYTHONQT_WRAP_Qt${qtlib})
83 #
83 #
84 # set(file_prefix generated_cpp${generated_cpp_suffix}/com_trolltech_qt_${qtlib}/com_trolltech_qt_${qtlib})
84 # set(file_prefix generated_cpp${generated_cpp_suffix}/com_trolltech_qt_${qtlib}/com_trolltech_qt_${qtlib})
85 #
85 #
86 # foreach(index RANGE 0 11)
86 # foreach(index RANGE 0 11)
87 #
87 #
88 # # Source files
88 # # Source files
89 # if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file_prefix}${index}.cpp)
89 # if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file_prefix}${index}.cpp)
90 # list(APPEND sources ${file_prefix}${index}.cpp)
90 # list(APPEND sources ${file_prefix}${index}.cpp)
91 # endif()
91 # endif()
92 #
92 #
93 # # Headers that should run through moc
93 # # Headers that should run through moc
94 # if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file_prefix}${index}.h)
94 # if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file_prefix}${index}.h)
95 # list(APPEND moc_sources ${file_prefix}${index}.h)
95 # list(APPEND moc_sources ${file_prefix}${index}.h)
96 # endif()
96 # endif()
97 #
97 #
98 # endforeach()
98 # endforeach()
99 #
99 #
100 # list(APPEND sources ${file_prefix}_init.cpp)
100 # list(APPEND sources ${file_prefix}_init.cpp)
101 #
101 #
102 # endif()
102 # endif()
103 #endforeach()
103 #endforeach()
104
104
105 #-----------------------------------------------------------------------------
105 #-----------------------------------------------------------------------------
106 # Find Python
106 # Find Python
107 option(PythonQt_Python3 "Use Python 3.x (3.3+)" OFF)
107 option(PythonQt_Python3 "Use Python 3.x (3.3+)" OFF)
108 if(PythonQt_Python3)
108 option(PythonQt_Python "Use specific Python Version" OFF)
109 set(PythonQt_PythonMin 3.3)
109 if(PythonQt_Python)
110 else(PythonQt_Python3)
110 find_package(Python ${PythonQt_Python} REQUIRED EXACT)
111 set(PythonQt_PythonMin 2.6)
111 elseif(PythonQt_Python3)
112 find_package(Python 3.3 REQUIRED)
113 else()
114 find_package(Python 2.6 REQUIRED)
112 endif()
115 endif()
113
116
114 find_package(Python ${PythonQt_PythonMin} REQUIRED)
115 include_directories(${PYTHON_INCLUDE_DIRS})
117 include_directories(${PYTHON_INCLUDE_DIRS})
116 add_definitions(-DPYTHONQT_USE_RELEASE_PYTHON_FALLBACK)
118 add_definitions(-DPYTHONQT_USE_RELEASE_PYTHON_FALLBACK)
117
119
120 #-----------------------------------------------------------------------------
121 # Core
118 add_subdirectory(src)
122 add_subdirectory(src)
119
123
120 #-----------------------------------------------------------------------------
124 #-----------------------------------------------------------------------------
121 # Tests
125 # Tests
122 add_subdirectory(tests EXCLUDE_FROM_ALL)
126 add_subdirectory(tests EXCLUDE_FROM_ALL)
123 # test alias
127 # test alias
124 add_custom_target(test COMMAND tests/PythonQtTest WORKING_DIRECTORY ${CURRENT_BINARY_DIR})
128 add_custom_target(test COMMAND tests/PythonQtTest WORKING_DIRECTORY ${CURRENT_BINARY_DIR})
125 add_dependencies(test PythonQtTest)
129 add_dependencies(test PythonQtTest)
126
130
127 #-----------------------------------------------------------------------------
131 #-----------------------------------------------------------------------------
128 # Extenseions (QtAll)
132 # Extenseions (QtAll)
129 add_subdirectory(extensions EXCLUDE_FROM_ALL)
133 add_subdirectory(extensions EXCLUDE_FROM_ALL)
130 # QtAll alias
134 # QtAll alias
131 add_custom_target(QtAll)
135 add_custom_target(QtAll)
132 add_dependencies(QtAll PythonQt_QtAll)
136 add_dependencies(QtAll PythonQt_QtAll)
133
137
134 #-----------------------------------------------------------------------------
138 #-----------------------------------------------------------------------------
135 # Examples
139 # Examples
136 include_directories(src)
140 include_directories(src)
137 include_directories(extensions/PythonQt_QtAll)
141 include_directories(extensions/PythonQt_QtAll)
138 add_subdirectory(examples EXCLUDE_FROM_ALL)
142 add_subdirectory(examples EXCLUDE_FROM_ALL)
@@ -1,2064 +1,2067
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, 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 "PythonQtSignal.h"
46 #include "PythonQtSignal.h"
47 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtSignalReceiver.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49 #include "PythonQtStdIn.h"
49 #include "PythonQtStdIn.h"
50 #include "PythonQtStdOut.h"
50 #include "PythonQtStdOut.h"
51 #include "PythonQtCppWrapperFactory.h"
51 #include "PythonQtCppWrapperFactory.h"
52 #include "PythonQtVariants.h"
52 #include "PythonQtVariants.h"
53 #include "PythonQtStdDecorators.h"
53 #include "PythonQtStdDecorators.h"
54 #include "PythonQtQFileImporter.h"
54 #include "PythonQtQFileImporter.h"
55 #include <pydebug.h>
55 #include <pydebug.h>
56 #include <vector>
56 #include <vector>
57
57
58 PythonQt* PythonQt::_self = NULL;
58 PythonQt* PythonQt::_self = NULL;
59 int PythonQt::_uniqueModuleCount = 0;
59 int PythonQt::_uniqueModuleCount = 0;
60
60
61 void PythonQt_init_QtGuiBuiltin(PyObject*);
61 void PythonQt_init_QtGuiBuiltin(PyObject*);
62 void PythonQt_init_QtCoreBuiltin(PyObject*);
62 void PythonQt_init_QtCoreBuiltin(PyObject*);
63
63
64
64
65 PyObject* PythonQtConvertFromStringRef(const void* inObject, int /*metaTypeId*/)
65 PyObject* PythonQtConvertFromStringRef(const void* inObject, int /*metaTypeId*/)
66 {
66 {
67 return PythonQtConv::QStringToPyObject(((QStringRef*)inObject)->toString());
67 return PythonQtConv::QStringToPyObject(((QStringRef*)inObject)->toString());
68 }
68 }
69
69
70 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
70 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
71 {
71 {
72 if (!_self) {
72 if (!_self) {
73 _self = new PythonQt(flags, pythonQtModuleName);
73 _self = new PythonQt(flags, pythonQtModuleName);
74
74
75 PythonQt::priv()->setupSharedLibrarySuffixes();
75 PythonQt::priv()->setupSharedLibrarySuffixes();
76
76
77 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
77 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
78 qRegisterMetaType<QList<QObject*> >("QList<void*>");
78 qRegisterMetaType<QList<QObject*> >("QList<void*>");
79
79
80 int stringRefId = qRegisterMetaType<QStringRef>("QStringRef");
80 int stringRefId = qRegisterMetaType<QStringRef>("QStringRef");
81 PythonQtConv::registerMetaTypeToPythonConverter(stringRefId, PythonQtConvertFromStringRef);
81 PythonQtConv::registerMetaTypeToPythonConverter(stringRefId, PythonQtConvertFromStringRef);
82
82
83 PythonQtRegisterToolClassesTemplateConverter(int);
83 PythonQtRegisterToolClassesTemplateConverter(int);
84 PythonQtRegisterToolClassesTemplateConverter(float);
84 PythonQtRegisterToolClassesTemplateConverter(float);
85 PythonQtRegisterToolClassesTemplateConverter(double);
85 PythonQtRegisterToolClassesTemplateConverter(double);
86 PythonQtRegisterToolClassesTemplateConverter(qint32);
86 PythonQtRegisterToolClassesTemplateConverter(qint32);
87 PythonQtRegisterToolClassesTemplateConverter(quint32);
87 PythonQtRegisterToolClassesTemplateConverter(quint32);
88 PythonQtRegisterToolClassesTemplateConverter(qint64);
88 PythonQtRegisterToolClassesTemplateConverter(qint64);
89 PythonQtRegisterToolClassesTemplateConverter(quint64);
89 PythonQtRegisterToolClassesTemplateConverter(quint64);
90 // TODO: which other POD types should be available for QList etc.
90 // TODO: which other POD types should be available for QList etc.
91
91
92 PythonQt_init_QtCoreBuiltin(NULL);
92 PythonQt_init_QtCoreBuiltin(NULL);
93 PythonQt_init_QtGuiBuiltin(NULL);
93 PythonQt_init_QtGuiBuiltin(NULL);
94
94
95 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
95 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
96 PythonQt::self()->registerCPPClass("QMetaObject",0, "QtCore", PythonQtCreateObject<PythonQtWrapper_QMetaObject>);
96 PythonQt::self()->registerCPPClass("QMetaObject",0, "QtCore", PythonQtCreateObject<PythonQtWrapper_QMetaObject>);
97
97
98 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
98 PythonQtRegisterToolClassesTemplateConverter(QByteArray);
99 PythonQtRegisterToolClassesTemplateConverter(QDate);
99 PythonQtRegisterToolClassesTemplateConverter(QDate);
100 PythonQtRegisterToolClassesTemplateConverter(QTime);
100 PythonQtRegisterToolClassesTemplateConverter(QTime);
101 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
101 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
102 PythonQtRegisterToolClassesTemplateConverter(QUrl);
102 PythonQtRegisterToolClassesTemplateConverter(QUrl);
103 PythonQtRegisterToolClassesTemplateConverter(QLocale);
103 PythonQtRegisterToolClassesTemplateConverter(QLocale);
104 PythonQtRegisterToolClassesTemplateConverter(QRect);
104 PythonQtRegisterToolClassesTemplateConverter(QRect);
105 PythonQtRegisterToolClassesTemplateConverter(QRectF);
105 PythonQtRegisterToolClassesTemplateConverter(QRectF);
106 PythonQtRegisterToolClassesTemplateConverter(QSize);
106 PythonQtRegisterToolClassesTemplateConverter(QSize);
107 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
107 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
108 PythonQtRegisterToolClassesTemplateConverter(QLine);
108 PythonQtRegisterToolClassesTemplateConverter(QLine);
109 PythonQtRegisterToolClassesTemplateConverter(QLineF);
109 PythonQtRegisterToolClassesTemplateConverter(QLineF);
110 PythonQtRegisterToolClassesTemplateConverter(QPoint);
110 PythonQtRegisterToolClassesTemplateConverter(QPoint);
111 PythonQtRegisterToolClassesTemplateConverter(QPointF);
111 PythonQtRegisterToolClassesTemplateConverter(QPointF);
112 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
112 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
113
113
114 PythonQtRegisterToolClassesTemplateConverter(QFont);
114 PythonQtRegisterToolClassesTemplateConverter(QFont);
115 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
115 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
116 PythonQtRegisterToolClassesTemplateConverter(QBrush);
116 PythonQtRegisterToolClassesTemplateConverter(QBrush);
117 PythonQtRegisterToolClassesTemplateConverter(QColor);
117 PythonQtRegisterToolClassesTemplateConverter(QColor);
118 PythonQtRegisterToolClassesTemplateConverter(QPalette);
118 PythonQtRegisterToolClassesTemplateConverter(QPalette);
119 PythonQtRegisterToolClassesTemplateConverter(QIcon);
119 PythonQtRegisterToolClassesTemplateConverter(QIcon);
120 PythonQtRegisterToolClassesTemplateConverter(QImage);
120 PythonQtRegisterToolClassesTemplateConverter(QImage);
121 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
121 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
122 PythonQtRegisterToolClassesTemplateConverter(QRegion);
122 PythonQtRegisterToolClassesTemplateConverter(QRegion);
123 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
123 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
124 PythonQtRegisterToolClassesTemplateConverter(QCursor);
124 PythonQtRegisterToolClassesTemplateConverter(QCursor);
125 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
125 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
126 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
126 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
127 PythonQtRegisterToolClassesTemplateConverter(QPen);
127 PythonQtRegisterToolClassesTemplateConverter(QPen);
128 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
128 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
129 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
129 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
130 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
130 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
131
131
132
132
133 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
133 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
134 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
134 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
135 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
135 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
136 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
136 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
137 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
137 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
138 for (unsigned int i = 0;i<16; i++) {
138 for (unsigned int i = 0;i<16; i++) {
139 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
139 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
140 if (obj) {
140 if (obj) {
141 PyModule_AddObject(pack, names[i], obj);
141 PyModule_AddObject(pack, names[i], obj);
142 Py_INCREF(obj);
142 Py_INCREF(obj);
143 PyModule_AddObject(pack2, names[i], obj);
143 PyModule_AddObject(pack2, names[i], obj);
144 } else {
144 } else {
145 std::cerr << "method not found " << names[i];
145 std::cerr << "method not found " << names[i] << std::endl;
146 }
146 }
147 }
147 }
148 }
148 }
149 }
149 }
150
150
151 void PythonQt::cleanup()
151 void PythonQt::cleanup()
152 {
152 {
153 if (_self) {
153 if (_self) {
154 delete _self;
154 delete _self;
155 _self = NULL;
155 _self = NULL;
156 }
156 }
157 }
157 }
158
158
159 PythonQt* PythonQt::self() { return _self; }
159 PythonQt* PythonQt::self() { return _self; }
160
160
161 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
161 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
162 {
162 {
163 _p = new PythonQtPrivate;
163 _p = new PythonQtPrivate;
164 _p->_initFlags = flags;
164 _p->_initFlags = flags;
165
165
166 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
166 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
167
167
168 if ((flags & PythonAlreadyInitialized) == 0) {
168 if ((flags & PythonAlreadyInitialized) == 0) {
169 #ifdef PY3K
169 #ifdef PY3K
170 Py_SetProgramName(const_cast<wchar_t*>(L"PythonQt"));
170 Py_SetProgramName(const_cast<wchar_t*>(L"PythonQt"));
171 #else
171 #else
172 Py_SetProgramName(const_cast<char*>("PythonQt"));
172 Py_SetProgramName(const_cast<char*>("PythonQt"));
173 #endif
173 #endif
174 if (flags & IgnoreSiteModule) {
174 if (flags & IgnoreSiteModule) {
175 // this prevents the automatic importing of Python site files
175 // this prevents the automatic importing of Python site files
176 Py_NoSiteFlag = 1;
176 Py_NoSiteFlag = 1;
177 }
177 }
178 Py_Initialize();
178 Py_Initialize();
179 }
179 }
180
180
181 // add our own python object types for qt object slots
181 // add our own python object types for qt object slots
182 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
182 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
183 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
183 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
184 }
184 }
185 Py_INCREF(&PythonQtSlotFunction_Type);
185 Py_INCREF(&PythonQtSlotFunction_Type);
186
186
187 if (PyType_Ready(&PythonQtSignalFunction_Type) < 0) {
187 if (PyType_Ready(&PythonQtSignalFunction_Type) < 0) {
188 std::cerr << "could not initialize PythonQtSignalFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
188 std::cerr << "could not initialize PythonQtSignalFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
189 }
189 }
190 Py_INCREF(&PythonQtSignalFunction_Type);
190 Py_INCREF(&PythonQtSignalFunction_Type);
191
191
192 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
192 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
193 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
193 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
194 // add our own python object types for classes
194 // add our own python object types for classes
195 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
195 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
196 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
196 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
197 }
197 }
198 Py_INCREF(&PythonQtClassWrapper_Type);
198 Py_INCREF(&PythonQtClassWrapper_Type);
199
199
200 // add our own python object types for CPP instances
200 // add our own python object types for CPP instances
201 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
201 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
202 PythonQt::handleError();
202 PythonQt::handleError();
203 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
203 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
204 }
204 }
205 Py_INCREF(&PythonQtInstanceWrapper_Type);
205 Py_INCREF(&PythonQtInstanceWrapper_Type);
206
206
207 // add our own python object types for redirection of stdout
207 // add our own python object types for redirection of stdout
208 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
208 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
209 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
209 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
210 }
210 }
211 Py_INCREF(&PythonQtStdOutRedirectType);
211 Py_INCREF(&PythonQtStdOutRedirectType);
212
212
213 // add our own python object types for redirection of stdin
213 // add our own python object types for redirection of stdin
214 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
214 if (PyType_Ready(&PythonQtStdInRedirectType) < 0) {
215 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
215 std::cerr << "could not initialize PythonQtStdInRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
216 }
216 }
217 Py_INCREF(&PythonQtStdInRedirectType);
217 Py_INCREF(&PythonQtStdInRedirectType);
218
218
219 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
219 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
220
220
221 }
221 }
222
222
223 PythonQt::~PythonQt() {
223 PythonQt::~PythonQt() {
224 delete _p;
224 delete _p;
225 _p = NULL;
225 _p = NULL;
226 }
226 }
227
227
228 PythonQtPrivate::~PythonQtPrivate() {
228 PythonQtPrivate::~PythonQtPrivate() {
229 delete _defaultImporter;
229 delete _defaultImporter;
230 _defaultImporter = NULL;
230 _defaultImporter = NULL;
231
231
232 {
232 {
233 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
233 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
234 while (i.hasNext()) {
234 while (i.hasNext()) {
235 delete i.next().value();
235 delete i.next().value();
236 }
236 }
237 }
237 }
238 PythonQtConv::global_valueStorage.clear();
238 PythonQtConv::global_valueStorage.clear();
239 PythonQtConv::global_ptrStorage.clear();
239 PythonQtConv::global_ptrStorage.clear();
240 PythonQtConv::global_variantStorage.clear();
240 PythonQtConv::global_variantStorage.clear();
241
241
242 PythonQtMethodInfo::cleanupCachedMethodInfos();
242 PythonQtMethodInfo::cleanupCachedMethodInfos();
243 }
243 }
244
244
245 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
245 void PythonQt::setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData)
246 {
246 {
247 if (!callback)
247 if (!callback)
248 {
248 {
249 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
249 std::cerr << "PythonQt::setRedirectStdInCallback - callback parameter is NULL !" << std::endl;
250 return;
250 return;
251 }
251 }
252
252
253 PythonQtObjectPtr sys;
253 PythonQtObjectPtr sys;
254 PythonQtObjectPtr in;
254 PythonQtObjectPtr in;
255 sys.setNewRef(PyImport_ImportModule("sys"));
255 sys.setNewRef(PyImport_ImportModule("sys"));
256
256
257 // Backup original 'sys.stdin' if not yet done
257 // Backup original 'sys.stdin' if not yet done
258 if( !PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") )
258 if( !PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") )
259 PyObject_SetAttrString(sys.object(), "pythonqt_original_stdin", PyObject_GetAttrString(sys.object(), "stdin"));
259 PyObject_SetAttrString(sys.object(), "pythonqt_original_stdin", PyObject_GetAttrString(sys.object(), "stdin"));
260
260
261 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
261 in = PythonQtStdInRedirectType.tp_new(&PythonQtStdInRedirectType, NULL, NULL);
262 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
262 ((PythonQtStdInRedirect*)in.object())->_cb = callback;
263 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
263 ((PythonQtStdInRedirect*)in.object())->_callData = callbackData;
264 // replace the built in file objects with our own objects
264 // replace the built in file objects with our own objects
265 PyModule_AddObject(sys.object(), "stdin", in);
265 PyModule_AddObject(sys.object(), "stdin", in);
266
266
267 // Backup custom 'stdin' into 'pythonqt_stdin'
267 // Backup custom 'stdin' into 'pythonqt_stdin'
268 Py_IncRef(in);
268 Py_IncRef(in);
269 PyModule_AddObject(sys.object(), "pythonqt_stdin", in);
269 PyModule_AddObject(sys.object(), "pythonqt_stdin", in);
270 }
270 }
271
271
272 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
272 void PythonQt::setRedirectStdInCallbackEnabled(bool enabled)
273 {
273 {
274 PythonQtObjectPtr sys;
274 PythonQtObjectPtr sys;
275 sys.setNewRef(PyImport_ImportModule("sys"));
275 sys.setNewRef(PyImport_ImportModule("sys"));
276
276
277 if (enabled)
277 if (enabled)
278 {
278 {
279 if( !PyObject_HasAttrString(sys.object(), "pythonqt_stdin") )
279 if( !PyObject_HasAttrString(sys.object(), "pythonqt_stdin") )
280 PyObject_SetAttrString(sys.object(), "stdin", PyObject_GetAttrString(sys.object(), "pythonqt_stdin"));
280 PyObject_SetAttrString(sys.object(), "stdin", PyObject_GetAttrString(sys.object(), "pythonqt_stdin"));
281 }
281 }
282 else
282 else
283 {
283 {
284 if( !PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") )
284 if( !PyObject_HasAttrString(sys.object(), "pythonqt_original_stdin") )
285 PyObject_SetAttrString(sys.object(), "stdin", PyObject_GetAttrString(sys.object(), "pythonqt_original_stdin"));
285 PyObject_SetAttrString(sys.object(), "stdin", PyObject_GetAttrString(sys.object(), "pythonqt_original_stdin"));
286 }
286 }
287 }
287 }
288
288
289 PythonQtImportFileInterface* PythonQt::importInterface()
289 PythonQtImportFileInterface* PythonQt::importInterface()
290 {
290 {
291 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
291 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
292 }
292 }
293
293
294 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
294 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
295 {
295 {
296 if (_self->_p->_noLongerWrappedCB) {
296 if (_self->_p->_noLongerWrappedCB) {
297 (*_self->_p->_noLongerWrappedCB)(o);
297 (*_self->_p->_noLongerWrappedCB)(o);
298 };
298 };
299 }
299 }
300
300
301 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
301 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
302 {
302 {
303 _p->registerClass(metaobject, package, wrapperCreator, shell);
303 _p->registerClass(metaobject, package, wrapperCreator, shell);
304 }
304 }
305
305
306 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
306 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
307 {
307 {
308 // we register all classes in the hierarchy
308 // we register all classes in the hierarchy
309 const QMetaObject* m = metaobject;
309 const QMetaObject* m = metaobject;
310 bool first = true;
310 bool first = true;
311 while (m) {
311 while (m) {
312 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
312 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
313 if (!info->pythonQtClassWrapper()) {
313 if (!info->pythonQtClassWrapper()) {
314 info->setTypeSlots(typeSlots);
314 info->setTypeSlots(typeSlots);
315 info->setupQObject(m);
315 info->setupQObject(m);
316 createPythonQtClassWrapper(info, package, module);
316 createPythonQtClassWrapper(info, package, module);
317 if (m->superClass()) {
317 if (m->superClass()) {
318 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
318 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
319 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
319 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
320 }
320 }
321 } else if (first && module) {
321 } else if (first && module) {
322 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
322 // There is a wrapper already, but if we got a module, we want to place the wrapper into that module as well,
323 // since it might have been placed into "private" earlier on.
323 // since it might have been placed into "private" earlier on.
324 // If the wrapper was already added to module before, it is just readded, which does no harm.
324 // If the wrapper was already added to module before, it is just readded, which does no harm.
325 PyObject* classWrapper = info->pythonQtClassWrapper();
325 PyObject* classWrapper = info->pythonQtClassWrapper();
326 // AddObject steals a reference, so we need to INCREF
326 // AddObject steals a reference, so we need to INCREF
327 Py_INCREF(classWrapper);
327 Py_INCREF(classWrapper);
328 PyModule_AddObject(module, info->className(), classWrapper);
328 PyModule_AddObject(module, info->className(), classWrapper);
329 }
329 }
330 if (first) {
330 if (first) {
331 first = false;
331 first = false;
332 if (wrapperCreator) {
332 if (wrapperCreator) {
333 info->setDecoratorProvider(wrapperCreator);
333 info->setDecoratorProvider(wrapperCreator);
334 }
334 }
335 if (shell) {
335 if (shell) {
336 info->setShellSetInstanceWrapperCB(shell);
336 info->setShellSetInstanceWrapperCB(shell);
337 }
337 }
338 }
338 }
339 m = m->superClass();
339 m = m->superClass();
340 }
340 }
341 }
341 }
342
342
343 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
343 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
344 {
344 {
345 PyObject* pack = module?module:packageByName(package);
345 PyObject* pack = module?module:packageByName(package);
346 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
346 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
347 PyModule_AddObject(pack, info->className(), pyobj);
347 PyModule_AddObject(pack, info->className(), pyobj);
348 if (!module && package && strncmp(package,"Qt",2)==0) {
348 if (!module && package && strncmp(package,"Qt",2)==0) {
349 // since PyModule_AddObject steals the reference, we need a incref once more...
349 // since PyModule_AddObject steals the reference, we need a incref once more...
350 Py_INCREF(pyobj);
350 Py_INCREF(pyobj);
351 // put all qt objects into Qt as well
351 // put all qt objects into Qt as well
352 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
352 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
353 }
353 }
354 info->setPythonQtClassWrapper(pyobj);
354 info->setPythonQtClassWrapper(pyobj);
355 }
355 }
356
356
357 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
357 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
358 {
358 {
359 if (!obj) {
359 if (!obj) {
360 Py_INCREF(Py_None);
360 Py_INCREF(Py_None);
361 return Py_None;
361 return Py_None;
362 }
362 }
363 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
363 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
364 if (wrap && wrap->_wrappedPtr) {
364 if (wrap && wrap->_wrappedPtr) {
365 // uh oh, we want to wrap a QObject, but have a C++ wrapper at that
365 // uh oh, we want to wrap a QObject, but have a C++ wrapper at that
366 // address, so probably that C++ wrapper has been deleted earlier and
366 // address, so probably that C++ wrapper has been deleted earlier and
367 // now we see a QObject with the same address.
367 // now we see a QObject with the same address.
368 // Do not use the old wrapper anymore.
368 // Do not use the old wrapper anymore.
369 wrap = NULL;
369 wrap = NULL;
370 }
370 }
371 if (!wrap) {
371 if (!wrap) {
372 // smuggling it in...
372 // smuggling it in...
373 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
373 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
374 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
374 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
375 registerClass(obj->metaObject());
375 registerClass(obj->metaObject());
376 classInfo = _knownClassInfos.value(obj->metaObject()->className());
376 classInfo = _knownClassInfos.value(obj->metaObject()->className());
377 }
377 }
378 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
378 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
379 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
379 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
380 } else {
380 } else {
381 Py_INCREF(wrap);
381 Py_INCREF(wrap);
382 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
382 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
383 }
383 }
384 return (PyObject*)wrap;
384 return (PyObject*)wrap;
385 }
385 }
386
386
387 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
387 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
388 {
388 {
389 if (!ptr) {
389 if (!ptr) {
390 Py_INCREF(Py_None);
390 Py_INCREF(Py_None);
391 return Py_None;
391 return Py_None;
392 }
392 }
393
393
394 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
394 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
395 PythonQtInstanceWrapper* possibleStillAliveWrapper = NULL;
395 PythonQtInstanceWrapper* possibleStillAliveWrapper = NULL;
396 if (wrap && wrap->_wrappedPtr) {
396 if (wrap && wrap->_wrappedPtr) {
397 // we have a previous C++ wrapper... if the wrapper is for a C++ object,
397 // we have a previous C++ wrapper... if the wrapper is for a C++ object,
398 // we are not sure if it may have been deleted earlier and we just see the same C++
398 // we are not sure if it may have been deleted earlier and we just see the same C++
399 // pointer once again. To make sure that we do not reuse a wrapper of the wrong type,
399 // pointer once again. To make sure that we do not reuse a wrapper of the wrong type,
400 // we compare the classInfo() pointer and only reuse the wrapper if it has the same
400 // we compare the classInfo() pointer and only reuse the wrapper if it has the same
401 // info. This is only needed for non-QObjects, since we know it when a QObject gets deleted.
401 // info. This is only needed for non-QObjects, since we know it when a QObject gets deleted.
402 possibleStillAliveWrapper = wrap;
402 possibleStillAliveWrapper = wrap;
403 wrap = NULL;
403 wrap = NULL;
404 }
404 }
405 if (!wrap) {
405 if (!wrap) {
406 PythonQtClassInfo* info = _knownClassInfos.value(name);
406 PythonQtClassInfo* info = _knownClassInfos.value(name);
407 if (!info) {
407 if (!info) {
408 // maybe it is a PyObject, which we can return directly
408 // maybe it is a PyObject, which we can return directly
409 if (name == "PyObject") {
409 if (name == "PyObject") {
410 PyObject* p = (PyObject*)ptr;
410 PyObject* p = (PyObject*)ptr;
411 Py_INCREF(p);
411 Py_INCREF(p);
412 return p;
412 return p;
413 }
413 }
414
414
415 // we do not know the metaobject yet, but we might know it by its name:
415 // we do not know the metaobject yet, but we might know it by its name:
416 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
416 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
417 // yes, we know it, so we can convert to QObject
417 // yes, we know it, so we can convert to QObject
418 QObject* qptr = (QObject*)ptr;
418 QObject* qptr = (QObject*)ptr;
419 registerClass(qptr->metaObject());
419 registerClass(qptr->metaObject());
420 info = _knownClassInfos.value(qptr->metaObject()->className());
420 info = _knownClassInfos.value(qptr->metaObject()->className());
421 }
421 }
422 }
422 }
423 if (info && info->isQObject()) {
423 if (info && info->isQObject()) {
424 QObject* qptr = (QObject*)ptr;
424 QObject* qptr = (QObject*)ptr;
425 // if the object is a derived object, we want to switch the class info to the one of the derived class:
425 // if the object is a derived object, we want to switch the class info to the one of the derived class:
426 if (name!=(qptr->metaObject()->className())) {
426 if (name!=(qptr->metaObject()->className())) {
427 info = _knownClassInfos.value(qptr->metaObject()->className());
427 info = _knownClassInfos.value(qptr->metaObject()->className());
428 if (!info) {
428 if (!info) {
429 registerClass(qptr->metaObject());
429 registerClass(qptr->metaObject());
430 info = _knownClassInfos.value(qptr->metaObject()->className());
430 info = _knownClassInfos.value(qptr->metaObject()->className());
431 }
431 }
432 }
432 }
433 wrap = createNewPythonQtInstanceWrapper(qptr, info);
433 wrap = createNewPythonQtInstanceWrapper(qptr, info);
434 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
434 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
435 return (PyObject*)wrap;
435 return (PyObject*)wrap;
436 }
436 }
437
437
438 // not a known QObject, try to wrap via foreign wrapper factories
438 // not a known QObject, try to wrap via foreign wrapper factories
439 PyObject* foreignWrapper = NULL;
439 PyObject* foreignWrapper = NULL;
440 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
440 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
441 foreignWrapper = _foreignWrapperFactories.at(i)->wrap(name, ptr);
441 foreignWrapper = _foreignWrapperFactories.at(i)->wrap(name, ptr);
442 if (foreignWrapper) {
442 if (foreignWrapper) {
443 return foreignWrapper;
443 return foreignWrapper;
444 }
444 }
445 }
445 }
446
446
447 // not a known QObject, so try our wrapper factory:
447 // not a known QObject, so try our wrapper factory:
448 QObject* wrapper = NULL;
448 QObject* wrapper = NULL;
449 for (int i=0; i<_cppWrapperFactories.size(); i++) {
449 for (int i=0; i<_cppWrapperFactories.size(); i++) {
450 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
450 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
451 if (wrapper) {
451 if (wrapper) {
452 break;
452 break;
453 }
453 }
454 }
454 }
455
455
456 if (info) {
456 if (info) {
457 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
457 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
458 ptr = info->castDownIfPossible(ptr, &info);
458 ptr = info->castDownIfPossible(ptr, &info);
459
459
460 // if downcasting found out that the object is a QObject,
460 // if downcasting found out that the object is a QObject,
461 // handle it like one:
461 // handle it like one:
462 if (info && info->isQObject()) {
462 if (info && info->isQObject()) {
463 QObject* qptr = (QObject*)ptr;
463 QObject* qptr = (QObject*)ptr;
464 // if the object is a derived object, we want to switch the class info to the one of the derived class:
464 // if the object is a derived object, we want to switch the class info to the one of the derived class:
465 if (name!=(qptr->metaObject()->className())) {
465 if (name!=(qptr->metaObject()->className())) {
466 registerClass(qptr->metaObject());
466 registerClass(qptr->metaObject());
467 info = _knownClassInfos.value(qptr->metaObject()->className());
467 info = _knownClassInfos.value(qptr->metaObject()->className());
468 }
468 }
469 wrap = createNewPythonQtInstanceWrapper(qptr, info);
469 wrap = createNewPythonQtInstanceWrapper(qptr, info);
470 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
470 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
471 return (PyObject*)wrap;
471 return (PyObject*)wrap;
472 }
472 }
473 }
473 }
474
474
475 if (!info || info->pythonQtClassWrapper()==NULL) {
475 if (!info || info->pythonQtClassWrapper()==NULL) {
476 // still unknown, register as CPP class
476 // still unknown, register as CPP class
477 registerCPPClass(name.constData());
477 registerCPPClass(name.constData());
478 info = _knownClassInfos.value(name);
478 info = _knownClassInfos.value(name);
479 }
479 }
480 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
480 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
481 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
481 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
482 info->setMetaObject(wrapper->metaObject());
482 info->setMetaObject(wrapper->metaObject());
483 }
483 }
484
484
485 if (possibleStillAliveWrapper && possibleStillAliveWrapper->classInfo() == info) {
485 if (possibleStillAliveWrapper && possibleStillAliveWrapper->classInfo() == info) {
486 wrap = possibleStillAliveWrapper;
486 wrap = possibleStillAliveWrapper;
487 Py_INCREF(wrap);
487 Py_INCREF(wrap);
488 } else {
488 } else {
489 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
489 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
490 }
490 }
491 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
491 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
492 } else {
492 } else {
493 Py_INCREF(wrap);
493 Py_INCREF(wrap);
494 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
494 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
495 }
495 }
496 return (PyObject*)wrap;
496 return (PyObject*)wrap;
497 }
497 }
498
498
499 PyObject* PythonQtPrivate::dummyTuple() {
499 PyObject* PythonQtPrivate::dummyTuple() {
500 static PyObject* dummyTuple = NULL;
500 static PyObject* dummyTuple = NULL;
501 if (dummyTuple==NULL) {
501 if (dummyTuple==NULL) {
502 dummyTuple = PyTuple_New(1);
502 dummyTuple = PyTuple_New(1);
503 #ifdef PY3K
503 #ifdef PY3K
504 PyTuple_SET_ITEM(dummyTuple, 0, PyUnicode_FromString("dummy"));
504 PyTuple_SET_ITEM(dummyTuple, 0, PyUnicode_FromString("dummy"));
505 #else
505 #else
506 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
506 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
507 #endif
507 #endif
508 }
508 }
509 return dummyTuple;
509 return dummyTuple;
510 }
510 }
511
511
512
512
513 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
513 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
514 // call the associated class type to create a new instance...
514 // call the associated class type to create a new instance...
515 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
515 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
516
516
517 result->setQObject(obj);
517 result->setQObject(obj);
518 result->_wrappedPtr = wrappedPtr;
518 result->_wrappedPtr = wrappedPtr;
519 result->_ownedByPythonQt = false;
519 result->_ownedByPythonQt = false;
520 result->_useQMetaTypeDestroy = false;
520 result->_useQMetaTypeDestroy = false;
521
521
522 if (wrappedPtr) {
522 if (wrappedPtr) {
523 _wrappedObjects.insert(wrappedPtr, result);
523 _wrappedObjects.insert(wrappedPtr, result);
524 } else {
524 } else {
525 _wrappedObjects.insert(obj, result);
525 _wrappedObjects.insert(obj, result);
526 if (obj->parent()== NULL && _wrappedCB) {
526 if (obj->parent()== NULL && _wrappedCB) {
527 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
527 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
528 (*_wrappedCB)(obj);
528 (*_wrappedCB)(obj);
529 }
529 }
530 }
530 }
531 return result;
531 return result;
532 }
532 }
533
533
534 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
534 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
535 PythonQtClassWrapper* result;
535 PythonQtClassWrapper* result;
536
536
537 #ifdef PY3K
537 #ifdef PY3K
538 PyObject* className = PyUnicode_FromString(info->className());
538 PyObject* className = PyUnicode_FromString(info->className());
539 #else
539 #else
540 PyObject* className = PyString_FromString(info->className());
540 PyObject* className = PyString_FromString(info->className());
541 #endif
541 #endif
542
542
543 PyObject* baseClasses = PyTuple_New(1);
543 PyObject* baseClasses = PyTuple_New(1);
544 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
544 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
545
545
546 PyObject* typeDict = PyDict_New();
546 PyObject* typeDict = PyDict_New();
547 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
547 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
548 PyDict_SetItemString(typeDict, "__module__", moduleName);
548 PyDict_SetItemString(typeDict, "__module__", moduleName);
549
549
550 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
550 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
551
551
552 // set the class info so that PythonQtClassWrapper_new can read it
552 // set the class info so that PythonQtClassWrapper_new can read it
553 _currentClassInfoForClassWrapperCreation = info;
553 _currentClassInfoForClassWrapperCreation = info;
554 // create the new type object by calling the type
554 // create the new type object by calling the type
555 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
555 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
556
556
557 Py_DECREF(baseClasses);
557 Py_DECREF(baseClasses);
558 Py_DECREF(typeDict);
558 Py_DECREF(typeDict);
559 Py_DECREF(args);
559 Py_DECREF(args);
560 Py_DECREF(className);
560 Py_DECREF(className);
561
561
562 return result;
562 return result;
563 }
563 }
564
564
565 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
565 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
566 {
566 {
567 PyObject* args = Py_BuildValue("(i)", enumValue);
567 PyObject* args = Py_BuildValue("(i)", enumValue);
568 PyObject* result = PyObject_Call(enumType, args, NULL);
568 PyObject* result = PyObject_Call(enumType, args, NULL);
569 Py_DECREF(args);
569 Py_DECREF(args);
570 return result;
570 return result;
571 }
571 }
572
572
573 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
573 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
574 PyObject* result;
574 PyObject* result;
575
575
576 #ifdef PY3K
576 #ifdef PY3K
577 PyObject* className = PyUnicode_FromString(enumName);
577 PyObject* className = PyUnicode_FromString(enumName);
578 #else
578 #else
579 PyObject* className = PyString_FromString(enumName);
579 PyObject* className = PyString_FromString(enumName);
580 #endif
580 #endif
581
581
582 PyObject* baseClasses = PyTuple_New(1);
582 PyObject* baseClasses = PyTuple_New(1);
583 #ifdef PY3K
583 #ifdef PY3K
584 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyLong_Type);
584 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyLong_Type);
585 #else
585 #else
586 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
586 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
587 #endif
587 #endif
588
588
589 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
589 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
590 PyObject* typeDict = PyDict_New();
590 PyObject* typeDict = PyDict_New();
591 PyDict_SetItemString(typeDict, "__module__", module);
591 PyDict_SetItemString(typeDict, "__module__", module);
592
592
593 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
593 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
594
594
595 // create the new int derived type object by calling the core type
595 // create the new int derived type object by calling the core type
596 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
596 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
597
597
598 Py_DECREF(baseClasses);
598 Py_DECREF(baseClasses);
599 Py_DECREF(typeDict);
599 Py_DECREF(typeDict);
600 Py_DECREF(args);
600 Py_DECREF(args);
601 Py_DECREF(className);
601 Py_DECREF(className);
602
602
603 return result;
603 return result;
604 }
604 }
605
605
606 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
606 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
607 {
607 {
608 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
608 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
609 if (!r) {
609 if (!r) {
610 r = new PythonQtSignalReceiver(obj);
610 r = new PythonQtSignalReceiver(obj);
611 _p->_signalReceivers.insert(obj, r);
611 _p->_signalReceivers.insert(obj, r);
612 }
612 }
613 return r;
613 return r;
614 }
614 }
615
615
616 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
616 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
617 {
617 {
618 bool flag = false;
618 bool flag = false;
619 PythonQtObjectPtr callable = lookupCallable(module, objectname);
619 PythonQtObjectPtr callable = lookupCallable(module, objectname);
620 if (callable) {
620 if (callable) {
621 PythonQtSignalReceiver* r = getSignalReceiver(obj);
621 PythonQtSignalReceiver* r = getSignalReceiver(obj);
622 flag = r->addSignalHandler(signal, callable);
622 flag = r->addSignalHandler(signal, callable);
623 if (!flag) {
623 if (!flag) {
624 // signal not found
624 // signal not found
625 }
625 }
626 } else {
626 } else {
627 // callable not found
627 // callable not found
628 }
628 }
629 return flag;
629 return flag;
630 }
630 }
631
631
632 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
632 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
633 {
633 {
634 bool flag = false;
634 bool flag = false;
635 PythonQtSignalReceiver* r = getSignalReceiver(obj);
635 PythonQtSignalReceiver* r = getSignalReceiver(obj);
636 if (r) {
636 if (r) {
637 flag = r->addSignalHandler(signal, receiver);
637 flag = r->addSignalHandler(signal, receiver);
638 }
638 }
639 return flag;
639 return flag;
640 }
640 }
641
641
642 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
642 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
643 {
643 {
644 bool flag = false;
644 bool flag = false;
645 PythonQtObjectPtr callable = lookupCallable(module, objectname);
645 PythonQtObjectPtr callable = lookupCallable(module, objectname);
646 if (callable) {
646 if (callable) {
647 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
647 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
648 if (r) {
648 if (r) {
649 flag = r->removeSignalHandler(signal, callable);
649 flag = r->removeSignalHandler(signal, callable);
650 }
650 }
651 } else {
651 } else {
652 // callable not found
652 // callable not found
653 }
653 }
654 return flag;
654 return flag;
655 }
655 }
656
656
657 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
657 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
658 {
658 {
659 bool flag = false;
659 bool flag = false;
660 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
660 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
661 if (r) {
661 if (r) {
662 flag = r->removeSignalHandler(signal, receiver);
662 flag = r->removeSignalHandler(signal, receiver);
663 }
663 }
664 return flag;
664 return flag;
665 }
665 }
666
666
667 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
667 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
668 {
668 {
669 PythonQtObjectPtr p = lookupObject(module, name);
669 PythonQtObjectPtr p = lookupObject(module, name);
670 if (p) {
670 if (p) {
671 if (PyCallable_Check(p)) {
671 if (PyCallable_Check(p)) {
672 return p;
672 return p;
673 }
673 }
674 }
674 }
675 PyErr_Clear();
675 PyErr_Clear();
676 return NULL;
676 return NULL;
677 }
677 }
678
678
679 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
679 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
680 {
680 {
681 QStringList l = name.split('.');
681 QStringList l = name.split('.');
682 PythonQtObjectPtr p = module;
682 PythonQtObjectPtr p = module;
683 PythonQtObjectPtr prev;
683 PythonQtObjectPtr prev;
684 QByteArray b;
684 QByteArray b;
685 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
685 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
686 prev = p;
686 prev = p;
687 b = (*i).toLatin1();
687 b = (*i).toLatin1();
688 if (PyDict_Check(p)) {
688 if (PyDict_Check(p)) {
689 p = PyDict_GetItemString(p, b.data());
689 p = PyDict_GetItemString(p, b.data());
690 } else {
690 } else {
691 p.setNewRef(PyObject_GetAttrString(p, b.data()));
691 p.setNewRef(PyObject_GetAttrString(p, b.data()));
692 }
692 }
693 }
693 }
694 PyErr_Clear();
694 PyErr_Clear();
695 return p;
695 return p;
696 }
696 }
697
697
698 PythonQtObjectPtr PythonQt::getMainModule() {
698 PythonQtObjectPtr PythonQt::getMainModule() {
699 //both borrowed
699 //both borrowed
700 PythonQtObjectPtr dict = PyImport_GetModuleDict();
700 PythonQtObjectPtr dict = PyImport_GetModuleDict();
701 return PyDict_GetItemString(dict, "__main__");
701 return PyDict_GetItemString(dict, "__main__");
702 }
702 }
703
703
704 PythonQtObjectPtr PythonQt::importModule(const QString& name)
704 PythonQtObjectPtr PythonQt::importModule(const QString& name)
705 {
705 {
706 PythonQtObjectPtr mod;
706 PythonQtObjectPtr mod;
707 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
707 mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData()));
708 return mod;
708 return mod;
709 }
709 }
710
710
711
711
712 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
712 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
713 QVariant result;
713 QVariant result;
714 clearError();
714 clearError();
715 if (pycode) {
715 if (pycode) {
716 PyObject* dict = NULL;
716 PyObject* dict = NULL;
717 PyObject* globals = NULL;
717 PyObject* globals = NULL;
718 if (PyModule_Check(object)) {
718 if (PyModule_Check(object)) {
719 dict = PyModule_GetDict(object);
719 dict = PyModule_GetDict(object);
720 globals = dict;
720 globals = dict;
721 } else if (PyDict_Check(object)) {
721 } else if (PyDict_Check(object)) {
722 dict = object;
722 dict = object;
723 globals = dict;
723 globals = dict;
724 } else {
724 } else {
725 dict = PyObject_GetAttrString(object, "__dict__");
725 dict = PyObject_GetAttrString(object, "__dict__");
726 globals = PyObject_GetAttrString(PyImport_ImportModule(
726 globals = PyObject_GetAttrString(PyImport_ImportModule(
727 #ifdef PY3K
727 #ifdef PY3K
728 PyUnicode_AsUTF8(
728 PyUnicode_AsUTF8(
729 #else
729 #else
730 PyString_AS_STRING(
730 PyString_AS_STRING(
731 #endif
731 #endif
732 PyObject_GetAttrString(object, "__module__"))),"__dict__");
732 PyObject_GetAttrString(object, "__module__"))),"__dict__");
733 }
733 }
734 PyObject* r = NULL;
734 PyObject* r = NULL;
735 if (dict) {
735 if (dict) {
736 #ifdef PY3K
736 #ifdef PY3K
737 r = PyEval_EvalCode(pycode, globals, dict);
737 r = PyEval_EvalCode(pycode, globals, dict);
738 #else
738 #else
739 r = PyEval_EvalCode((PyCodeObject*)pycode, globals , dict);
739 r = PyEval_EvalCode((PyCodeObject*)pycode, globals , dict);
740 #endif
740 #endif
741 }
741 }
742 if (r) {
742 if (r) {
743 result = PythonQtConv::PyObjToQVariant(r);
743 result = PythonQtConv::PyObjToQVariant(r);
744 Py_DECREF(r);
744 Py_DECREF(r);
745 } else {
745 } else {
746 handleError();
746 handleError();
747 }
747 }
748 } else {
748 } else {
749 handleError();
749 handleError();
750 }
750 }
751 return result;
751 return result;
752 }
752 }
753
753
754 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
754 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
755 {
755 {
756 QVariant result;
756 QVariant result;
757 PythonQtObjectPtr p;
757 PythonQtObjectPtr p;
758 PyObject* dict = NULL;
758 PyObject* dict = NULL;
759 clearError();
759 clearError();
760 if (PyModule_Check(object)) {
760 if (PyModule_Check(object)) {
761 dict = PyModule_GetDict(object);
761 dict = PyModule_GetDict(object);
762 } else if (PyDict_Check(object)) {
762 } else if (PyDict_Check(object)) {
763 dict = object;
763 dict = object;
764 }
764 }
765 if (dict) {
765 if (dict) {
766 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
766 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
767 }
767 }
768 if (p) {
768 if (p) {
769 result = PythonQtConv::PyObjToQVariant(p);
769 result = PythonQtConv::PyObjToQVariant(p);
770 } else {
770 } else {
771 handleError();
771 handleError();
772 }
772 }
773 return result;
773 return result;
774 }
774 }
775
775
776 void PythonQt::evalFile(PyObject* module, const QString& filename)
776 void PythonQt::evalFile(PyObject* module, const QString& filename)
777 {
777 {
778 PythonQtObjectPtr code = parseFile(filename);
778 PythonQtObjectPtr code = parseFile(filename);
779 clearError();
779 clearError();
780 if (code) {
780 if (code) {
781 evalCode(module, code);
781 evalCode(module, code);
782 } else {
782 } else {
783 handleError();
783 handleError();
784 }
784 }
785 }
785 }
786
786
787 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
787 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
788 {
788 {
789 PythonQtObjectPtr p;
789 PythonQtObjectPtr p;
790 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
790 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
791 clearError();
791 clearError();
792 if (!p) {
792 if (!p) {
793 handleError();
793 handleError();
794 }
794 }
795 return p;
795 return p;
796 }
796 }
797
797
798 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
798 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
799 {
799 {
800 PythonQtObjectPtr code = parseFile(filename);
800 PythonQtObjectPtr code = parseFile(filename);
801 PythonQtObjectPtr module = _p->createModule(name, code);
801 PythonQtObjectPtr module = _p->createModule(name, code);
802 return module;
802 return module;
803 }
803 }
804
804
805 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
805 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
806 {
806 {
807 PyErr_Clear();
807 PyErr_Clear();
808 QString scriptCode = script;
808 QString scriptCode = script;
809 if (scriptCode.isEmpty()) {
809 if (scriptCode.isEmpty()) {
810 // we always need at least a linefeed
810 // we always need at least a linefeed
811 scriptCode = "\n";
811 scriptCode = "\n";
812 }
812 }
813 PythonQtObjectPtr pycode;
813 PythonQtObjectPtr pycode;
814 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
814 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
815 PythonQtObjectPtr module = _p->createModule(name, pycode);
815 PythonQtObjectPtr module = _p->createModule(name, pycode);
816 return module;
816 return module;
817 }
817 }
818
818
819 PythonQtObjectPtr PythonQt::createUniqueModule()
819 PythonQtObjectPtr PythonQt::createUniqueModule()
820 {
820 {
821 static QString pyQtStr("PythonQt_module");
821 static QString pyQtStr("PythonQt_module");
822 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
822 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
823 return createModuleFromScript(moduleName);
823 return createModuleFromScript(moduleName);
824 }
824 }
825
825
826 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
826 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
827 {
827 {
828 if (PyModule_Check(object)) {
828 if (PyModule_Check(object)) {
829 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
829 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
830 } else if (PyDict_Check(object)) {
830 } else if (PyDict_Check(object)) {
831 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
831 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
832 } else {
832 } else {
833 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
833 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
834 }
834 }
835 }
835 }
836
836
837 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
837 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
838 {
838 {
839 if (PyModule_Check(object)) {
839 if (PyModule_Check(object)) {
840 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
840 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
841 } else if (PyDict_Check(object)) {
841 } else if (PyDict_Check(object)) {
842 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
842 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
843 } else {
843 } else {
844 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
844 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
845 }
845 }
846 }
846 }
847
847
848 void PythonQt::removeVariable(PyObject* object, const QString& name)
848 void PythonQt::removeVariable(PyObject* object, const QString& name)
849 {
849 {
850 if (PyDict_Check(object)) {
850 if (PyDict_Check(object)) {
851 PyDict_DelItemString(object, name.toLatin1().data());
851 PyDict_DelItemString(object, name.toLatin1().data());
852 } else {
852 } else {
853 PyObject_DelAttrString(object, name.toLatin1().data());
853 PyObject_DelAttrString(object, name.toLatin1().data());
854 }
854 }
855 }
855 }
856
856
857 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
857 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
858 {
858 {
859 QVariant result;
859 QVariant result;
860 PythonQtObjectPtr obj = lookupObject(object, objectname);
860 PythonQtObjectPtr obj = lookupObject(object, objectname);
861 if (obj) {
861 if (obj) {
862 result = PythonQtConv::PyObjToQVariant(obj);
862 result = PythonQtConv::PyObjToQVariant(obj);
863 }
863 }
864 return result;
864 return result;
865 }
865 }
866
866
867 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
867 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
868 {
868 {
869 QStringList results;
869 QStringList results;
870
870
871 PythonQtObjectPtr object;
871 PythonQtObjectPtr object;
872 if (objectname.isEmpty()) {
872 if (objectname.isEmpty()) {
873 object = module;
873 object = module;
874 } else {
874 } else {
875 object = lookupObject(module, objectname);
875 object = lookupObject(module, objectname);
876 if (!object && type == CallOverloads) {
876 if (!object && type == CallOverloads) {
877 PyObject* dict = lookupObject(module, "__builtins__");
877 PyObject* dict = lookupObject(module, "__builtins__");
878 if (dict) {
878 if (dict) {
879 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
879 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
880 }
880 }
881 }
881 }
882 }
882 }
883
883
884 if (object) {
884 if (object) {
885 results = introspectObject(object, type);
885 results = introspectObject(object, type);
886 }
886 }
887
887
888 return results;
888 return results;
889 }
889 }
890
890
891 QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
891 QStringList PythonQt::introspectObject(PyObject* object, ObjectType type)
892 {
892 {
893 QStringList results;
893 QStringList results;
894
894
895 if (type == CallOverloads) {
895 if (type == CallOverloads) {
896 if (PythonQtSlotFunction_Check(object)) {
896 if (PythonQtSlotFunction_Check(object)) {
897 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object;
897 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object;
898 PythonQtSlotInfo* info = o->m_ml;
898 PythonQtSlotInfo* info = o->m_ml;
899
899
900 while (info) {
900 while (info) {
901 results << info->fullSignature();
901 results << info->fullSignature();
902 info = info->nextInfo();
902 info = info->nextInfo();
903 }
903 }
904 } else if (PythonQtSignalFunction_Check(object)) {
904 } else if (PythonQtSignalFunction_Check(object)) {
905 PythonQtSignalFunctionObject* o = (PythonQtSignalFunctionObject*)object;
905 PythonQtSignalFunctionObject* o = (PythonQtSignalFunctionObject*)object;
906 PythonQtSlotInfo* info = o->m_ml;
906 PythonQtSlotInfo* info = o->m_ml;
907
907
908 while (info) {
908 while (info) {
909 results << info->fullSignature();
909 results << info->fullSignature();
910 info = info->nextInfo();
910 info = info->nextInfo();
911 }
911 }
912 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
912 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
913 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
913 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
914 PythonQtSlotInfo* info = o->classInfo()->constructors();
914 PythonQtSlotInfo* info = o->classInfo()->constructors();
915
915
916 while (info) {
916 while (info) {
917 results << info->fullSignature();
917 results << info->fullSignature();
918 info = info->nextInfo();
918 info = info->nextInfo();
919 }
919 }
920 } else {
920 } else {
921 QString signature = _p->getSignature(object);
921 QString signature = _p->getSignature(object);
922 if (!signature.isEmpty()) {
922 if (!signature.isEmpty()) {
923 results << signature;
923 results << signature;
924 } else {
924 } else {
925 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
925 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
926 if (doc) {
926 if (doc) {
927 #ifdef PY3K
927 #ifdef PY3K
928 results << PyUnicode_AsUTF8(doc);
928 results << PyUnicode_AsUTF8(doc);
929 #else
929 #else
930 results << PyString_AsString(doc);
930 results << PyString_AsString(doc);
931 #endif
931 #endif
932 Py_DECREF(doc);
932 Py_DECREF(doc);
933 }
933 }
934 }
934 }
935 }
935 }
936 } else {
936 } else {
937 PyObject* keys = NULL;
937 PyObject* keys = NULL;
938 bool isDict = false;
938 bool isDict = false;
939 if (PyDict_Check(object)) {
939 if (PyDict_Check(object)) {
940 keys = PyDict_Keys(object);
940 keys = PyDict_Keys(object);
941 isDict = true;
941 isDict = true;
942 } else {
942 } else {
943 keys = PyObject_Dir(object);
943 keys = PyObject_Dir(object);
944 }
944 }
945 if (keys) {
945 if (keys) {
946 int count = PyList_Size(keys);
946 int count = PyList_Size(keys);
947 PyObject* key;
947 PyObject* key;
948 PyObject* value;
948 PyObject* value;
949 QString keystr;
949 QString keystr;
950 for (int i = 0;i<count;i++) {
950 for (int i = 0;i<count;i++) {
951 key = PyList_GetItem(keys,i);
951 key = PyList_GetItem(keys,i);
952 if (isDict) {
952 if (isDict) {
953 value = PyDict_GetItem(object, key);
953 value = PyDict_GetItem(object, key);
954 Py_INCREF(value);
954 Py_INCREF(value);
955 } else {
955 } else {
956 value = PyObject_GetAttr(object, key);
956 value = PyObject_GetAttr(object, key);
957 }
957 }
958 if (!value) continue;
958 if (!value) continue;
959 #ifdef PY3K
959 #ifdef PY3K
960 keystr = PyUnicode_AsUTF8(key);
960 keystr = PyUnicode_AsUTF8(key);
961 #else
961 #else
962 keystr = PyString_AsString(key);
962 keystr = PyString_AsString(key);
963 #endif
963 #endif
964 static const QString underscoreStr("__tmp");
964 static const QString underscoreStr("__tmp");
965 if (!keystr.startsWith(underscoreStr)) {
965 if (!keystr.startsWith(underscoreStr)) {
966 switch (type) {
966 switch (type) {
967 case Anything:
967 case Anything:
968 results << keystr;
968 results << keystr;
969 break;
969 break;
970 case Class:
970 case Class:
971 #ifdef PY3K
971 #ifdef PY3K
972 if(PyType_Check(value)) {
972 if(PyType_Check(value)) {
973 #else
973 #else
974 if (value->ob_type == &PyClass_Type || value->ob_type == &PyType_Type) {
974 if (value->ob_type == &PyClass_Type || value->ob_type == &PyType_Type) {
975 #endif
975 #endif
976 results << keystr;
976 results << keystr;
977 }
977 }
978 break;
978 break;
979 case Variable:
979 case Variable:
980 if (
980 if (
981 #ifndef PY3K
981 #ifndef PY3K
982 value->ob_type != &PyClass_Type &&
982 value->ob_type != &PyClass_Type &&
983 #endif
983 #endif
984 value->ob_type != &PyCFunction_Type &&
984 value->ob_type != &PyCFunction_Type &&
985 value->ob_type != &PyFunction_Type &&
985 value->ob_type != &PyFunction_Type &&
986 value->ob_type != &PyMethod_Type &&
986 value->ob_type != &PyMethod_Type &&
987 value->ob_type != &PyModule_Type &&
987 value->ob_type != &PyModule_Type &&
988 value->ob_type != &PyType_Type &&
988 value->ob_type != &PyType_Type &&
989 value->ob_type != &PythonQtSlotFunction_Type
989 value->ob_type != &PythonQtSlotFunction_Type
990 ) {
990 ) {
991 results << keystr;
991 results << keystr;
992 }
992 }
993 break;
993 break;
994 case Function:
994 case Function:
995 if (value->ob_type == &PyCFunction_Type ||
995 if (value->ob_type == &PyCFunction_Type ||
996 value->ob_type == &PyFunction_Type ||
996 value->ob_type == &PyFunction_Type ||
997 value->ob_type == &PyMethod_Type ||
997 value->ob_type == &PyMethod_Type ||
998 value->ob_type == &PythonQtSlotFunction_Type
998 value->ob_type == &PythonQtSlotFunction_Type
999 ) {
999 ) {
1000 results << keystr;
1000 results << keystr;
1001 }
1001 }
1002 break;
1002 break;
1003 case Module:
1003 case Module:
1004 if (value->ob_type == &PyModule_Type) {
1004 if (value->ob_type == &PyModule_Type) {
1005 results << keystr;
1005 results << keystr;
1006 }
1006 }
1007 break;
1007 break;
1008 default:
1008 default:
1009 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
1009 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
1010 }
1010 }
1011 }
1011 }
1012 Py_DECREF(value);
1012 Py_DECREF(value);
1013 }
1013 }
1014 Py_DECREF(keys);
1014 Py_DECREF(keys);
1015 }
1015 }
1016 if ((type == Anything) || (type == Variable)) {
1016 if ((type == Anything) || (type == Variable)) {
1017 if (object->ob_type == &PythonQtClassWrapper_Type) {
1017 if (object->ob_type == &PythonQtClassWrapper_Type) {
1018 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
1018 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object;
1019 PythonQtClassInfo* info = o->classInfo();
1019 PythonQtClassInfo* info = o->classInfo();
1020 results += info->propertyList();
1020 results += info->propertyList();
1021 }
1021 }
1022 }
1022 }
1023 }
1023 }
1024 return results;
1024 return results;
1025 }
1025 }
1026
1026
1027 PyObject* PythonQt::getObjectByType(const QString& typeName)
1027 PyObject* PythonQt::getObjectByType(const QString& typeName)
1028 {
1028 {
1029 PythonQtObjectPtr sys;
1029 PythonQtObjectPtr sys;
1030 sys.setNewRef(PyImport_ImportModule("sys"));
1030 sys.setNewRef(PyImport_ImportModule("sys"));
1031 PythonQtObjectPtr modules = lookupObject(sys, "modules");
1031 PythonQtObjectPtr modules = lookupObject(sys, "modules");
1032 Q_ASSERT(PyDict_Check(modules));
1032 Q_ASSERT(PyDict_Check(modules));
1033
1033
1034 QStringList tmp = typeName.split(".");
1034 QStringList tmp = typeName.split(".");
1035 QString simpleTypeName = tmp.takeLast();
1035 QString simpleTypeName = tmp.takeLast();
1036 QString moduleName = tmp.join(".");
1036 QString moduleName = tmp.join(".");
1037
1037
1038 PyObject* object = NULL;
1038 PyObject* object = NULL;
1039 PyObject* moduleObject = PyDict_GetItemString(modules, moduleName.toLatin1().constData());
1039 PyObject* moduleObject = PyDict_GetItemString(modules, moduleName.toLatin1().constData());
1040 if (moduleObject) {
1040 if (moduleObject) {
1041 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
1041 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
1042 }
1042 }
1043
1043
1044 if (!object) {
1044 if (!object) {
1045 moduleObject = PyDict_GetItemString(modules, "__builtin__");
1045 moduleObject = PyDict_GetItemString(modules, "__builtin__");
1046 if (moduleObject) {
1046 if (moduleObject) {
1047 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
1047 object = PyObject_GetAttrString(moduleObject, simpleTypeName.toLatin1().constData());
1048 }
1048 }
1049 }
1049 }
1050
1050
1051 return object;
1051 return object;
1052 }
1052 }
1053
1053
1054 QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
1054 QStringList PythonQt::introspectType(const QString& typeName, ObjectType type)
1055 {
1055 {
1056 QStringList results;
1056 QStringList results;
1057 PyObject* object = getObjectByType(typeName);
1057 PyObject* object = getObjectByType(typeName);
1058 if (!object) {
1058 if (!object) {
1059 // the last item may be a member, split it away and try again
1059 // the last item may be a member, split it away and try again
1060 QStringList tmp = typeName.split(".");
1060 QStringList tmp = typeName.split(".");
1061 QString memberName = tmp.takeLast();
1061 QString memberName = tmp.takeLast();
1062 QString typeName;
1062 QString typeName;
1063 if (tmp.isEmpty()) {
1063 if (tmp.isEmpty()) {
1064 typeName = memberName;
1064 typeName = memberName;
1065 memberName.clear();
1065 memberName.clear();
1066 } else {
1066 } else {
1067 typeName = tmp.takeLast();
1067 typeName = tmp.takeLast();
1068 }
1068 }
1069 PyObject* typeObject = getObjectByType(typeName);
1069 PyObject* typeObject = getObjectByType(typeName);
1070 if (typeObject) {
1070 if (typeObject) {
1071 object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData());
1071 object = PyObject_GetAttrString(typeObject, memberName.toLatin1().constData());
1072 }
1072 }
1073 }
1073 }
1074 if (object) {
1074 if (object) {
1075 results = introspectObject(object, type);
1075 results = introspectObject(object, type);
1076 Py_DECREF(object);
1076 Py_DECREF(object);
1077 }
1077 }
1078 return results;
1078 return results;
1079 }
1079 }
1080
1080
1081 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args, const QVariantMap& kwargs)
1081 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args, const QVariantMap& kwargs)
1082 {
1082 {
1083 PythonQtObjectPtr callable = lookupCallable(object, name);
1083 PythonQtObjectPtr callable = lookupCallable(object, name);
1084 if (callable) {
1084 if (callable) {
1085 return call(callable, args, kwargs);
1085 return call(callable, args, kwargs);
1086 } else {
1086 } else {
1087 return QVariant();
1087 return QVariant();
1088 }
1088 }
1089 }
1089 }
1090
1090
1091 QVariant PythonQt::call(PyObject* callable, const QVariantList& args, const QVariantMap& kwargs)
1091 QVariant PythonQt::call(PyObject* callable, const QVariantList& args, const QVariantMap& kwargs)
1092 {
1092 {
1093 QVariant r;
1093 QVariant r;
1094 PythonQtObjectPtr result;
1094 PythonQtObjectPtr result;
1095 result.setNewRef(callAndReturnPyObject(callable, args, kwargs));
1095 result.setNewRef(callAndReturnPyObject(callable, args, kwargs));
1096 clearError();
1096 clearError();
1097 if (result) {
1097 if (result) {
1098 r = PythonQtConv::PyObjToQVariant(result);
1098 r = PythonQtConv::PyObjToQVariant(result);
1099 } else {
1099 } else {
1100 PythonQt::self()->handleError();
1100 PythonQt::self()->handleError();
1101 }
1101 }
1102 return r;
1102 return r;
1103 }
1103 }
1104
1104
1105 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args, const QVariantMap& kwargs)
1105 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args, const QVariantMap& kwargs)
1106 {
1106 {
1107 PyObject* result = NULL;
1107 PyObject* result = NULL;
1108 if (callable) {
1108 if (callable) {
1109 bool err = false;
1109 bool err = false;
1110 PythonQtObjectPtr pargs;
1110 PythonQtObjectPtr pargs;
1111 int count = args.size();
1111 int count = args.size();
1112 if ((count > 0) || (kwargs.count() > 0)) { // create empty tuple if kwargs are given
1112 if ((count > 0) || (kwargs.count() > 0)) { // create empty tuple if kwargs are given
1113 pargs.setNewRef(PyTuple_New(count));
1113 pargs.setNewRef(PyTuple_New(count));
1114
1114
1115 // transform QVariant arguments to Python
1115 // transform QVariant arguments to Python
1116 for (int i = 0; i < count; i++) {
1116 for (int i = 0; i < count; i++) {
1117 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
1117 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
1118 if (arg) {
1118 if (arg) {
1119 // steals reference, no unref
1119 // steals reference, no unref
1120 PyTuple_SetItem(pargs, i,arg);
1120 PyTuple_SetItem(pargs, i,arg);
1121 } else {
1121 } else {
1122 err = true;
1122 err = true;
1123 break;
1123 break;
1124 }
1124 }
1125 }
1125 }
1126 }
1126 }
1127 if (!err) {
1127 if (!err) {
1128 if (kwargs.isEmpty()) {
1128 if (kwargs.isEmpty()) {
1129 // do a direct call if we have no keyword arguments
1129 // do a direct call if we have no keyword arguments
1130 PyErr_Clear();
1130 PyErr_Clear();
1131 result = PyObject_CallObject(callable, pargs);
1131 result = PyObject_CallObject(callable, pargs);
1132 } else {
1132 } else {
1133 // convert keyword arguments to Python
1133 // convert keyword arguments to Python
1134 PythonQtObjectPtr pkwargs;
1134 PythonQtObjectPtr pkwargs;
1135 pkwargs.setNewRef(PyDict_New());
1135 pkwargs.setNewRef(PyDict_New());
1136 QMapIterator<QString, QVariant> it(kwargs);
1136 QMapIterator<QString, QVariant> it(kwargs);
1137 while (it.hasNext()) {
1137 while (it.hasNext()) {
1138 it.next();
1138 it.next();
1139 PyObject* arg = PythonQtConv::QVariantToPyObject(it.value());
1139 PyObject* arg = PythonQtConv::QVariantToPyObject(it.value());
1140 if (arg) {
1140 if (arg) {
1141 PyDict_SetItemString(pkwargs, it.key().toLatin1().constData(), arg);
1141 PyDict_SetItemString(pkwargs, it.key().toLatin1().constData(), arg);
1142 } else {
1142 } else {
1143 err = true;
1143 err = true;
1144 break;
1144 break;
1145 }
1145 }
1146 }
1146 }
1147 if (!err) {
1147 if (!err) {
1148 // call with arguments and keyword arguments
1148 // call with arguments and keyword arguments
1149 PyErr_Clear();
1149 PyErr_Clear();
1150 result = PyObject_Call(callable, pargs, pkwargs);
1150 result = PyObject_Call(callable, pargs, pkwargs);
1151 }
1151 }
1152 }
1152 }
1153 }
1153 }
1154 }
1154 }
1155 return result;
1155 return result;
1156 }
1156 }
1157
1157
1158 void PythonQt::addInstanceDecorators(QObject* o)
1158 void PythonQt::addInstanceDecorators(QObject* o)
1159 {
1159 {
1160 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
1160 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
1161 }
1161 }
1162
1162
1163 void PythonQt::addClassDecorators(QObject* o)
1163 void PythonQt::addClassDecorators(QObject* o)
1164 {
1164 {
1165 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
1165 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
1166 }
1166 }
1167
1167
1168 void PythonQt::addDecorators(QObject* o)
1168 void PythonQt::addDecorators(QObject* o)
1169 {
1169 {
1170 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
1170 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
1171 }
1171 }
1172
1172
1173 void PythonQt::registerQObjectClassNames(const QStringList& names)
1173 void PythonQt::registerQObjectClassNames(const QStringList& names)
1174 {
1174 {
1175 _p->registerQObjectClassNames(names);
1175 _p->registerQObjectClassNames(names);
1176 }
1176 }
1177
1177
1178 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
1178 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
1179 {
1179 {
1180 _p->_importInterface = importInterface;
1180 _p->_importInterface = importInterface;
1181 PythonQtImport::init();
1181 PythonQtImport::init();
1182 }
1182 }
1183
1183
1184 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
1184 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
1185 {
1185 {
1186 _p->_importIgnorePaths = paths;
1186 _p->_importIgnorePaths = paths;
1187 }
1187 }
1188
1188
1189 const QStringList& PythonQt::getImporterIgnorePaths()
1189 const QStringList& PythonQt::getImporterIgnorePaths()
1190 {
1190 {
1191 return _p->_importIgnorePaths;
1191 return _p->_importIgnorePaths;
1192 }
1192 }
1193
1193
1194 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
1194 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
1195 {
1195 {
1196 _p->_cppWrapperFactories.append(factory);
1196 _p->_cppWrapperFactories.append(factory);
1197 }
1197 }
1198
1198
1199 void PythonQt::addWrapperFactory( PythonQtForeignWrapperFactory* factory )
1199 void PythonQt::addWrapperFactory( PythonQtForeignWrapperFactory* factory )
1200 {
1200 {
1201 _p->_foreignWrapperFactories.append(factory);
1201 _p->_foreignWrapperFactories.append(factory);
1202 }
1202 }
1203
1203
1204 //---------------------------------------------------------------------------------------------------
1204 //---------------------------------------------------------------------------------------------------
1205 PythonQtPrivate::PythonQtPrivate()
1205 PythonQtPrivate::PythonQtPrivate()
1206 {
1206 {
1207 _importInterface = NULL;
1207 _importInterface = NULL;
1208 _defaultImporter = new PythonQtQFileImporter;
1208 _defaultImporter = new PythonQtQFileImporter;
1209 _noLongerWrappedCB = NULL;
1209 _noLongerWrappedCB = NULL;
1210 _wrappedCB = NULL;
1210 _wrappedCB = NULL;
1211 _currentClassInfoForClassWrapperCreation = NULL;
1211 _currentClassInfoForClassWrapperCreation = NULL;
1212 _profilingCB = NULL;
1212 _profilingCB = NULL;
1213 _hadError = false;
1213 _hadError = false;
1214 _systemExitExceptionHandlerEnabled = false;
1214 _systemExitExceptionHandlerEnabled = false;
1215 }
1215 }
1216
1216
1217 void PythonQtPrivate::setupSharedLibrarySuffixes()
1217 void PythonQtPrivate::setupSharedLibrarySuffixes()
1218 {
1218 {
1219 _sharedLibrarySuffixes.clear();
1219 _sharedLibrarySuffixes.clear();
1220 PythonQtObjectPtr imp;
1220 PythonQtObjectPtr imp;
1221 imp.setNewRef(PyImport_ImportModule("imp"));
1221 imp.setNewRef(PyImport_ImportModule("imp"));
1222 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
1222 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
1223 QVariant result = imp.call("get_suffixes");
1223 QVariant result = imp.call("get_suffixes");
1224 #ifdef __linux
1224 #ifdef __linux
1225 #ifdef _DEBUG
1225 #ifdef _DEBUG
1226 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
1226 // First look for shared libraries with the '_d' suffix in debug mode on Linux.
1227 // This is a workaround, because python does not append the '_d' suffix on Linux
1227 // This is a workaround, because python does not append the '_d' suffix on Linux
1228 // and would always load the release library otherwise.
1228 // and would always load the release library otherwise.
1229 _sharedLibrarySuffixes << "_d.so";
1229 _sharedLibrarySuffixes << "_d.so";
1230 #endif
1230 #endif
1231 #endif
1231 #endif
1232 Q_FOREACH (QVariant entry, result.toList()) {
1232 Q_FOREACH (QVariant entry, result.toList()) {
1233 QVariantList suffixEntry = entry.toList();
1233 QVariantList suffixEntry = entry.toList();
1234 if (suffixEntry.count()==3) {
1234 if (suffixEntry.count()==3) {
1235 int code = suffixEntry.at(2).toInt();
1235 int code = suffixEntry.at(2).toInt();
1236 if (code == cExtensionCode) {
1236 if (code == cExtensionCode) {
1237 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
1237 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
1238 }
1238 }
1239 }
1239 }
1240 }
1240 }
1241 }
1241 }
1242
1242
1243 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1243 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
1244 {
1244 {
1245 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1245 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
1246 _currentClassInfoForClassWrapperCreation = NULL;
1246 _currentClassInfoForClassWrapperCreation = NULL;
1247 return info;
1247 return info;
1248 }
1248 }
1249
1249
1250 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1250 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
1251 {
1251 {
1252 o->setParent(this);
1252 o->setParent(this);
1253 int numMethods = o->metaObject()->methodCount();
1253 int numMethods = o->metaObject()->methodCount();
1254 for (int i = 0; i < numMethods; i++) {
1254 for (int i = 0; i < numMethods; i++) {
1255 QMetaMethod m = o->metaObject()->method(i);
1255 QMetaMethod m = o->metaObject()->method(i);
1256 if ((m.methodType() == QMetaMethod::Method ||
1256 if ((m.methodType() == QMetaMethod::Method ||
1257 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1257 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
1258 // QMetaMethod::signature changed to QMetaMethod::methodSignature in QT5
1258 // QMetaMethod::signature changed to QMetaMethod::methodSignature in QT5
1259 #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) )
1259 #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) )
1260 QByteArray signature = m.methodSignature();
1260 QByteArray signature = m.methodSignature();
1261 #else
1261 #else
1262 QByteArray signature = m.signature();
1262 QByteArray signature = m.signature();
1263 #endif
1263 #endif
1264 if (signature.startsWith("new_")) {
1264 if (signature.startsWith("new_")) {
1265 if ((decoTypes & ConstructorDecorator) == 0) continue;
1265 if ((decoTypes & ConstructorDecorator) == 0) continue;
1266 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1266 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1267 if (info->parameters().at(0).pointerCount == 1) {
1267 if (info->parameters().at(0).pointerCount == 1) {
1268 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1268 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
1269 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1269 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1270 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1270 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1271 classInfo->addConstructor(newSlot);
1271 classInfo->addConstructor(newSlot);
1272 }
1272 }
1273 } else if (signature.startsWith("delete_")) {
1273 } else if (signature.startsWith("delete_")) {
1274 if ((decoTypes & DestructorDecorator) == 0) continue;
1274 if ((decoTypes & DestructorDecorator) == 0) continue;
1275 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1275 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
1276 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1276 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1277 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1277 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1278 classInfo->setDestructor(newSlot);
1278 classInfo->setDestructor(newSlot);
1279 } else if (signature.startsWith("static_")) {
1279 } else if (signature.startsWith("static_")) {
1280 if ((decoTypes & StaticDecorator) == 0) continue;
1280 if ((decoTypes & StaticDecorator) == 0) continue;
1281 QByteArray nameOfClass = signature.mid(7);
1281 QByteArray nameOfClass = signature.mid(7);
1282 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1282 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
1283 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1283 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
1284 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1284 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
1285 classInfo->addDecoratorSlot(newSlot);
1285 classInfo->addDecoratorSlot(newSlot);
1286 } else {
1286 } else {
1287 if ((decoTypes & InstanceDecorator) == 0) continue;
1287 if ((decoTypes & InstanceDecorator) == 0) continue;
1288 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1288 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
1289 if (info->parameters().count()>1) {
1289 if (info->parameters().count()>1) {
1290 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1290 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
1291 if (p.pointerCount==1) {
1291 if (p.pointerCount==1) {
1292 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1292 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
1293 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1293 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
1294 classInfo->addDecoratorSlot(newSlot);
1294 classInfo->addDecoratorSlot(newSlot);
1295 }
1295 }
1296 }
1296 }
1297 }
1297 }
1298 }
1298 }
1299 }
1299 }
1300 }
1300 }
1301
1301
1302 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1302 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
1303 {
1303 {
1304 Q_FOREACH(QString name, names) {
1304 Q_FOREACH(QString name, names) {
1305 _knownQObjectClassNames.insert(name.toLatin1(), true);
1305 _knownQObjectClassNames.insert(name.toLatin1(), true);
1306 }
1306 }
1307 }
1307 }
1308
1308
1309 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1309 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
1310 {
1310 {
1311 _signalReceivers.remove(obj);
1311 _signalReceivers.remove(obj);
1312 }
1312 }
1313
1313
1314 namespace
1314 namespace
1315 {
1315 {
1316 //! adapted from python source file "pythonrun.c", function "handle_system_exit"
1316 //! adapted from python source file "pythonrun.c", function "handle_system_exit"
1317 //! return the exitcode instead of calling "Py_Exit".
1317 //! return the exitcode instead of calling "Py_Exit".
1318 //! it gives the application an opportunity to properly terminate.
1318 //! it gives the application an opportunity to properly terminate.
1319 int custom_system_exit_exception_handler()
1319 int custom_system_exit_exception_handler()
1320 {
1320 {
1321 PyObject *exception, *value, *tb;
1321 PyObject *exception, *value, *tb;
1322 int exitcode = 0;
1322 int exitcode = 0;
1323
1323
1324 // if (Py_InspectFlag)
1324 // if (Py_InspectFlag)
1325 // /* Don't exit if -i flag was given. This flag is set to 0
1325 // /* Don't exit if -i flag was given. This flag is set to 0
1326 // * when entering interactive mode for inspecting. */
1326 // * when entering interactive mode for inspecting. */
1327 // return exitcode;
1327 // return exitcode;
1328
1328
1329 PyErr_Fetch(&exception, &value, &tb);
1329 PyErr_Fetch(&exception, &value, &tb);
1330 #ifdef PY3K
1330 #ifdef PY3K
1331 std::cout << std::endl;
1331 std::cout << std::endl;
1332 #else
1332 #else
1333 if (Py_FlushLine())
1333 if (Py_FlushLine())
1334 PyErr_Clear();
1334 PyErr_Clear();
1335 #endif
1335 #endif
1336 fflush(stdout);
1336 fflush(stdout);
1337 if (value == NULL || value == Py_None)
1337 if (value == NULL || value == Py_None)
1338 goto done;
1338 goto done;
1339 if (PyExceptionInstance_Check(value)) {
1339 if (PyExceptionInstance_Check(value)) {
1340 /* The error code should be in the `code' attribute. */
1340 /* The error code should be in the `code' attribute. */
1341 PyObject *code = PyObject_GetAttrString(value, "code");
1341 PyObject *code = PyObject_GetAttrString(value, "code");
1342 if (code) {
1342 if (code) {
1343 Py_DECREF(value);
1343 Py_DECREF(value);
1344 value = code;
1344 value = code;
1345 if (value == Py_None)
1345 if (value == Py_None)
1346 goto done;
1346 goto done;
1347 }
1347 }
1348 /* If we failed to dig out the 'code' attribute,
1348 /* If we failed to dig out the 'code' attribute,
1349 just let the else clause below print the error. */
1349 just let the else clause below print the error. */
1350 }
1350 }
1351 #ifdef PY3K
1351 #ifdef PY3K
1352 if (PyLong_Check(value))
1352 if (PyLong_Check(value))
1353 exitcode = (int)PyLong_AsLong(value);
1353 exitcode = (int)PyLong_AsLong(value);
1354 #else
1354 #else
1355 if (PyInt_Check(value))
1355 if (PyInt_Check(value))
1356 exitcode = (int)PyInt_AsLong(value);
1356 exitcode = (int)PyInt_AsLong(value);
1357 #endif
1357 #endif
1358 else {
1358 else {
1359 PyObject *sys_stderr = PySys_GetObject(const_cast<char*>("stderr"));
1359 PyObject *sys_stderr = PySys_GetObject(const_cast<char*>("stderr"));
1360 if (sys_stderr != NULL && sys_stderr != Py_None) {
1360 if (sys_stderr != NULL && sys_stderr != Py_None) {
1361 PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW);
1361 PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW);
1362 } else {
1362 } else {
1363 PyObject_Print(value, stderr, Py_PRINT_RAW);
1363 PyObject_Print(value, stderr, Py_PRINT_RAW);
1364 fflush(stderr);
1364 fflush(stderr);
1365 }
1365 }
1366 PySys_WriteStderr("\n");
1366 PySys_WriteStderr("\n");
1367 exitcode = 1;
1367 exitcode = 1;
1368 }
1368 }
1369 done:
1369 done:
1370 /* Restore and clear the exception info, in order to properly decref
1370 /* Restore and clear the exception info, in order to properly decref
1371 * the exception, value, and traceback. If we just exit instead,
1371 * the exception, value, and traceback. If we just exit instead,
1372 * these leak, which confuses PYTHONDUMPREFS output, and may prevent
1372 * these leak, which confuses PYTHONDUMPREFS output, and may prevent
1373 * some finalizers from running.
1373 * some finalizers from running.
1374 */
1374 */
1375 PyErr_Restore(exception, value, tb);
1375 PyErr_Restore(exception, value, tb);
1376 PyErr_Clear();
1376 PyErr_Clear();
1377 return exitcode;
1377 return exitcode;
1378 //Py_Exit(exitcode);
1378 //Py_Exit(exitcode);
1379 }
1379 }
1380 }
1380 }
1381
1381
1382 bool PythonQt::handleError()
1382 bool PythonQt::handleError()
1383 {
1383 {
1384 bool flag = false;
1384 bool flag = false;
1385 if (PyErr_Occurred()) {
1385 if (PyErr_Occurred()) {
1386
1386
1387 if (_p->_systemExitExceptionHandlerEnabled &&
1387 if (_p->_systemExitExceptionHandlerEnabled &&
1388 PyErr_ExceptionMatches(PyExc_SystemExit)) {
1388 PyErr_ExceptionMatches(PyExc_SystemExit)) {
1389 int exitcode = custom_system_exit_exception_handler();
1389 int exitcode = custom_system_exit_exception_handler();
1390 Q_EMIT PythonQt::self()->systemExitExceptionRaised(exitcode);
1390 Q_EMIT PythonQt::self()->systemExitExceptionRaised(exitcode);
1391 }
1391 }
1392 else
1392 else
1393 {
1393 {
1394 // currently we just print the error and the stderr handler parses the errors
1394 // currently we just print the error and the stderr handler parses the errors
1395 PyErr_Print();
1395 PyErr_Print();
1396
1396
1397 /*
1397 /*
1398 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1398 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1399 PyObject *ptype;
1399 PyObject *ptype;
1400 PyObject *pvalue;
1400 PyObject *pvalue;
1401 PyObject *ptraceback;
1401 PyObject *ptraceback;
1402 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1402 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1403
1403
1404 Py_XDECREF(ptype);
1404 Py_XDECREF(ptype);
1405 Py_XDECREF(pvalue);
1405 Py_XDECREF(pvalue);
1406 Py_XDECREF(ptraceback);
1406 Py_XDECREF(ptraceback);
1407 */
1407 */
1408 PyErr_Clear();
1408 PyErr_Clear();
1409 }
1409 }
1410 flag = true;
1410 flag = true;
1411 }
1411 }
1412 _p->_hadError = flag;
1412 _p->_hadError = flag;
1413 return flag;
1413 return flag;
1414 }
1414 }
1415
1415
1416 bool PythonQt::hadError()const
1416 bool PythonQt::hadError()const
1417 {
1417 {
1418 return _p->_hadError;
1418 return _p->_hadError;
1419 }
1419 }
1420
1420
1421 void PythonQt::clearError()
1421 void PythonQt::clearError()
1422 {
1422 {
1423 _p->_hadError = false;
1423 _p->_hadError = false;
1424 }
1424 }
1425
1425
1426 void PythonQt::setSystemExitExceptionHandlerEnabled(bool value)
1426 void PythonQt::setSystemExitExceptionHandlerEnabled(bool value)
1427 {
1427 {
1428 _p->_systemExitExceptionHandlerEnabled = value;
1428 _p->_systemExitExceptionHandlerEnabled = value;
1429 }
1429 }
1430
1430
1431 bool PythonQt::systemExitExceptionHandlerEnabled() const
1431 bool PythonQt::systemExitExceptionHandlerEnabled() const
1432 {
1432 {
1433 return _p->_systemExitExceptionHandlerEnabled;
1433 return _p->_systemExitExceptionHandlerEnabled;
1434 }
1434 }
1435
1435
1436 void PythonQt::addSysPath(const QString& path)
1436 void PythonQt::addSysPath(const QString& path)
1437 {
1437 {
1438 PythonQtObjectPtr sys;
1438 PythonQtObjectPtr sys;
1439 sys.setNewRef(PyImport_ImportModule("sys"));
1439 sys.setNewRef(PyImport_ImportModule("sys"));
1440 PythonQtObjectPtr obj = lookupObject(sys, "path");
1440 PythonQtObjectPtr obj = lookupObject(sys, "path");
1441 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1441 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1442 }
1442 }
1443
1443
1444 void PythonQt::overwriteSysPath(const QStringList& paths)
1444 void PythonQt::overwriteSysPath(const QStringList& paths)
1445 {
1445 {
1446 PythonQtObjectPtr sys;
1446 PythonQtObjectPtr sys;
1447 sys.setNewRef(PyImport_ImportModule("sys"));
1447 sys.setNewRef(PyImport_ImportModule("sys"));
1448 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1448 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1449 }
1449 }
1450
1450
1451 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1451 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1452 {
1452 {
1453 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1453 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1454 }
1454 }
1455
1455
1456 void PythonQt::stdOutRedirectCB(const QString& str)
1456 void PythonQt::stdOutRedirectCB(const QString& str)
1457 {
1457 {
1458 if (!PythonQt::self()) {
1458 if (!PythonQt::self()) {
1459 std::cout << str.toLatin1().data() << std::endl;
1459 std::cout << str.toLatin1().data() << std::endl;
1460 return;
1460 return;
1461 }
1461 }
1462 Q_EMIT PythonQt::self()->pythonStdOut(str);
1462 Q_EMIT PythonQt::self()->pythonStdOut(str);
1463 }
1463 }
1464
1464
1465 void PythonQt::stdErrRedirectCB(const QString& str)
1465 void PythonQt::stdErrRedirectCB(const QString& str)
1466 {
1466 {
1467 if (!PythonQt::self()) {
1467 if (!PythonQt::self()) {
1468 std::cerr << str.toLatin1().data() << std::endl;
1468 std::cerr << str.toLatin1().data() << std::endl;
1469 return;
1469 return;
1470 }
1470 }
1471 Q_EMIT PythonQt::self()->pythonStdErr(str);
1471 Q_EMIT PythonQt::self()->pythonStdErr(str);
1472 }
1472 }
1473
1473
1474 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1474 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1475 {
1475 {
1476 _p->_wrappedCB = cb;
1476 _p->_wrappedCB = cb;
1477 }
1477 }
1478
1478
1479 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1479 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1480 {
1480 {
1481 _p->_noLongerWrappedCB = cb;
1481 _p->_noLongerWrappedCB = cb;
1482 }
1482 }
1483
1483
1484 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1484 void PythonQt::setProfilingCallback(ProfilingCB* cb)
1485 {
1485 {
1486 _p->_profilingCB = cb;
1486 _p->_profilingCB = cb;
1487 }
1487 }
1488
1488
1489
1489
1490 static PyMethodDef PythonQtMethods[] = {
1490 static PyMethodDef PythonQtMethods[] = {
1491 {NULL, NULL, 0, NULL}
1491 {NULL, NULL, 0, NULL}
1492 };
1492 };
1493
1493
1494 #ifdef PY3K
1494 #ifdef PY3K
1495 static PyModuleDef PythonQtModule = {
1495 static PyModuleDef PythonQtModuleDef = {
1496 PyModuleDef_HEAD_INIT,
1496 PyModuleDef_HEAD_INIT,
1497 "",
1497 "",
1498 NULL,
1498 NULL,
1499 -1,
1499 -1,
1500 PythonQtMethods,
1500 PythonQtMethods,
1501 NULL,
1501 NULL,
1502 NULL,
1502 NULL,
1503 NULL,
1503 NULL,
1504 NULL
1504 NULL
1505 };
1505 };
1506 #endif
1506 #endif
1507
1507
1508 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1508 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1509 {
1509 {
1510 QByteArray name = "PythonQt";
1510 QByteArray name = "PythonQt";
1511 if (!pythonQtModuleName.isEmpty()) {
1511 if (!pythonQtModuleName.isEmpty()) {
1512 name = pythonQtModuleName;
1512 name = pythonQtModuleName;
1513 }
1513 }
1514 #ifdef PY3K
1514 #ifdef PY3K
1515 PythonQtModule.m_name = name.constData();
1515 PythonQtModuleDef.m_name = name.constData();
1516 _p->_pythonQtModule = PyModule_Create(&PythonQtModule);
1516 _p->_pythonQtModule = PyModule_Create(&PythonQtModuleDef);
1517 #else
1517 #else
1518 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1518 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1519 #endif
1519 #endif
1520 _p->_pythonQtModuleName = name;
1520 _p->_pythonQtModuleName = name;
1521
1521
1522 if (redirectStdOut) {
1523 PythonQtObjectPtr sys;
1522 PythonQtObjectPtr sys;
1523 sys.setNewRef(PyImport_ImportModule("sys"));
1524
1525 if (redirectStdOut) {
1524 PythonQtObjectPtr out;
1526 PythonQtObjectPtr out;
1525 PythonQtObjectPtr err;
1527 PythonQtObjectPtr err;
1526 sys.setNewRef(PyImport_ImportModule("sys"));
1527 // create a redirection object for stdout and stderr
1528 // create a redirection object for stdout and stderr
1528 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1529 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1529 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1530 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1530 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1531 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1531 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1532 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1532 // replace the built in file objects with our own objects
1533 // replace the built in file objects with our own objects
1533 PyModule_AddObject(sys, "stdout", out);
1534 PyModule_AddObject(sys, "stdout", out);
1534 PyModule_AddObject(sys, "stderr", err);
1535 PyModule_AddObject(sys, "stderr", err);
1535 }
1536 }
1536
1537
1537 // add PythonQt to the list of builtin module names
1538 // add PythonQt to the list of builtin module names
1538 PythonQtObjectPtr sys;
1539 sys.setNewRef(PyImport_ImportModule("sys"));
1540 PyObject *old_module_names = PyObject_GetAttrString(sys.object(),"builtin_module_names");
1539 PyObject *old_module_names = PyObject_GetAttrString(sys.object(),"builtin_module_names");
1541 Py_ssize_t old_size = PyTuple_Size(old_module_names);
1540 Py_ssize_t old_size = PyTuple_Size(old_module_names);
1542 PyObject *module_names = PyTuple_New(old_size+1);
1541 PyObject *module_names = PyTuple_New(old_size+1);
1543 for(Py_ssize_t i = 0; i < old_size; i++)
1542 for(Py_ssize_t i = 0; i < old_size; i++)
1544 PyTuple_SetItem(module_names, i, PyTuple_GetItem(old_module_names, i));
1543 PyTuple_SetItem(module_names, i, PyTuple_GetItem(old_module_names, i));
1545 #ifdef PY3K
1544 #ifdef PY3K
1546 PyTuple_SetItem(module_names, old_size, PyUnicode_FromString(name.constData()));
1545 PyTuple_SetItem(module_names, old_size, PyUnicode_FromString(name.constData()));
1547 #else
1546 #else
1548 PyTuple_SetItem(module_names, old_size, PyString_FromString(name.constData()));
1547 PyTuple_SetItem(module_names, old_size, PyString_FromString(name.constData()));
1549 #endif
1548 #endif
1550 PyModule_AddObject(sys.object(),"builtin_module_names",module_names);
1549 PyModule_AddObject(sys.object(),"builtin_module_names",module_names);
1551 Py_DecRef(old_module_names);
1550 Py_DecRef(old_module_names);
1551
1552 #ifdef PY3K
1553 PyDict_SetItem(PyObject_GetAttrString(sys.object(), "modules"), PyUnicode_FromString(name.constData()), _p->_pythonQtModule.object());
1554 #endif
1552 }
1555 }
1553
1556
1554 QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString& name)
1557 QString PythonQt::getReturnTypeOfWrappedMethod(PyObject* module, const QString& name)
1555 {
1558 {
1556 QStringList tmp = name.split(".");
1559 QStringList tmp = name.split(".");
1557 QString methodName = tmp.takeLast();
1560 QString methodName = tmp.takeLast();
1558 QString variableName = tmp.join(".");
1561 QString variableName = tmp.join(".");
1559 // TODO: the variableName may be a type name, this needs to be handled differently,
1562 // TODO: the variableName may be a type name, this needs to be handled differently,
1560 // because it is not necessarily known in the module context
1563 // because it is not necessarily known in the module context
1561 PythonQtObjectPtr variableObject = lookupObject(module, variableName);
1564 PythonQtObjectPtr variableObject = lookupObject(module, variableName);
1562 if (variableObject.isNull()) {
1565 if (variableObject.isNull()) {
1563 return "";
1566 return "";
1564 }
1567 }
1565
1568
1566 return getReturnTypeOfWrappedMethodHelper(variableObject, methodName, name);
1569 return getReturnTypeOfWrappedMethodHelper(variableObject, methodName, name);
1567 }
1570 }
1568
1571
1569 QString PythonQt::getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName)
1572 QString PythonQt::getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName)
1570 {
1573 {
1571 PythonQtObjectPtr typeObject = getObjectByType(typeName);
1574 PythonQtObjectPtr typeObject = getObjectByType(typeName);
1572 if (typeObject.isNull()) {
1575 if (typeObject.isNull()) {
1573 return "";
1576 return "";
1574 }
1577 }
1575 return getReturnTypeOfWrappedMethodHelper(typeObject, methodName, typeName + "." + methodName);
1578 return getReturnTypeOfWrappedMethodHelper(typeObject, methodName, typeName + "." + methodName);
1576 }
1579 }
1577
1580
1578 QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context)
1581 QString PythonQt::getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context)
1579 {
1582 {
1580 PythonQtObjectPtr methodObject;
1583 PythonQtObjectPtr methodObject;
1581 if (PyDict_Check(variableObject)) {
1584 if (PyDict_Check(variableObject)) {
1582 methodObject = PyDict_GetItemString(variableObject, methodName.toLatin1().constData());
1585 methodObject = PyDict_GetItemString(variableObject, methodName.toLatin1().constData());
1583 } else {
1586 } else {
1584 methodObject.setNewRef(PyObject_GetAttrString(variableObject, methodName.toLatin1().constData()));
1587 methodObject.setNewRef(PyObject_GetAttrString(variableObject, methodName.toLatin1().constData()));
1585 }
1588 }
1586 if (methodObject.isNull()) {
1589 if (methodObject.isNull()) {
1587 return "";
1590 return "";
1588 }
1591 }
1589
1592
1590 QString type;
1593 QString type;
1591
1594
1592 #ifdef PY3K
1595 #ifdef PY3K
1593 if (PyType_Check(methodObject)) {
1596 if (PyType_Check(methodObject)) {
1594 #else
1597 #else
1595 if (methodObject->ob_type == &PyClass_Type || methodObject->ob_type == &PyType_Type) {
1598 if (methodObject->ob_type == &PyClass_Type || methodObject->ob_type == &PyType_Type) {
1596 #endif
1599 #endif
1597 // the methodObject is not a method, but the name of a type/class. This means
1600 // the methodObject is not a method, but the name of a type/class. This means
1598 // a constructor is called. Return the context.
1601 // a constructor is called. Return the context.
1599 type = context;
1602 type = context;
1600 } else if (methodObject->ob_type == &PythonQtSlotFunction_Type) {
1603 } else if (methodObject->ob_type == &PythonQtSlotFunction_Type) {
1601 QString className;
1604 QString className;
1602
1605
1603 if (PyObject_TypeCheck(variableObject, &PythonQtInstanceWrapper_Type)) {
1606 if (PyObject_TypeCheck(variableObject, &PythonQtInstanceWrapper_Type)) {
1604 // the type name of wrapped instance is the class name
1607 // the type name of wrapped instance is the class name
1605 className = variableObject->ob_type->tp_name;
1608 className = variableObject->ob_type->tp_name;
1606 } else {
1609 } else {
1607 PyObject* classNameObject = PyObject_GetAttrString(variableObject, "__name__");
1610 PyObject* classNameObject = PyObject_GetAttrString(variableObject, "__name__");
1608 if (classNameObject) {
1611 if (classNameObject) {
1609 #ifdef PY3K
1612 #ifdef PY3K
1610 Q_ASSERT(PyUnicode_Check(classNameObject));
1613 Q_ASSERT(PyUnicode_Check(classNameObject));
1611 className = PyUnicode_AsUTF8(classNameObject);
1614 className = PyUnicode_AsUTF8(classNameObject);
1612 #else
1615 #else
1613 Q_ASSERT(PyString_Check(classNameObject));
1616 Q_ASSERT(PyString_Check(classNameObject));
1614 className = PyString_AsString(classNameObject);
1617 className = PyString_AsString(classNameObject);
1615 #endif
1618 #endif
1616 Py_DECREF(classNameObject);
1619 Py_DECREF(classNameObject);
1617 }
1620 }
1618 }
1621 }
1619
1622
1620 if (!className.isEmpty()) {
1623 if (!className.isEmpty()) {
1621 PythonQtClassInfo* info = _p->_knownClassInfos.value(className.toLatin1().constData());
1624 PythonQtClassInfo* info = _p->_knownClassInfos.value(className.toLatin1().constData());
1622 if (info) {
1625 if (info) {
1623 PythonQtSlotInfo* slotInfo = info->member(methodName.toLatin1().constData())._slot;
1626 PythonQtSlotInfo* slotInfo = info->member(methodName.toLatin1().constData())._slot;
1624 if (slotInfo) {
1627 if (slotInfo) {
1625 if (slotInfo->metaMethod()) {
1628 if (slotInfo->metaMethod()) {
1626 type = slotInfo->metaMethod()->typeName();
1629 type = slotInfo->metaMethod()->typeName();
1627 if (!type.isEmpty()) {
1630 if (!type.isEmpty()) {
1628 QChar c = type.at(type.length()-1);
1631 QChar c = type.at(type.length()-1);
1629 while (c == '*' || c == '&') {
1632 while (c == '*' || c == '&') {
1630 type.truncate(type.length()-1);
1633 type.truncate(type.length()-1);
1631 if (!type.isEmpty()) {
1634 if (!type.isEmpty()) {
1632 c = type.at(type.length()-1);
1635 c = type.at(type.length()-1);
1633 } else {
1636 } else {
1634 break;
1637 break;
1635 }
1638 }
1636 }
1639 }
1637 // split away template arguments
1640 // split away template arguments
1638 type = type.split("<").first();
1641 type = type.split("<").first();
1639 // split away const
1642 // split away const
1640 type = type.split(" ").last().trimmed();
1643 type = type.split(" ").last().trimmed();
1641
1644
1642 // if the type is a known class info, then create the full type name, i.e. include the
1645 // if the type is a known class info, then create the full type name, i.e. include the
1643 // module name. For example, the slot may return a QDate, then this looks up the
1646 // module name. For example, the slot may return a QDate, then this looks up the
1644 // name _PythonQt.QtCore.QDate.
1647 // name _PythonQt.QtCore.QDate.
1645 PythonQtClassInfo* typeInfo = _p->_knownClassInfos.value(type.toLatin1().constData());
1648 PythonQtClassInfo* typeInfo = _p->_knownClassInfos.value(type.toLatin1().constData());
1646 if (typeInfo && typeInfo->pythonQtClassWrapper()) {
1649 if (typeInfo && typeInfo->pythonQtClassWrapper()) {
1647 PyObject* s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__module__");
1650 PyObject* s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__module__");
1648 #ifdef PY3K
1651 #ifdef PY3K
1649 Q_ASSERT(PyUnicode_Check(s));
1652 Q_ASSERT(PyUnicode_Check(s));
1650 type = QString(PyUnicode_AsUTF8(s));
1653 type = QString(PyUnicode_AsUTF8(s));
1651 #else
1654 #else
1652 Q_ASSERT(PyString_Check(s));
1655 Q_ASSERT(PyString_Check(s));
1653 type = QString(PyString_AsString(s)) + "." + type;
1656 type = QString(PyString_AsString(s)) + "." + type;
1654 #endif
1657 #endif
1655 Py_DECREF(s);
1658 Py_DECREF(s);
1656 s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__name__");
1659 s = PyObject_GetAttrString(typeInfo->pythonQtClassWrapper(), "__name__");
1657 #ifdef PY3K
1660 #ifdef PY3K
1658 Q_ASSERT(PyUnicode_Check(s));
1661 Q_ASSERT(PyUnicode_Check(s));
1659 #else
1662 #else
1660 Q_ASSERT(PyString_Check(s));
1663 Q_ASSERT(PyString_Check(s));
1661 #endif
1664 #endif
1662 Py_DECREF(s);
1665 Py_DECREF(s);
1663 }
1666 }
1664 }
1667 }
1665 }
1668 }
1666 }
1669 }
1667 }
1670 }
1668 }
1671 }
1669 }
1672 }
1670 return type;
1673 return type;
1671 }
1674 }
1672
1675
1673 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1676 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1674 {
1677 {
1675 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1678 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1676 }
1679 }
1677
1680
1678
1681
1679 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1682 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1680 {
1683 {
1681 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1684 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1682 if (!info) {
1685 if (!info) {
1683 info = new PythonQtClassInfo();
1686 info = new PythonQtClassInfo();
1684 info->setupCPPObject(typeName);
1687 info->setupCPPObject(typeName);
1685 _knownClassInfos.insert(typeName, info);
1688 _knownClassInfos.insert(typeName, info);
1686 }
1689 }
1687 return info;
1690 return info;
1688 }
1691 }
1689
1692
1690 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1693 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1691 {
1694 {
1692 _p->addPolymorphicHandler(typeName, cb);
1695 _p->addPolymorphicHandler(typeName, cb);
1693 }
1696 }
1694
1697
1695 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1698 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1696 {
1699 {
1697 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1700 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1698 info->addPolymorphicHandler(cb);
1701 info->addPolymorphicHandler(cb);
1699 }
1702 }
1700
1703
1701 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1704 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1702 {
1705 {
1703 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1706 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1704 }
1707 }
1705
1708
1706 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1709 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1707 {
1710 {
1708 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1711 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1709 if (info) {
1712 if (info) {
1710 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1713 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1711 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1714 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1712 return true;
1715 return true;
1713 } else {
1716 } else {
1714 return false;
1717 return false;
1715 }
1718 }
1716 }
1719 }
1717
1720
1718 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1721 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1719 {
1722 {
1720 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1723 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1721 if (!info->pythonQtClassWrapper()) {
1724 if (!info->pythonQtClassWrapper()) {
1722 info->setTypeSlots(typeSlots);
1725 info->setTypeSlots(typeSlots);
1723 info->setupCPPObject(typeName);
1726 info->setupCPPObject(typeName);
1724 createPythonQtClassWrapper(info, package, module);
1727 createPythonQtClassWrapper(info, package, module);
1725 }
1728 }
1726 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1729 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1727 addParentClass(typeName, parentTypeName, 0);
1730 addParentClass(typeName, parentTypeName, 0);
1728 }
1731 }
1729 if (wrapperCreator) {
1732 if (wrapperCreator) {
1730 info->setDecoratorProvider(wrapperCreator);
1733 info->setDecoratorProvider(wrapperCreator);
1731 }
1734 }
1732 if (shell) {
1735 if (shell) {
1733 info->setShellSetInstanceWrapperCB(shell);
1736 info->setShellSetInstanceWrapperCB(shell);
1734 }
1737 }
1735 }
1738 }
1736
1739
1737 PyObject* PythonQtPrivate::packageByName(const char* name)
1740 PyObject* PythonQtPrivate::packageByName(const char* name)
1738 {
1741 {
1739 if (name==NULL || name[0]==0) {
1742 if (name==NULL || name[0]==0) {
1740 name = "private";
1743 name = "private";
1741 }
1744 }
1742 PyObject* v = _packages.value(name);
1745 PyObject* v = _packages.value(name);
1743 if (!v) {
1746 if (!v) {
1744 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1747 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1745 _packages.insert(name, v);
1748 _packages.insert(name, v);
1746 // AddObject steals the reference, so increment it!
1749 // AddObject steals the reference, so increment it!
1747 Py_INCREF(v);
1750 Py_INCREF(v);
1748 PyModule_AddObject(_pythonQtModule, name, v);
1751 PyModule_AddObject(_pythonQtModule, name, v);
1749 }
1752 }
1750 return v;
1753 return v;
1751 }
1754 }
1752
1755
1753 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1756 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1754 {
1757 {
1755 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1758 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1756 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1759 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1757 PythonQt::self()->handleError();
1760 PythonQt::self()->handleError();
1758 }
1761 }
1759
1762
1760 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1763 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1761 {
1764 {
1762 if (_p->_initFlags & ExternalHelp) {
1765 if (_p->_initFlags & ExternalHelp) {
1763 Q_EMIT pythonHelpRequest(QByteArray(info->className()));
1766 Q_EMIT pythonHelpRequest(QByteArray(info->className()));
1764 return Py_BuildValue("");
1767 return Py_BuildValue("");
1765 } else {
1768 } else {
1766 #ifdef PY3K
1769 #ifdef PY3K
1767 return PyUnicode_FromString(info->help().toLatin1().data());
1770 return PyUnicode_FromString(info->help().toLatin1().data());
1768 #else
1771 #else
1769 return PyString_FromString(info->help().toLatin1().data());
1772 return PyString_FromString(info->help().toLatin1().data());
1770 #endif
1773 #endif
1771 }
1774 }
1772 }
1775 }
1773
1776
1774 void PythonQt::clearNotFoundCachedMembers()
1777 void PythonQt::clearNotFoundCachedMembers()
1775 {
1778 {
1776 Q_FOREACH(PythonQtClassInfo* info, _p->_knownClassInfos) {
1779 Q_FOREACH(PythonQtClassInfo* info, _p->_knownClassInfos) {
1777 info->clearNotFoundCachedMembers();
1780 info->clearNotFoundCachedMembers();
1778 }
1781 }
1779 }
1782 }
1780
1783
1781 void PythonQt::removeWrapperFactory( PythonQtCppWrapperFactory* factory )
1784 void PythonQt::removeWrapperFactory( PythonQtCppWrapperFactory* factory )
1782 {
1785 {
1783 _p->_cppWrapperFactories.removeAll(factory);
1786 _p->_cppWrapperFactories.removeAll(factory);
1784 }
1787 }
1785
1788
1786 void PythonQt::removeWrapperFactory( PythonQtForeignWrapperFactory* factory )
1789 void PythonQt::removeWrapperFactory( PythonQtForeignWrapperFactory* factory )
1787 {
1790 {
1788 _p->_foreignWrapperFactories.removeAll(factory);
1791 _p->_foreignWrapperFactories.removeAll(factory);
1789 }
1792 }
1790
1793
1791 void PythonQtPrivate::removeWrapperPointer(void* obj)
1794 void PythonQtPrivate::removeWrapperPointer(void* obj)
1792 {
1795 {
1793 _wrappedObjects.remove(obj);
1796 _wrappedObjects.remove(obj);
1794 }
1797 }
1795
1798
1796 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1799 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1797 {
1800 {
1798 _wrappedObjects.insert(obj, wrapper);
1801 _wrappedObjects.insert(obj, wrapper);
1799 }
1802 }
1800
1803
1801 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1804 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1802 {
1805 {
1803 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1806 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1804 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1807 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1805 // this is a wrapper whose QObject was already removed due to destruction
1808 // this is a wrapper whose QObject was already removed due to destruction
1806 // so the obj pointer has to be a new QObject with the same address...
1809 // so the obj pointer has to be a new QObject with the same address...
1807 // we remove the old one and set the copy to NULL
1810 // we remove the old one and set the copy to NULL
1808 wrap->_objPointerCopy = NULL;
1811 wrap->_objPointerCopy = NULL;
1809 removeWrapperPointer(obj);
1812 removeWrapperPointer(obj);
1810 wrap = NULL;
1813 wrap = NULL;
1811 }
1814 }
1812 return wrap;
1815 return wrap;
1813 }
1816 }
1814
1817
1815 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1818 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1816 {
1819 {
1817 PythonQtObjectPtr result;
1820 PythonQtObjectPtr result;
1818 PythonQt::self()->clearError();
1821 PythonQt::self()->clearError();
1819 if (pycode) {
1822 if (pycode) {
1820 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1823 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1821 } else {
1824 } else {
1822 PythonQt::self()->handleError();
1825 PythonQt::self()->handleError();
1823 }
1826 }
1824 return result;
1827 return result;
1825 }
1828 }
1826
1829
1827 void* PythonQtPrivate::unwrapForeignWrapper( const QByteArray& classname, PyObject* obj )
1830 void* PythonQtPrivate::unwrapForeignWrapper( const QByteArray& classname, PyObject* obj )
1828 {
1831 {
1829 void* foreignObject = NULL;
1832 void* foreignObject = NULL;
1830 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
1833 for (int i=0; i<_foreignWrapperFactories.size(); i++) {
1831 foreignObject = _foreignWrapperFactories.at(i)->unwrap(classname, obj);
1834 foreignObject = _foreignWrapperFactories.at(i)->unwrap(classname, obj);
1832 if (foreignObject) {
1835 if (foreignObject) {
1833 return foreignObject;
1836 return foreignObject;
1834 }
1837 }
1835 }
1838 }
1836 return NULL;
1839 return NULL;
1837 }
1840 }
1838
1841
1839 bool PythonQtPrivate::isMethodDescriptor(PyObject* object) const
1842 bool PythonQtPrivate::isMethodDescriptor(PyObject* object) const
1840 {
1843 {
1841 // This implementation is the same as in inspect.ismethoddescriptor(), inspect.py.
1844 // This implementation is the same as in inspect.ismethoddescriptor(), inspect.py.
1842 if (PyObject_HasAttrString(object, "__get__") &&
1845 if (PyObject_HasAttrString(object, "__get__") &&
1843 !PyObject_HasAttrString(object, "__set__") &&
1846 !PyObject_HasAttrString(object, "__set__") &&
1844 !PyMethod_Check(object) &&
1847 !PyMethod_Check(object) &&
1845 !PyFunction_Check(object)
1848 !PyFunction_Check(object)
1846 #ifndef PY3K
1849 #ifndef PY3K
1847 && !PyClass_Check(object)
1850 && !PyClass_Check(object)
1848 #endif
1851 #endif
1849 ) {
1852 ) {
1850 return true;
1853 return true;
1851 }
1854 }
1852 return false;
1855 return false;
1853 }
1856 }
1854
1857
1855 QString PythonQtPrivate::getSignature(PyObject* object)
1858 QString PythonQtPrivate::getSignature(PyObject* object)
1856 {
1859 {
1857 QString signature;
1860 QString signature;
1858
1861
1859 if (object) {
1862 if (object) {
1860 PyMethodObject* method = NULL;
1863 PyMethodObject* method = NULL;
1861 PyFunctionObject* func = NULL;
1864 PyFunctionObject* func = NULL;
1862
1865
1863 bool decrefMethod = false;
1866 bool decrefMethod = false;
1864
1867
1865 #ifdef PY3K
1868 #ifdef PY3K
1866 if (PyType_Check(object)) {
1869 if (PyType_Check(object)) {
1867 #else
1870 #else
1868 if (object->ob_type == &PyClass_Type || object->ob_type == &PyType_Type) {
1871 if (object->ob_type == &PyClass_Type || object->ob_type == &PyType_Type) {
1869 #endif
1872 #endif
1870 method = (PyMethodObject*)PyObject_GetAttrString(object, "__init__");
1873 method = (PyMethodObject*)PyObject_GetAttrString(object, "__init__");
1871 decrefMethod = true;
1874 decrefMethod = true;
1872 } else if (object->ob_type == &PyFunction_Type) {
1875 } else if (object->ob_type == &PyFunction_Type) {
1873 func = (PyFunctionObject*)object;
1876 func = (PyFunctionObject*)object;
1874 } else if (object->ob_type == &PyMethod_Type) {
1877 } else if (object->ob_type == &PyMethod_Type) {
1875 method = (PyMethodObject*)object;
1878 method = (PyMethodObject*)object;
1876 }
1879 }
1877 if (method) {
1880 if (method) {
1878 if (PyFunction_Check(method->im_func)) {
1881 if (PyFunction_Check(method->im_func)) {
1879 func = (PyFunctionObject*)method->im_func;
1882 func = (PyFunctionObject*)method->im_func;
1880 } else if (isMethodDescriptor((PyObject*)method)) {
1883 } else if (isMethodDescriptor((PyObject*)method)) {
1881 QString docstr;
1884 QString docstr;
1882 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
1885 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
1883 if (doc) {
1886 if (doc) {
1884 #ifdef PY3K
1887 #ifdef PY3K
1885 docstr = PyUnicode_AsUTF8(doc);
1888 docstr = PyUnicode_AsUTF8(doc);
1886 #else
1889 #else
1887 docstr = PyString_AsString(doc);
1890 docstr = PyString_AsString(doc);
1888 #endif
1891 #endif
1889 Py_DECREF(doc);
1892 Py_DECREF(doc);
1890 }
1893 }
1891
1894
1892 PyObject* s = PyObject_GetAttrString(object, "__name__");
1895 PyObject* s = PyObject_GetAttrString(object, "__name__");
1893 if (s) {
1896 if (s) {
1894 #ifdef PY3K
1897 #ifdef PY3K
1895 Q_ASSERT(PyUnicode_Check(s));
1898 Q_ASSERT(PyUnicode_Check(s));
1896 signature = PyUnicode_AsUTF8(s);
1899 signature = PyUnicode_AsUTF8(s);
1897 #else
1900 #else
1898 Q_ASSERT(PyString_Check(s));
1901 Q_ASSERT(PyString_Check(s));
1899 signature = PyString_AsString(s);
1902 signature = PyString_AsString(s);
1900 #endif
1903 #endif
1901 if (docstr.startsWith(signature + "(")) {
1904 if (docstr.startsWith(signature + "(")) {
1902 signature = docstr;
1905 signature = docstr;
1903 } else {
1906 } else {
1904 signature += "(...)";
1907 signature += "(...)";
1905 if (!docstr.isEmpty()) {
1908 if (!docstr.isEmpty()) {
1906 signature += "\n\n" + docstr;
1909 signature += "\n\n" + docstr;
1907 }
1910 }
1908 }
1911 }
1909 Py_DECREF(s);
1912 Py_DECREF(s);
1910 }
1913 }
1911 }
1914 }
1912 }
1915 }
1913
1916
1914 if (func) {
1917 if (func) {
1915 QString funcName;
1918 QString funcName;
1916 PyObject* s = PyObject_GetAttrString((PyObject*)func, "__name__");
1919 PyObject* s = PyObject_GetAttrString((PyObject*)func, "__name__");
1917 if (s) {
1920 if (s) {
1918 #ifdef PY3K
1921 #ifdef PY3K
1919 Q_ASSERT(PyUnicode_Check(s));
1922 Q_ASSERT(PyUnicode_Check(s));
1920 funcName = PyUnicode_AsUTF8(s);
1923 funcName = PyUnicode_AsUTF8(s);
1921 #else
1924 #else
1922 Q_ASSERT(PyString_Check(s));
1925 Q_ASSERT(PyString_Check(s));
1923 funcName = PyString_AsString(s);
1926 funcName = PyString_AsString(s);
1924 #endif
1927 #endif
1925 Py_DECREF(s);
1928 Py_DECREF(s);
1926 }
1929 }
1927 if (method && funcName == "__init__") {
1930 if (method && funcName == "__init__") {
1928 PyObject* s = PyObject_GetAttrString(object, "__name__");
1931 PyObject* s = PyObject_GetAttrString(object, "__name__");
1929 if (s) {
1932 if (s) {
1930 #ifdef PY3K
1933 #ifdef PY3K
1931 Q_ASSERT(PyUnicode_Check(s));
1934 Q_ASSERT(PyUnicode_Check(s));
1932 funcName = PyUnicode_AsUTF8(s);
1935 funcName = PyUnicode_AsUTF8(s);
1933 #else
1936 #else
1934 Q_ASSERT(PyString_Check(s));
1937 Q_ASSERT(PyString_Check(s));
1935 funcName = PyString_AsString(s);
1938 funcName = PyString_AsString(s);
1936 #endif
1939 #endif
1937 Py_DECREF(s);
1940 Py_DECREF(s);
1938 }
1941 }
1939 }
1942 }
1940
1943
1941 QStringList arguments;
1944 QStringList arguments;
1942 QStringList defaults;
1945 QStringList defaults;
1943 QString varargs;
1946 QString varargs;
1944 QString varkeywords;
1947 QString varkeywords;
1945 // NOTE: This implementation is based on function getargs() in inspect.py.
1948 // NOTE: This implementation is based on function getargs() in inspect.py.
1946 // inspect.getargs() can handle anonymous (tuple) arguments, while this code does not.
1949 // inspect.getargs() can handle anonymous (tuple) arguments, while this code does not.
1947 // It can be implemented, but it may be rarely needed and not necessary.
1950 // It can be implemented, but it may be rarely needed and not necessary.
1948 PyCodeObject* code = (PyCodeObject*)func->func_code;
1951 PyCodeObject* code = (PyCodeObject*)func->func_code;
1949 if (code->co_varnames) {
1952 if (code->co_varnames) {
1950 int nargs = code->co_argcount;
1953 int nargs = code->co_argcount;
1951 Q_ASSERT(PyTuple_Check(code->co_varnames));
1954 Q_ASSERT(PyTuple_Check(code->co_varnames));
1952 for (int i=0; i<nargs; i++) {
1955 for (int i=0; i<nargs; i++) {
1953 PyObject* name = PyTuple_GetItem(code->co_varnames, i);
1956 PyObject* name = PyTuple_GetItem(code->co_varnames, i);
1954 #ifdef PY3K
1957 #ifdef PY3K
1955 Q_ASSERT(PyUnicode_Check(name));
1958 Q_ASSERT(PyUnicode_Check(name));
1956 arguments << PyUnicode_AsUTF8(name);
1959 arguments << PyUnicode_AsUTF8(name);
1957 #else
1960 #else
1958 Q_ASSERT(PyString_Check(name));
1961 Q_ASSERT(PyString_Check(name));
1959 arguments << PyString_AsString(name);
1962 arguments << PyString_AsString(name);
1960 #endif
1963 #endif
1961 }
1964 }
1962 if (code->co_flags & CO_VARARGS) {
1965 if (code->co_flags & CO_VARARGS) {
1963 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1966 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1964 #ifdef PY3K
1967 #ifdef PY3K
1965 Q_ASSERT(PyUnicode_Check(s));
1968 Q_ASSERT(PyUnicode_Check(s));
1966 varargs = PyUnicode_AsUTF8(s);
1969 varargs = PyUnicode_AsUTF8(s);
1967 #else
1970 #else
1968 Q_ASSERT(PyString_Check(s));
1971 Q_ASSERT(PyString_Check(s));
1969 varargs = PyString_AsString(s);
1972 varargs = PyString_AsString(s);
1970 #endif
1973 #endif
1971 nargs += 1;
1974 nargs += 1;
1972 }
1975 }
1973 if (code->co_flags & CO_VARKEYWORDS) {
1976 if (code->co_flags & CO_VARKEYWORDS) {
1974 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1977 PyObject* s = PyTuple_GetItem(code->co_varnames, nargs);
1975 #ifdef PY3K
1978 #ifdef PY3K
1976 Q_ASSERT(PyUnicode_Check(s));
1979 Q_ASSERT(PyUnicode_Check(s));
1977 varkeywords = PyUnicode_AsUTF8(s);
1980 varkeywords = PyUnicode_AsUTF8(s);
1978 #else
1981 #else
1979 Q_ASSERT(PyString_Check(s));
1982 Q_ASSERT(PyString_Check(s));
1980 varkeywords = PyString_AsString(s);
1983 varkeywords = PyString_AsString(s);
1981 #endif
1984 #endif
1982 }
1985 }
1983 }
1986 }
1984
1987
1985 PyObject* defaultsTuple = func->func_defaults;
1988 PyObject* defaultsTuple = func->func_defaults;
1986 if (defaultsTuple) {
1989 if (defaultsTuple) {
1987 Q_ASSERT(PyTuple_Check(defaultsTuple));
1990 Q_ASSERT(PyTuple_Check(defaultsTuple));
1988 for (Py_ssize_t i=0; i<PyTuple_Size(defaultsTuple); i++) {
1991 for (Py_ssize_t i=0; i<PyTuple_Size(defaultsTuple); i++) {
1989 PyObject* d = PyTuple_GetItem(defaultsTuple, i);
1992 PyObject* d = PyTuple_GetItem(defaultsTuple, i);
1990 PyObject* s = PyObject_Repr(d);
1993 PyObject* s = PyObject_Repr(d);
1991 #ifdef PY3K
1994 #ifdef PY3K
1992 Q_ASSERT(PyUnicode_Check(s));
1995 Q_ASSERT(PyUnicode_Check(s));
1993 defaults << PyUnicode_AsUTF8(s);
1996 defaults << PyUnicode_AsUTF8(s);
1994 #else
1997 #else
1995 Q_ASSERT(PyString_Check(s));
1998 Q_ASSERT(PyString_Check(s));
1996 defaults << PyString_AsString(s);
1999 defaults << PyString_AsString(s);
1997 #endif
2000 #endif
1998 Py_DECREF(s);
2001 Py_DECREF(s);
1999 }
2002 }
2000 }
2003 }
2001
2004
2002 int firstdefault = arguments.size() - defaults.size();
2005 int firstdefault = arguments.size() - defaults.size();
2003 for (int i=0; i<arguments.size(); i++) {
2006 for (int i=0; i<arguments.size(); i++) {
2004 if (!signature.isEmpty()) { signature += ", "; }
2007 if (!signature.isEmpty()) { signature += ", "; }
2005 if (!method || i>0 || arguments[i] != "self") {
2008 if (!method || i>0 || arguments[i] != "self") {
2006 signature += arguments[i];
2009 signature += arguments[i];
2007 if (i >= firstdefault) {
2010 if (i >= firstdefault) {
2008 signature += "=" + defaults[i-firstdefault];
2011 signature += "=" + defaults[i-firstdefault];
2009 }
2012 }
2010 }
2013 }
2011 }
2014 }
2012 if (!varargs.isEmpty()) {
2015 if (!varargs.isEmpty()) {
2013 if (!signature.isEmpty()) { signature += ", "; }
2016 if (!signature.isEmpty()) { signature += ", "; }
2014 signature += "*" + varargs;
2017 signature += "*" + varargs;
2015 }
2018 }
2016 if (!varkeywords.isEmpty()) {
2019 if (!varkeywords.isEmpty()) {
2017 if (!signature.isEmpty()) { signature += ", "; }
2020 if (!signature.isEmpty()) { signature += ", "; }
2018 signature += "**" + varkeywords;
2021 signature += "**" + varkeywords;
2019 }
2022 }
2020 signature = funcName + "(" + signature + ")";
2023 signature = funcName + "(" + signature + ")";
2021 }
2024 }
2022
2025
2023 if (method && decrefMethod) {
2026 if (method && decrefMethod) {
2024 Py_DECREF(method);
2027 Py_DECREF(method);
2025 }
2028 }
2026 }
2029 }
2027
2030
2028 return signature;
2031 return signature;
2029 }
2032 }
2030
2033
2031 void PythonQtPrivate::shellClassDeleted( void* shellClass )
2034 void PythonQtPrivate::shellClassDeleted( void* shellClass )
2032 {
2035 {
2033 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(shellClass);
2036 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(shellClass);
2034 if (wrap && wrap->_wrappedPtr) {
2037 if (wrap && wrap->_wrappedPtr) {
2035 // this is a pure C++ wrapper and the shell has gone, so we need
2038 // this is a pure C++ wrapper and the shell has gone, so we need
2036 // to set the _wrappedPtr to NULL on the wrapper
2039 // to set the _wrappedPtr to NULL on the wrapper
2037 wrap->_wrappedPtr = NULL;
2040 wrap->_wrappedPtr = NULL;
2038 // and then we remove the wrapper, since the wrapped class is gone
2041 // and then we remove the wrapper, since the wrapped class is gone
2039 _wrappedObjects.remove(shellClass);
2042 _wrappedObjects.remove(shellClass);
2040 }
2043 }
2041 // if the wrapper is a QObject, we do not handle this here,
2044 // if the wrapper is a QObject, we do not handle this here,
2042 // it will be handled by the QPointer<> to the QObject, which becomes NULL
2045 // it will be handled by the QPointer<> to the QObject, which becomes NULL
2043 // via the QObject destructor.
2046 // via the QObject destructor.
2044 }
2047 }
2045
2048
2046 PyObject* PythonQtPrivate::wrapMemoryAsBuffer( const void* data, Py_ssize_t size )
2049 PyObject* PythonQtPrivate::wrapMemoryAsBuffer( const void* data, Py_ssize_t size )
2047 {
2050 {
2048 // P3K port needed later on! -- not anymore :D
2051 // P3K port needed later on! -- not anymore :D
2049 #ifdef PY3K
2052 #ifdef PY3K
2050 return PyMemoryView_FromMemory((char*)data, size, PyBUF_READ);
2053 return PyMemoryView_FromMemory((char*)data, size, PyBUF_READ);
2051 #else
2054 #else
2052 return PyBuffer_FromMemory((char*)data, size);
2055 return PyBuffer_FromMemory((char*)data, size);
2053 #endif
2056 #endif
2054 }
2057 }
2055
2058
2056 PyObject* PythonQtPrivate::wrapMemoryAsBuffer( void* data, Py_ssize_t size )
2059 PyObject* PythonQtPrivate::wrapMemoryAsBuffer( void* data, Py_ssize_t size )
2057 {
2060 {
2058 // P3K port needed later on! -- not anymore :D
2061 // P3K port needed later on! -- not anymore :D
2059 #ifdef PY3K
2062 #ifdef PY3K
2060 return PyMemoryView_FromMemory((char*)data, size, PyBUF_READ | PyBUF_WRITE);
2063 return PyMemoryView_FromMemory((char*)data, size, PyBUF_READ | PyBUF_WRITE);
2061 #else
2064 #else
2062 return PyBuffer_FromReadWriteMemory((char*)data, size);
2065 return PyBuffer_FromReadWriteMemory((char*)data, size);
2063 #endif
2066 #endif
2064 }
2067 }
@@ -1,504 +1,504
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, 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 PythonQtClassWrapper.cpp
35 // \file PythonQtClassWrapper.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 "PythonQtClassWrapper.h"
42 #include "PythonQtClassWrapper.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 "PythonQtSignal.h"
47 #include "PythonQtSignal.h"
48 #include "PythonQtClassInfo.h"
48 #include "PythonQtClassInfo.h"
49 #include "PythonQtConversion.h"
49 #include "PythonQtConversion.h"
50 #include "PythonQtInstanceWrapper.h"
50 #include "PythonQtInstanceWrapper.h"
51
51
52 static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper)
52 static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper)
53 {
53 {
54 PyObject* result = NULL;
54 PyObject* result = NULL;
55 static QByteArray memberName = "__invert__";
55 static QByteArray memberName = "__invert__";
56 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
56 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
57 if (opSlot._type == PythonQtMemberInfo::Slot) {
57 if (opSlot._type == PythonQtMemberInfo::Slot) {
58 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
58 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
59 }
59 }
60 return result;
60 return result;
61 }
61 }
62
62
63 static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper)
63 static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper)
64 {
64 {
65 int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
65 int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
66 if (result) {
66 if (result) {
67 static QByteArray memberName = "__nonzero__";
67 static QByteArray memberName = "__nonzero__";
68 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
68 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
69 if (opSlot._type == PythonQtMemberInfo::Slot) {
69 if (opSlot._type == PythonQtMemberInfo::Slot) {
70 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
70 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
71 if (resultObj == Py_False) {
71 if (resultObj == Py_False) {
72 result = 0;
72 result = 0;
73 }
73 }
74 Py_XDECREF(resultObj);
74 Py_XDECREF(resultObj);
75 }
75 }
76 }
76 }
77 return result;
77 return result;
78 }
78 }
79
79
80
80
81 static PyObject* PythonQtInstanceWrapper_binaryfunc(PyObject* self, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray())
81 static PyObject* PythonQtInstanceWrapper_binaryfunc(PyObject* self, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray())
82 {
82 {
83 // since we disabled type checking, we can receive any object as self, but we currently only support
83 // since we disabled type checking, we can receive any object as self, but we currently only support
84 // different objects on the right. Otherwise we would need to generate __radd__ etc. methods.
84 // different objects on the right. Otherwise we would need to generate __radd__ etc. methods.
85 if (!PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
85 if (!PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
86 QString error = "Unsupported operation " + opName + "(" + self->ob_type->tp_name + ", " + other->ob_type->tp_name + ")";
86 QString error = "Unsupported operation " + opName + "(" + self->ob_type->tp_name + ", " + other->ob_type->tp_name + ")";
87 PyErr_SetString(PyExc_ArithmeticError, error.toLatin1().data());
87 PyErr_SetString(PyExc_ArithmeticError, error.toLatin1().data());
88 return NULL;
88 return NULL;
89 }
89 }
90 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
90 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
91 PyObject* result = NULL;
91 PyObject* result = NULL;
92 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName);
92 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName);
93 if (opSlot._type == PythonQtMemberInfo::Slot) {
93 if (opSlot._type == PythonQtMemberInfo::Slot) {
94 // TODO get rid of tuple
94 // TODO get rid of tuple
95 PyObject* args = PyTuple_New(1);
95 PyObject* args = PyTuple_New(1);
96 Py_INCREF(other);
96 Py_INCREF(other);
97 PyTuple_SET_ITEM(args, 0, other);
97 PyTuple_SET_ITEM(args, 0, other);
98 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
98 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
99 Py_DECREF(args);
99 Py_DECREF(args);
100 if (!result && !fallbackOpName.isEmpty()) {
100 if (!result && !fallbackOpName.isEmpty()) {
101 // try fallback if we did not get a result
101 // try fallback if we did not get a result
102 result = PythonQtInstanceWrapper_binaryfunc(self, other, fallbackOpName);
102 result = PythonQtInstanceWrapper_binaryfunc(self, other, fallbackOpName);
103 }
103 }
104 }
104 }
105 return result;
105 return result;
106 }
106 }
107
107
108 #define BINARY_OP(NAME) \
108 #define BINARY_OP(NAME) \
109 static PyObject* PythonQtInstanceWrapper_ ## NAME(PyObject* self, PyObject* other) \
109 static PyObject* PythonQtInstanceWrapper_ ## NAME(PyObject* self, PyObject* other) \
110 { \
110 { \
111 static const QByteArray opName("__" #NAME "__"); \
111 static const QByteArray opName("__" #NAME "__"); \
112 return PythonQtInstanceWrapper_binaryfunc(self, other, opName); \
112 return PythonQtInstanceWrapper_binaryfunc(self, other, opName); \
113 }
113 }
114
114
115 #define BINARY_OP_INPLACE(NAME) \
115 #define BINARY_OP_INPLACE(NAME) \
116 static PyObject* PythonQtInstanceWrapper_i ## NAME(PyObject* self, PyObject* other) \
116 static PyObject* PythonQtInstanceWrapper_i ## NAME(PyObject* self, PyObject* other) \
117 { \
117 { \
118 static const QByteArray opName("__i" #NAME "__"); \
118 static const QByteArray opName("__i" #NAME "__"); \
119 static const QByteArray fallbackName("__" #NAME "__"); \
119 static const QByteArray fallbackName("__" #NAME "__"); \
120 return PythonQtInstanceWrapper_binaryfunc(self, other, opName, fallbackName); \
120 return PythonQtInstanceWrapper_binaryfunc(self, other, opName, fallbackName); \
121 }
121 }
122
122
123 BINARY_OP(add)
123 BINARY_OP(add)
124 BINARY_OP(sub)
124 BINARY_OP(sub)
125 BINARY_OP(mul)
125 BINARY_OP(mul)
126 BINARY_OP(div)
126 BINARY_OP(div)
127 BINARY_OP(and)
127 BINARY_OP(and)
128 BINARY_OP(or)
128 BINARY_OP(or)
129 BINARY_OP(xor)
129 BINARY_OP(xor)
130 BINARY_OP(mod)
130 BINARY_OP(mod)
131 BINARY_OP(lshift)
131 BINARY_OP(lshift)
132 BINARY_OP(rshift)
132 BINARY_OP(rshift)
133
133
134 BINARY_OP_INPLACE(add)
134 BINARY_OP_INPLACE(add)
135 BINARY_OP_INPLACE(sub)
135 BINARY_OP_INPLACE(sub)
136 BINARY_OP_INPLACE(mul)
136 BINARY_OP_INPLACE(mul)
137 BINARY_OP_INPLACE(div)
137 BINARY_OP_INPLACE(div)
138 BINARY_OP_INPLACE(and)
138 BINARY_OP_INPLACE(and)
139 BINARY_OP_INPLACE(or)
139 BINARY_OP_INPLACE(or)
140 BINARY_OP_INPLACE(xor)
140 BINARY_OP_INPLACE(xor)
141 BINARY_OP_INPLACE(mod)
141 BINARY_OP_INPLACE(mod)
142 BINARY_OP_INPLACE(lshift)
142 BINARY_OP_INPLACE(lshift)
143 BINARY_OP_INPLACE(rshift)
143 BINARY_OP_INPLACE(rshift)
144
144
145 static void initializeSlots(PythonQtClassWrapper* wrap)
145 static void initializeSlots(PythonQtClassWrapper* wrap)
146 {
146 {
147 int typeSlots = wrap->classInfo()->typeSlots();
147 int typeSlots = wrap->classInfo()->typeSlots();
148 if (typeSlots) {
148 if (typeSlots) {
149 if (typeSlots & PythonQt::Type_Add) {
149 if (typeSlots & PythonQt::Type_Add) {
150 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_add;
150 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_add;
151 }
151 }
152 if (typeSlots & PythonQt::Type_Subtract) {
152 if (typeSlots & PythonQt::Type_Subtract) {
153 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_sub;
153 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_sub;
154 }
154 }
155 if (typeSlots & PythonQt::Type_Multiply) {
155 if (typeSlots & PythonQt::Type_Multiply) {
156 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul;
156 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul;
157 }
157 }
158 if (typeSlots & PythonQt::Type_Divide) {
158 if (typeSlots & PythonQt::Type_Divide) {
159 #ifndef PY3K
159 #ifndef PY3K
160 wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div;
160 wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div;
161 #endif
161 #endif
162 wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div;
162 wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div;
163 }
163 }
164 if (typeSlots & PythonQt::Type_And) {
164 if (typeSlots & PythonQt::Type_And) {
165 wrap->_base.as_number.nb_and = (binaryfunc)PythonQtInstanceWrapper_and;
165 wrap->_base.as_number.nb_and = (binaryfunc)PythonQtInstanceWrapper_and;
166 }
166 }
167 if (typeSlots & PythonQt::Type_Or) {
167 if (typeSlots & PythonQt::Type_Or) {
168 wrap->_base.as_number.nb_or = (binaryfunc)PythonQtInstanceWrapper_or;
168 wrap->_base.as_number.nb_or = (binaryfunc)PythonQtInstanceWrapper_or;
169 }
169 }
170 if (typeSlots & PythonQt::Type_Xor) {
170 if (typeSlots & PythonQt::Type_Xor) {
171 wrap->_base.as_number.nb_xor = (binaryfunc)PythonQtInstanceWrapper_xor;
171 wrap->_base.as_number.nb_xor = (binaryfunc)PythonQtInstanceWrapper_xor;
172 }
172 }
173 if (typeSlots & PythonQt::Type_Mod) {
173 if (typeSlots & PythonQt::Type_Mod) {
174 wrap->_base.as_number.nb_remainder = (binaryfunc)PythonQtInstanceWrapper_mod;
174 wrap->_base.as_number.nb_remainder = (binaryfunc)PythonQtInstanceWrapper_mod;
175 }
175 }
176 if (typeSlots & PythonQt::Type_LShift) {
176 if (typeSlots & PythonQt::Type_LShift) {
177 wrap->_base.as_number.nb_lshift = (binaryfunc)PythonQtInstanceWrapper_lshift;
177 wrap->_base.as_number.nb_lshift = (binaryfunc)PythonQtInstanceWrapper_lshift;
178 }
178 }
179 if (typeSlots & PythonQt::Type_RShift) {
179 if (typeSlots & PythonQt::Type_RShift) {
180 wrap->_base.as_number.nb_rshift = (binaryfunc)PythonQtInstanceWrapper_rshift;
180 wrap->_base.as_number.nb_rshift = (binaryfunc)PythonQtInstanceWrapper_rshift;
181 }
181 }
182
182
183 if (typeSlots & PythonQt::Type_InplaceAdd) {
183 if (typeSlots & PythonQt::Type_InplaceAdd) {
184 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_iadd;
184 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_iadd;
185 }
185 }
186 if (typeSlots & PythonQt::Type_InplaceSubtract) {
186 if (typeSlots & PythonQt::Type_InplaceSubtract) {
187 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_isub;
187 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_isub;
188 }
188 }
189 if (typeSlots & PythonQt::Type_InplaceMultiply) {
189 if (typeSlots & PythonQt::Type_InplaceMultiply) {
190 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul;
190 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul;
191 }
191 }
192 if (typeSlots & PythonQt::Type_InplaceDivide) {
192 if (typeSlots & PythonQt::Type_InplaceDivide) {
193 #ifndef PY3K
193 #ifndef PY3K
194 wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
194 wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
195 #endif
195 #endif
196 wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
196 wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
197 }
197 }
198 if (typeSlots & PythonQt::Type_InplaceAnd) {
198 if (typeSlots & PythonQt::Type_InplaceAnd) {
199 wrap->_base.as_number.nb_inplace_and = (binaryfunc)PythonQtInstanceWrapper_iand;
199 wrap->_base.as_number.nb_inplace_and = (binaryfunc)PythonQtInstanceWrapper_iand;
200 }
200 }
201 if (typeSlots & PythonQt::Type_InplaceOr) {
201 if (typeSlots & PythonQt::Type_InplaceOr) {
202 wrap->_base.as_number.nb_inplace_or = (binaryfunc)PythonQtInstanceWrapper_ior;
202 wrap->_base.as_number.nb_inplace_or = (binaryfunc)PythonQtInstanceWrapper_ior;
203 }
203 }
204 if (typeSlots & PythonQt::Type_InplaceXor) {
204 if (typeSlots & PythonQt::Type_InplaceXor) {
205 wrap->_base.as_number.nb_inplace_xor = (binaryfunc)PythonQtInstanceWrapper_ixor;
205 wrap->_base.as_number.nb_inplace_xor = (binaryfunc)PythonQtInstanceWrapper_ixor;
206 }
206 }
207 if (typeSlots & PythonQt::Type_InplaceMod) {
207 if (typeSlots & PythonQt::Type_InplaceMod) {
208 wrap->_base.as_number.nb_inplace_remainder = (binaryfunc)PythonQtInstanceWrapper_imod;
208 wrap->_base.as_number.nb_inplace_remainder = (binaryfunc)PythonQtInstanceWrapper_imod;
209 }
209 }
210 if (typeSlots & PythonQt::Type_InplaceLShift) {
210 if (typeSlots & PythonQt::Type_InplaceLShift) {
211 wrap->_base.as_number.nb_inplace_lshift = (binaryfunc)PythonQtInstanceWrapper_ilshift;
211 wrap->_base.as_number.nb_inplace_lshift = (binaryfunc)PythonQtInstanceWrapper_ilshift;
212 }
212 }
213 if (typeSlots & PythonQt::Type_InplaceRShift) {
213 if (typeSlots & PythonQt::Type_InplaceRShift) {
214 wrap->_base.as_number.nb_inplace_rshift = (binaryfunc)PythonQtInstanceWrapper_irshift;
214 wrap->_base.as_number.nb_inplace_rshift = (binaryfunc)PythonQtInstanceWrapper_irshift;
215 }
215 }
216 if (typeSlots & PythonQt::Type_Invert) {
216 if (typeSlots & PythonQt::Type_Invert) {
217 wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert;
217 wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert;
218 }
218 }
219 if (typeSlots & PythonQt::Type_NonZero) {
219 if (typeSlots & PythonQt::Type_NonZero) {
220 #ifdef PY3K
220 #ifdef PY3K
221 wrap->_base.as_number.nb_bool = (inquiry)PythonQtInstanceWrapper_nonzero;
221 wrap->_base.as_number.nb_bool = (inquiry)PythonQtInstanceWrapper_nonzero;
222 #else
222 #else
223 wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero;
223 wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero;
224 #endif
224 #endif
225 }
225 }
226 }
226 }
227 }
227 }
228
228
229 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
229 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
230 {
230 {
231 // call the default type alloc
231 // call the default type alloc
232 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
232 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
233
233
234 // take current class type, if we are called via newPythonQtClassWrapper()
234 // take current class type, if we are called via newPythonQtClassWrapper()
235 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
235 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
236 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
236 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
237 if (wrap->_classInfo) {
237 if (wrap->_classInfo) {
238 initializeSlots(wrap);
238 initializeSlots(wrap);
239 }
239 }
240
240
241 return obj;
241 return obj;
242 }
242 }
243
243
244
244
245 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
245 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
246 {
246 {
247 // call the default type init
247 // call the default type init
248 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
248 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
249 return -1;
249 return -1;
250 }
250 }
251
251
252 // if we have no CPP class information, try our base class
252 // if we have no CPP class information, try our base class
253 if (!self->classInfo()) {
253 if (!self->classInfo()) {
254 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
254 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
255
255
256 // recursively search for PythonQtClassWrapper superclass,
256 // recursively search for PythonQtClassWrapper superclass,
257 // this is needed for multiple levels of inheritance in python,
257 // this is needed for multiple levels of inheritance in python,
258 // e.g.
258 // e.g.
259 // class MyWidgetBase(QWidget):
259 // class MyWidgetBase(QWidget):
260 // ...
260 // ...
261 // class MyWidget(MyWidgetBase):
261 // class MyWidget(MyWidgetBase):
262 // ...
262 // ...
263 while( superType && Py_TYPE(superType) != &PythonQtClassWrapper_Type )
263 while( superType && Py_TYPE(superType) != &PythonQtClassWrapper_Type )
264 superType = superType->tp_base;
264 superType = superType->tp_base;
265
265
266 if (!superType || (Py_TYPE(superType) != &PythonQtClassWrapper_Type)) {
266 if (!superType || (Py_TYPE(superType) != &PythonQtClassWrapper_Type)) {
267 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
267 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
268 return -1;
268 return -1;
269 }
269 }
270
270
271 // take the class info from the superType
271 // take the class info from the superType
272 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
272 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
273 }
273 }
274
274
275 return 0;
275 return 0;
276 }
276 }
277
277
278 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
278 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
279 {
279 {
280 #ifdef PY3K
280 #ifdef PY3K
281 return PyUnicode_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
281 return PyUnicode_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
282 #else
282 #else
283 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
283 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
284 #endif
284 #endif
285 }
285 }
286
286
287 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
287 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
288 {
288 {
289 return PythonQt::self()->helpCalled(type->classInfo());
289 return PythonQt::self()->helpCalled(type->classInfo());
290 }
290 }
291
291
292 PyObject *PythonQtClassWrapper_delete(PythonQtClassWrapper *type, PyObject *args)
292 PyObject *PythonQtClassWrapper_delete(PythonQtClassWrapper *type, PyObject *args)
293 {
293 {
294 Q_UNUSED(type);
294 Q_UNUSED(type);
295
295
296 Py_ssize_t argc = PyTuple_Size(args);
296 Py_ssize_t argc = PyTuple_Size(args);
297 if (argc>0) {
297 if (argc>0) {
298 PyObject* self = PyTuple_GET_ITEM(args, 0);
298 PyObject* self = PyTuple_GET_ITEM(args, 0);
299 if (PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
299 if (PyObject_TypeCheck(self, &PythonQtInstanceWrapper_Type)) {
300 return PythonQtInstanceWrapper_delete((PythonQtInstanceWrapper*)self);
300 return PythonQtInstanceWrapper_delete((PythonQtInstanceWrapper*)self);
301 }
301 }
302 }
302 }
303 return NULL;
303 return NULL;
304 }
304 }
305
305
306 PyObject *PythonQtClassWrapper_inherits(PythonQtClassWrapper *type, PyObject *args)
306 PyObject *PythonQtClassWrapper_inherits(PythonQtClassWrapper *type, PyObject *args)
307 {
307 {
308 Q_UNUSED(type);
308 Q_UNUSED(type);
309 PythonQtInstanceWrapper* wrapper = NULL;
309 PythonQtInstanceWrapper* wrapper = NULL;
310 char *name = NULL;
310 char *name = NULL;
311 if (!PyArg_ParseTuple(args, "O!s:PythonQtClassWrapper.inherits",&PythonQtInstanceWrapper_Type, &wrapper, &name)) {
311 if (!PyArg_ParseTuple(args, "O!s:PythonQtClassWrapper.inherits",&PythonQtInstanceWrapper_Type, &wrapper, &name)) {
312 return NULL;
312 return NULL;
313 }
313 }
314 return PythonQtConv::GetPyBool(wrapper->classInfo()->inherits(name));
314 return PythonQtConv::GetPyBool(wrapper->classInfo()->inherits(name));
315 }
315 }
316
316
317
317
318 static PyMethodDef PythonQtClassWrapper_methods[] = {
318 static PyMethodDef PythonQtClassWrapper_methods[] = {
319 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
319 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
320 "Return the classname of the object"
320 "Return the classname of the object"
321 },
321 },
322 {"inherits", (PyCFunction)PythonQtClassWrapper_inherits, METH_VARARGS,
322 {"inherits", (PyCFunction)PythonQtClassWrapper_inherits, METH_VARARGS,
323 "Returns if the class inherits or is of given type name"
323 "Returns if the class inherits or is of given type name"
324 },
324 },
325 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
325 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
326 "Shows the help of available methods for this class"
326 "Shows the help of available methods for this class"
327 },
327 },
328 {"delete", (PyCFunction)PythonQtClassWrapper_delete, METH_VARARGS,
328 {"delete", (PyCFunction)PythonQtClassWrapper_delete, METH_VARARGS,
329 "Deletes the given C++ object"
329 "Deletes the given C++ object"
330 },
330 },
331 {NULL, NULL, 0 , NULL} /* Sentinel */
331 {NULL, NULL, 0 , NULL} /* Sentinel */
332 };
332 };
333
333
334
334
335 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
335 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
336 {
336 {
337 const char *attributeName;
337 const char *attributeName;
338 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
338 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
339
339
340 #ifdef PY3K
340 #ifdef PY3K
341 if ((attributeName = PyUnicode_AsUTF8(name)) == NULL) {
341 if ((attributeName = PyUnicode_AsUTF8(name)) == NULL) {
342 #else
342 #else
343 if ((attributeName = PyString_AsString(name)) == NULL) {
343 if ((attributeName = PyString_AsString(name)) == NULL) {
344 #endif
344 #endif
345 return NULL;
345 return NULL;
346 }
346 }
347 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
347 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
348 return NULL;
348 return NULL;
349 }
349 }
350
350
351 if (qstrcmp(attributeName, "__dict__")==0) {
351 if (qstrcmp(attributeName, "__dict__")==0) {
352 PyObject* objectDict = ((PyTypeObject *)wrapper)->tp_dict;
352 PyObject* objectDict = ((PyTypeObject *)wrapper)->tp_dict;
353 if (!wrapper->classInfo()) {
353 if (!wrapper->classInfo()) {
354 Py_INCREF(objectDict);
354 Py_INCREF(objectDict);
355 return objectDict;
355 return objectDict;
356 }
356 }
357 PyObject* dict = PyDict_New();
357 PyObject* dict = PyDict_New();
358
358
359 QStringList l = wrapper->classInfo()->memberList();
359 QStringList l = wrapper->classInfo()->memberList();
360 Q_FOREACH (QString name, l) {
360 Q_FOREACH (QString name, l) {
361 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
361 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
362 if (o) {
362 if (o) {
363 PyDict_SetItemString(dict, name.toLatin1().data(), o);
363 PyDict_SetItemString(dict, name.toLatin1().data(), o);
364 Py_DECREF(o);
364 Py_DECREF(o);
365 } else {
365 } else {
366 // it must have been a property or child, which we do not know as a class object...
366 // it must have been a property or child, which we do not know as a class object...
367 PyErr_Clear();
367 PyErr_Clear();
368 }
368 }
369 }
369 }
370 if (wrapper->classInfo()->constructors()) {
370 if (wrapper->classInfo()->constructors()) {
371 #ifdef PY3K
371 #ifdef PY3K
372 PyObject* initName = PyUnicode_FromString("__init__");
372 PyObject* initName = PyUnicode_FromString("__init__");
373 #else
373 #else
374 PyObject* initName = PyString_FromString("__init__");
374 PyObject* initName = PyString_FromString("__init__");
375 #endif
375 #endif
376 PyObject* func = PyType_Type.tp_getattro(obj, initName);
376 PyObject* func = PyType_Type.tp_getattro(obj, initName);
377 Py_DECREF(initName);
377 Py_DECREF(initName);
378 PyDict_SetItemString(dict, "__init__", func);
378 PyDict_SetItemString(dict, "__init__", func);
379 Py_DECREF(func);
379 Py_DECREF(func);
380 }
380 }
381 for (int i = 0; PythonQtClassWrapper_methods[i].ml_name != NULL; i++) {
381 for (int i = 0; PythonQtClassWrapper_methods[i].ml_name != NULL; i++) {
382 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
382 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
383 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
383 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
384 Py_DECREF(func);
384 Py_DECREF(func);
385 }
385 }
386
386
387 PyDict_Update(dict, objectDict);
387 PyDict_Update(dict, objectDict);
388 return dict;
388 return dict;
389 }
389 }
390
390
391 // look in Python to support derived Python classes
391 // look in Python to support derived Python classes
392 #ifdef PY3K
393 return PyObject_GenericGetAttr(obj, name);
394 #else
395 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
392 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
396 if (superAttr) {
393 if (superAttr) {
397 return superAttr;
394 return superAttr;
398 }
395 }
399 PyErr_Clear();
396 PyErr_Clear();
400
397
401 if (wrapper->classInfo()) {
398 if (wrapper->classInfo()) {
402 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
399 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
403 if (member._type == PythonQtMemberInfo::EnumValue) {
400 if (member._type == PythonQtMemberInfo::EnumValue) {
404 PyObject* enumValue = member._enumValue;
401 PyObject* enumValue = member._enumValue;
405 Py_INCREF(enumValue);
402 Py_INCREF(enumValue);
406 return enumValue;
403 return enumValue;
407 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
404 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
408 PyObject* enumWrapper = member._enumWrapper;
405 PyObject* enumWrapper = member._enumWrapper;
409 Py_INCREF(enumWrapper);
406 Py_INCREF(enumWrapper);
410 return enumWrapper;
407 return enumWrapper;
411 } else if (member._type == PythonQtMemberInfo::Slot) {
408 } else if (member._type == PythonQtMemberInfo::Slot) {
412 // we return all slots, even the instance slots, since they are callable as unbound slots with self argument
409 // we return all slots, even the instance slots, since they are callable as unbound slots with self argument
413 return PythonQtSlotFunction_New(member._slot, obj, NULL);
410 return PythonQtSlotFunction_New(member._slot, obj, NULL);
414 } else if (member._type == PythonQtMemberInfo::Signal) {
411 } else if (member._type == PythonQtMemberInfo::Signal) {
415 // we return all signals, even the instance signals, since they are callable as unbound signals with self argument
412 // we return all signals, even the instance signals, since they are callable as unbound signals with self argument
416 return PythonQtSignalFunction_New(member._slot, obj, NULL);
413 return PythonQtSignalFunction_New(member._slot, obj, NULL);
417 }
414 }
418 }
415 }
419
416
420 // look for the internal methods (className(), help())
417 // look for the internal methods (className(), help())
418 #ifdef PY3K
419 PyObject* internalMethod = PyObject_GenericGetAttr(obj, name);
420 #else
421 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
421 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
422 #endif
422 if (internalMethod) {
423 if (internalMethod) {
423 return internalMethod;
424 return internalMethod;
424 }
425 }
425
426
426 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
427 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
427 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
428 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
428 return NULL;
429 return NULL;
429 #endif
430 }
430 }
431
431
432 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
432 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
433 {
433 {
434 return PyType_Type.tp_setattro(obj,name,value);
434 return PyType_Type.tp_setattro(obj,name,value);
435 }
435 }
436
436
437 /*
437 /*
438 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
438 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
439 {
439 {
440 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
440 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
441 if (wrapper->classInfo()->isCPPWrapper()) {
441 if (wrapper->classInfo()->isCPPWrapper()) {
442 const QMetaObject* meta = wrapper->classInfo()->metaObject();
442 const QMetaObject* meta = wrapper->classInfo()->metaObject();
443 if (!meta) {
443 if (!meta) {
444 QObject* decorator = wrapper->classInfo()->decorator();
444 QObject* decorator = wrapper->classInfo()->decorator();
445 if (decorator) {
445 if (decorator) {
446 meta = decorator->metaObject();
446 meta = decorator->metaObject();
447 }
447 }
448 }
448 }
449 if (meta) {
449 if (meta) {
450 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
450 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
451 } else {
451 } else {
452 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
452 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
453 }
453 }
454 } else {
454 } else {
455 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
455 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
456 }
456 }
457 }
457 }
458
458
459 */
459 */
460
460
461 PyTypeObject PythonQtClassWrapper_Type = {
461 PyTypeObject PythonQtClassWrapper_Type = {
462 PyVarObject_HEAD_INIT(NULL, 0)
462 PyVarObject_HEAD_INIT(NULL, 0)
463 "PythonQt.PythonQtClassWrapper", /*tp_name*/
463 "PythonQt.PythonQtClassWrapper", /*tp_name*/
464 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
464 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
465 0, /*tp_itemsize*/
465 0, /*tp_itemsize*/
466 0, /*tp_dealloc*/
466 0, /*tp_dealloc*/
467 0, /*tp_print*/
467 0, /*tp_print*/
468 0, /*tp_getattr*/
468 0, /*tp_getattr*/
469 0, /*tp_setattr*/
469 0, /*tp_setattr*/
470 0, /*tp_compare*/
470 0, /*tp_compare*/
471 0, //PythonQtClassWrapper_repr, /*tp_repr*/
471 0, //PythonQtClassWrapper_repr, /*tp_repr*/
472 0, /*tp_as_number*/
472 0, /*tp_as_number*/
473 0, /*tp_as_sequence*/
473 0, /*tp_as_sequence*/
474 0, /*tp_as_mapping*/
474 0, /*tp_as_mapping*/
475 0, /*tp_hash */
475 0, /*tp_hash */
476 0, /*tp_call*/
476 0, /*tp_call*/
477 0, /*tp_str*/
477 0, /*tp_str*/
478 PythonQtClassWrapper_getattro, /*tp_getattro*/
478 PythonQtClassWrapper_getattro, /*tp_getattro*/
479 PythonQtClassWrapper_setattro, /*tp_setattro*/
479 PythonQtClassWrapper_setattro, /*tp_setattro*/
480 0, /*tp_as_buffer*/
480 0, /*tp_as_buffer*/
481 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
481 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
482 0, /* tp_doc */
482 0, /* tp_doc */
483 0, /* tp_traverse */
483 0, /* tp_traverse */
484 0, /* tp_clear */
484 0, /* tp_clear */
485 0, /* tp_richcompare */
485 0, /* tp_richcompare */
486 0, /* tp_weaklistoffset */
486 0, /* tp_weaklistoffset */
487 0, /* tp_iter */
487 0, /* tp_iter */
488 0, /* tp_iternext */
488 0, /* tp_iternext */
489 0, /* tp_methods */
489 PythonQtClassWrapper_methods, /* tp_methods */
490 0, /* tp_members */
490 0, /* tp_members */
491 0, /* tp_getset */
491 0, /* tp_getset */
492 0, /* tp_base */
492 0, /* tp_base */
493 0, /* tp_dict */
493 0, /* tp_dict */
494 0, /* tp_descr_get */
494 0, /* tp_descr_get */
495 0, /* tp_descr_set */
495 0, /* tp_descr_set */
496 0, /* tp_dictoffset */
496 0, /* tp_dictoffset */
497 (initproc)PythonQtClassWrapper_init, /* tp_init */
497 (initproc)PythonQtClassWrapper_init, /* tp_init */
498 PythonQtClassWrapper_alloc, /* tp_alloc */
498 PythonQtClassWrapper_alloc, /* tp_alloc */
499 0, /* tp_new */
499 0, /* tp_new */
500 0, /* tp_free */
500 0, /* tp_free */
501 };
501 };
502
502
503 //-------------------------------------------------------
503 //-------------------------------------------------------
504
504
@@ -1,1378 +1,1374
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, 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 <QDateTime>
44 #include <QDateTime>
45 #include <QTime>
45 #include <QTime>
46 #include <QDate>
46 #include <QDate>
47
47
48 #if PY_MAJOR_VERSION >= 3
49 #define PY3K
50 #endif
51
52 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
48 PythonQtValueStorage<qint64, 128> PythonQtConv::global_valueStorage;
53 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
49 PythonQtValueStorage<void*, 128> PythonQtConv::global_ptrStorage;
54 PythonQtValueStorageWithCleanup<QVariant, 128> PythonQtConv::global_variantStorage;
50 PythonQtValueStorageWithCleanup<QVariant, 128> PythonQtConv::global_variantStorage;
55
51
56 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
52 QHash<int, PythonQtConvertMetaTypeToPythonCB*> PythonQtConv::_metaTypeToPythonConverters;
57 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
53 QHash<int, PythonQtConvertPythonToMetaTypeCB*> PythonQtConv::_pythonToMetaTypeConverters;
58
54
59 PyObject* PythonQtConv::GetPyBool(bool val)
55 PyObject* PythonQtConv::GetPyBool(bool val)
60 {
56 {
61 PyObject* r = val?Py_True:Py_False;
57 PyObject* r = val?Py_True:Py_False;
62 Py_INCREF(r);
58 Py_INCREF(r);
63 return r;
59 return r;
64 }
60 }
65
61
66 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
62 PyObject* PythonQtConv::ConvertQtValueToPython(const PythonQtMethodInfo::ParameterInfo& info, const void* data) {
67 // is it an enum value?
63 // is it an enum value?
68 if (info.enumWrapper) {
64 if (info.enumWrapper) {
69 if (info.pointerCount==0) {
65 if (info.pointerCount==0) {
70 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
66 return PythonQtPrivate::createEnumValueInstance(info.enumWrapper, *((unsigned int*)data));
71 } else {
67 } else {
72 // we do not support pointers to enums (who needs them?)
68 // we do not support pointers to enums (who needs them?)
73 Py_INCREF(Py_None);
69 Py_INCREF(Py_None);
74 return Py_None;
70 return Py_None;
75 }
71 }
76 }
72 }
77
73
78 if (info.typeId == QMetaType::Void) {
74 if (info.typeId == QMetaType::Void) {
79 Py_INCREF(Py_None);
75 Py_INCREF(Py_None);
80 return Py_None;
76 return Py_None;
81 } else if ((info.pointerCount == 1) && (info.typeId == QMetaType::Char)) {
77 } else if ((info.pointerCount == 1) && (info.typeId == QMetaType::Char)) {
82 // a char ptr will probably be a null terminated string, so we support that:
78 // a char ptr will probably be a null terminated string, so we support that:
83 char* charPtr = *((char**)data);
79 char* charPtr = *((char**)data);
84 if (charPtr) {
80 if (charPtr) {
85 #ifdef PY3K
81 #ifdef PY3K
86 return PyUnicode_FromString(charPtr);
82 return PyUnicode_FromString(charPtr);
87 #else
83 #else
88 return PyString_FromString(charPtr);
84 return PyString_FromString(charPtr);
89 #endif
85 #endif
90 } else {
86 } else {
91 Py_INCREF(Py_None);
87 Py_INCREF(Py_None);
92 return Py_None;
88 return Py_None;
93 }
89 }
94 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
90 } else if ((info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) &&
95 info.name.startsWith("QList<")) {
91 info.name.startsWith("QList<")) {
96 // it is a QList template:
92 // it is a QList template:
97 QByteArray innerType = info.name.mid(6,info.name.length()-7);
93 QByteArray innerType = info.name.mid(6,info.name.length()-7);
98 if (innerType.endsWith("*")) {
94 if (innerType.endsWith("*")) {
99 innerType.truncate(innerType.length()-1);
95 innerType.truncate(innerType.length()-1);
100 QList<void*>* listPtr = NULL;
96 QList<void*>* listPtr = NULL;
101 if (info.pointerCount == 1) {
97 if (info.pointerCount == 1) {
102 listPtr = *((QList<void*>**)data);
98 listPtr = *((QList<void*>**)data);
103 } else if (info.pointerCount == 0) {
99 } else if (info.pointerCount == 0) {
104 listPtr = (QList<void*>*)data;
100 listPtr = (QList<void*>*)data;
105 }
101 }
106 if (listPtr) {
102 if (listPtr) {
107 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
103 return ConvertQListOfPointerTypeToPythonList(listPtr, innerType);
108 } else {
104 } else {
109 return NULL;
105 return NULL;
110 }
106 }
111 }
107 }
112 }
108 }
113
109
114 if (info.typeId >= QMetaType::User) {
110 if (info.typeId >= QMetaType::User) {
115 // if a converter is registered, we use is:
111 // if a converter is registered, we use is:
116 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
112 PythonQtConvertMetaTypeToPythonCB* converter = _metaTypeToPythonConverters.value(info.typeId);
117 if (converter) {
113 if (converter) {
118 return (*converter)(data, info.typeId);
114 return (*converter)(data, info.typeId);
119 }
115 }
120 }
116 }
121
117
122 // special handling did not match, so we convert the usual way (either pointer or value version):
118 // special handling did not match, so we convert the usual way (either pointer or value version):
123 if (info.pointerCount == 1) {
119 if (info.pointerCount == 1) {
124 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
120 // convert the pointer to a Python Object (we can handle ANY C++ object, in the worst case we just know the type and the pointer)
125 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
121 return PythonQt::priv()->wrapPtr(*((void**)data), info.name);
126 } else if (info.pointerCount == 0) {
122 } else if (info.pointerCount == 0) {
127 // handle values that are not yet handled and not pointers
123 // handle values that are not yet handled and not pointers
128 return ConvertQtValueToPythonInternal(info.typeId, data);
124 return ConvertQtValueToPythonInternal(info.typeId, data);
129 } else {
125 } else {
130 return NULL;
126 return NULL;
131 }
127 }
132 }
128 }
133
129
134 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
130 PyObject* PythonQtConv::ConvertQtValueToPythonInternal(int type, const void* data) {
135 switch (type) {
131 switch (type) {
136 case QMetaType::Void:
132 case QMetaType::Void:
137 Py_INCREF(Py_None);
133 Py_INCREF(Py_None);
138 return Py_None;
134 return Py_None;
139 case QMetaType::Char:
135 case QMetaType::Char:
140 return PyLong_FromLong(*((char*)data));
136 return PyLong_FromLong(*((char*)data));
141 case QMetaType::UChar:
137 case QMetaType::UChar:
142 return PyLong_FromLong(*((unsigned char*)data));
138 return PyLong_FromLong(*((unsigned char*)data));
143 case QMetaType::Short:
139 case QMetaType::Short:
144 return PyLong_FromLong(*((short*)data));
140 return PyLong_FromLong(*((short*)data));
145 case QMetaType::UShort:
141 case QMetaType::UShort:
146 return PyLong_FromLong(*((unsigned short*)data));
142 return PyLong_FromLong(*((unsigned short*)data));
147 case QMetaType::Long:
143 case QMetaType::Long:
148 return PyLong_FromLong(*((long*)data));
144 return PyLong_FromLong(*((long*)data));
149 case QMetaType::ULong:
145 case QMetaType::ULong:
150 // does not fit into simple int of python
146 // does not fit into simple int of python
151 return PyLong_FromUnsignedLong(*((unsigned long*)data));
147 return PyLong_FromUnsignedLong(*((unsigned long*)data));
152 case QMetaType::Bool:
148 case QMetaType::Bool:
153 return PythonQtConv::GetPyBool(*((bool*)data));
149 return PythonQtConv::GetPyBool(*((bool*)data));
154 case QMetaType::Int:
150 case QMetaType::Int:
155 return PyLong_FromLong(*((int*)data));
151 return PyLong_FromLong(*((int*)data));
156 case QMetaType::UInt:
152 case QMetaType::UInt:
157 // does not fit into simple int of python
153 // does not fit into simple int of python
158 return PyLong_FromUnsignedLong(*((unsigned int*)data));
154 return PyLong_FromUnsignedLong(*((unsigned int*)data));
159 case QMetaType::QChar:
155 case QMetaType::QChar:
160 return PyLong_FromLong(*((short*)data));
156 return PyLong_FromLong(*((short*)data));
161 case QMetaType::Float:
157 case QMetaType::Float:
162 return PyFloat_FromDouble(*((float*)data));
158 return PyFloat_FromDouble(*((float*)data));
163 case QMetaType::Double:
159 case QMetaType::Double:
164 return PyFloat_FromDouble(*((double*)data));
160 return PyFloat_FromDouble(*((double*)data));
165 case QMetaType::LongLong:
161 case QMetaType::LongLong:
166 return PyLong_FromLongLong(*((qint64*)data));
162 return PyLong_FromLongLong(*((qint64*)data));
167 case QMetaType::ULongLong:
163 case QMetaType::ULongLong:
168 return PyLong_FromUnsignedLongLong(*((quint64*)data));
164 return PyLong_FromUnsignedLongLong(*((quint64*)data));
169 // implicit conversion from QByteArray to str has been removed:
165 // implicit conversion from QByteArray to str has been removed:
170 //case QMetaType::QByteArray: {
166 //case QMetaType::QByteArray: {
171 // QByteArray* v = (QByteArray*) data;
167 // QByteArray* v = (QByteArray*) data;
172 // return PyString_FromStringAndSize(*v, v->size());
168 // return PyString_FromStringAndSize(*v, v->size());
173 // }
169 // }
174 case QMetaType::QVariantMap:
170 case QMetaType::QVariantMap:
175 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
171 return PythonQtConv::QVariantMapToPyObject(*((QVariantMap*)data));
176 case QMetaType::QVariantList:
172 case QMetaType::QVariantList:
177 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
173 return PythonQtConv::QVariantListToPyObject(*((QVariantList*)data));
178 case QMetaType::QString:
174 case QMetaType::QString:
179 return PythonQtConv::QStringToPyObject(*((QString*)data));
175 return PythonQtConv::QStringToPyObject(*((QString*)data));
180 case QMetaType::QStringList:
176 case QMetaType::QStringList:
181 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
177 return PythonQtConv::QStringListToPyObject(*((QStringList*)data));
182
178
183 case PythonQtMethodInfo::Variant:
179 case PythonQtMethodInfo::Variant:
184 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
180 return PythonQtConv::QVariantToPyObject(*((QVariant*)data));
185 case QMetaType::QObjectStar:
181 case QMetaType::QObjectStar:
186 #if( QT_VERSION < QT_VERSION_CHECK(5,0,0) )
182 #if( QT_VERSION < QT_VERSION_CHECK(5,0,0) )
187 case QMetaType::QWidgetStar:
183 case QMetaType::QWidgetStar:
188 #endif
184 #endif
189 return PythonQt::priv()->wrapQObject(*((QObject**)data));
185 return PythonQt::priv()->wrapQObject(*((QObject**)data));
190
186
191 default:
187 default:
192 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
188 if (PythonQt::priv()->isPythonQtObjectPtrMetaId(type)) {
193 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
189 // special case, it is a PythonQtObjectPtr which contains a PyObject, take it directly:
194 PyObject* o = ((PythonQtObjectPtr*)data)->object();
190 PyObject* o = ((PythonQtObjectPtr*)data)->object();
195 Py_INCREF(o);
191 Py_INCREF(o);
196 return o;
192 return o;
197 } else {
193 } else {
198 if (type > 0) {
194 if (type > 0) {
199 // if the type is known, we can construct it via QMetaType::construct
195 // if the type is known, we can construct it via QMetaType::construct
200 #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) )
196 #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) )
201 void* newCPPObject = QMetaType::create(type, data);
197 void* newCPPObject = QMetaType::create(type, data);
202 #else
198 #else
203 void* newCPPObject = QMetaType::construct(type, data);
199 void* newCPPObject = QMetaType::construct(type, data);
204 #endif
200 #endif
205 // XXX this could be optimized by using metatypeid directly
201 // XXX this could be optimized by using metatypeid directly
206 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
202 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)PythonQt::priv()->wrapPtr(newCPPObject, QMetaType::typeName(type));
207 wrap->_ownedByPythonQt = true;
203 wrap->_ownedByPythonQt = true;
208 wrap->_useQMetaTypeDestroy = true;
204 wrap->_useQMetaTypeDestroy = true;
209 return (PyObject*)wrap;
205 return (PyObject*)wrap;
210 }
206 }
211 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
207 std::cerr << "Unknown type that can not be converted to Python: " << type << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
212 }
208 }
213 }
209 }
214 Py_INCREF(Py_None);
210 Py_INCREF(Py_None);
215 return Py_None;
211 return Py_None;
216 }
212 }
217
213
218 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
214 void* PythonQtConv::CreateQtReturnValue(const PythonQtMethodInfo::ParameterInfo& info) {
219 void* ptr = NULL;
215 void* ptr = NULL;
220 if (info.pointerCount>1) {
216 if (info.pointerCount>1) {
221 return NULL;
217 return NULL;
222 } else if (info.pointerCount==1) {
218 } else if (info.pointerCount==1) {
223 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
219 PythonQtValueStorage_ADD_VALUE(global_ptrStorage, void*, NULL, ptr);
224 } else if (info.enumWrapper) {
220 } else if (info.enumWrapper) {
225 // create enum return value
221 // create enum return value
226 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
222 PythonQtValueStorage_ADD_VALUE(PythonQtConv::global_valueStorage, long, 0, ptr);
227 } else {
223 } else {
228 switch (info.typeId) {
224 switch (info.typeId) {
229 case QMetaType::Char:
225 case QMetaType::Char:
230 case QMetaType::UChar:
226 case QMetaType::UChar:
231 case QMetaType::Short:
227 case QMetaType::Short:
232 case QMetaType::UShort:
228 case QMetaType::UShort:
233 case QMetaType::Long:
229 case QMetaType::Long:
234 case QMetaType::ULong:
230 case QMetaType::ULong:
235 case QMetaType::Bool:
231 case QMetaType::Bool:
236 case QMetaType::Int:
232 case QMetaType::Int:
237 case QMetaType::UInt:
233 case QMetaType::UInt:
238 case QMetaType::QChar:
234 case QMetaType::QChar:
239 case QMetaType::Float:
235 case QMetaType::Float:
240 case QMetaType::Double:
236 case QMetaType::Double:
241 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
237 PythonQtValueStorage_ADD_VALUE(global_valueStorage, qint64, 0, ptr);
242 break;
238 break;
243 case PythonQtMethodInfo::Variant:
239 case PythonQtMethodInfo::Variant:
244 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
240 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, 0, ptr);
245 // return the ptr to the variant
241 // return the ptr to the variant
246 break;
242 break;
247 default:
243 default:
248 if (info.typeId == PythonQtMethodInfo::Unknown) {
244 if (info.typeId == PythonQtMethodInfo::Unknown) {
249 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
245 // check if we have a QList of pointers, which we can circumvent with a QList<void*>
250 if (info.name.startsWith("QList<")) {
246 if (info.name.startsWith("QList<")) {
251 QByteArray innerType = info.name.mid(6,info.name.length()-7);
247 QByteArray innerType = info.name.mid(6,info.name.length()-7);
252 if (innerType.endsWith("*")) {
248 if (innerType.endsWith("*")) {
253 static int id = QMetaType::type("QList<void*>");
249 static int id = QMetaType::type("QList<void*>");
254 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
250 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(id), ptr);
255 // return the constData pointer that will be filled with the result value later on
251 // return the constData pointer that will be filled with the result value later on
256 ptr = (void*)((QVariant*)ptr)->constData();
252 ptr = (void*)((QVariant*)ptr)->constData();
257 }
253 }
258 }
254 }
259 }
255 }
260
256
261 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
257 if (!ptr && info.typeId!=PythonQtMethodInfo::Unknown) {
262 // everything else is stored in a QVariant, if we know the meta type...
258 // everything else is stored in a QVariant, if we know the meta type...
263 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
259 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
264 // return the constData pointer that will be filled with the result value later on
260 // return the constData pointer that will be filled with the result value later on
265 ptr = (void*)((QVariant*)ptr)->constData();
261 ptr = (void*)((QVariant*)ptr)->constData();
266 }
262 }
267 }
263 }
268 }
264 }
269 return ptr;
265 return ptr;
270 }
266 }
271
267
272 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
268 void* PythonQtConv::castWrapperTo(PythonQtInstanceWrapper* wrapper, const QByteArray& className, bool& ok)
273 {
269 {
274 void* object;
270 void* object;
275 if (wrapper->classInfo()->isCPPWrapper()) {
271 if (wrapper->classInfo()->isCPPWrapper()) {
276 object = wrapper->_wrappedPtr;
272 object = wrapper->_wrappedPtr;
277 } else {
273 } else {
278 QObject* tmp = wrapper->_obj;
274 QObject* tmp = wrapper->_obj;
279 object = tmp;
275 object = tmp;
280 }
276 }
281 if (object) {
277 if (object) {
282 // if we can be upcasted to the given name, we pass the casted pointer in:
278 // if we can be upcasted to the given name, we pass the casted pointer in:
283 object = wrapper->classInfo()->castTo(object, className);
279 object = wrapper->classInfo()->castTo(object, className);
284 ok = object!=NULL;
280 ok = object!=NULL;
285 } else {
281 } else {
286 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
282 // if it is a NULL ptr, we need to check if it inherits, so that we might pass the NULL ptr
287 ok = wrapper->classInfo()->inherits(className);
283 ok = wrapper->classInfo()->inherits(className);
288 }
284 }
289 return object;
285 return object;
290 }
286 }
291
287
292 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
288 void* PythonQtConv::handlePythonToQtAutoConversion(int typeId, PyObject* obj, void* alreadyAllocatedCPPObject)
293 {
289 {
294 void* ptr = alreadyAllocatedCPPObject;
290 void* ptr = alreadyAllocatedCPPObject;
295
291
296 static int penId = QMetaType::type("QPen");
292 static int penId = QMetaType::type("QPen");
297 static int brushId = QMetaType::type("QBrush");
293 static int brushId = QMetaType::type("QBrush");
298 static int cursorId = QMetaType::type("QCursor");
294 static int cursorId = QMetaType::type("QCursor");
299 static int colorId = QMetaType::type("QColor");
295 static int colorId = QMetaType::type("QColor");
300 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
296 static PyObject* qtGlobalColorEnum = PythonQtClassInfo::findEnumWrapper("Qt::GlobalColor", NULL);
301 if (typeId == cursorId) {
297 if (typeId == cursorId) {
302 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
298 static PyObject* qtCursorShapeEnum = PythonQtClassInfo::findEnumWrapper("Qt::CursorShape", NULL);
303 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
299 if ((PyObject*)obj->ob_type == qtCursorShapeEnum) {
304 Qt::CursorShape val = (Qt::CursorShape)PyLong_AsLong(obj);
300 Qt::CursorShape val = (Qt::CursorShape)PyLong_AsLong(obj);
305 if (!ptr) {
301 if (!ptr) {
306 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
302 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QCursor(), ptr);
307 ptr = (void*)((QVariant*)ptr)->constData();
303 ptr = (void*)((QVariant*)ptr)->constData();
308 }
304 }
309 *((QCursor*)ptr) = QCursor(val);
305 *((QCursor*)ptr) = QCursor(val);
310 return ptr;
306 return ptr;
311 }
307 }
312 } else if (typeId == penId) {
308 } else if (typeId == penId) {
313 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
309 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
314 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
310 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
315 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
311 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
316 Qt::GlobalColor val = (Qt::GlobalColor)PyLong_AsLong(obj);
312 Qt::GlobalColor val = (Qt::GlobalColor)PyLong_AsLong(obj);
317 if (!ptr) {
313 if (!ptr) {
318 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
314 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
319 ptr = (void*)((QVariant*)ptr)->constData();
315 ptr = (void*)((QVariant*)ptr)->constData();
320 }
316 }
321 *((QPen*)ptr) = QPen(QColor(val));
317 *((QPen*)ptr) = QPen(QColor(val));
322 return ptr;
318 return ptr;
323 } else if ((PyObject*)obj->ob_type == qtColorClass) {
319 } else if ((PyObject*)obj->ob_type == qtColorClass) {
324 if (!ptr) {
320 if (!ptr) {
325 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
321 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QPen(), ptr);
326 ptr = (void*)((QVariant*)ptr)->constData();
322 ptr = (void*)((QVariant*)ptr)->constData();
327 }
323 }
328 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
324 *((QPen*)ptr) = QPen(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
329 return ptr;
325 return ptr;
330 }
326 }
331 } else if (typeId == brushId) {
327 } else if (typeId == brushId) {
332 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
328 // brushes can be created from QColor and from Qt::GlobalColor (and from brushes, but that's the default)
333 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
329 static PyObject* qtColorClass = PythonQt::priv()->getClassInfo("QColor")->pythonQtClassWrapper();
334 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
330 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
335 Qt::GlobalColor val = (Qt::GlobalColor)PyLong_AsLong(obj);
331 Qt::GlobalColor val = (Qt::GlobalColor)PyLong_AsLong(obj);
336 if (!ptr) {
332 if (!ptr) {
337 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
333 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
338 ptr = (void*)((QVariant*)ptr)->constData();
334 ptr = (void*)((QVariant*)ptr)->constData();
339 }
335 }
340 *((QBrush*)ptr) = QBrush(QColor(val));
336 *((QBrush*)ptr) = QBrush(QColor(val));
341 return ptr;
337 return ptr;
342 } else if ((PyObject*)obj->ob_type == qtColorClass) {
338 } else if ((PyObject*)obj->ob_type == qtColorClass) {
343 if (!ptr) {
339 if (!ptr) {
344 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
340 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QBrush(), ptr);
345 ptr = (void*)((QVariant*)ptr)->constData();
341 ptr = (void*)((QVariant*)ptr)->constData();
346 }
342 }
347 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
343 *((QBrush*)ptr) = QBrush(*((QColor*)((PythonQtInstanceWrapper*)obj)->_wrappedPtr));
348 return ptr;
344 return ptr;
349 }
345 }
350 } else if (typeId == colorId) {
346 } else if (typeId == colorId) {
351 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
347 // colors can be created from Qt::GlobalColor (and from colors, but that's the default)
352 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
348 if ((PyObject*)obj->ob_type == qtGlobalColorEnum) {
353 Qt::GlobalColor val = (Qt::GlobalColor)PyLong_AsLong(obj);
349 Qt::GlobalColor val = (Qt::GlobalColor)PyLong_AsLong(obj);
354 if (!ptr) {
350 if (!ptr) {
355 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
351 PythonQtValueStorage_ADD_VALUE(global_variantStorage, QVariant, QColor(), ptr);
356 ptr = (void*)((QVariant*)ptr)->constData();
352 ptr = (void*)((QVariant*)ptr)->constData();
357 }
353 }
358 *((QColor*)ptr) = QColor(val);
354 *((QColor*)ptr) = QColor(val);
359 return ptr;
355 return ptr;
360 }
356 }
361 }
357 }
362 return NULL;
358 return NULL;
363 }
359 }
364
360
365 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
361 void* PythonQtConv::ConvertPythonToQt(const PythonQtMethodInfo::ParameterInfo& info, PyObject* obj, bool strict, PythonQtClassInfo* /*classInfo*/, void* alreadyAllocatedCPPObject)
366 {
362 {
367 bool ok = false;
363 bool ok = false;
368 void* ptr = NULL;
364 void* ptr = NULL;
369
365
370 // autoconversion of QPen/QBrush/QCursor/QColor from different type
366 // autoconversion of QPen/QBrush/QCursor/QColor from different type
371 if (info.pointerCount==0 && !strict) {
367 if (info.pointerCount==0 && !strict) {
372 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
368 ptr = handlePythonToQtAutoConversion(info.typeId, obj, alreadyAllocatedCPPObject);
373 if (ptr) {
369 if (ptr) {
374 return ptr;
370 return ptr;
375 }
371 }
376 }
372 }
377
373
378 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
374 if (PyObject_TypeCheck(obj, &PythonQtInstanceWrapper_Type) && info.typeId != PythonQtMethodInfo::Variant) {
379 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
375 // if we have a Qt wrapper object and if we do not need a QVariant, we do the following:
380 // (the Variant case is handled below in a switch)
376 // (the Variant case is handled below in a switch)
381
377
382 // a C++ wrapper (can be passed as pointer or reference)
378 // a C++ wrapper (can be passed as pointer or reference)
383 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
379 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)obj;
384 void* object = castWrapperTo(wrap, info.name, ok);
380 void* object = castWrapperTo(wrap, info.name, ok);
385 if (ok) {
381 if (ok) {
386 if (info.pointerCount==1) {
382 if (info.pointerCount==1) {
387 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
383 // store the wrapped pointer in an extra pointer and let ptr point to the extra pointer
388 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
384 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, object, ptr);
389 } else if (info.pointerCount==0) {
385 } else if (info.pointerCount==0) {
390 // store the wrapped pointer directly, since we are a reference
386 // store the wrapped pointer directly, since we are a reference
391 ptr = object;
387 ptr = object;
392 }
388 }
393 } else {
389 } else {
394 // not matching, maybe a PyObject*?
390 // not matching, maybe a PyObject*?
395 if (info.name == "PyObject" && info.pointerCount==1) {
391 if (info.name == "PyObject" && info.pointerCount==1) {
396 // handle low level PyObject directly
392 // handle low level PyObject directly
397 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
393 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
398 }
394 }
399 }
395 }
400 } else if (info.pointerCount == 1) {
396 } else if (info.pointerCount == 1) {
401 // a pointer
397 // a pointer
402 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
398 if (info.typeId == QMetaType::Char || info.typeId == QMetaType::UChar)
403 {
399 {
404 #ifdef PY3K
400 #ifdef PY3K
405 if (PyUnicode_Check(obj)) {
401 if (PyUnicode_Check(obj)) {
406 QByteArray bytes(PyUnicode_AsUTF8(obj));
402 QByteArray bytes(PyUnicode_AsUTF8(obj));
407 void* ptr2 = NULL;
403 void* ptr2 = NULL;
408 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(bytes), ptr2);
404 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(bytes), ptr2);
409 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
405 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
410 #else
406 #else
411 if (obj->ob_type == &PyString_Type) {
407 if (obj->ob_type == &PyString_Type) {
412 // take direct reference to string data
408 // take direct reference to string data
413 const char* data = PyString_AS_STRING(obj);
409 const char* data = PyString_AS_STRING(obj);
414 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)data, ptr);
410 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)data, ptr);
415 #endif
411 #endif
416 } else {
412 } else {
417 // convert to string
413 // convert to string
418 QString str = PyObjGetString(obj, strict, ok);
414 QString str = PyObjGetString(obj, strict, ok);
419 if (ok) {
415 if (ok) {
420 QByteArray bytes;
416 QByteArray bytes;
421 bytes = str.toUtf8();
417 bytes = str.toUtf8();
422 if (ok) {
418 if (ok) {
423 void* ptr2 = NULL;
419 void* ptr2 = NULL;
424 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(bytes), ptr2);
420 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(bytes), ptr2);
425 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
421 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (((QByteArray*)((QVariant*)ptr2)->constData())->data()), ptr);
426 }
422 }
427 }
423 }
428 }
424 }
429 } else if (info.typeId == QMetaType::QString) {
425 } else if (info.typeId == QMetaType::QString) {
430 // TODO: this is a special case for bad Qt APIs which take a QString*, like QtGui.QFileDialog.getSaveFileName
426 // TODO: this is a special case for bad Qt APIs which take a QString*, like QtGui.QFileDialog.getSaveFileName
431 // In general we would need to decide to either support * args for all basic types (ignoring the fact that the
427 // In general we would need to decide to either support * args for all basic types (ignoring the fact that the
432 // result value is not useable in Python), or if all these APIs need to be wrapped manually/differently, like PyQt/PySide do.
428 // result value is not useable in Python), or if all these APIs need to be wrapped manually/differently, like PyQt/PySide do.
433 QString str = PyObjGetString(obj, strict, ok);
429 QString str = PyObjGetString(obj, strict, ok);
434 if (ok) {
430 if (ok) {
435 void* ptr2 = NULL;
431 void* ptr2 = NULL;
436 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(str), ptr2);
432 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(NULL,global_variantStorage, QVariant, QVariant(str), ptr2);
437 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)((QVariant*)ptr2)->constData(), ptr);
433 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, (void*)((QVariant*)ptr2)->constData(), ptr);
438 }
434 }
439 } else if (info.name == "PyObject") {
435 } else if (info.name == "PyObject") {
440 // handle low level PyObject directly
436 // handle low level PyObject directly
441 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
437 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, obj, ptr);
442 } else if (obj == Py_None) {
438 } else if (obj == Py_None) {
443 // None is treated as a NULL ptr
439 // None is treated as a NULL ptr
444 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
440 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
445 } else {
441 } else {
446 void* foreignWrapper = PythonQt::priv()->unwrapForeignWrapper(info.name, obj);
442 void* foreignWrapper = PythonQt::priv()->unwrapForeignWrapper(info.name, obj);
447 if (foreignWrapper) {
443 if (foreignWrapper) {
448 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, foreignWrapper, ptr);
444 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, foreignWrapper, ptr);
449 } else {
445 } else {
450 // if we are not strict, we try if we are passed a 0 integer
446 // if we are not strict, we try if we are passed a 0 integer
451 if (!strict) {
447 if (!strict) {
452 bool ok;
448 bool ok;
453 int value = PyObjGetInt(obj, true, ok);
449 int value = PyObjGetInt(obj, true, ok);
454 if (ok && value==0) {
450 if (ok && value==0) {
455 // TODOXXX is this wise? or should it be expected from the programmer to use None?
451 // TODOXXX is this wise? or should it be expected from the programmer to use None?
456 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
452 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_ptrStorage, void*, NULL, ptr);
457 }
453 }
458 }
454 }
459 }
455 }
460 }
456 }
461 } else if (info.pointerCount == 0) {
457 } else if (info.pointerCount == 0) {
462 // not a pointer
458 // not a pointer
463 switch (info.typeId) {
459 switch (info.typeId) {
464 case QMetaType::Char:
460 case QMetaType::Char:
465 {
461 {
466 int val = PyObjGetInt(obj, strict, ok);
462 int val = PyObjGetInt(obj, strict, ok);
467 if (ok) {
463 if (ok) {
468 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
464 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, char, val, ptr);
469 }
465 }
470 }
466 }
471 break;
467 break;
472 case QMetaType::UChar:
468 case QMetaType::UChar:
473 {
469 {
474 int val = PyObjGetInt(obj, strict, ok);
470 int val = PyObjGetInt(obj, strict, ok);
475 if (ok) {
471 if (ok) {
476 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
472 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned char, val, ptr);
477 }
473 }
478 }
474 }
479 break;
475 break;
480 case QMetaType::Short:
476 case QMetaType::Short:
481 {
477 {
482 int val = PyObjGetInt(obj, strict, ok);
478 int val = PyObjGetInt(obj, strict, ok);
483 if (ok) {
479 if (ok) {
484 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
480 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
485 }
481 }
486 }
482 }
487 break;
483 break;
488 case QMetaType::UShort:
484 case QMetaType::UShort:
489 {
485 {
490 int val = PyObjGetInt(obj, strict, ok);
486 int val = PyObjGetInt(obj, strict, ok);
491 if (ok) {
487 if (ok) {
492 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
488 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned short, val, ptr);
493 }
489 }
494 }
490 }
495 break;
491 break;
496 case QMetaType::Long:
492 case QMetaType::Long:
497 {
493 {
498 long val = (long)PyObjGetLongLong(obj, strict, ok);
494 long val = (long)PyObjGetLongLong(obj, strict, ok);
499 if (ok) {
495 if (ok) {
500 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
496 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, long, val, ptr);
501 }
497 }
502 }
498 }
503 break;
499 break;
504 case QMetaType::ULong:
500 case QMetaType::ULong:
505 {
501 {
506 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
502 unsigned long val = (unsigned long)PyObjGetLongLong(obj, strict, ok);
507 if (ok) {
503 if (ok) {
508 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
504 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned long, val, ptr);
509 }
505 }
510 }
506 }
511 break;
507 break;
512 case QMetaType::Bool:
508 case QMetaType::Bool:
513 {
509 {
514 bool val = PyObjGetBool(obj, strict, ok);
510 bool val = PyObjGetBool(obj, strict, ok);
515 if (ok) {
511 if (ok) {
516 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
512 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, bool, val, ptr);
517 }
513 }
518 }
514 }
519 break;
515 break;
520 case QMetaType::Int:
516 case QMetaType::Int:
521 {
517 {
522 int val = PyObjGetInt(obj, strict, ok);
518 int val = PyObjGetInt(obj, strict, ok);
523 if (ok) {
519 if (ok) {
524 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
520 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, int, val, ptr);
525 }
521 }
526 }
522 }
527 break;
523 break;
528 case QMetaType::UInt:
524 case QMetaType::UInt:
529 {
525 {
530 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
526 unsigned int val = (unsigned int)PyObjGetLongLong(obj, strict, ok);
531 if (ok) {
527 if (ok) {
532 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
528 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
533 }
529 }
534 }
530 }
535 break;
531 break;
536 case QMetaType::QChar:
532 case QMetaType::QChar:
537 {
533 {
538 int val = PyObjGetInt(obj, strict, ok);
534 int val = PyObjGetInt(obj, strict, ok);
539 if (ok) {
535 if (ok) {
540 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
536 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, short, val, ptr);
541 }
537 }
542 }
538 }
543 break;
539 break;
544 case QMetaType::Float:
540 case QMetaType::Float:
545 {
541 {
546 float val = (float)PyObjGetDouble(obj, strict, ok);
542 float val = (float)PyObjGetDouble(obj, strict, ok);
547 if (ok) {
543 if (ok) {
548 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
544 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, float, val, ptr);
549 }
545 }
550 }
546 }
551 break;
547 break;
552 case QMetaType::Double:
548 case QMetaType::Double:
553 {
549 {
554 double val = (double)PyObjGetDouble(obj, strict, ok);
550 double val = (double)PyObjGetDouble(obj, strict, ok);
555 if (ok) {
551 if (ok) {
556 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
552 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, double, val, ptr);
557 }
553 }
558 }
554 }
559 break;
555 break;
560 case QMetaType::LongLong:
556 case QMetaType::LongLong:
561 {
557 {
562 qint64 val = PyObjGetLongLong(obj, strict, ok);
558 qint64 val = PyObjGetLongLong(obj, strict, ok);
563 if (ok) {
559 if (ok) {
564 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
560 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, qint64, val, ptr);
565 }
561 }
566 }
562 }
567 break;
563 break;
568 case QMetaType::ULongLong:
564 case QMetaType::ULongLong:
569 {
565 {
570 quint64 val = PyObjGetULongLong(obj, strict, ok);
566 quint64 val = PyObjGetULongLong(obj, strict, ok);
571 if (ok) {
567 if (ok) {
572 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
568 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, quint64, val, ptr);
573 }
569 }
574 }
570 }
575 break;
571 break;
576 case QMetaType::QByteArray:
572 case QMetaType::QByteArray:
577 {
573 {
578 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
574 QByteArray bytes = PyObjGetBytes(obj, strict, ok);
579 if (ok) {
575 if (ok) {
580 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
576 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(bytes), ptr);
581 ptr = (void*)((QVariant*)ptr)->constData();
577 ptr = (void*)((QVariant*)ptr)->constData();
582 }
578 }
583 }
579 }
584 break;
580 break;
585 case QMetaType::QString:
581 case QMetaType::QString:
586 {
582 {
587 QString str = PyObjGetString(obj, strict, ok);
583 QString str = PyObjGetString(obj, strict, ok);
588 if (ok) {
584 if (ok) {
589 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
585 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(str), ptr);
590 ptr = (void*)((QVariant*)ptr)->constData();
586 ptr = (void*)((QVariant*)ptr)->constData();
591 }
587 }
592 }
588 }
593 break;
589 break;
594 case QMetaType::QStringList:
590 case QMetaType::QStringList:
595 {
591 {
596 QStringList l = PyObjToStringList(obj, strict, ok);
592 QStringList l = PyObjToStringList(obj, strict, ok);
597 if (ok) {
593 if (ok) {
598 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
594 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant(l), ptr);
599 ptr = (void*)((QVariant*)ptr)->constData();
595 ptr = (void*)((QVariant*)ptr)->constData();
600 }
596 }
601 }
597 }
602 break;
598 break;
603
599
604 case PythonQtMethodInfo::Variant:
600 case PythonQtMethodInfo::Variant:
605 {
601 {
606 QVariant v = PyObjToQVariant(obj);
602 QVariant v = PyObjToQVariant(obj);
607 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
603 // the only case where conversion can fail it None and we want to pass that to, e.g. setProperty(),
608 // so we do not check v.isValid() here
604 // so we do not check v.isValid() here
609 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
605 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
610 }
606 }
611 break;
607 break;
612 default:
608 default:
613 {
609 {
614 // check for enum case
610 // check for enum case
615 if (info.enumWrapper) {
611 if (info.enumWrapper) {
616 unsigned int val;
612 unsigned int val;
617 ok = false;
613 ok = false;
618 if ((PyObject*)obj->ob_type == info.enumWrapper) {
614 if ((PyObject*)obj->ob_type == info.enumWrapper) {
619 // we have a exact enum type match:
615 // we have a exact enum type match:
620 val = PyLong_AsLong(obj);
616 val = PyLong_AsLong(obj);
621 ok = true;
617 ok = true;
622 } else if (!strict) {
618 } else if (!strict) {
623 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
619 // we try to get any integer, when not being strict. If we are strict, integers are not wanted because
624 // we want an integer overload to be taken first!
620 // we want an integer overload to be taken first!
625 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
621 val = (unsigned int)PyObjGetLongLong(obj, false, ok);
626 }
622 }
627 if (ok) {
623 if (ok) {
628 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
624 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_valueStorage, unsigned int, val, ptr);
629 return ptr;
625 return ptr;
630 } else {
626 } else {
631 return NULL;
627 return NULL;
632 }
628 }
633 }
629 }
634
630
635 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
631 if (info.typeId == PythonQtMethodInfo::Unknown || info.typeId >= QMetaType::User) {
636 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
632 // check for QList<AnyPtr*> case, where we will use a QList<void*> QVariant
637 if (info.name.startsWith("QList<")) {
633 if (info.name.startsWith("QList<")) {
638 QByteArray innerType = info.name.mid(6,info.name.length()-7);
634 QByteArray innerType = info.name.mid(6,info.name.length()-7);
639 if (innerType.endsWith("*")) {
635 if (innerType.endsWith("*")) {
640 innerType.truncate(innerType.length()-1);
636 innerType.truncate(innerType.length()-1);
641 static int id = QMetaType::type("QList<void*>");
637 static int id = QMetaType::type("QList<void*>");
642 if (!alreadyAllocatedCPPObject) {
638 if (!alreadyAllocatedCPPObject) {
643 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
639 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(id), ptr);
644 ptr = (void*)((QVariant*)ptr)->constData();
640 ptr = (void*)((QVariant*)ptr)->constData();
645 } else {
641 } else {
646 ptr = alreadyAllocatedCPPObject;
642 ptr = alreadyAllocatedCPPObject;
647 }
643 }
648 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
644 ok = ConvertPythonListToQListOfPointerType(obj, (QList<void*>*)ptr, innerType, strict);
649 if (ok) {
645 if (ok) {
650 return ptr;
646 return ptr;
651 } else {
647 } else {
652 return NULL;
648 return NULL;
653 }
649 }
654 }
650 }
655 }
651 }
656 }
652 }
657
653
658 // We only do this for registered type > QMetaType::User for performance reasons.
654 // We only do this for registered type > QMetaType::User for performance reasons.
659 if (info.typeId >= QMetaType::User) {
655 if (info.typeId >= QMetaType::User) {
660 // Maybe we have a special converter that is registered for that type:
656 // Maybe we have a special converter that is registered for that type:
661 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
657 PythonQtConvertPythonToMetaTypeCB* converter = _pythonToMetaTypeConverters.value(info.typeId);
662 if (converter) {
658 if (converter) {
663 if (!alreadyAllocatedCPPObject) {
659 if (!alreadyAllocatedCPPObject) {
664 // create a new empty variant of concrete type:
660 // create a new empty variant of concrete type:
665 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
661 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, QVariant::Type(info.typeId), ptr);
666 ptr = (void*)((QVariant*)ptr)->constData();
662 ptr = (void*)((QVariant*)ptr)->constData();
667 } else {
663 } else {
668 ptr = alreadyAllocatedCPPObject;
664 ptr = alreadyAllocatedCPPObject;
669 }
665 }
670 // now call the converter, passing the internal object of the variant
666 // now call the converter, passing the internal object of the variant
671 ok = (*converter)(obj, ptr, info.typeId, strict);
667 ok = (*converter)(obj, ptr, info.typeId, strict);
672 if (ok) {
668 if (ok) {
673 return ptr;
669 return ptr;
674 } else {
670 } else {
675 return NULL;
671 return NULL;
676 }
672 }
677 }
673 }
678 }
674 }
679 // if no type id is available, conversion to a QVariant makes no sense/is not possible
675 // if no type id is available, conversion to a QVariant makes no sense/is not possible
680 if (info.typeId != PythonQtMethodInfo::Unknown) {
676 if (info.typeId != PythonQtMethodInfo::Unknown) {
681 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
677 // for all other types, we use the same qvariant conversion and pass out the constData of the variant:
682 QVariant v = PyObjToQVariant(obj, info.typeId);
678 QVariant v = PyObjToQVariant(obj, info.typeId);
683 if (v.isValid()) {
679 if (v.isValid()) {
684 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
680 PythonQtValueStorage_ADD_VALUE_IF_NEEDED(alreadyAllocatedCPPObject,global_variantStorage, QVariant, v, ptr);
685 ptr = (void*)((QVariant*)ptr)->constData();
681 ptr = (void*)((QVariant*)ptr)->constData();
686 }
682 }
687 }
683 }
688 }
684 }
689 }
685 }
690 }
686 }
691 return ptr;
687 return ptr;
692 }
688 }
693
689
694
690
695 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
691 QStringList PythonQtConv::PyObjToStringList(PyObject* val, bool strict, bool& ok) {
696 QStringList v;
692 QStringList v;
697 ok = false;
693 ok = false;
698 // if we are strict, we do not want to convert a string to a stringlist
694 // if we are strict, we do not want to convert a string to a stringlist
699 // (strings in python are detected to be sequences)
695 // (strings in python are detected to be sequences)
700 if (strict && (
696 if (strict && (
701 #ifndef PY3K
697 #ifndef PY3K
702 val->ob_type == &PyString_Type ||
698 val->ob_type == &PyString_Type ||
703 #endif
699 #endif
704 PyUnicode_Check(val))) {
700 PyUnicode_Check(val))) {
705 ok = false;
701 ok = false;
706 return v;
702 return v;
707 }
703 }
708 if (PySequence_Check(val)) {
704 if (PySequence_Check(val)) {
709 int count = PySequence_Size(val);
705 int count = PySequence_Size(val);
710 for (int i = 0;i<count;i++) {
706 for (int i = 0;i<count;i++) {
711 PyObject* value = PySequence_GetItem(val,i);
707 PyObject* value = PySequence_GetItem(val,i);
712 v.append(PyObjGetString(value,false,ok));
708 v.append(PyObjGetString(value,false,ok));
713 }
709 }
714 ok = true;
710 ok = true;
715 }
711 }
716 return v;
712 return v;
717 }
713 }
718
714
719 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
715 QString PythonQtConv::PyObjGetRepresentation(PyObject* val)
720 {
716 {
721 QString r;
717 QString r;
722 PyObject* str = PyObject_Repr(val);
718 PyObject* str = PyObject_Repr(val);
723 if (str) {
719 if (str) {
724 #ifdef PY3K
720 #ifdef PY3K
725 Py_UCS4 *x = PyUnicode_AsUCS4Copy(str);
721 Py_UCS4 *x = PyUnicode_AsUCS4Copy(str);
726 r = QString::fromUcs4(x, PyUnicode_GetLength(str));
722 r = QString::fromUcs4(x, PyUnicode_GetLength(str));
727 PyMem_Free(x);
723 PyMem_Free(x);
728 #else
724 #else
729 r = QString(PyString_AS_STRING(str));
725 r = QString(PyString_AS_STRING(str));
730 #endif
726 #endif
731 Py_DECREF(str);
727 Py_DECREF(str);
732 }
728 }
733 return r;
729 return r;
734 }
730 }
735
731
736 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
732 QString PythonQtConv::PyObjGetString(PyObject* val, bool strict, bool& ok) {
737 QString r;
733 QString r;
738 ok = true;
734 ok = true;
739 #ifndef PY3K
735 #ifndef PY3K
740 if (Py_TYPE(val) == &PyString_Type) {
736 if (Py_TYPE(val) == &PyString_Type) {
741 r = QString(PyString_AS_STRING(val));
737 r = QString(PyString_AS_STRING(val));
742 } else
738 } else
743 #endif
739 #endif
744 if (PyUnicode_Check(val)) {
740 if (PyUnicode_Check(val)) {
745 #ifdef PY3K
741 #ifdef PY3K
746 Py_UCS4 *x = PyUnicode_AsUCS4Copy(val);
742 Py_UCS4 *x = PyUnicode_AsUCS4Copy(val);
747 r = QString::fromUcs4(x, PyUnicode_GetLength(val));
743 r = QString::fromUcs4(x, PyUnicode_GetLength(val));
748 PyMem_Free(x);
744 PyMem_Free(x);
749 #else
745 #else
750 PyObject *ptmp = PyUnicode_AsUTF8String(val);
746 PyObject *ptmp = PyUnicode_AsUTF8String(val);
751 if(ptmp) {
747 if(ptmp) {
752 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
748 r = QString::fromUtf8(PyString_AS_STRING(ptmp));
753 Py_DECREF(ptmp);
749 Py_DECREF(ptmp);
754 }
750 }
755 #endif
751 #endif
756 } else if (!strict) {
752 } else if (!strict) {
757 // EXTRA: could also use _Unicode, but why should we?
753 // EXTRA: could also use _Unicode, but why should we?
758 PyObject* str = PyObject_Str(val);
754 PyObject* str = PyObject_Str(val);
759 if (str) {
755 if (str) {
760 #ifdef PY3K
756 #ifdef PY3K
761 Py_UCS4 *x = PyUnicode_AsUCS4Copy(str);
757 Py_UCS4 *x = PyUnicode_AsUCS4Copy(str);
762 r = QString::fromUcs4(x, PyUnicode_GetLength(str));
758 r = QString::fromUcs4(x, PyUnicode_GetLength(str));
763 PyMem_Free(x);
759 PyMem_Free(x);
764 #else
760 #else
765 r = QString(PyString_AS_STRING(str));
761 r = QString(PyString_AS_STRING(str));
766 #endif
762 #endif
767 Py_DECREF(str);
763 Py_DECREF(str);
768 } else {
764 } else {
769 ok = false;
765 ok = false;
770 }
766 }
771 } else {
767 } else {
772 ok = false;
768 ok = false;
773 }
769 }
774 return r;
770 return r;
775 }
771 }
776
772
777 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
773 QByteArray PythonQtConv::PyObjGetBytes(PyObject* val, bool /*strict*/, bool& ok) {
778 // TODO: support buffer objects in general
774 // TODO: support buffer objects in general
779 QByteArray r;
775 QByteArray r;
780 ok = true;
776 ok = true;
781 #ifdef PY3K
777 #ifdef PY3K
782 if (PyBytes_Check(val)) {
778 if (PyBytes_Check(val)) {
783 r = QByteArray(PyBytes_AS_STRING(val), PyBytes_GET_SIZE(val));
779 r = QByteArray(PyBytes_AS_STRING(val), PyBytes_GET_SIZE(val));
784 #else
780 #else
785 if (Py_TYPE(val) == &PyString_Type) {
781 if (Py_TYPE(val) == &PyString_Type) {
786 long size = PyString_GET_SIZE(val);
782 long size = PyString_GET_SIZE(val);
787 r = QByteArray(PyString_AS_STRING(val), size);
783 r = QByteArray(PyString_AS_STRING(val), size);
788 #endif
784 #endif
789 } else {
785 } else {
790 ok = false;
786 ok = false;
791 }
787 }
792 return r;
788 return r;
793 }
789 }
794
790
795 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
791 bool PythonQtConv::PyObjGetBool(PyObject* val, bool strict, bool &ok) {
796 bool d = false;
792 bool d = false;
797 ok = false;
793 ok = false;
798 if (val == Py_False) {
794 if (val == Py_False) {
799 d = false;
795 d = false;
800 ok = true;
796 ok = true;
801 } else if (val == Py_True) {
797 } else if (val == Py_True) {
802 d = true;
798 d = true;
803 ok = true;
799 ok = true;
804 } else if (!strict) {
800 } else if (!strict) {
805 int result = PyObject_IsTrue(val);
801 int result = PyObject_IsTrue(val);
806 d = (result == 1);
802 d = (result == 1);
807 // the result is -1 if an error occurred, handle this:
803 // the result is -1 if an error occurred, handle this:
808 ok = (result != -1);
804 ok = (result != -1);
809 }
805 }
810 return d;
806 return d;
811 }
807 }
812
808
813 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
809 int PythonQtConv::PyObjGetInt(PyObject* val, bool strict, bool &ok) {
814 int d = 0;
810 int d = 0;
815 ok = true;
811 ok = true;
816 #ifndef PY3K
812 #ifndef PY3K
817 if (val->ob_type == &PyInt_Type) {
813 if (val->ob_type == &PyInt_Type) {
818 d = PyInt_AS_LONG(val);
814 d = PyInt_AS_LONG(val);
819 } else
815 } else
820 #endif
816 #endif
821 if (Py_TYPE(val) == &PyLong_Type) {
817 if (Py_TYPE(val) == &PyLong_Type) {
822 // handle error on overflow!
818 // handle error on overflow!
823 d = PyLong_AsLong(val);
819 d = PyLong_AsLong(val);
824 } else if (!strict) {
820 } else if (!strict) {
825 #ifndef PY3K
821 #ifndef PY3K
826 if (PyObject_TypeCheck(val, &PyInt_Type)) {
822 if (PyObject_TypeCheck(val, &PyInt_Type)) {
827 // support for derived int classes, e.g. for our enums
823 // support for derived int classes, e.g. for our enums
828 d = PyInt_AS_LONG(val);
824 d = PyInt_AS_LONG(val);
829 } else
825 } else
830 #endif
826 #endif
831 if (PyObject_TypeCheck(val, &PyLong_Type)) {
827 if (PyObject_TypeCheck(val, &PyLong_Type)) {
832 d = PyLong_AsLong(val);
828 d = PyLong_AsLong(val);
833 } else if (Py_TYPE(val) == &PyFloat_Type) {
829 } else if (Py_TYPE(val) == &PyFloat_Type) {
834 d = floor(PyFloat_AS_DOUBLE(val));
830 d = floor(PyFloat_AS_DOUBLE(val));
835 } else if (val == Py_False) {
831 } else if (val == Py_False) {
836 d = 0;
832 d = 0;
837 } else if (val == Py_True) {
833 } else if (val == Py_True) {
838 d = 1;
834 d = 1;
839 } else {
835 } else {
840 PyErr_Clear();
836 PyErr_Clear();
841 // PyInt_AsLong will try conversion to an int if the object is not an int:
837 // PyInt_AsLong will try conversion to an int if the object is not an int:
842 d = PyLong_AsLong(val);
838 d = PyLong_AsLong(val);
843 if (PyErr_Occurred()) {
839 if (PyErr_Occurred()) {
844 ok = false;
840 ok = false;
845 PyErr_Clear();
841 PyErr_Clear();
846 }
842 }
847 }
843 }
848 } else {
844 } else {
849 ok = false;
845 ok = false;
850 }
846 }
851 return d;
847 return d;
852 }
848 }
853
849
854 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
850 qint64 PythonQtConv::PyObjGetLongLong(PyObject* val, bool strict, bool &ok) {
855 qint64 d = 0;
851 qint64 d = 0;
856 ok = true;
852 ok = true;
857 #ifndef PY3K
853 #ifndef PY3K
858 if (val->ob_type == &PyInt_Type) {
854 if (val->ob_type == &PyInt_Type) {
859 d = PyInt_AS_LONG(val);
855 d = PyInt_AS_LONG(val);
860 } else
856 } else
861 #endif
857 #endif
862 if (Py_TYPE(val) == &PyLong_Type) {
858 if (Py_TYPE(val) == &PyLong_Type) {
863 d = PyLong_AsLongLong(val);
859 d = PyLong_AsLongLong(val);
864 } else if (!strict) {
860 } else if (!strict) {
865 #ifndef PY3K
861 #ifndef PY3K
866 if (PyObject_TypeCheck(val, &PyInt_Type)) {
862 if (PyObject_TypeCheck(val, &PyInt_Type)) {
867 // support for derived int classes, e.g. for our enums
863 // support for derived int classes, e.g. for our enums
868 d = PyInt_AS_LONG(val);
864 d = PyInt_AS_LONG(val);
869 } else
865 } else
870 #endif
866 #endif
871 if (PyObject_TypeCheck(val, &PyLong_Type)) {
867 if (PyObject_TypeCheck(val, &PyLong_Type)) {
872 d = PyLong_AsLong(val);
868 d = PyLong_AsLong(val);
873 } else if (Py_TYPE(val) == &PyFloat_Type) {
869 } else if (Py_TYPE(val) == &PyFloat_Type) {
874 d = floor(PyFloat_AS_DOUBLE(val));
870 d = floor(PyFloat_AS_DOUBLE(val));
875 } else if (val == Py_False) {
871 } else if (val == Py_False) {
876 d = 0;
872 d = 0;
877 } else if (val == Py_True) {
873 } else if (val == Py_True) {
878 d = 1;
874 d = 1;
879 } else {
875 } else {
880 PyErr_Clear();
876 PyErr_Clear();
881 // PyLong_AsLongLong will try conversion to an int if the object is not an int:
877 // PyLong_AsLongLong will try conversion to an int if the object is not an int:
882 d = PyLong_AsLongLong(val);
878 d = PyLong_AsLongLong(val);
883 if (PyErr_Occurred()) {
879 if (PyErr_Occurred()) {
884 ok = false;
880 ok = false;
885 PyErr_Clear();
881 PyErr_Clear();
886 }
882 }
887 }
883 }
888 } else {
884 } else {
889 ok = false;
885 ok = false;
890 }
886 }
891 return d;
887 return d;
892 }
888 }
893
889
894 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
890 quint64 PythonQtConv::PyObjGetULongLong(PyObject* val, bool strict, bool &ok) {
895 quint64 d = 0;
891 quint64 d = 0;
896 ok = true;
892 ok = true;
897 #ifndef PY3K
893 #ifndef PY3K
898 if (Py_TYPE(val) == &PyInt_Type) {
894 if (Py_TYPE(val) == &PyInt_Type) {
899 d = PyInt_AS_LONG(val);
895 d = PyInt_AS_LONG(val);
900 } else
896 } else
901 #endif
897 #endif
902 if (Py_TYPE(val) == &PyLong_Type) {
898 if (Py_TYPE(val) == &PyLong_Type) {
903 d = PyLong_AsLongLong(val);
899 d = PyLong_AsLongLong(val);
904 } else if (!strict) {
900 } else if (!strict) {
905 #ifndef PY3K
901 #ifndef PY3K
906 if (PyObject_TypeCheck(val, &PyInt_Type)) {
902 if (PyObject_TypeCheck(val, &PyInt_Type)) {
907 // support for derived int classes, e.g. for our enums
903 // support for derived int classes, e.g. for our enums
908 d = PyInt_AS_LONG(val);
904 d = PyInt_AS_LONG(val);
909 } else
905 } else
910 #endif
906 #endif
911 if (PyObject_TypeCheck(val, &PyLong_Type)) {
907 if (PyObject_TypeCheck(val, &PyLong_Type)) {
912 d = PyLong_AsLong(val);
908 d = PyLong_AsLong(val);
913 } else if (Py_TYPE(val) == &PyFloat_Type) {
909 } else if (Py_TYPE(val) == &PyFloat_Type) {
914 d = floor(PyFloat_AS_DOUBLE(val));
910 d = floor(PyFloat_AS_DOUBLE(val));
915 } else if (val == Py_False) {
911 } else if (val == Py_False) {
916 d = 0;
912 d = 0;
917 } else if (val == Py_True) {
913 } else if (val == Py_True) {
918 d = 1;
914 d = 1;
919 } else {
915 } else {
920 PyErr_Clear();
916 PyErr_Clear();
921 // PyLong_AsLongLong will try conversion to an int if the object is not an int:
917 // PyLong_AsLongLong will try conversion to an int if the object is not an int:
922 d = PyLong_AsLongLong(val);
918 d = PyLong_AsLongLong(val);
923 if (PyErr_Occurred()) {
919 if (PyErr_Occurred()) {
924 PyErr_Clear();
920 PyErr_Clear();
925 ok = false;
921 ok = false;
926 }
922 }
927 }
923 }
928 } else {
924 } else {
929 ok = false;
925 ok = false;
930 }
926 }
931 return d;
927 return d;
932 }
928 }
933
929
934 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
930 double PythonQtConv::PyObjGetDouble(PyObject* val, bool strict, bool &ok) {
935 double d = 0;
931 double d = 0;
936 ok = true;
932 ok = true;
937 if (val->ob_type == &PyFloat_Type) {
933 if (val->ob_type == &PyFloat_Type) {
938 d = PyFloat_AS_DOUBLE(val);
934 d = PyFloat_AS_DOUBLE(val);
939 } else if (!strict) {
935 } else if (!strict) {
940 #ifndef PY3K
936 #ifndef PY3K
941 if (PyObject_TypeCheck(val, &PyInt_Type)) {
937 if (PyObject_TypeCheck(val, &PyInt_Type)) {
942 d = PyInt_AS_LONG(val);
938 d = PyInt_AS_LONG(val);
943 } else
939 } else
944 #endif
940 #endif
945 if (PyLong_Check(val)) {
941 if (PyLong_Check(val)) {
946 d = PyLong_AsLong(val);
942 d = PyLong_AsLong(val);
947 } else if (val == Py_False) {
943 } else if (val == Py_False) {
948 d = 0;
944 d = 0;
949 } else if (val == Py_True) {
945 } else if (val == Py_True) {
950 d = 1;
946 d = 1;
951 } else {
947 } else {
952 PyErr_Clear();
948 PyErr_Clear();
953 // PyFloat_AsDouble will try conversion to a double if the object is not a float:
949 // PyFloat_AsDouble will try conversion to a double if the object is not a float:
954 d = PyFloat_AsDouble(val);
950 d = PyFloat_AsDouble(val);
955 if (PyErr_Occurred()) {
951 if (PyErr_Occurred()) {
956 PyErr_Clear();
952 PyErr_Clear();
957 ok = false;
953 ok = false;
958 }
954 }
959 }
955 }
960 } else {
956 } else {
961 ok = false;
957 ok = false;
962 }
958 }
963 return d;
959 return d;
964 }
960 }
965
961
966 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
962 QVariant PythonQtConv::PyObjToQVariant(PyObject* val, int type)
967 {
963 {
968 QVariant v;
964 QVariant v;
969 bool ok = true;
965 bool ok = true;
970
966
971 if (type==-1) {
967 if (type==-1) {
972 // no special type requested
968 // no special type requested
973 #ifdef PY3K
969 #ifdef PY3K
974 if (PyBytes_Check(val)) {
970 if (PyBytes_Check(val)) {
975 type = QVariant::ByteArray;
971 type = QVariant::ByteArray;
976 } else if (PyUnicode_Check(val)) {
972 } else if (PyUnicode_Check(val)) {
977 #else
973 #else
978 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
974 if (val->ob_type==&PyString_Type || val->ob_type==&PyUnicode_Type) {
979 #endif
975 #endif
980 type = QVariant::String;
976 type = QVariant::String;
981 } else if (val == Py_False || val == Py_True) {
977 } else if (val == Py_False || val == Py_True) {
982 type = QVariant::Bool;
978 type = QVariant::Bool;
983 #ifndef PY3K
979 #ifndef PY3K
984 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
980 } else if (PyObject_TypeCheck(val, &PyInt_Type)) {
985 type = QVariant::Int;
981 type = QVariant::Int;
986 #endif
982 #endif
987 } else if (PyLong_Check(val)) {
983 } else if (PyLong_Check(val)) {
988 type = QVariant::LongLong;
984 type = QVariant::LongLong;
989 } else if (PyFloat_Check(val)) {
985 } else if (PyFloat_Check(val)) {
990 type = QVariant::Double;
986 type = QVariant::Double;
991 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
987 } else if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
992 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
988 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
993 // c++ wrapper, check if the class names of the c++ objects match
989 // c++ wrapper, check if the class names of the c++ objects match
994 if (wrap->classInfo()->isCPPWrapper()) {
990 if (wrap->classInfo()->isCPPWrapper()) {
995 if (wrap->classInfo()->metaTypeId()>0) {
991 if (wrap->classInfo()->metaTypeId()>0) {
996 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
992 // construct a new variant from the C++ object if it has a meta type (this will COPY the object!)
997 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
993 v = QVariant(wrap->classInfo()->metaTypeId(), wrap->_wrappedPtr);
998 } else {
994 } else {
999 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
995 // TODOXXX we could as well check if there is a registered meta type for "classname*", so that we may pass
1000 // the pointer here...
996 // the pointer here...
1001 // is this worth anything? we loose the knowledge of the cpp object type
997 // is this worth anything? we loose the knowledge of the cpp object type
1002 v = qVariantFromValue(wrap->_wrappedPtr);
998 v = qVariantFromValue(wrap->_wrappedPtr);
1003 }
999 }
1004 } else {
1000 } else {
1005 // this gives us a QObject pointer
1001 // this gives us a QObject pointer
1006 QObject* myObject = wrap->_obj;
1002 QObject* myObject = wrap->_obj;
1007 v = qVariantFromValue(myObject);
1003 v = qVariantFromValue(myObject);
1008 }
1004 }
1009 return v;
1005 return v;
1010 } else if (PyDict_Check(val)) {
1006 } else if (PyDict_Check(val)) {
1011 type = QVariant::Map;
1007 type = QVariant::Map;
1012 } else if (PyList_Check(val) || PyTuple_Check(val) || PySequence_Check(val)) {
1008 } else if (PyList_Check(val) || PyTuple_Check(val) || PySequence_Check(val)) {
1013 type = QVariant::List;
1009 type = QVariant::List;
1014 } else if (val == Py_None) {
1010 } else if (val == Py_None) {
1015 // none is invalid
1011 // none is invalid
1016 type = QVariant::Invalid;
1012 type = QVariant::Invalid;
1017 } else {
1013 } else {
1018 // this used to be:
1014 // this used to be:
1019 // type = QVariant::String;
1015 // type = QVariant::String;
1020 // but now we want to transport the Python Objects directly:
1016 // but now we want to transport the Python Objects directly:
1021 PythonQtObjectPtr o(val);
1017 PythonQtObjectPtr o(val);
1022 v = qVariantFromValue(o);
1018 v = qVariantFromValue(o);
1023 return v;
1019 return v;
1024 }
1020 }
1025 }
1021 }
1026 // special type request:
1022 // special type request:
1027 switch (type) {
1023 switch (type) {
1028 case QVariant::Invalid:
1024 case QVariant::Invalid:
1029 return v;
1025 return v;
1030 break;
1026 break;
1031 case QVariant::Int:
1027 case QVariant::Int:
1032 {
1028 {
1033 int d = PyObjGetInt(val, false, ok);
1029 int d = PyObjGetInt(val, false, ok);
1034 if (ok) return QVariant(d);
1030 if (ok) return QVariant(d);
1035 }
1031 }
1036 break;
1032 break;
1037 case QVariant::UInt:
1033 case QVariant::UInt:
1038 {
1034 {
1039 int d = PyObjGetInt(val, false,ok);
1035 int d = PyObjGetInt(val, false,ok);
1040 if (ok) v = QVariant((unsigned int)d);
1036 if (ok) v = QVariant((unsigned int)d);
1041 }
1037 }
1042 break;
1038 break;
1043 case QVariant::Bool:
1039 case QVariant::Bool:
1044 {
1040 {
1045 int d = PyObjGetBool(val,false,ok);
1041 int d = PyObjGetBool(val,false,ok);
1046 if (ok) v = QVariant((bool)(d!=0));
1042 if (ok) v = QVariant((bool)(d!=0));
1047 }
1043 }
1048 break;
1044 break;
1049 case QVariant::Double:
1045 case QVariant::Double:
1050 {
1046 {
1051 double d = PyObjGetDouble(val,false,ok);
1047 double d = PyObjGetDouble(val,false,ok);
1052 if (ok) v = QVariant(d);
1048 if (ok) v = QVariant(d);
1053 break;
1049 break;
1054 }
1050 }
1055 case QMetaType::Float:
1051 case QMetaType::Float:
1056 {
1052 {
1057 float d = (float) PyObjGetDouble(val,false,ok);
1053 float d = (float) PyObjGetDouble(val,false,ok);
1058 if (ok) v = qVariantFromValue(d);
1054 if (ok) v = qVariantFromValue(d);
1059 break;
1055 break;
1060 }
1056 }
1061 case QMetaType::Long:
1057 case QMetaType::Long:
1062 {
1058 {
1063 long d = (long) PyObjGetLongLong(val,false,ok);
1059 long d = (long) PyObjGetLongLong(val,false,ok);
1064 if (ok) v = qVariantFromValue(d);
1060 if (ok) v = qVariantFromValue(d);
1065 break;
1061 break;
1066 }
1062 }
1067 case QMetaType::ULong:
1063 case QMetaType::ULong:
1068 {
1064 {
1069 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
1065 unsigned long d = (unsigned long) PyObjGetLongLong(val,false,ok);
1070 if (ok) v = qVariantFromValue(d);
1066 if (ok) v = qVariantFromValue(d);
1071 break;
1067 break;
1072 }
1068 }
1073 case QMetaType::LongLong:
1069 case QMetaType::LongLong:
1074 {
1070 {
1075 qint64 d = PyObjGetLongLong(val, false, ok);
1071 qint64 d = PyObjGetLongLong(val, false, ok);
1076 if (ok) v = qVariantFromValue(d);
1072 if (ok) v = qVariantFromValue(d);
1077 }
1073 }
1078 break;
1074 break;
1079 case QMetaType::ULongLong:
1075 case QMetaType::ULongLong:
1080 {
1076 {
1081 quint64 d = PyObjGetULongLong(val, false, ok);
1077 quint64 d = PyObjGetULongLong(val, false, ok);
1082 if (ok) v = qVariantFromValue(d);
1078 if (ok) v = qVariantFromValue(d);
1083 }
1079 }
1084 break;
1080 break;
1085 case QMetaType::Short:
1081 case QMetaType::Short:
1086 {
1082 {
1087 short d = (short) PyObjGetInt(val,false,ok);
1083 short d = (short) PyObjGetInt(val,false,ok);
1088 if (ok) v = qVariantFromValue(d);
1084 if (ok) v = qVariantFromValue(d);
1089 break;
1085 break;
1090 }
1086 }
1091 case QMetaType::UShort:
1087 case QMetaType::UShort:
1092 {
1088 {
1093 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
1089 unsigned short d = (unsigned short) PyObjGetInt(val,false,ok);
1094 if (ok) v = qVariantFromValue(d);
1090 if (ok) v = qVariantFromValue(d);
1095 break;
1091 break;
1096 }
1092 }
1097 case QMetaType::Char:
1093 case QMetaType::Char:
1098 {
1094 {
1099 char d = (char) PyObjGetInt(val,false,ok);
1095 char d = (char) PyObjGetInt(val,false,ok);
1100 if (ok) v = qVariantFromValue(d);
1096 if (ok) v = qVariantFromValue(d);
1101 break;
1097 break;
1102 }
1098 }
1103 case QMetaType::UChar:
1099 case QMetaType::UChar:
1104 {
1100 {
1105 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
1101 unsigned char d = (unsigned char) PyObjGetInt(val,false,ok);
1106 if (ok) v = qVariantFromValue(d);
1102 if (ok) v = qVariantFromValue(d);
1107 break;
1103 break;
1108 }
1104 }
1109
1105
1110 case QVariant::ByteArray:
1106 case QVariant::ByteArray:
1111 case QVariant::String:
1107 case QVariant::String:
1112 {
1108 {
1113 bool ok;
1109 bool ok;
1114 v = QVariant(PyObjGetString(val, false, ok));
1110 v = QVariant(PyObjGetString(val, false, ok));
1115 }
1111 }
1116 break;
1112 break;
1117
1113
1118 // these are important for MeVisLab
1114 // these are important for MeVisLab
1119 case QVariant::Map:
1115 case QVariant::Map:
1120 {
1116 {
1121 if (PyMapping_Check(val)) {
1117 if (PyMapping_Check(val)) {
1122 QMap<QString,QVariant> map;
1118 QMap<QString,QVariant> map;
1123 PyObject* items = PyMapping_Items(val);
1119 PyObject* items = PyMapping_Items(val);
1124 if (items) {
1120 if (items) {
1125 int count = PyList_Size(items);
1121 int count = PyList_Size(items);
1126 PyObject* value;
1122 PyObject* value;
1127 PyObject* key;
1123 PyObject* key;
1128 PyObject* tuple;
1124 PyObject* tuple;
1129 for (int i = 0;i<count;i++) {
1125 for (int i = 0;i<count;i++) {
1130 tuple = PyList_GetItem(items,i);
1126 tuple = PyList_GetItem(items,i);
1131 key = PyTuple_GetItem(tuple, 0);
1127 key = PyTuple_GetItem(tuple, 0);
1132 value = PyTuple_GetItem(tuple, 1);
1128 value = PyTuple_GetItem(tuple, 1);
1133 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
1129 map.insert(PyObjGetString(key), PyObjToQVariant(value,-1));
1134 }
1130 }
1135 Py_DECREF(items);
1131 Py_DECREF(items);
1136 v = map;
1132 v = map;
1137 }
1133 }
1138 }
1134 }
1139 }
1135 }
1140 break;
1136 break;
1141 case QVariant::List:
1137 case QVariant::List:
1142 if (PySequence_Check(val)) {
1138 if (PySequence_Check(val)) {
1143 QVariantList list;
1139 QVariantList list;
1144 int count = PySequence_Size(val);
1140 int count = PySequence_Size(val);
1145 PyObject* value;
1141 PyObject* value;
1146 for (int i = 0;i<count;i++) {
1142 for (int i = 0;i<count;i++) {
1147 value = PySequence_GetItem(val,i);
1143 value = PySequence_GetItem(val,i);
1148 list.append(PyObjToQVariant(value, -1));
1144 list.append(PyObjToQVariant(value, -1));
1149 }
1145 }
1150 v = list;
1146 v = list;
1151 }
1147 }
1152 break;
1148 break;
1153 case QVariant::StringList:
1149 case QVariant::StringList:
1154 {
1150 {
1155 bool ok;
1151 bool ok;
1156 QStringList l = PyObjToStringList(val, false, ok);
1152 QStringList l = PyObjToStringList(val, false, ok);
1157 if (ok) {
1153 if (ok) {
1158 v = l;
1154 v = l;
1159 }
1155 }
1160 }
1156 }
1161 break;
1157 break;
1162
1158
1163 default:
1159 default:
1164 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1160 if (PyObject_TypeCheck(val, &PythonQtInstanceWrapper_Type)) {
1165 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1161 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)val;
1166 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1162 if (wrap->classInfo()->isCPPWrapper() && wrap->classInfo()->metaTypeId() == type) {
1167 // construct a new variant from the C++ object if it has the same meta type
1163 // construct a new variant from the C++ object if it has the same meta type
1168 v = QVariant(type, wrap->_wrappedPtr);
1164 v = QVariant(type, wrap->_wrappedPtr);
1169 } else {
1165 } else {
1170 v = QVariant();
1166 v = QVariant();
1171 }
1167 }
1172 } else {
1168 } else {
1173 v = QVariant();
1169 v = QVariant();
1174 }
1170 }
1175 }
1171 }
1176 return v;
1172 return v;
1177 }
1173 }
1178
1174
1179 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1175 PyObject* PythonQtConv::QStringToPyObject(const QString& str)
1180 {
1176 {
1181 if (str.isNull()) {
1177 if (str.isNull()) {
1182 #ifdef PY3K
1178 #ifdef PY3K
1183 return PyUnicode_New(0, 0);
1179 return PyUnicode_New(0, 0);
1184 #else
1180 #else
1185 return PyString_FromString("");
1181 return PyString_FromString("");
1186 #endif
1182 #endif
1187 } else {
1183 } else {
1188 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1184 return PyUnicode_DecodeUTF16((const char*)str.utf16(), str.length()*2, NULL, NULL);
1189 }
1185 }
1190 }
1186 }
1191
1187
1192 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1188 PyObject* PythonQtConv::QStringListToPyObject(const QStringList& list)
1193 {
1189 {
1194 PyObject* result = PyTuple_New(list.count());
1190 PyObject* result = PyTuple_New(list.count());
1195 int i = 0;
1191 int i = 0;
1196 QString str;
1192 QString str;
1197 Q_FOREACH (str, list) {
1193 Q_FOREACH (str, list) {
1198 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1194 PyTuple_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(str));
1199 i++;
1195 i++;
1200 }
1196 }
1201 // why is the error state bad after this?
1197 // why is the error state bad after this?
1202 PyErr_Clear();
1198 PyErr_Clear();
1203 return result;
1199 return result;
1204 }
1200 }
1205
1201
1206 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1202 PyObject* PythonQtConv::QStringListToPyList(const QStringList& list)
1207 {
1203 {
1208 PyObject* result = PyList_New(list.count());
1204 PyObject* result = PyList_New(list.count());
1209 int i = 0;
1205 int i = 0;
1210 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1206 for (QStringList::ConstIterator it = list.begin(); it!=list.end(); ++it) {
1211 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1207 PyList_SET_ITEM(result, i, PythonQtConv::QStringToPyObject(*it));
1212 i++;
1208 i++;
1213 }
1209 }
1214 return result;
1210 return result;
1215 }
1211 }
1216
1212
1217 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1213 PyObject* PythonQtConv::QVariantToPyObject(const QVariant& v)
1218 {
1214 {
1219 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1215 return ConvertQtValueToPythonInternal(v.userType(), (void*)v.constData());
1220 }
1216 }
1221
1217
1222 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1218 PyObject* PythonQtConv::QVariantMapToPyObject(const QVariantMap& m) {
1223 PyObject* result = PyDict_New();
1219 PyObject* result = PyDict_New();
1224 QVariantMap::const_iterator t = m.constBegin();
1220 QVariantMap::const_iterator t = m.constBegin();
1225 PyObject* key;
1221 PyObject* key;
1226 PyObject* val;
1222 PyObject* val;
1227 for (;t!=m.end();t++) {
1223 for (;t!=m.end();t++) {
1228 key = QStringToPyObject(t.key());
1224 key = QStringToPyObject(t.key());
1229 val = QVariantToPyObject(t.value());
1225 val = QVariantToPyObject(t.value());
1230 PyDict_SetItem(result, key, val);
1226 PyDict_SetItem(result, key, val);
1231 Py_DECREF(key);
1227 Py_DECREF(key);
1232 Py_DECREF(val);
1228 Py_DECREF(val);
1233 }
1229 }
1234 return result;
1230 return result;
1235 }
1231 }
1236
1232
1237 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1233 PyObject* PythonQtConv::QVariantListToPyObject(const QVariantList& l) {
1238 PyObject* result = PyTuple_New(l.count());
1234 PyObject* result = PyTuple_New(l.count());
1239 int i = 0;
1235 int i = 0;
1240 QVariant v;
1236 QVariant v;
1241 Q_FOREACH (v, l) {
1237 Q_FOREACH (v, l) {
1242 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1238 PyTuple_SET_ITEM(result, i, PythonQtConv::QVariantToPyObject(v));
1243 i++;
1239 i++;
1244 }
1240 }
1245 // why is the error state bad after this?
1241 // why is the error state bad after this?
1246 PyErr_Clear();
1242 PyErr_Clear();
1247 return result;
1243 return result;
1248 }
1244 }
1249
1245
1250 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1246 PyObject* PythonQtConv::ConvertQListOfPointerTypeToPythonList(QList<void*>* list, const QByteArray& typeName)
1251 {
1247 {
1252 PyObject* result = PyTuple_New(list->count());
1248 PyObject* result = PyTuple_New(list->count());
1253 int i = 0;
1249 int i = 0;
1254 Q_FOREACH (void* value, *list) {
1250 Q_FOREACH (void* value, *list) {
1255 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1251 PyTuple_SET_ITEM(result, i, PythonQt::priv()->wrapPtr(value, typeName));
1256 i++;
1252 i++;
1257 }
1253 }
1258 return result;
1254 return result;
1259 }
1255 }
1260
1256
1261 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1257 bool PythonQtConv::ConvertPythonListToQListOfPointerType(PyObject* obj, QList<void*>* list, const QByteArray& type, bool /*strict*/)
1262 {
1258 {
1263 bool result = false;
1259 bool result = false;
1264 if (PySequence_Check(obj)) {
1260 if (PySequence_Check(obj)) {
1265 result = true;
1261 result = true;
1266 int count = PySequence_Size(obj);
1262 int count = PySequence_Size(obj);
1267 PyObject* value;
1263 PyObject* value;
1268 for (int i = 0;i<count;i++) {
1264 for (int i = 0;i<count;i++) {
1269 value = PySequence_GetItem(obj,i);
1265 value = PySequence_GetItem(obj,i);
1270 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1266 if (PyObject_TypeCheck(value, &PythonQtInstanceWrapper_Type)) {
1271 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1267 PythonQtInstanceWrapper* wrap = (PythonQtInstanceWrapper*)value;
1272 bool ok;
1268 bool ok;
1273 void* object = castWrapperTo(wrap, type, ok);
1269 void* object = castWrapperTo(wrap, type, ok);
1274 if (ok) {
1270 if (ok) {
1275 list->append(object);
1271 list->append(object);
1276 } else {
1272 } else {
1277 result = false;
1273 result = false;
1278 break;
1274 break;
1279 }
1275 }
1280 }
1276 }
1281 }
1277 }
1282 }
1278 }
1283 return result;
1279 return result;
1284 }
1280 }
1285
1281
1286 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1282 int PythonQtConv::getInnerTemplateMetaType(const QByteArray& typeName)
1287 {
1283 {
1288 int idx = typeName.indexOf("<");
1284 int idx = typeName.indexOf("<");
1289 if (idx>0) {
1285 if (idx>0) {
1290 int idx2 = typeName.indexOf(">");
1286 int idx2 = typeName.indexOf(">");
1291 if (idx2>0) {
1287 if (idx2>0) {
1292 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1288 QByteArray innerType = typeName.mid(idx+1,idx2-idx-1);
1293 return QMetaType::type(innerType.constData());
1289 return QMetaType::type(innerType.constData());
1294 }
1290 }
1295 }
1291 }
1296 return QMetaType::Void;
1292 return QMetaType::Void;
1297 }
1293 }
1298
1294
1299
1295
1300 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1296 QString PythonQtConv::CPPObjectToString(int type, const void* data) {
1301 QString r;
1297 QString r;
1302 switch (type) {
1298 switch (type) {
1303 case QVariant::Size: {
1299 case QVariant::Size: {
1304 const QSize* s = static_cast<const QSize*>(data);
1300 const QSize* s = static_cast<const QSize*>(data);
1305 r = QString::number(s->width()) + ", " + QString::number(s->height());
1301 r = QString::number(s->width()) + ", " + QString::number(s->height());
1306 }
1302 }
1307 break;
1303 break;
1308 case QVariant::SizeF: {
1304 case QVariant::SizeF: {
1309 const QSizeF* s = static_cast<const QSizeF*>(data);
1305 const QSizeF* s = static_cast<const QSizeF*>(data);
1310 r = QString::number(s->width()) + ", " + QString::number(s->height());
1306 r = QString::number(s->width()) + ", " + QString::number(s->height());
1311 }
1307 }
1312 break;
1308 break;
1313 case QVariant::Point: {
1309 case QVariant::Point: {
1314 const QPoint* s = static_cast<const QPoint*>(data);
1310 const QPoint* s = static_cast<const QPoint*>(data);
1315 r = QString::number(s->x()) + ", " + QString::number(s->y());
1311 r = QString::number(s->x()) + ", " + QString::number(s->y());
1316 }
1312 }
1317 break;
1313 break;
1318 case QVariant::PointF: {
1314 case QVariant::PointF: {
1319 const QPointF* s = static_cast<const QPointF*>(data);
1315 const QPointF* s = static_cast<const QPointF*>(data);
1320 r = QString::number(s->x()) + ", " + QString::number(s->y());
1316 r = QString::number(s->x()) + ", " + QString::number(s->y());
1321 }
1317 }
1322 break;
1318 break;
1323 case QVariant::Rect: {
1319 case QVariant::Rect: {
1324 const QRect* s = static_cast<const QRect*>(data);
1320 const QRect* s = static_cast<const QRect*>(data);
1325 r = QString::number(s->x()) + ", " + QString::number(s->y());
1321 r = QString::number(s->x()) + ", " + QString::number(s->y());
1326 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1322 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1327 }
1323 }
1328 break;
1324 break;
1329 case QVariant::RectF: {
1325 case QVariant::RectF: {
1330 const QRectF* s = static_cast<const QRectF*>(data);
1326 const QRectF* s = static_cast<const QRectF*>(data);
1331 r = QString::number(s->x()) + ", " + QString::number(s->y());
1327 r = QString::number(s->x()) + ", " + QString::number(s->y());
1332 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1328 r += ", " + QString::number(s->width()) + ", " + QString::number(s->height());
1333 }
1329 }
1334 break;
1330 break;
1335 case QVariant::Date: {
1331 case QVariant::Date: {
1336 const QDate* s = static_cast<const QDate*>(data);
1332 const QDate* s = static_cast<const QDate*>(data);
1337 r = s->toString(Qt::ISODate);
1333 r = s->toString(Qt::ISODate);
1338 }
1334 }
1339 break;
1335 break;
1340 case QVariant::DateTime: {
1336 case QVariant::DateTime: {
1341 const QDateTime* s = static_cast<const QDateTime*>(data);
1337 const QDateTime* s = static_cast<const QDateTime*>(data);
1342 r = s->toString(Qt::ISODate);
1338 r = s->toString(Qt::ISODate);
1343 }
1339 }
1344 break;
1340 break;
1345 case QVariant::Time: {
1341 case QVariant::Time: {
1346 const QTime* s = static_cast<const QTime*>(data);
1342 const QTime* s = static_cast<const QTime*>(data);
1347 r = s->toString(Qt::ISODate);
1343 r = s->toString(Qt::ISODate);
1348 }
1344 }
1349 break;
1345 break;
1350 case QVariant::Pixmap:
1346 case QVariant::Pixmap:
1351 {
1347 {
1352 const QPixmap* s = static_cast<const QPixmap*>(data);
1348 const QPixmap* s = static_cast<const QPixmap*>(data);
1353 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1349 r = QString("Pixmap ") + QString::number(s->width()) + ", " + QString::number(s->height());
1354 }
1350 }
1355 break;
1351 break;
1356 case QVariant::Image:
1352 case QVariant::Image:
1357 {
1353 {
1358 const QImage* s = static_cast<const QImage*>(data);
1354 const QImage* s = static_cast<const QImage*>(data);
1359 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1355 r = QString("Image ") + QString::number(s->width()) + ", " + QString::number(s->height());
1360 }
1356 }
1361 break;
1357 break;
1362 case QVariant::Url:
1358 case QVariant::Url:
1363 {
1359 {
1364 const QUrl* s = static_cast<const QUrl*>(data);
1360 const QUrl* s = static_cast<const QUrl*>(data);
1365 r = s->toString();
1361 r = s->toString();
1366 }
1362 }
1367 break;
1363 break;
1368 //TODO: add more printing for other variant types
1364 //TODO: add more printing for other variant types
1369 default:
1365 default:
1370 // this creates a copy, but that should not be expensive for typical simple variants
1366 // this creates a copy, but that should not be expensive for typical simple variants
1371 // (but we do not want to do this for our won user types!
1367 // (but we do not want to do this for our won user types!
1372 if (type>0 && type < (int)QVariant::UserType) {
1368 if (type>0 && type < (int)QVariant::UserType) {
1373 QVariant v(type, data);
1369 QVariant v(type, data);
1374 r = v.toString();
1370 r = v.toString();
1375 }
1371 }
1376 }
1372 }
1377 return r;
1373 return r;
1378 }
1374 }
@@ -1,853 +1,849
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, 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 "PythonQtConversion.h"
50 #include "PythonQtConversion.h"
51 #include <QFile>
51 #include <QFile>
52 #include <QFileInfo>
52 #include <QFileInfo>
53
53
54 #if PY_MAJOR_VERSION >= 3
55 #define PY3K
56 #endif
57
58 #define IS_SOURCE 0x0
54 #define IS_SOURCE 0x0
59 #define IS_BYTECODE 0x1
55 #define IS_BYTECODE 0x1
60 #define IS_PACKAGE 0x2
56 #define IS_PACKAGE 0x2
61
57
62 struct st_mlab_searchorder {
58 struct st_mlab_searchorder {
63 char suffix[14];
59 char suffix[14];
64 int type;
60 int type;
65 };
61 };
66
62
67 /* mlab_searchorder defines how we search for a module in the Zip
63 /* mlab_searchorder defines how we search for a module in the Zip
68 archive: we first search for a package __init__, then for
64 archive: we first search for a package __init__, then for
69 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
65 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
70 are swapped by initmlabimport() if we run in optimized mode. Also,
66 are swapped by initmlabimport() if we run in optimized mode. Also,
71 '/' is replaced by SEP there. */
67 '/' is replaced by SEP there. */
72 struct st_mlab_searchorder mlab_searchorder[] = {
68 struct st_mlab_searchorder mlab_searchorder[] = {
73 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
69 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
74 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
70 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
75 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
71 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
76 {".pyc", IS_BYTECODE},
72 {".pyc", IS_BYTECODE},
77 {".pyo", IS_BYTECODE},
73 {".pyo", IS_BYTECODE},
78 {".py", IS_SOURCE},
74 {".py", IS_SOURCE},
79 {"", 0}
75 {"", 0}
80 };
76 };
81
77
82 extern PyTypeObject PythonQtImporter_Type;
78 extern PyTypeObject PythonQtImporter_Type;
83 PyObject *PythonQtImportError;
79 PyObject *PythonQtImportError;
84
80
85 QString PythonQtImport::getSubName(const QString& str)
81 QString PythonQtImport::getSubName(const QString& str)
86 {
82 {
87 int idx = str.lastIndexOf('.');
83 int idx = str.lastIndexOf('.');
88 if (idx!=-1) {
84 if (idx!=-1) {
89 return str.mid(idx+1);
85 return str.mid(idx+1);
90 } else {
86 } else {
91 return str;
87 return str;
92 }
88 }
93 }
89 }
94
90
95 PythonQtImport::ModuleInfo PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
91 PythonQtImport::ModuleInfo PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
96 {
92 {
97 ModuleInfo info;
93 ModuleInfo info;
98 QString subname;
94 QString subname;
99 struct st_mlab_searchorder *zso;
95 struct st_mlab_searchorder *zso;
100
96
101 subname = getSubName(fullname);
97 subname = getSubName(fullname);
102 QString path = *self->_path + "/" + subname;
98 QString path = *self->_path + "/" + subname;
103
99
104 QString test;
100 QString test;
105 for (zso = mlab_searchorder; *zso->suffix; zso++) {
101 for (zso = mlab_searchorder; *zso->suffix; zso++) {
106 test = path + zso->suffix;
102 test = path + zso->suffix;
107 if (PythonQt::importInterface()->exists(test)) {
103 if (PythonQt::importInterface()->exists(test)) {
108 info.fullPath = test;
104 info.fullPath = test;
109 info.moduleName = subname;
105 info.moduleName = subname;
110 info.type = (zso->type & IS_PACKAGE)?MI_PACKAGE:MI_MODULE;
106 info.type = (zso->type & IS_PACKAGE)?MI_PACKAGE:MI_MODULE;
111 return info;
107 return info;
112 }
108 }
113 }
109 }
114 // test if it is a shared library
110 // test if it is a shared library
115 Q_FOREACH(const QString& suffix, PythonQt::priv()->sharedLibrarySuffixes()) {
111 Q_FOREACH(const QString& suffix, PythonQt::priv()->sharedLibrarySuffixes()) {
116 test = path+suffix;
112 test = path+suffix;
117 if (PythonQt::importInterface()->exists(test)) {
113 if (PythonQt::importInterface()->exists(test)) {
118 info.fullPath = test;
114 info.fullPath = test;
119 info.moduleName = subname;
115 info.moduleName = subname;
120 info.type = MI_SHAREDLIBRARY;
116 info.type = MI_SHAREDLIBRARY;
121 return info;
117 return info;
122 }
118 }
123 }
119 }
124 return info;
120 return info;
125 }
121 }
126
122
127
123
128 /* PythonQtImporter.__init__
124 /* PythonQtImporter.__init__
129 Just store the path argument (or reject if it is in the ignorePaths list
125 Just store the path argument (or reject if it is in the ignorePaths list
130 */
126 */
131 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
127 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
132 {
128 {
133 self->_path = NULL;
129 self->_path = NULL;
134
130
135 const char* cpath;
131 const char* cpath;
136 if (!PyArg_ParseTuple(args, "s",
132 if (!PyArg_ParseTuple(args, "s",
137 &cpath))
133 &cpath))
138 return -1;
134 return -1;
139
135
140 QString path(cpath);
136 QString path(cpath);
141 if (PythonQt::importInterface()->exists(path)) {
137 if (PythonQt::importInterface()->exists(path)) {
142 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
138 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
143 Q_FOREACH(QString ignorePath, ignorePaths) {
139 Q_FOREACH(QString ignorePath, ignorePaths) {
144 if (path.startsWith(ignorePath)) {
140 if (path.startsWith(ignorePath)) {
145 PyErr_SetString(PythonQtImportError,
141 PyErr_SetString(PythonQtImportError,
146 "path ignored");
142 "path ignored");
147 return -1;
143 return -1;
148 }
144 }
149 }
145 }
150
146
151 self->_path = new QString(path);
147 self->_path = new QString(path);
152 return 0;
148 return 0;
153 } else {
149 } else {
154 PyErr_SetString(PythonQtImportError,
150 PyErr_SetString(PythonQtImportError,
155 "path does not exist error");
151 "path does not exist error");
156 return -1;
152 return -1;
157 }
153 }
158 }
154 }
159
155
160 void
156 void
161 PythonQtImporter_dealloc(PythonQtImporter *self)
157 PythonQtImporter_dealloc(PythonQtImporter *self)
162 {
158 {
163 // free the stored path
159 // free the stored path
164 if (self->_path) delete self->_path;
160 if (self->_path) delete self->_path;
165 // free ourself
161 // free ourself
166 Py_TYPE(self)->tp_free((PyObject *)self);
162 Py_TYPE(self)->tp_free((PyObject *)self);
167 }
163 }
168
164
169
165
170 /* Check whether we can satisfy the import of the module named by
166 /* Check whether we can satisfy the import of the module named by
171 'fullname'. Return self if we can, None if we can't. */
167 'fullname'. Return self if we can, None if we can't. */
172 PyObject *
168 PyObject *
173 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
169 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
174 {
170 {
175 PythonQtImporter *self = (PythonQtImporter *)obj;
171 PythonQtImporter *self = (PythonQtImporter *)obj;
176 PyObject *path = NULL;
172 PyObject *path = NULL;
177 char *fullname;
173 char *fullname;
178
174
179 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
175 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
180 &fullname, &path))
176 &fullname, &path))
181 return NULL;
177 return NULL;
182
178
183 //qDebug() << "looking for " << fullname << " at " << *self->_path;
179 //qDebug() << "looking for " << fullname << " at " << *self->_path;
184
180
185 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
181 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
186 if (info.type != PythonQtImport::MI_NOT_FOUND) {
182 if (info.type != PythonQtImport::MI_NOT_FOUND) {
187 Py_INCREF(self);
183 Py_INCREF(self);
188 return (PyObject *)self;
184 return (PyObject *)self;
189 } else {
185 } else {
190 Py_INCREF(Py_None);
186 Py_INCREF(Py_None);
191 return Py_None;
187 return Py_None;
192 }
188 }
193 }
189 }
194
190
195 /* Load and return the module named by 'fullname'. */
191 /* Load and return the module named by 'fullname'. */
196 PyObject *
192 PyObject *
197 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
193 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
198 {
194 {
199 PythonQtImporter *self = (PythonQtImporter *)obj;
195 PythonQtImporter *self = (PythonQtImporter *)obj;
200 PyObject *code = NULL, *mod = NULL, *dict = NULL;
196 PyObject *code = NULL, *mod = NULL, *dict = NULL;
201 char *fullname;
197 char *fullname;
202
198
203 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
199 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
204 &fullname))
200 &fullname))
205 return NULL;
201 return NULL;
206
202
207 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
203 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
208 if (info.type == PythonQtImport::MI_NOT_FOUND) {
204 if (info.type == PythonQtImport::MI_NOT_FOUND) {
209 return NULL;
205 return NULL;
210 }
206 }
211
207
212 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
208 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
213 QString fullPath;
209 QString fullPath;
214 code = PythonQtImport::getModuleCode(self, fullname, fullPath);
210 code = PythonQtImport::getModuleCode(self, fullname, fullPath);
215 if (code == NULL) {
211 if (code == NULL) {
216 return NULL;
212 return NULL;
217 }
213 }
218
214
219 mod = PyImport_AddModule(fullname);
215 mod = PyImport_AddModule(fullname);
220 if (mod == NULL) {
216 if (mod == NULL) {
221 Py_DECREF(code);
217 Py_DECREF(code);
222 return NULL;
218 return NULL;
223 }
219 }
224 dict = PyModule_GetDict(mod);
220 dict = PyModule_GetDict(mod);
225
221
226 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
222 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
227 Py_DECREF(code);
223 Py_DECREF(code);
228 Py_DECREF(mod);
224 Py_DECREF(mod);
229 return NULL;
225 return NULL;
230 }
226 }
231
227
232 if (info.type == PythonQtImport::MI_PACKAGE) {
228 if (info.type == PythonQtImport::MI_PACKAGE) {
233 PyObject *pkgpath, *fullpath;
229 PyObject *pkgpath, *fullpath;
234 QString subname = info.moduleName;
230 QString subname = info.moduleName;
235 int err;
231 int err;
236
232
237 #ifdef PY3K
233 #ifdef PY3K
238 fullpath = PyUnicode_FromFormat("%s%c%s",
234 fullpath = PyUnicode_FromFormat("%s%c%s",
239 #else
235 #else
240 fullpath = PyString_FromFormat("%s%c%s",
236 fullpath = PyString_FromFormat("%s%c%s",
241 #endif
237 #endif
242 self->_path->toLatin1().constData(),
238 self->_path->toLatin1().constData(),
243 SEP,
239 SEP,
244 subname.toLatin1().constData());
240 subname.toLatin1().constData());
245 if (fullpath == NULL) {
241 if (fullpath == NULL) {
246 Py_DECREF(code);
242 Py_DECREF(code);
247 Py_DECREF(mod);
243 Py_DECREF(mod);
248 return NULL;
244 return NULL;
249 }
245 }
250
246
251 pkgpath = Py_BuildValue("[O]", fullpath);
247 pkgpath = Py_BuildValue("[O]", fullpath);
252 Py_DECREF(fullpath);
248 Py_DECREF(fullpath);
253 if (pkgpath == NULL) {
249 if (pkgpath == NULL) {
254 Py_DECREF(code);
250 Py_DECREF(code);
255 Py_DECREF(mod);
251 Py_DECREF(mod);
256 return NULL;
252 return NULL;
257 }
253 }
258 err = PyDict_SetItemString(dict, "__path__", pkgpath);
254 err = PyDict_SetItemString(dict, "__path__", pkgpath);
259 Py_DECREF(pkgpath);
255 Py_DECREF(pkgpath);
260 if (err != 0) {
256 if (err != 0) {
261 Py_DECREF(code);
257 Py_DECREF(code);
262 Py_DECREF(mod);
258 Py_DECREF(mod);
263 return NULL;
259 return NULL;
264 }
260 }
265 }
261 }
266
262
267 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
263 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
268
264
269 if (PythonQt::importInterface()) {
265 if (PythonQt::importInterface()) {
270 PythonQt::importInterface()->importedModule(fullname);
266 PythonQt::importInterface()->importedModule(fullname);
271 }
267 }
272
268
273 Py_DECREF(code);
269 Py_DECREF(code);
274 if (Py_VerboseFlag) {
270 if (Py_VerboseFlag) {
275 PySys_WriteStderr("import %s # loaded from %s\n",
271 PySys_WriteStderr("import %s # loaded from %s\n",
276 fullname, fullPath.toLatin1().constData());
272 fullname, fullPath.toLatin1().constData());
277 }
273 }
278 } else {
274 } else {
279 PythonQtObjectPtr imp;
275 PythonQtObjectPtr imp;
280 imp.setNewRef(PyImport_ImportModule("imp"));
276 imp.setNewRef(PyImport_ImportModule("imp"));
281
277
282 // Create a PyList with the current path as its single element,
278 // Create a PyList with the current path as its single element,
283 // which is required for find_module (it won't accept a tuple...)
279 // which is required for find_module (it won't accept a tuple...)
284 PythonQtObjectPtr pathList;
280 PythonQtObjectPtr pathList;
285 pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
281 pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
286
282
287 QVariantList args;
283 QVariantList args;
288 // Pass the module name without the package prefix
284 // Pass the module name without the package prefix
289 args.append(info.moduleName);
285 args.append(info.moduleName);
290 // And the path where we know that the shared library is
286 // And the path where we know that the shared library is
291 args.append(QVariant::fromValue(pathList));
287 args.append(QVariant::fromValue(pathList));
292 QVariant result = imp.call("find_module", args);
288 QVariant result = imp.call("find_module", args);
293 if (result.isValid()) {
289 if (result.isValid()) {
294 // This will return a tuple with (file, pathname, description=(suffix,mode,type))
290 // This will return a tuple with (file, pathname, description=(suffix,mode,type))
295 QVariantList list = result.toList();
291 QVariantList list = result.toList();
296 if (list.count()==3) {
292 if (list.count()==3) {
297 // We prepend the full module name (including package prefix)
293 // We prepend the full module name (including package prefix)
298 list.prepend(fullname);
294 list.prepend(fullname);
299 #ifdef __linux
295 #ifdef __linux
300 #ifdef _DEBUG
296 #ifdef _DEBUG
301 // imp_find_module() does not respect the debug suffix '_d' on Linux,
297 // imp_find_module() does not respect the debug suffix '_d' on Linux,
302 // so it does not return the correct file path and we correct it now
298 // so it does not return the correct file path and we correct it now
303 // find_module opened a file to the release library, but that file handle is
299 // find_module opened a file to the release library, but that file handle is
304 // ignored on Linux and Windows, maybe on MacOS also.
300 // ignored on Linux and Windows, maybe on MacOS also.
305 list[2] = info.fullPath;
301 list[2] = info.fullPath;
306 #endif
302 #endif
307 #endif
303 #endif
308 // And call "load_module" with (fullname, file, pathname, description=(suffix,mode,type))
304 // And call "load_module" with (fullname, file, pathname, description=(suffix,mode,type))
309 PythonQtObjectPtr module = imp.call("load_module", list);
305 PythonQtObjectPtr module = imp.call("load_module", list);
310 mod = module.object();
306 mod = module.object();
311 if (mod) {
307 if (mod) {
312 Py_INCREF(mod);
308 Py_INCREF(mod);
313 }
309 }
314
310
315 // Finally, we need to close the file again, which find_module opened for us
311 // Finally, we need to close the file again, which find_module opened for us
316 PythonQtObjectPtr file = list.at(1);
312 PythonQtObjectPtr file = list.at(1);
317 file.call("close");
313 file.call("close");
318 }
314 }
319 }
315 }
320 }
316 }
321 return mod;
317 return mod;
322 }
318 }
323
319
324
320
325 PyObject *
321 PyObject *
326 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
322 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
327 {
323 {
328 // EXTRA, NOT YET IMPLEMENTED
324 // EXTRA, NOT YET IMPLEMENTED
329 return NULL;
325 return NULL;
330 }
326 }
331
327
332 PyObject *
328 PyObject *
333 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
329 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
334 {
330 {
335 PythonQtImporter *self = (PythonQtImporter *)obj;
331 PythonQtImporter *self = (PythonQtImporter *)obj;
336 char *fullname;
332 char *fullname;
337
333
338 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
334 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
339 return NULL;
335 return NULL;
340
336
341 QString notused;
337 QString notused;
342 return PythonQtImport::getModuleCode(self, fullname, notused);
338 return PythonQtImport::getModuleCode(self, fullname, notused);
343 }
339 }
344
340
345 PyObject *
341 PyObject *
346 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
342 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
347 {
343 {
348 // EXTRA, NOT YET IMPLEMENTED
344 // EXTRA, NOT YET IMPLEMENTED
349 return NULL;
345 return NULL;
350 }
346 }
351
347
352 PyDoc_STRVAR(doc_find_module,
348 PyDoc_STRVAR(doc_find_module,
353 "find_module(fullname, path=None) -> self or None.\n\
349 "find_module(fullname, path=None) -> self or None.\n\
354 \n\
350 \n\
355 Search for a module specified by 'fullname'. 'fullname' must be the\n\
351 Search for a module specified by 'fullname'. 'fullname' must be the\n\
356 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
352 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
357 instance itself if the module was found, or None if it wasn't.\n\
353 instance itself if the module was found, or None if it wasn't.\n\
358 The optional 'path' argument is ignored -- it's there for compatibility\n\
354 The optional 'path' argument is ignored -- it's there for compatibility\n\
359 with the importer protocol.");
355 with the importer protocol.");
360
356
361 PyDoc_STRVAR(doc_load_module,
357 PyDoc_STRVAR(doc_load_module,
362 "load_module(fullname) -> module.\n\
358 "load_module(fullname) -> module.\n\
363 \n\
359 \n\
364 Load the module specified by 'fullname'. 'fullname' must be the\n\
360 Load the module specified by 'fullname'. 'fullname' must be the\n\
365 fully qualified (dotted) module name. It returns the imported\n\
361 fully qualified (dotted) module name. It returns the imported\n\
366 module, or raises PythonQtImportError if it wasn't found.");
362 module, or raises PythonQtImportError if it wasn't found.");
367
363
368 PyDoc_STRVAR(doc_get_data,
364 PyDoc_STRVAR(doc_get_data,
369 "get_data(pathname) -> string with file data.\n\
365 "get_data(pathname) -> string with file data.\n\
370 \n\
366 \n\
371 Return the data associated with 'pathname'. Raise IOError if\n\
367 Return the data associated with 'pathname'. Raise IOError if\n\
372 the file wasn't found.");
368 the file wasn't found.");
373
369
374 PyDoc_STRVAR(doc_get_code,
370 PyDoc_STRVAR(doc_get_code,
375 "get_code(fullname) -> code object.\n\
371 "get_code(fullname) -> code object.\n\
376 \n\
372 \n\
377 Return the code object for the specified module. Raise PythonQtImportError\n\
373 Return the code object for the specified module. Raise PythonQtImportError\n\
378 is the module couldn't be found.");
374 is the module couldn't be found.");
379
375
380 PyDoc_STRVAR(doc_get_source,
376 PyDoc_STRVAR(doc_get_source,
381 "get_source(fullname) -> source string.\n\
377 "get_source(fullname) -> source string.\n\
382 \n\
378 \n\
383 Return the source code for the specified module. Raise PythonQtImportError\n\
379 Return the source code for the specified module. Raise PythonQtImportError\n\
384 is the module couldn't be found, return None if the archive does\n\
380 is the module couldn't be found, return None if the archive does\n\
385 contain the module, but has no source for it.");
381 contain the module, but has no source for it.");
386
382
387 PyMethodDef PythonQtImporter_methods[] = {
383 PyMethodDef PythonQtImporter_methods[] = {
388 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
384 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
389 doc_find_module},
385 doc_find_module},
390 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
386 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
391 doc_load_module},
387 doc_load_module},
392 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
388 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
393 doc_get_data},
389 doc_get_data},
394 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
390 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
395 doc_get_code},
391 doc_get_code},
396 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
392 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
397 doc_get_source},
393 doc_get_source},
398 {NULL, NULL, 0 , NULL} /* sentinel */
394 {NULL, NULL, 0 , NULL} /* sentinel */
399 };
395 };
400
396
401
397
402 PyDoc_STRVAR(PythonQtImporter_doc,
398 PyDoc_STRVAR(PythonQtImporter_doc,
403 "PythonQtImporter(path) -> PythonQtImporter object\n\
399 "PythonQtImporter(path) -> PythonQtImporter object\n\
404 \n\
400 \n\
405 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
401 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
406 . Every path is accepted.");
402 . Every path is accepted.");
407
403
408 #define DEFERRED_ADDRESS(ADDR) 0
404 #define DEFERRED_ADDRESS(ADDR) 0
409
405
410 PyTypeObject PythonQtImporter_Type = {
406 PyTypeObject PythonQtImporter_Type = {
411 PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
407 PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
412 "PythonQtImport.PythonQtImporter",
408 "PythonQtImport.PythonQtImporter",
413 sizeof(PythonQtImporter),
409 sizeof(PythonQtImporter),
414 0, /* tp_itemsize */
410 0, /* tp_itemsize */
415 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
411 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
416 0, /* tp_print */
412 0, /* tp_print */
417 0, /* tp_getattr */
413 0, /* tp_getattr */
418 0, /* tp_setattr */
414 0, /* tp_setattr */
419 0, /* tp_compare */
415 0, /* tp_compare */
420 0, /* tp_repr */
416 0, /* tp_repr */
421 0, /* tp_as_number */
417 0, /* tp_as_number */
422 0, /* tp_as_sequence */
418 0, /* tp_as_sequence */
423 0, /* tp_as_mapping */
419 0, /* tp_as_mapping */
424 0, /* tp_hash */
420 0, /* tp_hash */
425 0, /* tp_call */
421 0, /* tp_call */
426 0, /* tp_str */
422 0, /* tp_str */
427 PyObject_GenericGetAttr, /* tp_getattro */
423 PyObject_GenericGetAttr, /* tp_getattro */
428 0, /* tp_setattro */
424 0, /* tp_setattro */
429 0, /* tp_as_buffer */
425 0, /* tp_as_buffer */
430 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
426 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
431 PythonQtImporter_doc, /* tp_doc */
427 PythonQtImporter_doc, /* tp_doc */
432 0, /* tp_traverse */
428 0, /* tp_traverse */
433 0, /* tp_clear */
429 0, /* tp_clear */
434 0, /* tp_richcompare */
430 0, /* tp_richcompare */
435 0, /* tp_weaklistoffset */
431 0, /* tp_weaklistoffset */
436 0, /* tp_iter */
432 0, /* tp_iter */
437 0, /* tp_iternext */
433 0, /* tp_iternext */
438 PythonQtImporter_methods, /* tp_methods */
434 PythonQtImporter_methods, /* tp_methods */
439 0, /* tp_members */
435 0, /* tp_members */
440 0, /* tp_getset */
436 0, /* tp_getset */
441 0, /* tp_base */
437 0, /* tp_base */
442 0, /* tp_dict */
438 0, /* tp_dict */
443 0, /* tp_descr_get */
439 0, /* tp_descr_get */
444 0, /* tp_descr_set */
440 0, /* tp_descr_set */
445 0, /* tp_dictoffset */
441 0, /* tp_dictoffset */
446 (initproc)PythonQtImporter_init, /* tp_init */
442 (initproc)PythonQtImporter_init, /* tp_init */
447 PyType_GenericAlloc, /* tp_alloc */
443 PyType_GenericAlloc, /* tp_alloc */
448 PyType_GenericNew, /* tp_new */
444 PyType_GenericNew, /* tp_new */
449 PyObject_Del, /* tp_free */
445 PyObject_Del, /* tp_free */
450 };
446 };
451
447
452
448
453 /* Given a buffer, return the long that is represented by the first
449 /* Given a buffer, return the long that is represented by the first
454 4 bytes, encoded as little endian. This partially reimplements
450 4 bytes, encoded as little endian. This partially reimplements
455 marshal.c:r_long() */
451 marshal.c:r_long() */
456 long
452 long
457 PythonQtImport::getLong(unsigned char *buf)
453 PythonQtImport::getLong(unsigned char *buf)
458 {
454 {
459 long x;
455 long x;
460 x = buf[0];
456 x = buf[0];
461 x |= (long)buf[1] << 8;
457 x |= (long)buf[1] << 8;
462 x |= (long)buf[2] << 16;
458 x |= (long)buf[2] << 16;
463 x |= (long)buf[3] << 24;
459 x |= (long)buf[3] << 24;
464 #if SIZEOF_LONG > 4
460 #if SIZEOF_LONG > 4
465 /* Sign extension for 64-bit machines */
461 /* Sign extension for 64-bit machines */
466 x |= -(x & 0x80000000L);
462 x |= -(x & 0x80000000L);
467 #endif
463 #endif
468 return x;
464 return x;
469 }
465 }
470
466
471 FILE *
467 FILE *
472 open_exclusive(const QString& filename)
468 open_exclusive(const QString& filename)
473 {
469 {
474 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
470 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
475 /* Use O_EXCL to avoid a race condition when another process tries to
471 /* Use O_EXCL to avoid a race condition when another process tries to
476 write the same file. When that happens, our open() call fails,
472 write the same file. When that happens, our open() call fails,
477 which is just fine (since it's only a cache).
473 which is just fine (since it's only a cache).
478 XXX If the file exists and is writable but the directory is not
474 XXX If the file exists and is writable but the directory is not
479 writable, the file will never be written. Oh well.
475 writable, the file will never be written. Oh well.
480 */
476 */
481 QFile::remove(filename);
477 QFile::remove(filename);
482
478
483 int fd;
479 int fd;
484 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
480 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
485 #ifdef O_BINARY
481 #ifdef O_BINARY
486 flags |= O_BINARY; /* necessary for Windows */
482 flags |= O_BINARY; /* necessary for Windows */
487 #endif
483 #endif
488 #ifdef WIN32
484 #ifdef WIN32
489 fd = _wopen(filename.ucs2(), flags, 0666);
485 fd = _wopen(filename.ucs2(), flags, 0666);
490 #else
486 #else
491 fd = open(filename.local8Bit(), flags, 0666);
487 fd = open(filename.local8Bit(), flags, 0666);
492 #endif
488 #endif
493 if (fd < 0)
489 if (fd < 0)
494 return NULL;
490 return NULL;
495 return fdopen(fd, "wb");
491 return fdopen(fd, "wb");
496 #else
492 #else
497 /* Best we can do -- on Windows this can't happen anyway */
493 /* Best we can do -- on Windows this can't happen anyway */
498 return fopen(filename.toLocal8Bit().constData(), "wb");
494 return fopen(filename.toLocal8Bit().constData(), "wb");
499 #endif
495 #endif
500 }
496 }
501
497
502
498
503 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
499 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
504 {
500 {
505 FILE *fp;
501 FILE *fp;
506 // we do not want to write Qt resources to disk, do we?
502 // we do not want to write Qt resources to disk, do we?
507 if (filename.startsWith(":")) {
503 if (filename.startsWith(":")) {
508 return;
504 return;
509 }
505 }
510 fp = open_exclusive(filename);
506 fp = open_exclusive(filename);
511 if (fp == NULL) {
507 if (fp == NULL) {
512 if (Py_VerboseFlag)
508 if (Py_VerboseFlag)
513 PySys_WriteStderr(
509 PySys_WriteStderr(
514 "# can't create %s\n", filename.toLatin1().constData());
510 "# can't create %s\n", filename.toLatin1().constData());
515 return;
511 return;
516 }
512 }
517 #if PY_VERSION_HEX < 0x02040000
513 #if PY_VERSION_HEX < 0x02040000
518 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
514 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
519 #else
515 #else
520 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
516 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
521 #endif
517 #endif
522 /* First write a 0 for mtime */
518 /* First write a 0 for mtime */
523 #if PY_VERSION_HEX < 0x02040000
519 #if PY_VERSION_HEX < 0x02040000
524 PyMarshal_WriteLongToFile(0L, fp);
520 PyMarshal_WriteLongToFile(0L, fp);
525 #else
521 #else
526 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
522 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
527 #endif
523 #endif
528 #if PY_VERSION_HEX < 0x02040000
524 #if PY_VERSION_HEX < 0x02040000
529 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
525 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
530 #else
526 #else
531 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
527 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
532 #endif
528 #endif
533 if (ferror(fp)) {
529 if (ferror(fp)) {
534 if (Py_VerboseFlag)
530 if (Py_VerboseFlag)
535 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
531 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
536 /* Don't keep partial file */
532 /* Don't keep partial file */
537 fclose(fp);
533 fclose(fp);
538 QFile::remove(filename);
534 QFile::remove(filename);
539 return;
535 return;
540 }
536 }
541 /* Now write the true mtime */
537 /* Now write the true mtime */
542 fseek(fp, 4L, 0);
538 fseek(fp, 4L, 0);
543 #if PY_VERSION_HEX < 0x02040000
539 #if PY_VERSION_HEX < 0x02040000
544 PyMarshal_WriteLongToFile(mtime, fp);
540 PyMarshal_WriteLongToFile(mtime, fp);
545 #else
541 #else
546 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
542 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
547 #endif
543 #endif
548 fflush(fp);
544 fflush(fp);
549 fclose(fp);
545 fclose(fp);
550 if (Py_VerboseFlag)
546 if (Py_VerboseFlag)
551 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
547 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
552 //#ifdef macintosh
548 //#ifdef macintosh
553 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
549 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
554 //#endif
550 //#endif
555 }
551 }
556
552
557 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
553 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
558 and return the code object. Return None if it the magic word doesn't
554 and return the code object. Return None if it the magic word doesn't
559 match (we do this instead of raising an exception as we fall back
555 match (we do this instead of raising an exception as we fall back
560 to .py if available and we don't want to mask other errors).
556 to .py if available and we don't want to mask other errors).
561 Returns a new reference. */
557 Returns a new reference. */
562 PyObject *
558 PyObject *
563 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
559 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
564 {
560 {
565 PyObject *code;
561 PyObject *code;
566 // ugly cast, but Python API is not const safe
562 // ugly cast, but Python API is not const safe
567 char *buf = (char*) data.constData();
563 char *buf = (char*) data.constData();
568 int size = data.size();
564 int size = data.size();
569
565
570 if (size <= 9) {
566 if (size <= 9) {
571 PySys_WriteStderr("# %s has bad pyc data\n",
567 PySys_WriteStderr("# %s has bad pyc data\n",
572 path.toLatin1().constData());
568 path.toLatin1().constData());
573 Py_INCREF(Py_None);
569 Py_INCREF(Py_None);
574 return Py_None;
570 return Py_None;
575 }
571 }
576
572
577 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
573 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
578 if (Py_VerboseFlag)
574 if (Py_VerboseFlag)
579 PySys_WriteStderr("# %s has bad magic\n",
575 PySys_WriteStderr("# %s has bad magic\n",
580 path.toLatin1().constData());
576 path.toLatin1().constData());
581 Py_INCREF(Py_None);
577 Py_INCREF(Py_None);
582 return Py_None;
578 return Py_None;
583 }
579 }
584
580
585 if (mtime != 0) {
581 if (mtime != 0) {
586 time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime;
582 time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime;
587 if (timeDiff<0) { timeDiff = -timeDiff; }
583 if (timeDiff<0) { timeDiff = -timeDiff; }
588 if (timeDiff > 1) {
584 if (timeDiff > 1) {
589 if (Py_VerboseFlag)
585 if (Py_VerboseFlag)
590 PySys_WriteStderr("# %s has bad mtime\n",
586 PySys_WriteStderr("# %s has bad mtime\n",
591 path.toLatin1().constData());
587 path.toLatin1().constData());
592 Py_INCREF(Py_None);
588 Py_INCREF(Py_None);
593 return Py_None;
589 return Py_None;
594 }
590 }
595 }
591 }
596
592
597 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
593 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
598 if (code == NULL)
594 if (code == NULL)
599 return NULL;
595 return NULL;
600 if (!PyCode_Check(code)) {
596 if (!PyCode_Check(code)) {
601 Py_DECREF(code);
597 Py_DECREF(code);
602 PyErr_Format(PyExc_TypeError,
598 PyErr_Format(PyExc_TypeError,
603 "compiled module %.200s is not a code object",
599 "compiled module %.200s is not a code object",
604 path.toLatin1().constData());
600 path.toLatin1().constData());
605 return NULL;
601 return NULL;
606 }
602 }
607 return code;
603 return code;
608 }
604 }
609
605
610
606
611 /* Given a string buffer containing Python source code, compile it
607 /* Given a string buffer containing Python source code, compile it
612 return and return a code object as a new reference. */
608 return and return a code object as a new reference. */
613 PyObject *
609 PyObject *
614 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
610 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
615 {
611 {
616 PyObject *code;
612 PyObject *code;
617 QByteArray data1 = data;
613 QByteArray data1 = data;
618 // in qt4, data is null terminated
614 // in qt4, data is null terminated
619 // data1.resize(data.size()+1);
615 // data1.resize(data.size()+1);
620 // data1.data()[data.size()-1] = 0;
616 // data1.data()[data.size()-1] = 0;
621 code = Py_CompileString(data.data(), path.toLatin1().constData(),
617 code = Py_CompileString(data.data(), path.toLatin1().constData(),
622 Py_file_input);
618 Py_file_input);
623 return code;
619 return code;
624 }
620 }
625
621
626
622
627 /* Return the code object for the module named by 'fullname' from the
623 /* Return the code object for the module named by 'fullname' from the
628 Zip archive as a new reference. */
624 Zip archive as a new reference. */
629 PyObject *
625 PyObject *
630 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
626 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
631 {
627 {
632 PyObject *code;
628 PyObject *code;
633
629
634 QByteArray qdata;
630 QByteArray qdata;
635 if (!isbytecode) {
631 if (!isbytecode) {
636 // mlabDebugConst("MLABPython", "reading source " << path);
632 // mlabDebugConst("MLABPython", "reading source " << path);
637 bool ok;
633 bool ok;
638 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
634 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
639 if (!ok) {
635 if (!ok) {
640 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
636 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
641 return NULL;
637 return NULL;
642 }
638 }
643 if (qdata == " ") {
639 if (qdata == " ") {
644 qdata.clear();
640 qdata.clear();
645 }
641 }
646 } else {
642 } else {
647 qdata = PythonQt::importInterface()->readFileAsBytes(path);
643 qdata = PythonQt::importInterface()->readFileAsBytes(path);
648 }
644 }
649
645
650 if (isbytecode) {
646 if (isbytecode) {
651 // mlabDebugConst("MLABPython", "reading bytecode " << path);
647 // mlabDebugConst("MLABPython", "reading bytecode " << path);
652 code = unmarshalCode(path, qdata, mtime);
648 code = unmarshalCode(path, qdata, mtime);
653 }
649 }
654 else {
650 else {
655 // mlabDebugConst("MLABPython", "compiling source " << path);
651 // mlabDebugConst("MLABPython", "compiling source " << path);
656 code = compileSource(path, qdata);
652 code = compileSource(path, qdata);
657 if (code) {
653 if (code) {
658 // save a pyc file if possible
654 // save a pyc file if possible
659 QDateTime time;
655 QDateTime time;
660 time = PythonQt::importInterface()->lastModifiedDate(path);
656 time = PythonQt::importInterface()->lastModifiedDate(path);
661 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
657 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
662 }
658 }
663 }
659 }
664 return code;
660 return code;
665 }
661 }
666
662
667 time_t
663 time_t
668 PythonQtImport::getMTimeOfSource(const QString& path)
664 PythonQtImport::getMTimeOfSource(const QString& path)
669 {
665 {
670 time_t mtime = 0;
666 time_t mtime = 0;
671 QString path2 = path;
667 QString path2 = path;
672 path2.truncate(path.length()-1);
668 path2.truncate(path.length()-1);
673
669
674 if (PythonQt::importInterface()->exists(path2)) {
670 if (PythonQt::importInterface()->exists(path2)) {
675 QDateTime t = PythonQt::importInterface()->lastModifiedDate(path2);
671 QDateTime t = PythonQt::importInterface()->lastModifiedDate(path2);
676 if (t.isValid()) {
672 if (t.isValid()) {
677 mtime = t.toTime_t();
673 mtime = t.toTime_t();
678 }
674 }
679 }
675 }
680
676
681 return mtime;
677 return mtime;
682 }
678 }
683
679
684 /* Get the code object associated with the module specified by
680 /* Get the code object associated with the module specified by
685 'fullname'. */
681 'fullname'. */
686 PyObject *
682 PyObject *
687 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
683 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
688 {
684 {
689 QString subname;
685 QString subname;
690 struct st_mlab_searchorder *zso;
686 struct st_mlab_searchorder *zso;
691
687
692 subname = getSubName(fullname);
688 subname = getSubName(fullname);
693 QString path = *self->_path + "/" + subname;
689 QString path = *self->_path + "/" + subname;
694
690
695 QString test;
691 QString test;
696 for (zso = mlab_searchorder; *zso->suffix; zso++) {
692 for (zso = mlab_searchorder; *zso->suffix; zso++) {
697 PyObject *code = NULL;
693 PyObject *code = NULL;
698 test = path + zso->suffix;
694 test = path + zso->suffix;
699
695
700 if (Py_VerboseFlag > 1)
696 if (Py_VerboseFlag > 1)
701 PySys_WriteStderr("# trying %s\n",
697 PySys_WriteStderr("# trying %s\n",
702 test.toLatin1().constData());
698 test.toLatin1().constData());
703 if (PythonQt::importInterface()->exists(test)) {
699 if (PythonQt::importInterface()->exists(test)) {
704 time_t mtime = 0;
700 time_t mtime = 0;
705 int ispackage = zso->type & IS_PACKAGE;
701 int ispackage = zso->type & IS_PACKAGE;
706 int isbytecode = zso->type & IS_BYTECODE;
702 int isbytecode = zso->type & IS_BYTECODE;
707
703
708 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
704 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
709 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
705 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
710 // even if a newer *.py file exists. This is a release optimization where
706 // even if a newer *.py file exists. This is a release optimization where
711 // typically only *.pyc files are delivered without *.py files and reading file
707 // typically only *.pyc files are delivered without *.py files and reading file
712 // modification time is slow.
708 // modification time is slow.
713 if (isbytecode && !PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
709 if (isbytecode && !PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
714 mtime = getMTimeOfSource(test);
710 mtime = getMTimeOfSource(test);
715 }
711 }
716 code = getCodeFromData(test, isbytecode, ispackage, mtime);
712 code = getCodeFromData(test, isbytecode, ispackage, mtime);
717 if (code == Py_None) {
713 if (code == Py_None) {
718 Py_DECREF(code);
714 Py_DECREF(code);
719 continue;
715 continue;
720 }
716 }
721 if (code != NULL) {
717 if (code != NULL) {
722 modpath = test;
718 modpath = test;
723 }
719 }
724 return code;
720 return code;
725 }
721 }
726 }
722 }
727 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
723 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
728
724
729 return NULL;
725 return NULL;
730 }
726 }
731
727
732 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
728 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
733 {
729 {
734 QString r;
730 QString r;
735 int i = str.lastIndexOf('.');
731 int i = str.lastIndexOf('.');
736 if (i!=-1) {
732 if (i!=-1) {
737 r = str.mid(0,i) + "." + ext;
733 r = str.mid(0,i) + "." + ext;
738 } else {
734 } else {
739 r = str + "." + ext;
735 r = str + "." + ext;
740 }
736 }
741 return r;
737 return r;
742 }
738 }
743
739
744 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
740 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
745 {
741 {
746 PyObject* code;
742 PyObject* code;
747 const static QString pycStr("pyc");
743 const static QString pycStr("pyc");
748 QString pyc = replaceExtension(file, pycStr);
744 QString pyc = replaceExtension(file, pycStr);
749 if (PythonQt::importInterface()->exists(pyc)) {
745 if (PythonQt::importInterface()->exists(pyc)) {
750 time_t mtime = 0;
746 time_t mtime = 0;
751 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
747 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
752 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
748 // and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
753 // even if a newer *.py file exists. This is a release optimization where
749 // even if a newer *.py file exists. This is a release optimization where
754 // typically only *.pyc files are delivered without *.py files and reading file
750 // typically only *.pyc files are delivered without *.py files and reading file
755 // modification time is slow.
751 // modification time is slow.
756 if (!PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
752 if (!PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
757 mtime = getMTimeOfSource(pyc);
753 mtime = getMTimeOfSource(pyc);
758 }
754 }
759 code = getCodeFromData(pyc, true, false, mtime);
755 code = getCodeFromData(pyc, true, false, mtime);
760 if (code != Py_None && code != NULL) {
756 if (code != Py_None && code != NULL) {
761 return code;
757 return code;
762 }
758 }
763 if (code) {
759 if (code) {
764 Py_DECREF(code);
760 Py_DECREF(code);
765 }
761 }
766 }
762 }
767 code = getCodeFromData(file,false,false,0);
763 code = getCodeFromData(file,false,false,0);
768 return code;
764 return code;
769 }
765 }
770
766
771 /* Module init */
767 /* Module init */
772
768
773 PyDoc_STRVAR(mlabimport_doc,
769 PyDoc_STRVAR(mlabimport_doc,
774 "Imports python files into PythonQt, completely replaces internal python import");
770 "Imports python files into PythonQt, completely replaces internal python import");
775
771
776 #ifdef PY3K
772 #ifdef PY3K
777 static struct PyModuleDef PythonQtImport_def = {
773 static struct PyModuleDef PythonQtImport_def = {
778 PyModuleDef_HEAD_INIT,
774 PyModuleDef_HEAD_INIT,
779 "PythonQtImport", /* m_name */
775 "PythonQtImport", /* m_name */
780 mlabimport_doc, /* m_doc */
776 mlabimport_doc, /* m_doc */
781 -1, /* m_size */
777 -1, /* m_size */
782 NULL, /* m_methods */
778 NULL, /* m_methods */
783 NULL, /* m_reload */
779 NULL, /* m_reload */
784 NULL, /* m_traverse */
780 NULL, /* m_traverse */
785 NULL, /* m_clear */
781 NULL, /* m_clear */
786 NULL /* m_free */
782 NULL /* m_free */
787 };
783 };
788 #endif
784 #endif
789
785
790 void PythonQtImport::init()
786 void PythonQtImport::init()
791 {
787 {
792 static bool first = true;
788 static bool first = true;
793 if (!first) {
789 if (!first) {
794 return;
790 return;
795 }
791 }
796 first = false;
792 first = false;
797
793
798 PyObject *mod;
794 PyObject *mod;
799
795
800 if (PyType_Ready(&PythonQtImporter_Type) < 0)
796 if (PyType_Ready(&PythonQtImporter_Type) < 0)
801 return;
797 return;
802
798
803 /* Correct directory separator */
799 /* Correct directory separator */
804 mlab_searchorder[0].suffix[0] = SEP;
800 mlab_searchorder[0].suffix[0] = SEP;
805 mlab_searchorder[1].suffix[0] = SEP;
801 mlab_searchorder[1].suffix[0] = SEP;
806 mlab_searchorder[2].suffix[0] = SEP;
802 mlab_searchorder[2].suffix[0] = SEP;
807 if (Py_OptimizeFlag) {
803 if (Py_OptimizeFlag) {
808 /* Reverse *.pyc and *.pyo */
804 /* Reverse *.pyc and *.pyo */
809 struct st_mlab_searchorder tmp;
805 struct st_mlab_searchorder tmp;
810 tmp = mlab_searchorder[0];
806 tmp = mlab_searchorder[0];
811 mlab_searchorder[0] = mlab_searchorder[1];
807 mlab_searchorder[0] = mlab_searchorder[1];
812 mlab_searchorder[1] = tmp;
808 mlab_searchorder[1] = tmp;
813 tmp = mlab_searchorder[3];
809 tmp = mlab_searchorder[3];
814 mlab_searchorder[3] = mlab_searchorder[4];
810 mlab_searchorder[3] = mlab_searchorder[4];
815 mlab_searchorder[4] = tmp;
811 mlab_searchorder[4] = tmp;
816 }
812 }
817
813
818 #ifdef PY3K
814 #ifdef PY3K
819 mod = PyModule_Create(&PythonQtImport_def);
815 mod = PyModule_Create(&PythonQtImport_def);
820 #else
816 #else
821 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
817 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
822 NULL, PYTHON_API_VERSION);
818 NULL, PYTHON_API_VERSION);
823 #endif
819 #endif
824
820
825 PythonQtImportError = PyErr_NewException(const_cast<char*>("PythonQtImport.PythonQtImportError"),
821 PythonQtImportError = PyErr_NewException(const_cast<char*>("PythonQtImport.PythonQtImportError"),
826 PyExc_ImportError, NULL);
822 PyExc_ImportError, NULL);
827 if (PythonQtImportError == NULL)
823 if (PythonQtImportError == NULL)
828 return;
824 return;
829
825
830 Py_INCREF(PythonQtImportError);
826 Py_INCREF(PythonQtImportError);
831 if (PyModule_AddObject(mod, "PythonQtImportError",
827 if (PyModule_AddObject(mod, "PythonQtImportError",
832 PythonQtImportError) < 0)
828 PythonQtImportError) < 0)
833 return;
829 return;
834
830
835 Py_INCREF(&PythonQtImporter_Type);
831 Py_INCREF(&PythonQtImporter_Type);
836 if (PyModule_AddObject(mod, "PythonQtImporter",
832 if (PyModule_AddObject(mod, "PythonQtImporter",
837 (PyObject *)&PythonQtImporter_Type) < 0)
833 (PyObject *)&PythonQtImporter_Type) < 0)
838 return;
834 return;
839
835
840 // set our importer into the path_hooks to handle all path on sys.path
836 // set our importer into the path_hooks to handle all path on sys.path
841 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
837 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
842 PyObject* path_hooks = PySys_GetObject(const_cast<char*>("path_hooks"));
838 PyObject* path_hooks = PySys_GetObject(const_cast<char*>("path_hooks"));
843 PyList_Append(path_hooks, classobj);
839 PyList_Append(path_hooks, classobj);
844
840
845 #ifndef WIN32
841 #ifndef WIN32
846 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
842 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
847 PyObject* modules = PyImport_GetModuleDict();
843 PyObject* modules = PyImport_GetModuleDict();
848 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
844 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
849 if (encodingsModule != NULL) {
845 if (encodingsModule != NULL) {
850 PyImport_ReloadModule(encodingsModule);
846 PyImport_ReloadModule(encodingsModule);
851 }
847 }
852 #endif
848 #endif
853 }
849 }
@@ -1,848 +1,844
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, 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 PythonQtInstanceWrapper.cpp
35 // \file PythonQtInstanceWrapper.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 "PythonQtInstanceWrapper.h"
42 #include "PythonQtInstanceWrapper.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 "PythonQtSignal.h"
46 #include "PythonQtSignal.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49 #include "PythonQtClassWrapper.h"
49 #include "PythonQtClassWrapper.h"
50
50
51 #if PY_MAJOR_VERSION >= 3
52 #define PY3K
53 #endif
54
55 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
51 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
56 {
52 {
57 // take the class info from our type object
53 // take the class info from our type object
58 return ((PythonQtClassWrapper*)Py_TYPE(this))->_classInfo;
54 return ((PythonQtClassWrapper*)Py_TYPE(this))->_classInfo;
59 }
55 }
60
56
61 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
57 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
62
58
63 // is this a C++ wrapper?
59 // is this a C++ wrapper?
64 if (self->_wrappedPtr) {
60 if (self->_wrappedPtr) {
65 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
61 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
66
62
67 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
63 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
68 // we own our qobject, so we delete it now:
64 // we own our qobject, so we delete it now:
69 delete self->_obj;
65 delete self->_obj;
70 self->_obj = NULL;
66 self->_obj = NULL;
71 if (force || self->_ownedByPythonQt) {
67 if (force || self->_ownedByPythonQt) {
72 int type = self->classInfo()->metaTypeId();
68 int type = self->classInfo()->metaTypeId();
73 if (self->_useQMetaTypeDestroy && type>=0) {
69 if (self->_useQMetaTypeDestroy && type>=0) {
74 // use QMetaType to destroy the object
70 // use QMetaType to destroy the object
75 QMetaType::destroy(type, self->_wrappedPtr);
71 QMetaType::destroy(type, self->_wrappedPtr);
76 } else {
72 } else {
77 PythonQtSlotInfo* slot = self->classInfo()->destructor();
73 PythonQtSlotInfo* slot = self->classInfo()->destructor();
78 if (slot) {
74 if (slot) {
79 void* args[2];
75 void* args[2];
80 args[0] = NULL;
76 args[0] = NULL;
81 args[1] = &self->_wrappedPtr;
77 args[1] = &self->_wrappedPtr;
82 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
78 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
83 self->_wrappedPtr = NULL;
79 self->_wrappedPtr = NULL;
84 } else {
80 } else {
85 if (type>=0) {
81 if (type>=0) {
86 // use QMetaType to destroy the object
82 // use QMetaType to destroy the object
87 QMetaType::destroy(type, self->_wrappedPtr);
83 QMetaType::destroy(type, self->_wrappedPtr);
88 } else {
84 } else {
89 // TODO: warn about not being able to destroy the object?
85 // TODO: warn about not being able to destroy the object?
90 }
86 }
91 }
87 }
92 }
88 }
93 }
89 }
94 } else {
90 } else {
95 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
91 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
96 if (self->_objPointerCopy) {
92 if (self->_objPointerCopy) {
97 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
93 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
98 }
94 }
99 if (self->_obj) {
95 if (self->_obj) {
100 if (force || self->_ownedByPythonQt) {
96 if (force || self->_ownedByPythonQt) {
101 if (force || !self->_obj->parent()) {
97 if (force || !self->_obj->parent()) {
102 delete self->_obj;
98 delete self->_obj;
103 }
99 }
104 } else {
100 } else {
105 if (self->_obj->parent()==NULL) {
101 if (self->_obj->parent()==NULL) {
106 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
102 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
107 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
103 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
108 }
104 }
109 }
105 }
110 }
106 }
111 }
107 }
112 self->_obj = NULL;
108 self->_obj = NULL;
113 }
109 }
114
110
115 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
111 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
116 {
112 {
117 PythonQtInstanceWrapper_deleteObject(self);
113 PythonQtInstanceWrapper_deleteObject(self);
118 self->_obj.~QPointer<QObject>();
114 self->_obj.~QPointer<QObject>();
119 Py_TYPE(self)->tp_free((PyObject*)self);
115 Py_TYPE(self)->tp_free((PyObject*)self);
120 }
116 }
121
117
122 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
118 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
123 {
119 {
124 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
120 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
125 PythonQtInstanceWrapper *self;
121 PythonQtInstanceWrapper *self;
126 static PyObject* emptyTuple = NULL;
122 static PyObject* emptyTuple = NULL;
127 if (emptyTuple==NULL) {
123 if (emptyTuple==NULL) {
128 emptyTuple = PyTuple_New(0);
124 emptyTuple = PyTuple_New(0);
129 }
125 }
130
126
131 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
127 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
132
128
133 if (self != NULL) {
129 if (self != NULL) {
134 new (&self->_obj) QPointer<QObject>();
130 new (&self->_obj) QPointer<QObject>();
135 self->_wrappedPtr = NULL;
131 self->_wrappedPtr = NULL;
136 self->_ownedByPythonQt = false;
132 self->_ownedByPythonQt = false;
137 self->_useQMetaTypeDestroy = false;
133 self->_useQMetaTypeDestroy = false;
138 self->_isShellInstance = false;
134 self->_isShellInstance = false;
139 }
135 }
140 return (PyObject *)self;
136 return (PyObject *)self;
141 }
137 }
142
138
143 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
139 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
144 {
140 {
145 if (args == PythonQtPrivate::dummyTuple()) {
141 if (args == PythonQtPrivate::dummyTuple()) {
146 // we are called from the internal PythonQt API, so our data will be filled later on...
142 // we are called from the internal PythonQt API, so our data will be filled later on...
147 return 0;
143 return 0;
148 }
144 }
149
145
150 // we are called from python, try to construct our object
146 // we are called from python, try to construct our object
151 if (self->classInfo()->constructors()) {
147 if (self->classInfo()->constructors()) {
152 void* directCPPPointer = NULL;
148 void* directCPPPointer = NULL;
153 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
149 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
154 if (PyErr_Occurred()) {
150 if (PyErr_Occurred()) {
155 return -1;
151 return -1;
156 }
152 }
157 if (directCPPPointer) {
153 if (directCPPPointer) {
158 // change ownershipflag to be owned by PythonQt
154 // change ownershipflag to be owned by PythonQt
159 self->_ownedByPythonQt = true;
155 self->_ownedByPythonQt = true;
160 self->_useQMetaTypeDestroy = false;
156 self->_useQMetaTypeDestroy = false;
161 if (self->classInfo()->isCPPWrapper()) {
157 if (self->classInfo()->isCPPWrapper()) {
162 self->_wrappedPtr = directCPPPointer;
158 self->_wrappedPtr = directCPPPointer;
163 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
159 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
164 } else {
160 } else {
165 self->setQObject((QObject*)directCPPPointer);
161 self->setQObject((QObject*)directCPPPointer);
166 }
162 }
167 // register with PythonQt
163 // register with PythonQt
168 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
164 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
169
165
170 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
166 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
171 if (cb) {
167 if (cb) {
172 // if we are a derived python class, we set the wrapper
168 // if we are a derived python class, we set the wrapper
173 // to activate the shell class, otherwise we just ignore that it is a shell...
169 // to activate the shell class, otherwise we just ignore that it is a shell...
174 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
170 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
175 // which is the case for all non-python derived types
171 // which is the case for all non-python derived types
176 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
172 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
177 // set the wrapper and remember that we have a shell instance!
173 // set the wrapper and remember that we have a shell instance!
178 (*cb)(directCPPPointer, self);
174 (*cb)(directCPPPointer, self);
179 self->_isShellInstance = true;
175 self->_isShellInstance = true;
180 }
176 }
181 }
177 }
182 }
178 }
183 } else {
179 } else {
184 QString error = QString("No constructors available for ") + self->classInfo()->className();
180 QString error = QString("No constructors available for ") + self->classInfo()->className();
185 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
181 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
186 return -1;
182 return -1;
187 }
183 }
188 return 0;
184 return 0;
189 }
185 }
190
186
191 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
187 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
192 {
188 {
193 bool validPtrs = false;
189 bool validPtrs = false;
194 bool areSamePtrs = false;
190 bool areSamePtrs = false;
195 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
191 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
196 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
192 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
197 validPtrs = true;
193 validPtrs = true;
198 PythonQtInstanceWrapper* w1 = wrapper;
194 PythonQtInstanceWrapper* w1 = wrapper;
199 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
195 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
200 // check pointers directly
196 // check pointers directly
201 if (w1->_wrappedPtr != NULL) {
197 if (w1->_wrappedPtr != NULL) {
202 if (w1->_wrappedPtr == w2->_wrappedPtr) {
198 if (w1->_wrappedPtr == w2->_wrappedPtr) {
203 areSamePtrs = true;
199 areSamePtrs = true;
204 }
200 }
205 } else if (w1->_obj == w2->_obj) {
201 } else if (w1->_obj == w2->_obj) {
206 areSamePtrs = true;
202 areSamePtrs = true;
207 }
203 }
208 } else if (other == Py_None) {
204 } else if (other == Py_None) {
209 validPtrs = true;
205 validPtrs = true;
210 if (wrapper->_obj || wrapper->_wrappedPtr) {
206 if (wrapper->_obj || wrapper->_wrappedPtr) {
211 areSamePtrs = false;
207 areSamePtrs = false;
212 } else {
208 } else {
213 areSamePtrs = true;
209 areSamePtrs = true;
214 }
210 }
215 }
211 }
216 }
212 }
217
213
218 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
214 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
219 // shortcut if richcompare is not supported:
215 // shortcut if richcompare is not supported:
220 if (validPtrs && code == Py_EQ) {
216 if (validPtrs && code == Py_EQ) {
221 return PythonQtConv::GetPyBool(areSamePtrs);
217 return PythonQtConv::GetPyBool(areSamePtrs);
222 } else if (validPtrs && code == Py_NE) {
218 } else if (validPtrs && code == Py_NE) {
223 return PythonQtConv::GetPyBool(!areSamePtrs);
219 return PythonQtConv::GetPyBool(!areSamePtrs);
224 }
220 }
225 Py_INCREF(Py_NotImplemented);
221 Py_INCREF(Py_NotImplemented);
226 return Py_NotImplemented;
222 return Py_NotImplemented;
227 }
223 }
228
224
229 QByteArray memberName;
225 QByteArray memberName;
230 switch (code) {
226 switch (code) {
231 case Py_LT:
227 case Py_LT:
232 {
228 {
233 static QByteArray name = "__lt__";
229 static QByteArray name = "__lt__";
234 memberName = name;
230 memberName = name;
235 }
231 }
236 break;
232 break;
237
233
238 case Py_LE:
234 case Py_LE:
239 {
235 {
240 static QByteArray name = "__le__";
236 static QByteArray name = "__le__";
241 memberName = name;
237 memberName = name;
242 }
238 }
243 break;
239 break;
244
240
245 case Py_EQ:
241 case Py_EQ:
246 {
242 {
247 static QByteArray name = "__eq__";
243 static QByteArray name = "__eq__";
248 memberName = name;
244 memberName = name;
249 }
245 }
250 break;
246 break;
251
247
252 case Py_NE:
248 case Py_NE:
253 {
249 {
254 static QByteArray name = "__ne__";
250 static QByteArray name = "__ne__";
255 memberName = name;
251 memberName = name;
256 }
252 }
257 break;
253 break;
258
254
259 case Py_GT:
255 case Py_GT:
260 {
256 {
261 static QByteArray name = "__gt__";
257 static QByteArray name = "__gt__";
262 memberName = name;
258 memberName = name;
263 }
259 }
264 break;
260 break;
265
261
266 case Py_GE:
262 case Py_GE:
267 {
263 {
268 static QByteArray name = "__ge__";
264 static QByteArray name = "__ge__";
269 memberName = name;
265 memberName = name;
270 }
266 }
271 break;
267 break;
272 }
268 }
273
269
274 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
270 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
275 if (opSlot._type == PythonQtMemberInfo::Slot) {
271 if (opSlot._type == PythonQtMemberInfo::Slot) {
276 // TODO get rid of tuple
272 // TODO get rid of tuple
277 PyObject* args = PyTuple_New(1);
273 PyObject* args = PyTuple_New(1);
278 Py_INCREF(other);
274 Py_INCREF(other);
279 PyTuple_SET_ITEM(args, 0, other);
275 PyTuple_SET_ITEM(args, 0, other);
280 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
276 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
281 Py_DECREF(args);
277 Py_DECREF(args);
282 return result;
278 return result;
283 } else {
279 } else {
284 // not implemented, let python try something else!
280 // not implemented, let python try something else!
285 Py_INCREF(Py_NotImplemented);
281 Py_INCREF(Py_NotImplemented);
286 return Py_NotImplemented;
282 return Py_NotImplemented;
287 }
283 }
288 }
284 }
289
285
290
286
291 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
287 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
292 {
288 {
293 #ifdef PY3K
289 #ifdef PY3K
294 return PyUnicode_FromString(Py_TYPE(obj)->tp_name);
290 return PyUnicode_FromString(Py_TYPE(obj)->tp_name);
295 #else
291 #else
296 return PyString_FromString(Py_TYPE(obj)->tp_name);
292 return PyString_FromString(Py_TYPE(obj)->tp_name);
297 #endif
293 #endif
298 }
294 }
299
295
300 PyObject *PythonQtInstanceWrapper_inherits(PythonQtInstanceWrapper* obj, PyObject *args)
296 PyObject *PythonQtInstanceWrapper_inherits(PythonQtInstanceWrapper* obj, PyObject *args)
301 {
297 {
302 char *name = NULL;
298 char *name = NULL;
303 if (!PyArg_ParseTuple(args, "s:PythonQtInstanceWrapper.inherits",&name)) {
299 if (!PyArg_ParseTuple(args, "s:PythonQtInstanceWrapper.inherits",&name)) {
304 return NULL;
300 return NULL;
305 }
301 }
306 return PythonQtConv::GetPyBool(obj->classInfo()->inherits(name));
302 return PythonQtConv::GetPyBool(obj->classInfo()->inherits(name));
307 }
303 }
308
304
309 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
305 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
310 {
306 {
311 return PythonQt::self()->helpCalled(obj->classInfo());
307 return PythonQt::self()->helpCalled(obj->classInfo());
312 }
308 }
313
309
314 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
310 PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
315 {
311 {
316 PythonQtInstanceWrapper_deleteObject(self, true);
312 PythonQtInstanceWrapper_deleteObject(self, true);
317 Py_INCREF(Py_None);
313 Py_INCREF(Py_None);
318 return Py_None;
314 return Py_None;
319 }
315 }
320
316
321
317
322 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
318 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
323 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
319 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
324 "Return the classname of the object"
320 "Return the classname of the object"
325 },
321 },
326 {"inherits", (PyCFunction)PythonQtInstanceWrapper_inherits, METH_VARARGS,
322 {"inherits", (PyCFunction)PythonQtInstanceWrapper_inherits, METH_VARARGS,
327 "Returns if the class inherits or is of given type name"
323 "Returns if the class inherits or is of given type name"
328 },
324 },
329 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
325 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
330 "Shows the help of available methods for this class"
326 "Shows the help of available methods for this class"
331 },
327 },
332 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
328 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
333 "Deletes the C++ object (at your own risk, my friend!)"
329 "Deletes the C++ object (at your own risk, my friend!)"
334 },
330 },
335 {NULL, NULL, 0, NULL} /* Sentinel */
331 {NULL, NULL, 0, NULL} /* Sentinel */
336 };
332 };
337
333
338
334
339 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
335 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
340 {
336 {
341 const char *attributeName;
337 const char *attributeName;
342 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
338 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
343
339
344 #ifdef PY3K
340 #ifdef PY3K
345 if ((attributeName = PyUnicode_AsUTF8(name)) == NULL) {
341 if ((attributeName = PyUnicode_AsUTF8(name)) == NULL) {
346 #else
342 #else
347 if ((attributeName = PyString_AsString(name)) == NULL) {
343 if ((attributeName = PyString_AsString(name)) == NULL) {
348 #endif
344 #endif
349 return NULL;
345 return NULL;
350 }
346 }
351
347
352 if (qstrcmp(attributeName, "__dict__")==0) {
348 if (qstrcmp(attributeName, "__dict__")==0) {
353 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
349 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
354 dict = PyDict_Copy(dict);
350 dict = PyDict_Copy(dict);
355
351
356 if (wrapper->_obj) {
352 if (wrapper->_obj) {
357 // only the properties are missing, the rest is already available from
353 // only the properties are missing, the rest is already available from
358 // PythonQtClassWrapper...
354 // PythonQtClassWrapper...
359 QStringList l = wrapper->classInfo()->propertyList();
355 QStringList l = wrapper->classInfo()->propertyList();
360 Q_FOREACH (QString name, l) {
356 Q_FOREACH (QString name, l) {
361 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
357 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
362 if (o) {
358 if (o) {
363 PyDict_SetItemString(dict, name.toLatin1().data(), o);
359 PyDict_SetItemString(dict, name.toLatin1().data(), o);
364 Py_DECREF(o);
360 Py_DECREF(o);
365 } else {
361 } else {
366 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
362 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
367 }
363 }
368 }
364 }
369
365
370 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
366 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
371 Q_FOREACH (QByteArray name, dynamicProps) {
367 Q_FOREACH (QByteArray name, dynamicProps) {
372 PyObject* o = PyObject_GetAttrString(obj, name.data());
368 PyObject* o = PyObject_GetAttrString(obj, name.data());
373 if (o) {
369 if (o) {
374 PyDict_SetItemString(dict, name.data(), o);
370 PyDict_SetItemString(dict, name.data(), o);
375 Py_DECREF(o);
371 Py_DECREF(o);
376 } else {
372 } else {
377 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
373 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
378 }
374 }
379 }
375 }
380 }
376 }
381 // Note: we do not put children into the dict, is would look confusing?!
377 // Note: we do not put children into the dict, is would look confusing?!
382 return dict;
378 return dict;
383 }
379 }
384
380
385 // first look in super, to return derived methods from base object first
381 // first look in super, to return derived methods from base object first
386 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
382 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
387 if (superAttr) {
383 if (superAttr) {
388 return superAttr;
384 return superAttr;
389 }
385 }
390 PyErr_Clear();
386 PyErr_Clear();
391
387
392 // mlabDebugConst("Python","get " << attributeName);
388 // mlabDebugConst("Python","get " << attributeName);
393
389
394 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
390 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
395 switch (member._type) {
391 switch (member._type) {
396 case PythonQtMemberInfo::Property:
392 case PythonQtMemberInfo::Property:
397 if (wrapper->_obj) {
393 if (wrapper->_obj) {
398 if (member._property.userType() != QVariant::Invalid) {
394 if (member._property.userType() != QVariant::Invalid) {
399
395
400 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
396 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
401 if (profilingCB) {
397 if (profilingCB) {
402 QString methodName = "getProperty(";
398 QString methodName = "getProperty(";
403 methodName += attributeName;
399 methodName += attributeName;
404 methodName += ")";
400 methodName += ")";
405 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
401 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
406 }
402 }
407
403
408 PyObject* value = PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
404 PyObject* value = PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
409
405
410 if (profilingCB) {
406 if (profilingCB) {
411 profilingCB(PythonQt::Leave, NULL, NULL);
407 profilingCB(PythonQt::Leave, NULL, NULL);
412 }
408 }
413
409
414 return value;
410 return value;
415
411
416 } else {
412 } else {
417 Py_INCREF(Py_None);
413 Py_INCREF(Py_None);
418 return Py_None;
414 return Py_None;
419 }
415 }
420 } else {
416 } else {
421 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
417 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
422 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
418 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
423 return NULL;
419 return NULL;
424 }
420 }
425 break;
421 break;
426 case PythonQtMemberInfo::Slot:
422 case PythonQtMemberInfo::Slot:
427 return PythonQtSlotFunction_New(member._slot, obj, NULL);
423 return PythonQtSlotFunction_New(member._slot, obj, NULL);
428 break;
424 break;
429 case PythonQtMemberInfo::Signal:
425 case PythonQtMemberInfo::Signal:
430 return PythonQtSignalFunction_New(member._slot, obj, NULL);
426 return PythonQtSignalFunction_New(member._slot, obj, NULL);
431 break;
427 break;
432 case PythonQtMemberInfo::EnumValue:
428 case PythonQtMemberInfo::EnumValue:
433 {
429 {
434 PyObject* enumValue = member._enumValue;
430 PyObject* enumValue = member._enumValue;
435 Py_INCREF(enumValue);
431 Py_INCREF(enumValue);
436 return enumValue;
432 return enumValue;
437 }
433 }
438 break;
434 break;
439 case PythonQtMemberInfo::EnumWrapper:
435 case PythonQtMemberInfo::EnumWrapper:
440 {
436 {
441 PyObject* enumWrapper = member._enumWrapper;
437 PyObject* enumWrapper = member._enumWrapper;
442 Py_INCREF(enumWrapper);
438 Py_INCREF(enumWrapper);
443 return enumWrapper;
439 return enumWrapper;
444 }
440 }
445 break;
441 break;
446 case PythonQtMemberInfo::NotFound:
442 case PythonQtMemberInfo::NotFound:
447 {
443 {
448 static const QByteArray getterString("py_get_");
444 static const QByteArray getterString("py_get_");
449 // check for a getter slot
445 // check for a getter slot
450 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
446 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
451 if (member._type == PythonQtMemberInfo::Slot) {
447 if (member._type == PythonQtMemberInfo::Slot) {
452 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
448 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
453 }
449 }
454
450
455 // handle dynamic properties
451 // handle dynamic properties
456 if (wrapper->_obj) {
452 if (wrapper->_obj) {
457 QVariant v = wrapper->_obj->property(attributeName);
453 QVariant v = wrapper->_obj->property(attributeName);
458 if (v.isValid()) {
454 if (v.isValid()) {
459 return PythonQtConv::QVariantToPyObject(v);
455 return PythonQtConv::QVariantToPyObject(v);
460 }
456 }
461 }
457 }
462 }
458 }
463 break;
459 break;
464 default:
460 default:
465 // is an invalid type, go on
461 // is an invalid type, go on
466 break;
462 break;
467 }
463 }
468
464
469 // look for the internal methods (className(), help())
465 // look for the internal methods (className(), help())
470 #ifdef PY3K
466 #ifdef PY3K
471 PyObject* internalMethod = PyObject_GenericGetAttr(obj, name);
467 PyObject* internalMethod = PyObject_GenericGetAttr(obj, name);
472 #else
468 #else
473 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
469 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
474 #endif
470 #endif
475 if (internalMethod) {
471 if (internalMethod) {
476 return internalMethod;
472 return internalMethod;
477 }
473 }
478 PyErr_Clear();
474 PyErr_Clear();
479
475
480 if (wrapper->_obj) {
476 if (wrapper->_obj) {
481 // look for a child
477 // look for a child
482 QObjectList children = wrapper->_obj->children();
478 QObjectList children = wrapper->_obj->children();
483 for (int i = 0; i < children.count(); i++) {
479 for (int i = 0; i < children.count(); i++) {
484 QObject *child = children.at(i);
480 QObject *child = children.at(i);
485 if (child->objectName() == attributeName) {
481 if (child->objectName() == attributeName) {
486 return PythonQt::priv()->wrapQObject(child);
482 return PythonQt::priv()->wrapQObject(child);
487 }
483 }
488 }
484 }
489 }
485 }
490
486
491 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
487 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
492 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
488 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
493 return NULL;
489 return NULL;
494 }
490 }
495
491
496 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
492 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
497 {
493 {
498 QString error;
494 QString error;
499 const char *attributeName;
495 const char *attributeName;
500 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
496 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
501
497
502 #ifdef PY3K
498 #ifdef PY3K
503 if ((attributeName = PyUnicode_AsUTF8(name)) == NULL)
499 if ((attributeName = PyUnicode_AsUTF8(name)) == NULL)
504 #else
500 #else
505 if ((attributeName = PyString_AsString(name)) == NULL)
501 if ((attributeName = PyString_AsString(name)) == NULL)
506 #endif
502 #endif
507 return -1;
503 return -1;
508
504
509 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
505 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
510 if (member._type == PythonQtMemberInfo::Property) {
506 if (member._type == PythonQtMemberInfo::Property) {
511
507
512 if (!wrapper->_obj) {
508 if (!wrapper->_obj) {
513 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
509 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
514 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
510 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
515 return -1;
511 return -1;
516 }
512 }
517
513
518 QMetaProperty prop = member._property;
514 QMetaProperty prop = member._property;
519 if (prop.isWritable()) {
515 if (prop.isWritable()) {
520 QVariant v;
516 QVariant v;
521 if (prop.isEnumType()) {
517 if (prop.isEnumType()) {
522 // this will give us either a string or an int, everything else will probably be an error
518 // this will give us either a string or an int, everything else will probably be an error
523 v = PythonQtConv::PyObjToQVariant(value);
519 v = PythonQtConv::PyObjToQVariant(value);
524 } else {
520 } else {
525 int t = prop.userType();
521 int t = prop.userType();
526 v = PythonQtConv::PyObjToQVariant(value, t);
522 v = PythonQtConv::PyObjToQVariant(value, t);
527 }
523 }
528 bool success = false;
524 bool success = false;
529 if (v.isValid()) {
525 if (v.isValid()) {
530 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
526 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
531 if (profilingCB) {
527 if (profilingCB) {
532 QString methodName = "setProperty(";
528 QString methodName = "setProperty(";
533 methodName += attributeName;
529 methodName += attributeName;
534 methodName += ")";
530 methodName += ")";
535 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
531 profilingCB(PythonQt::Enter, wrapper->_obj->metaObject()->className(), methodName.toLatin1());
536 }
532 }
537
533
538 success = prop.write(wrapper->_obj, v);
534 success = prop.write(wrapper->_obj, v);
539
535
540 if (profilingCB) {
536 if (profilingCB) {
541 profilingCB(PythonQt::Leave, NULL, NULL);
537 profilingCB(PythonQt::Leave, NULL, NULL);
542 }
538 }
543 }
539 }
544 if (success) {
540 if (success) {
545 return 0;
541 return 0;
546 } else {
542 } else {
547 error = QString("Property '") + attributeName + "' of type '" +
543 error = QString("Property '") + attributeName + "' of type '" +
548 prop.typeName() + "' does not accept an object of type "
544 prop.typeName() + "' does not accept an object of type "
549 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
545 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
550 }
546 }
551 } else {
547 } else {
552 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
548 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
553 }
549 }
554 } else if (member._type == PythonQtMemberInfo::Slot) {
550 } else if (member._type == PythonQtMemberInfo::Slot) {
555 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
551 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
556 } else if (member._type == PythonQtMemberInfo::Signal) {
552 } else if (member._type == PythonQtMemberInfo::Signal) {
557 error = QString("Signal '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
553 error = QString("Signal '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
558 } else if (member._type == PythonQtMemberInfo::EnumValue) {
554 } else if (member._type == PythonQtMemberInfo::EnumValue) {
559 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
555 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
560 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
556 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
561 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
557 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
562 } else if (member._type == PythonQtMemberInfo::NotFound) {
558 } else if (member._type == PythonQtMemberInfo::NotFound) {
563 // check for a setter slot
559 // check for a setter slot
564 static const QByteArray setterString("py_set_");
560 static const QByteArray setterString("py_set_");
565 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
561 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
566 if (setter._type == PythonQtMemberInfo::Slot) {
562 if (setter._type == PythonQtMemberInfo::Slot) {
567 // call the setter and ignore the result value
563 // call the setter and ignore the result value
568 void* result;
564 void* result;
569 PyObject* args = PyTuple_New(1);
565 PyObject* args = PyTuple_New(1);
570 Py_INCREF(value);
566 Py_INCREF(value);
571 PyTuple_SET_ITEM(args, 0, value);
567 PyTuple_SET_ITEM(args, 0, value);
572 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
568 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
573 Py_DECREF(args);
569 Py_DECREF(args);
574 return 0;
570 return 0;
575 }
571 }
576
572
577 // handle dynamic properties
573 // handle dynamic properties
578 if (wrapper->_obj) {
574 if (wrapper->_obj) {
579 QVariant prop = wrapper->_obj->property(attributeName);
575 QVariant prop = wrapper->_obj->property(attributeName);
580 if (prop.isValid()) {
576 if (prop.isValid()) {
581 QVariant v = PythonQtConv::PyObjToQVariant(value);
577 QVariant v = PythonQtConv::PyObjToQVariant(value);
582 if (v.isValid()) {
578 if (v.isValid()) {
583 wrapper->_obj->setProperty(attributeName, v);
579 wrapper->_obj->setProperty(attributeName, v);
584 return 0;
580 return 0;
585 } else {
581 } else {
586 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
582 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
587 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
583 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
588 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
584 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
589 return -1;
585 return -1;
590 }
586 }
591 }
587 }
592 }
588 }
593
589
594 // if we are a derived python class, we allow setting attributes.
590 // if we are a derived python class, we allow setting attributes.
595 // if we are a direct CPP wrapper, we do NOT allow it, since
591 // if we are a direct CPP wrapper, we do NOT allow it, since
596 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
592 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
597 // and when it is recreated from a CPP pointer the attributes are gone...
593 // and when it is recreated from a CPP pointer the attributes are gone...
598 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
594 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
599 return PyBaseObject_Type.tp_setattro(obj,name,value);
595 return PyBaseObject_Type.tp_setattro(obj,name,value);
600 } else {
596 } else {
601 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
597 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
602 }
598 }
603 }
599 }
604
600
605 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
601 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
606 return -1;
602 return -1;
607 }
603 }
608
604
609 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
605 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
610 QString result;
606 QString result;
611 if (wrapper->_wrappedPtr) {
607 if (wrapper->_wrappedPtr) {
612 // first try some manually string conversions for some variants
608 // first try some manually string conversions for some variants
613 int metaid = wrapper->classInfo()->metaTypeId();
609 int metaid = wrapper->classInfo()->metaTypeId();
614 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
610 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
615 if (!result.isEmpty()) {
611 if (!result.isEmpty()) {
616 return result;
612 return result;
617 }
613 }
618 }
614 }
619 if (wrapper->_wrappedPtr || wrapper->_obj) {
615 if (wrapper->_wrappedPtr || wrapper->_obj) {
620 // next, try to call py_toString
616 // next, try to call py_toString
621 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
617 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
622 if (info._type == PythonQtMemberInfo::Slot) {
618 if (info._type == PythonQtMemberInfo::Slot) {
623 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
619 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
624 if (resultObj) {
620 if (resultObj) {
625 // TODO this is one conversion too much, would be nicer to call the slot directly...
621 // TODO this is one conversion too much, would be nicer to call the slot directly...
626 result = PythonQtConv::PyObjGetString(resultObj);
622 result = PythonQtConv::PyObjGetString(resultObj);
627 Py_DECREF(resultObj);
623 Py_DECREF(resultObj);
628 }
624 }
629 }
625 }
630 }
626 }
631 return result;
627 return result;
632 }
628 }
633
629
634 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
630 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
635 {
631 {
636 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
632 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
637
633
638 // QByteArray should be directly returned as a str
634 // QByteArray should be directly returned as a str
639 if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) {
635 if (wrapper->classInfo()->metaTypeId()==QVariant::ByteArray) {
640 QByteArray* b = (QByteArray*) wrapper->_wrappedPtr;
636 QByteArray* b = (QByteArray*) wrapper->_wrappedPtr;
641 if (b->data()) {
637 if (b->data()) {
642 #ifdef PY3K
638 #ifdef PY3K
643 return PyUnicode_FromStringAndSize(b->data(), b->size());
639 return PyUnicode_FromStringAndSize(b->data(), b->size());
644 #else
640 #else
645 return PyString_FromStringAndSize(b->data(), b->size());
641 return PyString_FromStringAndSize(b->data(), b->size());
646 #endif
642 #endif
647 } else {
643 } else {
648 #ifdef PY3K
644 #ifdef PY3K
649 return PyUnicode_New(0, 0);
645 return PyUnicode_New(0, 0);
650 #else
646 #else
651 return PyString_FromString("");
647 return PyString_FromString("");
652 #endif
648 #endif
653 }
649 }
654 }
650 }
655
651
656 const char* typeName = obj->ob_type->tp_name;
652 const char* typeName = obj->ob_type->tp_name;
657 QObject *qobj = wrapper->_obj;
653 QObject *qobj = wrapper->_obj;
658 QString str = getStringFromObject(wrapper);
654 QString str = getStringFromObject(wrapper);
659 if (!str.isEmpty()) {
655 if (!str.isEmpty()) {
660 #ifdef PY3K
656 #ifdef PY3K
661 return PyUnicode_FromFormat("%s", str.toLatin1().constData());
657 return PyUnicode_FromFormat("%s", str.toLatin1().constData());
662 #else
658 #else
663 return PyString_FromFormat("%s", str.toLatin1().constData());
659 return PyString_FromFormat("%s", str.toLatin1().constData());
664 #endif
660 #endif
665 }
661 }
666 if (wrapper->_wrappedPtr) {
662 if (wrapper->_wrappedPtr) {
667 if (wrapper->_obj) {
663 if (wrapper->_obj) {
668 #ifdef PY3K
664 #ifdef PY3K
669 return PyUnicode_FromFormat("%s (C++ Object %p wrapped by %s %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
665 return PyUnicode_FromFormat("%s (C++ Object %p wrapped by %s %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
670 #else
666 #else
671 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
667 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
672 #endif
668 #endif
673 } else {
669 } else {
674 #ifdef PY3K
670 #ifdef PY3K
675 return PyUnicode_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
671 return PyUnicode_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
676 #else
672 #else
677 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
673 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
678 #endif
674 #endif
679 }
675 }
680 } else {
676 } else {
681 #ifdef PY3K
677 #ifdef PY3K
682 return PyUnicode_FromFormat("%s (QObject %p)", typeName, qobj);
678 return PyUnicode_FromFormat("%s (QObject %p)", typeName, qobj);
683 #else
679 #else
684 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
680 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
685 #endif
681 #endif
686 }
682 }
687 }
683 }
688
684
689 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
685 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
690 {
686 {
691 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
687 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
692 const char* typeName = obj->ob_type->tp_name;
688 const char* typeName = obj->ob_type->tp_name;
693
689
694 QObject *qobj = wrapper->_obj;
690 QObject *qobj = wrapper->_obj;
695 QString str = getStringFromObject(wrapper);
691 QString str = getStringFromObject(wrapper);
696 if (!str.isEmpty()) {
692 if (!str.isEmpty()) {
697 if (str.startsWith(typeName)) {
693 if (str.startsWith(typeName)) {
698 #ifdef PY3K
694 #ifdef PY3K
699 return PyUnicode_FromFormat("%s", str.toLatin1().constData());
695 return PyUnicode_FromFormat("%s", str.toLatin1().constData());
700 #else
696 #else
701 return PyString_FromFormat("%s", str.toLatin1().constData());
697 return PyString_FromFormat("%s", str.toLatin1().constData());
702 #endif
698 #endif
703 } else {
699 } else {
704 #ifdef PY3K
700 #ifdef PY3K
705 return PyUnicode_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj);
701 return PyUnicode_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj);
706 #else
702 #else
707 return PyString_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj);
703 return PyString_FromFormat("%s (%s, at: %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr ? wrapper->_wrappedPtr : qobj);
708 #endif
704 #endif
709 }
705 }
710 }
706 }
711 if (wrapper->_wrappedPtr) {
707 if (wrapper->_wrappedPtr) {
712 if (wrapper->_obj) {
708 if (wrapper->_obj) {
713 #ifdef PY3K
709 #ifdef PY3K
714 return PyUnicode_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
710 return PyUnicode_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
715 #else
711 #else
716 return PyString_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
712 return PyString_FromFormat("%s (C++ object at: %p wrapped by %s at: %p)", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
717 #endif
713 #endif
718 } else {
714 } else {
719 #ifdef PY3K
715 #ifdef PY3K
720 return PyUnicode_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr);
716 return PyUnicode_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr);
721 #else
717 #else
722 return PyString_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr);
718 return PyString_FromFormat("%s (C++ object at: %p)", typeName, wrapper->_wrappedPtr);
723 #endif
719 #endif
724 }
720 }
725 } else {
721 } else {
726 #ifdef PY3K
722 #ifdef PY3K
727 return PyUnicode_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj);
723 return PyUnicode_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj);
728 #else
724 #else
729 return PyString_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj);
725 return PyString_FromFormat("%s (%s at: %p)", typeName, wrapper->classInfo()->className(), qobj);
730 #endif
726 #endif
731 }
727 }
732 }
728 }
733
729
734 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
730 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
735 {
731 {
736 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
732 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
737 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
733 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
738 }
734 }
739
735
740
736
741 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
737 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
742 {
738 {
743 if (obj->_wrappedPtr != NULL) {
739 if (obj->_wrappedPtr != NULL) {
744 return reinterpret_cast<long>(obj->_wrappedPtr);
740 return reinterpret_cast<long>(obj->_wrappedPtr);
745 } else {
741 } else {
746 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
742 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
747 return reinterpret_cast<long>(qobj);
743 return reinterpret_cast<long>(qobj);
748 }
744 }
749 }
745 }
750
746
751
747
752
748
753 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
749 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
754 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
750 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
755 0, /* nb_add */
751 0, /* nb_add */
756 0, /* nb_subtract */
752 0, /* nb_subtract */
757 0, /* nb_multiply */
753 0, /* nb_multiply */
758 #ifndef PY3K
754 #ifndef PY3K
759 0, /* nb_divide */
755 0, /* nb_divide */
760 #endif
756 #endif
761 0, /* nb_remainder */
757 0, /* nb_remainder */
762 0, /* nb_divmod */
758 0, /* nb_divmod */
763 0, /* nb_power */
759 0, /* nb_power */
764 0, /* nb_negative */
760 0, /* nb_negative */
765 0, /* nb_positive */
761 0, /* nb_positive */
766 0, /* nb_absolute */
762 0, /* nb_absolute */
767 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero / nb_bool in Py3K */
763 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero / nb_bool in Py3K */
768 0, /* nb_invert */
764 0, /* nb_invert */
769 0, /* nb_lshift */
765 0, /* nb_lshift */
770 0, /* nb_rshift */
766 0, /* nb_rshift */
771 0, /* nb_and */
767 0, /* nb_and */
772 0, /* nb_xor */
768 0, /* nb_xor */
773 0, /* nb_or */
769 0, /* nb_or */
774 #ifndef PY3K
770 #ifndef PY3K
775 0, /* nb_coerce */
771 0, /* nb_coerce */
776 #endif
772 #endif
777 0, /* nb_int */
773 0, /* nb_int */
778 0, /* nb_long / nb_reserved in Py3K */
774 0, /* nb_long / nb_reserved in Py3K */
779 0, /* nb_float */
775 0, /* nb_float */
780 #ifndef PY3K
776 #ifndef PY3K
781 0, /* nb_oct */
777 0, /* nb_oct */
782 0, /* nb_hex */
778 0, /* nb_hex */
783 #endif
779 #endif
784 0, /* nb_inplace_add */
780 0, /* nb_inplace_add */
785 0, /* nb_inplace_subtract */
781 0, /* nb_inplace_subtract */
786 0, /* nb_inplace_multiply */
782 0, /* nb_inplace_multiply */
787 #ifndef PY3K
783 #ifndef PY3K
788 0, /* nb_inplace_divide */
784 0, /* nb_inplace_divide */
789 #endif
785 #endif
790 0, /* nb_inplace_remainder */
786 0, /* nb_inplace_remainder */
791 0, /* nb_inplace_power */
787 0, /* nb_inplace_power */
792 0, /* nb_inplace_lshift */
788 0, /* nb_inplace_lshift */
793 0, /* nb_inplace_rshift */
789 0, /* nb_inplace_rshift */
794 0, /* nb_inplace_and */
790 0, /* nb_inplace_and */
795 0, /* nb_inplace_xor */
791 0, /* nb_inplace_xor */
796 0, /* nb_inplace_or */
792 0, /* nb_inplace_or */
797 0, /* nb_floor_divide */
793 0, /* nb_floor_divide */
798 0, /* nb_true_divide */
794 0, /* nb_true_divide */
799 0, /* nb_inplace_floor_divide */
795 0, /* nb_inplace_floor_divide */
800 0, /* nb_inplace_true_divide */
796 0, /* nb_inplace_true_divide */
801 #ifdef PY3K
797 #ifdef PY3K
802 0, /* nb_index in Py3K */
798 0, /* nb_index in Py3K */
803 #endif
799 #endif
804 };
800 };
805
801
806 PyTypeObject PythonQtInstanceWrapper_Type = {
802 PyTypeObject PythonQtInstanceWrapper_Type = {
807 PyVarObject_HEAD_INIT(&PythonQtClassWrapper_Type, 0)
803 PyVarObject_HEAD_INIT(&PythonQtClassWrapper_Type, 0)
808 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
804 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
809 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
805 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
810 0, /*tp_itemsize*/
806 0, /*tp_itemsize*/
811 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
807 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
812 0, /*tp_print*/
808 0, /*tp_print*/
813 0, /*tp_getattr*/
809 0, /*tp_getattr*/
814 0, /*tp_setattr*/
810 0, /*tp_setattr*/
815 0, /*tp_compare*/
811 0, /*tp_compare*/
816 PythonQtInstanceWrapper_repr, /*tp_repr*/
812 PythonQtInstanceWrapper_repr, /*tp_repr*/
817 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
813 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
818 0, /*tp_as_sequence*/
814 0, /*tp_as_sequence*/
819 0, /*tp_as_mapping*/
815 0, /*tp_as_mapping*/
820 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
816 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
821 0, /*tp_call*/
817 0, /*tp_call*/
822 PythonQtInstanceWrapper_str, /*tp_str*/
818 PythonQtInstanceWrapper_str, /*tp_str*/
823 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
819 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
824 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
820 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
825 0, /*tp_as_buffer*/
821 0, /*tp_as_buffer*/
826 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE /*| Py_TPFLAGS_CHECKTYPES FIXME Py_TPFLAGS_CHECKTYPES removal */, /*tp_flags*/
822 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE /*| Py_TPFLAGS_CHECKTYPES FIXME Py_TPFLAGS_CHECKTYPES removal */, /*tp_flags*/
827 "PythonQtInstanceWrapper object", /* tp_doc */
823 "PythonQtInstanceWrapper object", /* tp_doc */
828 0, /* tp_traverse */
824 0, /* tp_traverse */
829 0, /* tp_clear */
825 0, /* tp_clear */
830 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
826 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
831 0, /* tp_weaklistoffset */
827 0, /* tp_weaklistoffset */
832 0, /* tp_iter */
828 0, /* tp_iter */
833 0, /* tp_iternext */
829 0, /* tp_iternext */
834 0, /* tp_methods */
830 PythonQtInstanceWrapper_methods, /* tp_methods */
835 0, /* tp_members */
831 0, /* tp_members */
836 0, /* tp_getset */
832 0, /* tp_getset */
837 0, /* tp_base */
833 0, /* tp_base */
838 0, /* tp_dict */
834 0, /* tp_dict */
839 0, /* tp_descr_get */
835 0, /* tp_descr_get */
840 0, /* tp_descr_set */
836 0, /* tp_descr_set */
841 0, /* tp_dictoffset */
837 0, /* tp_dictoffset */
842 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
838 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
843 0, /* tp_alloc */
839 0, /* tp_alloc */
844 PythonQtInstanceWrapper_new, /* tp_new */
840 PythonQtInstanceWrapper_new, /* tp_new */
845 };
841 };
846
842
847 //-------------------------------------------------------
843 //-------------------------------------------------------
848
844
@@ -1,735 +1,731
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, 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 "PythonQtInstanceWrapper.h"
44 #include "PythonQtInstanceWrapper.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 #include <exception>
50 #include <exception>
51 #include <stdexcept>
51 #include <stdexcept>
52
52
53 #include <QByteArray>
53 #include <QByteArray>
54
54
55 #if PY_MAJOR_VERSION >= 3
56 #define PY3K
57 #endif
58
59 #define PYTHONQT_MAX_ARGS 32
55 #define PYTHONQT_MAX_ARGS 32
60
56
61
57
62 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
58 bool PythonQtCallSlot(PythonQtClassInfo* classInfo, QObject* objectToCall, PyObject* args, bool strict, PythonQtSlotInfo* info, void* firstArgument, PyObject** pythonReturnValue, void** directReturnValuePointer)
63 {
59 {
64 static unsigned int recursiveEntry = 0;
60 static unsigned int recursiveEntry = 0;
65
61
66 if (directReturnValuePointer) {
62 if (directReturnValuePointer) {
67 *directReturnValuePointer = NULL;
63 *directReturnValuePointer = NULL;
68 }
64 }
69 // store the current storage position, so that we can get back to this state after a slot is called
65 // store the current storage position, so that we can get back to this state after a slot is called
70 // (do this locally, so that we have all positions on the stack
66 // (do this locally, so that we have all positions on the stack
71 PythonQtValueStoragePosition globalValueStoragePos;
67 PythonQtValueStoragePosition globalValueStoragePos;
72 PythonQtValueStoragePosition globalPtrStoragePos;
68 PythonQtValueStoragePosition globalPtrStoragePos;
73 PythonQtValueStoragePosition globalVariantStoragePos;
69 PythonQtValueStoragePosition globalVariantStoragePos;
74 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
70 PythonQtConv::global_valueStorage.getPos(globalValueStoragePos);
75 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
71 PythonQtConv::global_ptrStorage.getPos(globalPtrStoragePos);
76 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
72 PythonQtConv::global_variantStorage.getPos(globalVariantStoragePos);
77
73
78 recursiveEntry++;
74 recursiveEntry++;
79
75
80 // the arguments that are passed to qt_metacall
76 // the arguments that are passed to qt_metacall
81 void* argList[PYTHONQT_MAX_ARGS];
77 void* argList[PYTHONQT_MAX_ARGS];
82 PyObject* result = NULL;
78 PyObject* result = NULL;
83 int argc = info->parameterCount();
79 int argc = info->parameterCount();
84 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
80 const QList<PythonQtSlotInfo::ParameterInfo>& params = info->parameters();
85
81
86 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
82 const PythonQtSlotInfo::ParameterInfo& returnValueParam = params.at(0);
87 // set return argument to NULL
83 // set return argument to NULL
88 argList[0] = NULL;
84 argList[0] = NULL;
89
85
90 bool ok = true;
86 bool ok = true;
91 bool skipFirst = false;
87 bool skipFirst = false;
92 if (info->isInstanceDecorator()) {
88 if (info->isInstanceDecorator()) {
93 skipFirst = true;
89 skipFirst = true;
94
90
95 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
91 // for decorators on CPP objects, we take the cpp ptr, for QObjects we take the QObject pointer
96 void* arg1 = firstArgument;
92 void* arg1 = firstArgument;
97 if (!arg1) {
93 if (!arg1) {
98 arg1 = objectToCall;
94 arg1 = objectToCall;
99 }
95 }
100 if (arg1) {
96 if (arg1) {
101 // upcast to correct parent class
97 // upcast to correct parent class
102 arg1 = ((char*)arg1)+info->upcastingOffset();
98 arg1 = ((char*)arg1)+info->upcastingOffset();
103 }
99 }
104
100
105 argList[1] = &arg1;
101 argList[1] = &arg1;
106 if (ok) {
102 if (ok) {
107 for (int i = 2; i<argc && ok; i++) {
103 for (int i = 2; i<argc && ok; i++) {
108 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
104 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
109 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
105 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-2), strict, classInfo);
110 if (argList[i]==NULL) {
106 if (argList[i]==NULL) {
111 ok = false;
107 ok = false;
112 break;
108 break;
113 }
109 }
114 }
110 }
115 }
111 }
116 } else {
112 } else {
117 for (int i = 1; i<argc && ok; i++) {
113 for (int i = 1; i<argc && ok; i++) {
118 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
114 const PythonQtSlotInfo::ParameterInfo& param = params.at(i);
119 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
115 argList[i] = PythonQtConv::ConvertPythonToQt(param, PyTuple_GET_ITEM(args, i-1), strict, classInfo);
120 if (argList[i]==NULL) {
116 if (argList[i]==NULL) {
121 ok = false;
117 ok = false;
122 break;
118 break;
123 }
119 }
124 }
120 }
125 }
121 }
126
122
127 if (ok) {
123 if (ok) {
128 // parameters are ok, now create the qt return value which is assigned to by metacall
124 // parameters are ok, now create the qt return value which is assigned to by metacall
129 if (returnValueParam.typeId != QMetaType::Void) {
125 if (returnValueParam.typeId != QMetaType::Void) {
130 // create empty default value for the return value
126 // create empty default value for the return value
131 if (!directReturnValuePointer) {
127 if (!directReturnValuePointer) {
132 // create empty default value for the return value
128 // create empty default value for the return value
133 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
129 argList[0] = PythonQtConv::CreateQtReturnValue(returnValueParam);
134 if (argList[0]==NULL) {
130 if (argList[0]==NULL) {
135 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
131 // return value could not be created, maybe we have a registered class with a default constructor, so that we can construct the pythonqt wrapper object and
136 // pass its internal pointer
132 // pass its internal pointer
137 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
133 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(returnValueParam.name);
138 if (info && info->pythonQtClassWrapper()) {
134 if (info && info->pythonQtClassWrapper()) {
139 PyObject* emptyTuple = PyTuple_New(0);
135 PyObject* emptyTuple = PyTuple_New(0);
140 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
136 // 1) default construct an empty object as python object (owned by PythonQt), by calling the meta class with empty arguments
141 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
137 result = PyObject_Call((PyObject*)info->pythonQtClassWrapper(), emptyTuple, NULL);
142 if (result) {
138 if (result) {
143 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
139 argList[0] = ((PythonQtInstanceWrapper*)result)->_wrappedPtr;
144 }
140 }
145 Py_DECREF(emptyTuple);
141 Py_DECREF(emptyTuple);
146 }
142 }
147 }
143 }
148 } else {
144 } else {
149 // we can use our pointer directly!
145 // we can use our pointer directly!
150 argList[0] = directReturnValuePointer;
146 argList[0] = directReturnValuePointer;
151 }
147 }
152 }
148 }
153
149
154
150
155 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
151 PythonQt::ProfilingCB* profilingCB = PythonQt::priv()->profilingCB();
156 if (profilingCB) {
152 if (profilingCB) {
157 const char* className = NULL;
153 const char* className = NULL;
158 if (info->decorator()) {
154 if (info->decorator()) {
159 className = info->decorator()->metaObject()->className();
155 className = info->decorator()->metaObject()->className();
160 } else {
156 } else {
161 className = objectToCall->metaObject()->className();
157 className = objectToCall->metaObject()->className();
162 }
158 }
163
159
164 #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) )
160 #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) )
165 profilingCB(PythonQt::Enter, className, info->metaMethod()->methodSignature());
161 profilingCB(PythonQt::Enter, className, info->metaMethod()->methodSignature());
166 #else
162 #else
167 profilingCB(PythonQt::Enter, className, info->metaMethod()->signature());
163 profilingCB(PythonQt::Enter, className, info->metaMethod()->signature());
168 #endif
164 #endif
169 }
165 }
170
166
171 // invoke the slot via metacall
167 // invoke the slot via metacall
172 bool hadException = false;
168 bool hadException = false;
173 QObject* obj = info->decorator()?info->decorator():objectToCall;
169 QObject* obj = info->decorator()?info->decorator():objectToCall;
174 if (!obj) {
170 if (!obj) {
175 hadException = true;
171 hadException = true;
176 PyErr_SetString(PyExc_RuntimeError, "Trying to call a slot on a deleted QObject!");
172 PyErr_SetString(PyExc_RuntimeError, "Trying to call a slot on a deleted QObject!");
177 } else {
173 } else {
178 try {
174 try {
179 obj->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
175 obj->qt_metacall(QMetaObject::InvokeMetaMethod, info->slotIndex(), argList);
180 } catch (std::bad_alloc & e) {
176 } catch (std::bad_alloc & e) {
181 hadException = true;
177 hadException = true;
182 QByteArray what("std::bad_alloc: ");
178 QByteArray what("std::bad_alloc: ");
183 what += e.what();
179 what += e.what();
184 PyErr_SetString(PyExc_MemoryError, what.constData());
180 PyErr_SetString(PyExc_MemoryError, what.constData());
185 } catch (std::runtime_error & e) {
181 } catch (std::runtime_error & e) {
186 hadException = true;
182 hadException = true;
187 QByteArray what("std::runtime_error: ");
183 QByteArray what("std::runtime_error: ");
188 what += e.what();
184 what += e.what();
189 PyErr_SetString(PyExc_RuntimeError, what.constData());
185 PyErr_SetString(PyExc_RuntimeError, what.constData());
190 } catch (std::logic_error & e) {
186 } catch (std::logic_error & e) {
191 hadException = true;
187 hadException = true;
192 QByteArray what("std::logic_error: ");
188 QByteArray what("std::logic_error: ");
193 what += e.what();
189 what += e.what();
194 PyErr_SetString(PyExc_RuntimeError, what.constData());
190 PyErr_SetString(PyExc_RuntimeError, what.constData());
195 } catch (std::exception& e) {
191 } catch (std::exception& e) {
196 hadException = true;
192 hadException = true;
197 QByteArray what("std::exception: ");
193 QByteArray what("std::exception: ");
198 what += e.what();
194 what += e.what();
199 #ifdef PY3K
195 #ifdef PY3K
200 PyErr_SetString(PyExc_RuntimeError, what.constData());
196 PyErr_SetString(PyExc_RuntimeError, what.constData());
201 #else
197 #else
202 PyErr_SetString(PyExc_StandardError, what.constData());
198 PyErr_SetString(PyExc_StandardError, what.constData());
203 #endif
199 #endif
204 }
200 }
205 }
201 }
206
202
207 if (profilingCB) {
203 if (profilingCB) {
208 profilingCB(PythonQt::Leave, NULL, NULL);
204 profilingCB(PythonQt::Leave, NULL, NULL);
209 }
205 }
210
206
211 // handle the return value (which in most cases still needs to be converted to a Python object)
207 // handle the return value (which in most cases still needs to be converted to a Python object)
212 if (!hadException) {
208 if (!hadException) {
213 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
209 if (argList[0] || returnValueParam.typeId == QMetaType::Void) {
214 if (directReturnValuePointer) {
210 if (directReturnValuePointer) {
215 result = NULL;
211 result = NULL;
216 } else {
212 } else {
217 // the resulting object maybe present already, because we created it above at 1)...
213 // the resulting object maybe present already, because we created it above at 1)...
218 if (!result) {
214 if (!result) {
219 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
215 result = PythonQtConv::ConvertQtValueToPython(returnValueParam, argList[0]);
220 }
216 }
221 }
217 }
222 } else {
218 } else {
223 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
219 QString e = QString("Called ") + info->fullSignature() + ", return type '" + returnValueParam.name + "' is ignored because it is unknown to PythonQt. Probably you should register it using qRegisterMetaType() or add a default constructor decorator to the class.";
224 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
220 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
225 result = NULL;
221 result = NULL;
226 }
222 }
227 } else {
223 } else {
228 result = NULL;
224 result = NULL;
229 }
225 }
230 }
226 }
231 recursiveEntry--;
227 recursiveEntry--;
232
228
233 // reset the parameter storage position to the stored pos to "pop" the parameter stack
229 // reset the parameter storage position to the stored pos to "pop" the parameter stack
234 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
230 PythonQtConv::global_valueStorage.setPos(globalValueStoragePos);
235 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
231 PythonQtConv::global_ptrStorage.setPos(globalPtrStoragePos);
236 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
232 PythonQtConv::global_variantStorage.setPos(globalVariantStoragePos);
237
233
238 *pythonReturnValue = result;
234 *pythonReturnValue = result;
239 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
235 // NOTE: it is important to only return here, otherwise the stack will not be popped!!!
240 return result || (directReturnValuePointer && *directReturnValuePointer);
236 return result || (directReturnValuePointer && *directReturnValuePointer);
241 }
237 }
242
238
243 //-----------------------------------------------------------------------------------
239 //-----------------------------------------------------------------------------------
244
240
245 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
241 static PythonQtSlotFunctionObject *pythonqtslot_free_list = NULL;
246
242
247 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
243 PyObject *PythonQtSlotFunction_Call(PyObject *func, PyObject *args, PyObject *kw)
248 {
244 {
249 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
245 PythonQtSlotFunctionObject* f = (PythonQtSlotFunctionObject*)func;
250 return PythonQtMemberFunction_Call(f->m_ml, f->m_self, args, kw);
246 return PythonQtMemberFunction_Call(f->m_ml, f->m_self, args, kw);
251 }
247 }
252
248
253 PyObject *PythonQtMemberFunction_Call(PythonQtSlotInfo* info, PyObject* m_self, PyObject *args, PyObject *kw)
249 PyObject *PythonQtMemberFunction_Call(PythonQtSlotInfo* info, PyObject* m_self, PyObject *args, PyObject *kw)
254 {
250 {
255 if (PyObject_TypeCheck(m_self, &PythonQtInstanceWrapper_Type)) {
251 if (PyObject_TypeCheck(m_self, &PythonQtInstanceWrapper_Type)) {
256 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) m_self;
252 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*) m_self;
257 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
253 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
258 QString error = QString("Trying to call '") + info->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
254 QString error = QString("Trying to call '") + info->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
259 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
255 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
260 return NULL;
256 return NULL;
261 } else {
257 } else {
262 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
258 return PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, args, kw, self->_wrappedPtr);
263 }
259 }
264 } else if (m_self->ob_type == &PythonQtClassWrapper_Type) {
260 } else if (m_self->ob_type == &PythonQtClassWrapper_Type) {
265 PythonQtClassWrapper* type = (PythonQtClassWrapper*) m_self;
261 PythonQtClassWrapper* type = (PythonQtClassWrapper*) m_self;
266 if (info->isClassDecorator()) {
262 if (info->isClassDecorator()) {
267 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
263 return PythonQtSlotFunction_CallImpl(type->classInfo(), NULL, info, args, kw);
268 } else {
264 } else {
269 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
265 // otherwise, it is an unbound call and we have an instanceDecorator or normal slot...
270 Py_ssize_t argc = PyTuple_Size(args);
266 Py_ssize_t argc = PyTuple_Size(args);
271 if (argc>0) {
267 if (argc>0) {
272 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
268 PyObject* firstArg = PyTuple_GET_ITEM(args, 0);
273 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
269 if (PyObject_TypeCheck(firstArg, (PyTypeObject*)&PythonQtInstanceWrapper_Type)
274 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
270 && ((PythonQtInstanceWrapper*)firstArg)->classInfo()->inherits(type->classInfo())) {
275 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
271 PythonQtInstanceWrapper* self = (PythonQtInstanceWrapper*)firstArg;
276 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
272 if (!info->isClassDecorator() && (self->_obj==NULL && self->_wrappedPtr==NULL)) {
277 QString error = QString("Trying to call '") + info->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
273 QString error = QString("Trying to call '") + info->slotName() + "' on a destroyed " + self->classInfo()->className() + " object";
278 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
274 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
279 return NULL;
275 return NULL;
280 }
276 }
281 // strip the first argument...
277 // strip the first argument...
282 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
278 PyObject* newargs = PyTuple_GetSlice(args, 1, argc);
283 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
279 PyObject* result = PythonQtSlotFunction_CallImpl(self->classInfo(), self->_obj, info, newargs, kw, self->_wrappedPtr);
284 Py_DECREF(newargs);
280 Py_DECREF(newargs);
285 return result;
281 return result;
286 } else {
282 } else {
287 // first arg is not of correct type!
283 // first arg is not of correct type!
288 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
284 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument, got " + firstArg->ob_type->tp_name;
289 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
285 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
290 return NULL;
286 return NULL;
291 }
287 }
292 } else {
288 } else {
293 // wrong number of args
289 // wrong number of args
294 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
290 QString error = "slot " + info->fullSignature() + " requires " + type->classInfo()->className() + " instance as first argument.";
295 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
291 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
296 return NULL;
292 return NULL;
297 }
293 }
298 }
294 }
299 }
295 }
300 return NULL;
296 return NULL;
301 }
297 }
302
298
303 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
299 PyObject *PythonQtSlotFunction_CallImpl(PythonQtClassInfo* classInfo, QObject* objectToCall, PythonQtSlotInfo* info, PyObject *args, PyObject * /*kw*/, void* firstArg, void** directReturnValuePointer)
304 {
300 {
305 int argc = args?PyTuple_Size(args):0;
301 int argc = args?PyTuple_Size(args):0;
306
302
307 #ifdef PYTHONQT_DEBUG
303 #ifdef PYTHONQT_DEBUG
308 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
304 std::cout << "called " << info->metaMethod()->typeName() << " " << info->metaMethod()->signature() << std::endl;
309 #endif
305 #endif
310
306
311 PyObject* r = NULL;
307 PyObject* r = NULL;
312 bool ok = false;
308 bool ok = false;
313 if (directReturnValuePointer) {
309 if (directReturnValuePointer) {
314 *directReturnValuePointer = NULL;
310 *directReturnValuePointer = NULL;
315 }
311 }
316 if (info->nextInfo()) {
312 if (info->nextInfo()) {
317 // overloaded slot call, try on all slots with strict conversion first
313 // overloaded slot call, try on all slots with strict conversion first
318 bool strict = true;
314 bool strict = true;
319 PythonQtSlotInfo* i = info;
315 PythonQtSlotInfo* i = info;
320 while (i) {
316 while (i) {
321 bool skipFirst = i->isInstanceDecorator();
317 bool skipFirst = i->isInstanceDecorator();
322 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
318 if (i->parameterCount()-1-(skipFirst?1:0) == argc) {
323 PyErr_Clear();
319 PyErr_Clear();
324 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
320 ok = PythonQtCallSlot(classInfo, objectToCall, args, strict, i, firstArg, &r, directReturnValuePointer);
325 if (PyErr_Occurred() || ok) break;
321 if (PyErr_Occurred() || ok) break;
326 }
322 }
327 i = i->nextInfo();
323 i = i->nextInfo();
328 if (!i) {
324 if (!i) {
329 if (strict) {
325 if (strict) {
330 // one more run without being strict
326 // one more run without being strict
331 strict = false;
327 strict = false;
332 i = info;
328 i = info;
333 }
329 }
334 }
330 }
335 }
331 }
336 if (!ok && !PyErr_Occurred()) {
332 if (!ok && !PyErr_Occurred()) {
337 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
333 QString e = QString("Could not find matching overload for given arguments:\n" + PythonQtConv::PyObjGetString(args) + "\n The following slots are available:\n");
338 PythonQtSlotInfo* i = info;
334 PythonQtSlotInfo* i = info;
339 while (i) {
335 while (i) {
340 e += QString(i->fullSignature()) + "\n";
336 e += QString(i->fullSignature()) + "\n";
341 i = i->nextInfo();
337 i = i->nextInfo();
342 }
338 }
343 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
339 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
344 }
340 }
345 } else {
341 } else {
346 // simple (non-overloaded) slot call
342 // simple (non-overloaded) slot call
347 bool skipFirst = info->isInstanceDecorator();
343 bool skipFirst = info->isInstanceDecorator();
348 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
344 if (info->parameterCount()-1-(skipFirst?1:0) == argc) {
349 PyErr_Clear();
345 PyErr_Clear();
350 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
346 ok = PythonQtCallSlot(classInfo, objectToCall, args, false, info, firstArg, &r, directReturnValuePointer);
351 if (!ok && !PyErr_Occurred()) {
347 if (!ok && !PyErr_Occurred()) {
352 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
348 QString e = QString("Called ") + info->fullSignature() + " with wrong arguments: " + PythonQtConv::PyObjGetString(args);
353 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
349 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
354 }
350 }
355 } else {
351 } else {
356 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
352 QString e = QString("Called ") + info->fullSignature() + " with wrong number of arguments: " + PythonQtConv::PyObjGetString(args);
357 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
353 PyErr_SetString(PyExc_ValueError, e.toLatin1().data());
358 }
354 }
359 }
355 }
360
356
361 return r;
357 return r;
362 }
358 }
363
359
364 PyObject *
360 PyObject *
365 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
361 PythonQtSlotFunction_New(PythonQtSlotInfo *ml, PyObject *self, PyObject *module)
366 {
362 {
367 PythonQtSlotFunctionObject *op;
363 PythonQtSlotFunctionObject *op;
368 op = pythonqtslot_free_list;
364 op = pythonqtslot_free_list;
369 if (op != NULL) {
365 if (op != NULL) {
370 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
366 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(op->m_self);
371 PyObject_INIT(op, &PythonQtSlotFunction_Type);
367 PyObject_INIT(op, &PythonQtSlotFunction_Type);
372 }
368 }
373 else {
369 else {
374 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
370 op = PyObject_GC_New(PythonQtSlotFunctionObject, &PythonQtSlotFunction_Type);
375 if (op == NULL)
371 if (op == NULL)
376 return NULL;
372 return NULL;
377 }
373 }
378 op->m_ml = ml;
374 op->m_ml = ml;
379 Py_XINCREF(self);
375 Py_XINCREF(self);
380 op->m_self = self;
376 op->m_self = self;
381 Py_XINCREF(module);
377 Py_XINCREF(module);
382 op->m_module = module;
378 op->m_module = module;
383 PyObject_GC_Track(op);
379 PyObject_GC_Track(op);
384 return (PyObject *)op;
380 return (PyObject *)op;
385 }
381 }
386
382
387 PythonQtSlotInfo*
383 PythonQtSlotInfo*
388 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
384 PythonQtSlotFunction_GetSlotInfo(PyObject *op)
389 {
385 {
390 if (!PythonQtSlotFunction_Check(op)) {
386 if (!PythonQtSlotFunction_Check(op)) {
391 PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__);
387 PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__);
392 return NULL;
388 return NULL;
393 }
389 }
394 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
390 return ((PythonQtSlotFunctionObject *)op) -> m_ml;
395 }
391 }
396
392
397 PyObject *
393 PyObject *
398 PythonQtSlotFunction_GetSelf(PyObject *op)
394 PythonQtSlotFunction_GetSelf(PyObject *op)
399 {
395 {
400 if (!PythonQtSlotFunction_Check(op)) {
396 if (!PythonQtSlotFunction_Check(op)) {
401 PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__);
397 PyErr_Format(PyExc_SystemError, "%s:%d: bad argument to internal function", __FILE__, __LINE__);
402 return NULL;
398 return NULL;
403 }
399 }
404 return ((PythonQtSlotFunctionObject *)op) -> m_self;
400 return ((PythonQtSlotFunctionObject *)op) -> m_self;
405 }
401 }
406
402
407 /* Methods (the standard built-in methods, that is) */
403 /* Methods (the standard built-in methods, that is) */
408
404
409 static void
405 static void
410 meth_dealloc(PythonQtSlotFunctionObject *m)
406 meth_dealloc(PythonQtSlotFunctionObject *m)
411 {
407 {
412 PyObject_GC_UnTrack(m);
408 PyObject_GC_UnTrack(m);
413 Py_XDECREF(m->m_self);
409 Py_XDECREF(m->m_self);
414 Py_XDECREF(m->m_module);
410 Py_XDECREF(m->m_module);
415 m->m_self = (PyObject *)pythonqtslot_free_list;
411 m->m_self = (PyObject *)pythonqtslot_free_list;
416 pythonqtslot_free_list = m;
412 pythonqtslot_free_list = m;
417 }
413 }
418
414
419 static PyObject *
415 static PyObject *
420 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
416 meth_get__doc__(PythonQtSlotFunctionObject * /*m*/, void * /*closure*/)
421 {
417 {
422 Py_INCREF(Py_None);
418 Py_INCREF(Py_None);
423 return Py_None;
419 return Py_None;
424 }
420 }
425
421
426 static PyObject *
422 static PyObject *
427 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
423 meth_get__name__(PythonQtSlotFunctionObject *m, void * /*closure*/)
428 {
424 {
429 #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) )
425 #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) )
430 #ifdef PY3K
426 #ifdef PY3K
431 return PyUnicode_FromString(m->m_ml->metaMethod()->methodSignature());
427 return PyUnicode_FromString(m->m_ml->metaMethod()->methodSignature());
432 #else
428 #else
433 return PyString_FromString(m->m_ml->metaMethod()->methodSignature());
429 return PyString_FromString(m->m_ml->metaMethod()->methodSignature());
434 #endif
430 #endif
435 #else
431 #else
436 #ifdef PY3K
432 #ifdef PY3K
437 return PyUnicode_FromString(m->m_ml->metaMethod()->signature());
433 return PyUnicode_FromString(m->m_ml->metaMethod()->signature());
438 #else
434 #else
439 return PyString_FromString(m->m_ml->metaMethod()->signature());
435 return PyString_FromString(m->m_ml->metaMethod()->signature());
440 #endif
436 #endif
441 #endif
437 #endif
442 }
438 }
443
439
444 static int
440 static int
445 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
441 meth_traverse(PythonQtSlotFunctionObject *m, visitproc visit, void *arg)
446 {
442 {
447 int err;
443 int err;
448 if (m->m_self != NULL) {
444 if (m->m_self != NULL) {
449 err = visit(m->m_self, arg);
445 err = visit(m->m_self, arg);
450 if (err)
446 if (err)
451 return err;
447 return err;
452 }
448 }
453 if (m->m_module != NULL) {
449 if (m->m_module != NULL) {
454 err = visit(m->m_module, arg);
450 err = visit(m->m_module, arg);
455 if (err)
451 if (err)
456 return err;
452 return err;
457 }
453 }
458 return 0;
454 return 0;
459 }
455 }
460
456
461 static PyObject *
457 static PyObject *
462 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
458 meth_get__self__(PythonQtSlotFunctionObject *m, void * /*closure*/)
463 {
459 {
464 PyObject *self;
460 PyObject *self;
465 #ifndef PY3K
461 #ifndef PY3K
466 if (PyEval_GetRestricted()) {
462 if (PyEval_GetRestricted()) {
467 PyErr_SetString(PyExc_RuntimeError,
463 PyErr_SetString(PyExc_RuntimeError,
468 "method.__self__ not accessible in restricted mode");
464 "method.__self__ not accessible in restricted mode");
469 return NULL;
465 return NULL;
470 }
466 }
471 #endif
467 #endif
472 self = m->m_self;
468 self = m->m_self;
473 if (self == NULL)
469 if (self == NULL)
474 self = Py_None;
470 self = Py_None;
475 Py_INCREF(self);
471 Py_INCREF(self);
476 return self;
472 return self;
477 }
473 }
478
474
479 static PyGetSetDef meth_getsets [] = {
475 static PyGetSetDef meth_getsets [] = {
480 {const_cast<char*>("__doc__"), (getter)meth_get__doc__, NULL, NULL},
476 {const_cast<char*>("__doc__"), (getter)meth_get__doc__, NULL, NULL},
481 {const_cast<char*>("__name__"), (getter)meth_get__name__, NULL, NULL},
477 {const_cast<char*>("__name__"), (getter)meth_get__name__, NULL, NULL},
482 {const_cast<char*>("__self__"), (getter)meth_get__self__, NULL, NULL},
478 {const_cast<char*>("__self__"), (getter)meth_get__self__, NULL, NULL},
483 {NULL, NULL, NULL,NULL},
479 {NULL, NULL, NULL,NULL},
484 };
480 };
485
481
486 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
482 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 6
487 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
483 #define PY_WRITE_RESTRICTED WRITE_RESTRICTED
488 #endif
484 #endif
489
485
490 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
486 #define OFF(x) offsetof(PythonQtSlotFunctionObject, x)
491
487
492 static PyMemberDef meth_members[] = {
488 static PyMemberDef meth_members[] = {
493 {const_cast<char*>("__module__"), T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
489 {const_cast<char*>("__module__"), T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
494 {NULL}
490 {NULL}
495 };
491 };
496
492
497 static PyObject *PythonQtSlotFunction_parameterTypes(PythonQtSlotFunctionObject* type)
493 static PyObject *PythonQtSlotFunction_parameterTypes(PythonQtSlotFunctionObject* type)
498 {
494 {
499 return PythonQtMemberFunction_parameterTypes(type->m_ml);
495 return PythonQtMemberFunction_parameterTypes(type->m_ml);
500 }
496 }
501
497
502 static PyObject *PythonQtSlotFunction_parameterNames(PythonQtSlotFunctionObject* type)
498 static PyObject *PythonQtSlotFunction_parameterNames(PythonQtSlotFunctionObject* type)
503 {
499 {
504 return PythonQtMemberFunction_parameterNames(type->m_ml);
500 return PythonQtMemberFunction_parameterNames(type->m_ml);
505 }
501 }
506
502
507 static PyObject *PythonQtSlotFunction_typeName(PythonQtSlotFunctionObject* type)
503 static PyObject *PythonQtSlotFunction_typeName(PythonQtSlotFunctionObject* type)
508 {
504 {
509 return PythonQtMemberFunction_typeName(type->m_ml);
505 return PythonQtMemberFunction_typeName(type->m_ml);
510 }
506 }
511
507
512 PyObject *PythonQtMemberFunction_parameterTypes(PythonQtSlotInfo* theInfo)
508 PyObject *PythonQtMemberFunction_parameterTypes(PythonQtSlotInfo* theInfo)
513 {
509 {
514 PythonQtSlotInfo* info = theInfo;
510 PythonQtSlotInfo* info = theInfo;
515 int count = 0;
511 int count = 0;
516 while (info) {
512 while (info) {
517 info = info->nextInfo();
513 info = info->nextInfo();
518 count++;
514 count++;
519 }
515 }
520 info = theInfo;
516 info = theInfo;
521 PyObject* result = PyTuple_New(count);
517 PyObject* result = PyTuple_New(count);
522 for (int j = 0;j<count;j++) {
518 for (int j = 0;j<count;j++) {
523 QList<QByteArray> types = info->metaMethod()->parameterTypes();
519 QList<QByteArray> types = info->metaMethod()->parameterTypes();
524 PyObject* tuple = PyTuple_New(types.count());
520 PyObject* tuple = PyTuple_New(types.count());
525 for (int i = 0; i<types.count();i++) {
521 for (int i = 0; i<types.count();i++) {
526 #ifdef PY3K
522 #ifdef PY3K
527 PyTuple_SET_ITEM(tuple, i, PyUnicode_FromString(types.at(i).constData()));
523 PyTuple_SET_ITEM(tuple, i, PyUnicode_FromString(types.at(i).constData()));
528 #else
524 #else
529 PyTuple_SET_ITEM(tuple, i, PyString_FromString(types.at(i).constData()));
525 PyTuple_SET_ITEM(tuple, i, PyString_FromString(types.at(i).constData()));
530 #endif
526 #endif
531 }
527 }
532 info = info->nextInfo();
528 info = info->nextInfo();
533 PyTuple_SET_ITEM(result, j, tuple);
529 PyTuple_SET_ITEM(result, j, tuple);
534 }
530 }
535 return result;
531 return result;
536 }
532 }
537
533
538 PyObject *PythonQtMemberFunction_parameterNames(PythonQtSlotInfo* theInfo)
534 PyObject *PythonQtMemberFunction_parameterNames(PythonQtSlotInfo* theInfo)
539 {
535 {
540 PythonQtSlotInfo* info = theInfo;
536 PythonQtSlotInfo* info = theInfo;
541 int count = 0;
537 int count = 0;
542 while (info) {
538 while (info) {
543 info = info->nextInfo();
539 info = info->nextInfo();
544 count++;
540 count++;
545 }
541 }
546 info = theInfo;
542 info = theInfo;
547 PyObject* result = PyTuple_New(count);
543 PyObject* result = PyTuple_New(count);
548 for (int j = 0;j<count;j++) {
544 for (int j = 0;j<count;j++) {
549 QList<QByteArray> names = info->metaMethod()->parameterNames();
545 QList<QByteArray> names = info->metaMethod()->parameterNames();
550 PyObject* tuple = PyTuple_New(names.count());
546 PyObject* tuple = PyTuple_New(names.count());
551 for (int i = 0; i<names.count();i++) {
547 for (int i = 0; i<names.count();i++) {
552 #ifdef PY3K
548 #ifdef PY3K
553 PyTuple_SET_ITEM(tuple, i, PyUnicode_FromString(names.at(i).constData()));
549 PyTuple_SET_ITEM(tuple, i, PyUnicode_FromString(names.at(i).constData()));
554 #else
550 #else
555 PyTuple_SET_ITEM(tuple, i, PyString_FromString(names.at(i).constData()));
551 PyTuple_SET_ITEM(tuple, i, PyString_FromString(names.at(i).constData()));
556 #endif
552 #endif
557 }
553 }
558 info = info->nextInfo();
554 info = info->nextInfo();
559 PyTuple_SET_ITEM(result, j, tuple);
555 PyTuple_SET_ITEM(result, j, tuple);
560 }
556 }
561 return result;
557 return result;
562 }
558 }
563
559
564 PyObject *PythonQtMemberFunction_typeName(PythonQtSlotInfo* theInfo)
560 PyObject *PythonQtMemberFunction_typeName(PythonQtSlotInfo* theInfo)
565 {
561 {
566 PythonQtSlotInfo* info = theInfo;
562 PythonQtSlotInfo* info = theInfo;
567 int count = 0;
563 int count = 0;
568 while (info) {
564 while (info) {
569 info = info->nextInfo();
565 info = info->nextInfo();
570 count++;
566 count++;
571 }
567 }
572 info = theInfo;
568 info = theInfo;
573 PyObject* result = PyTuple_New(count);
569 PyObject* result = PyTuple_New(count);
574 for (int j = 0;j<count;j++) {
570 for (int j = 0;j<count;j++) {
575 QByteArray name = info->metaMethod()->typeName();
571 QByteArray name = info->metaMethod()->typeName();
576 #ifdef PY3K
572 #ifdef PY3K
577 PyTuple_SET_ITEM(result, j, PyUnicode_FromString(name.constData()));
573 PyTuple_SET_ITEM(result, j, PyUnicode_FromString(name.constData()));
578 #else
574 #else
579 PyTuple_SET_ITEM(result, j, PyString_FromString(name.constData()));
575 PyTuple_SET_ITEM(result, j, PyString_FromString(name.constData()));
580 #endif
576 #endif
581 info = info->nextInfo();
577 info = info->nextInfo();
582 }
578 }
583 return result;
579 return result;
584 }
580 }
585
581
586 static PyMethodDef meth_methods[] = {
582 static PyMethodDef meth_methods[] = {
587 {"parameterTypes", (PyCFunction)PythonQtSlotFunction_parameterTypes, METH_NOARGS,
583 {"parameterTypes", (PyCFunction)PythonQtSlotFunction_parameterTypes, METH_NOARGS,
588 "Returns a tuple of tuples of the C++ parameter types for all overloads of the slot"
584 "Returns a tuple of tuples of the C++ parameter types for all overloads of the slot"
589 },
585 },
590 {"parameterNames", (PyCFunction)PythonQtSlotFunction_parameterNames, METH_NOARGS,
586 {"parameterNames", (PyCFunction)PythonQtSlotFunction_parameterNames, METH_NOARGS,
591 "Returns a tuple of tuples of the C++ parameter type names (if available), for all overloads of the slot"
587 "Returns a tuple of tuples of the C++ parameter type names (if available), for all overloads of the slot"
592 },
588 },
593 {"typeName", (PyCFunction)PythonQtSlotFunction_typeName, METH_NOARGS,
589 {"typeName", (PyCFunction)PythonQtSlotFunction_typeName, METH_NOARGS,
594 "Returns a tuple of the C++ return value types of each slot overload"
590 "Returns a tuple of the C++ return value types of each slot overload"
595 },
591 },
596 {NULL, NULL, 0 , NULL} /* Sentinel */
592 {NULL, NULL, 0 , NULL} /* Sentinel */
597 };
593 };
598
594
599 static PyObject *
595 static PyObject *
600 meth_repr(PythonQtSlotFunctionObject *f)
596 meth_repr(PythonQtSlotFunctionObject *f)
601 {
597 {
602 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
598 if (f->m_self->ob_type == &PythonQtClassWrapper_Type) {
603 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
599 PythonQtClassWrapper* self = (PythonQtClassWrapper*) f->m_self;
604 #ifdef PY3K
600 #ifdef PY3K
605 return PyUnicode_FromFormat("<unbound qt slot %s of %s type>",
601 return PyUnicode_FromFormat("<unbound qt slot %s of %s type>",
606 #else
602 #else
607 return PyString_FromFormat("<unbound qt slot %s of %s type>",
603 return PyString_FromFormat("<unbound qt slot %s of %s type>",
608 #endif
604 #endif
609 f->m_ml->slotName().data(),
605 f->m_ml->slotName().data(),
610 self->classInfo()->className());
606 self->classInfo()->className());
611 } else {
607 } else {
612 #ifdef PY3K
608 #ifdef PY3K
613 return PyUnicode_FromFormat("<qt slot %s of %s instance at %p",
609 return PyUnicode_FromFormat("<qt slot %s of %s instance at %p",
614 #else
610 #else
615 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
611 return PyString_FromFormat("<qt slot %s of %s instance at %p>",
616 #endif
612 #endif
617 f->m_ml->slotName().data(),
613 f->m_ml->slotName().data(),
618 f->m_self->ob_type->tp_name,
614 f->m_self->ob_type->tp_name,
619 f->m_self);
615 f->m_self);
620 }
616 }
621 }
617 }
622
618
623 static int
619 static int
624 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
620 meth_compare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b)
625 {
621 {
626 if (a->m_self != b->m_self)
622 if (a->m_self != b->m_self)
627 return (a->m_self < b->m_self) ? -1 : 1;
623 return (a->m_self < b->m_self) ? -1 : 1;
628 if (a->m_ml == b->m_ml)
624 if (a->m_ml == b->m_ml)
629 return 0;
625 return 0;
630 #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) )
626 #if( QT_VERSION >= QT_VERSION_CHECK(5,0,0) )
631 if (strcmp(a->m_ml->metaMethod()->methodSignature(), b->m_ml->metaMethod()->methodSignature()) < 0)
627 if (strcmp(a->m_ml->metaMethod()->methodSignature(), b->m_ml->metaMethod()->methodSignature()) < 0)
632 #else
628 #else
633 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
629 if (strcmp(a->m_ml->metaMethod()->signature(), b->m_ml->metaMethod()->signature()) < 0)
634 #endif
630 #endif
635 return -1;
631 return -1;
636 else
632 else
637 return 1;
633 return 1;
638 }
634 }
639
635
640 static long
636 static long
641 meth_hash(PythonQtSlotFunctionObject *a)
637 meth_hash(PythonQtSlotFunctionObject *a)
642 {
638 {
643 long x,y;
639 long x,y;
644 if (a->m_self == NULL)
640 if (a->m_self == NULL)
645 x = 0;
641 x = 0;
646 else {
642 else {
647 x = PyObject_Hash(a->m_self);
643 x = PyObject_Hash(a->m_self);
648 if (x == -1)
644 if (x == -1)
649 return -1;
645 return -1;
650 }
646 }
651 y = _Py_HashPointer((void*)(a->m_ml));
647 y = _Py_HashPointer((void*)(a->m_ml));
652 if (y == -1)
648 if (y == -1)
653 return -1;
649 return -1;
654 x ^= y;
650 x ^= y;
655 if (x == -1)
651 if (x == -1)
656 x = -2;
652 x = -2;
657 return x;
653 return x;
658 }
654 }
659
655
660 // for python 3.x
656 // for python 3.x
661 static PyObject*
657 static PyObject*
662 meth_richcompare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b, int op)
658 meth_richcompare(PythonQtSlotFunctionObject *a, PythonQtSlotFunctionObject *b, int op)
663 {
659 {
664 int x = meth_compare(a, b);
660 int x = meth_compare(a, b);
665 bool r;
661 bool r;
666 if (op == Py_LT)
662 if (op == Py_LT)
667 r = x < 0;
663 r = x < 0;
668 else if (op == Py_LE)
664 else if (op == Py_LE)
669 r = x < 1;
665 r = x < 1;
670 else if (op == Py_EQ)
666 else if (op == Py_EQ)
671 r = x == 0;
667 r = x == 0;
672 else if (op == Py_NE)
668 else if (op == Py_NE)
673 r = x != 0;
669 r = x != 0;
674 else if (op == Py_GE)
670 else if (op == Py_GE)
675 r = x > -1;
671 r = x > -1;
676 else if (op == Py_GT)
672 else if (op == Py_GT)
677 r = x > 0;
673 r = x > 0;
678 if (r)
674 if (r)
679 Py_RETURN_TRUE;
675 Py_RETURN_TRUE;
680 else
676 else
681 Py_RETURN_FALSE;
677 Py_RETURN_FALSE;
682 }
678 }
683
679
684
680
685 PyTypeObject PythonQtSlotFunction_Type = {
681 PyTypeObject PythonQtSlotFunction_Type = {
686 PyVarObject_HEAD_INIT(&PyType_Type, 0)
682 PyVarObject_HEAD_INIT(&PyType_Type, 0)
687 "builtin_qt_slot",
683 "builtin_qt_slot",
688 sizeof(PythonQtSlotFunctionObject),
684 sizeof(PythonQtSlotFunctionObject),
689 0,
685 0,
690 (destructor)meth_dealloc, /* tp_dealloc */
686 (destructor)meth_dealloc, /* tp_dealloc */
691 0, /* tp_print */
687 0, /* tp_print */
692 0, /* tp_getattr */
688 0, /* tp_getattr */
693 0, /* tp_setattr */
689 0, /* tp_setattr */
694 #ifdef PY3K
690 #ifdef PY3K
695 0,
691 0,
696 #else
692 #else
697 (cmpfunc)meth_compare, /* tp_compare */
693 (cmpfunc)meth_compare, /* tp_compare */
698 #endif
694 #endif
699 (reprfunc)meth_repr, /* tp_repr */
695 (reprfunc)meth_repr, /* tp_repr */
700 0, /* tp_as_number */
696 0, /* tp_as_number */
701 0, /* tp_as_sequence */
697 0, /* tp_as_sequence */
702 0, /* tp_as_mapping */
698 0, /* tp_as_mapping */
703 (hashfunc)meth_hash, /* tp_hash */
699 (hashfunc)meth_hash, /* tp_hash */
704 PythonQtSlotFunction_Call, /* tp_call */
700 PythonQtSlotFunction_Call, /* tp_call */
705 0, /* tp_str */
701 0, /* tp_str */
706 PyObject_GenericGetAttr, /* tp_getattro */
702 PyObject_GenericGetAttr, /* tp_getattro */
707 0, /* tp_setattro */
703 0, /* tp_setattro */
708 0, /* tp_as_buffer */
704 0, /* tp_as_buffer */
709 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
705 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
710 0, /* tp_doc */
706 0, /* tp_doc */
711 (traverseproc)meth_traverse, /* tp_traverse */
707 (traverseproc)meth_traverse, /* tp_traverse */
712 0, /* tp_clear */
708 0, /* tp_clear */
713 (richcmpfunc)meth_richcompare, /* tp_richcompare */
709 (richcmpfunc)meth_richcompare, /* tp_richcompare */
714 0, /* tp_weaklistoffset */
710 0, /* tp_weaklistoffset */
715 0, /* tp_iter */
711 0, /* tp_iter */
716 0, /* tp_iternext */
712 0, /* tp_iternext */
717 meth_methods, /* tp_methods */
713 meth_methods, /* tp_methods */
718 meth_members, /* tp_members */
714 meth_members, /* tp_members */
719 meth_getsets, /* tp_getset */
715 meth_getsets, /* tp_getset */
720 0, /* tp_base */
716 0, /* tp_base */
721 0, /* tp_dict */
717 0, /* tp_dict */
722 };
718 };
723
719
724 /* Clear out the free list */
720 /* Clear out the free list */
725
721
726 void
722 void
727 PythonQtSlotFunction_Fini(void)
723 PythonQtSlotFunction_Fini(void)
728 {
724 {
729 while (pythonqtslot_free_list) {
725 while (pythonqtslot_free_list) {
730 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
726 PythonQtSlotFunctionObject *v = pythonqtslot_free_list;
731 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
727 pythonqtslot_free_list = (PythonQtSlotFunctionObject *)(v->m_self);
732 PyObject_GC_Del(v);
728 PyObject_GC_Del(v);
733 }
729 }
734 }
730 }
735
731
@@ -1,587 +1,595
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
3 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
26 * Contact information: MeVis Medical Solutions AG, 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 PythonQtTests.cpp
35 // \file PythonQtTests.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 "PythonQtTests.h"
42 #include "PythonQtTests.h"
43
43
44 void PythonQtTestSlotCalling::initTestCase()
44 void PythonQtTestSlotCalling::initTestCase()
45 {
45 {
46 _helper = new PythonQtTestSlotCallingHelper(this);
46 _helper = new PythonQtTestSlotCallingHelper(this);
47 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
47 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
48 main.evalScript("import PythonQt");
48 main.evalScript("import PythonQt");
49 PythonQt::self()->addObject(main, "obj", _helper);
49 PythonQt::self()->addObject(main, "obj", _helper);
50 }
50 }
51
51
52 void PythonQtTestSlotCalling::init() {
52 void PythonQtTestSlotCalling::init() {
53
53
54 }
54 }
55
55
56
56
57 void* polymorphic_ClassB_Handler(const void* ptr, const char** className) {
57 void* polymorphic_ClassB_Handler(const void* ptr, const char** className) {
58 ClassB* o = (ClassB*)ptr;
58 ClassB* o = (ClassB*)ptr;
59 if (o->type()==2) {
59 if (o->type()==2) {
60 *className = "ClassB";
60 *className = "ClassB";
61 return (ClassB*)o;
61 return (ClassB*)o;
62 }
62 }
63 if (o->type()==3) {
63 if (o->type()==3) {
64 *className = "ClassC";
64 *className = "ClassC";
65 return (ClassC*)o;
65 return (ClassC*)o;
66 }
66 }
67 if (o->type()==4) {
67 if (o->type()==4) {
68 *className = "ClassD";
68 *className = "ClassD";
69 return (ClassD*)o;
69 return (ClassD*)o;
70 }
70 }
71 return NULL;
71 return NULL;
72 }
72 }
73
73
74 void PythonQtTestSlotCalling::testInheritance() {
74 void PythonQtTestSlotCalling::testInheritance() {
75 PythonQt::self()->registerCPPClass("ClassA",NULL,NULL, PythonQtCreateObject<ClassAWrapper>);
75 PythonQt::self()->registerCPPClass("ClassA",NULL,NULL, PythonQtCreateObject<ClassAWrapper>);
76 PythonQt::self()->registerCPPClass("ClassB",NULL,NULL, PythonQtCreateObject<ClassBWrapper>);
76 PythonQt::self()->registerCPPClass("ClassB",NULL,NULL, PythonQtCreateObject<ClassBWrapper>);
77 PythonQt::self()->registerCPPClass("ClassC",NULL,NULL, PythonQtCreateObject<ClassCWrapper>);
77 PythonQt::self()->registerCPPClass("ClassC",NULL,NULL, PythonQtCreateObject<ClassCWrapper>);
78 PythonQt::self()->addParentClass("ClassC", "ClassA", PythonQtUpcastingOffset<ClassC,ClassA>());
78 PythonQt::self()->addParentClass("ClassC", "ClassA", PythonQtUpcastingOffset<ClassC,ClassA>());
79 PythonQt::self()->addParentClass("ClassC", "ClassB", PythonQtUpcastingOffset<ClassC,ClassB>());
79 PythonQt::self()->addParentClass("ClassC", "ClassB", PythonQtUpcastingOffset<ClassC,ClassB>());
80 PythonQt::self()->registerClass(&ClassD::staticMetaObject, NULL, PythonQtCreateObject<ClassDWrapper>);
80 PythonQt::self()->registerClass(&ClassD::staticMetaObject, NULL, PythonQtCreateObject<ClassDWrapper>);
81 PythonQt::self()->addParentClass("ClassD", "ClassA", PythonQtUpcastingOffset<ClassD,ClassA>());
81 PythonQt::self()->addParentClass("ClassD", "ClassA", PythonQtUpcastingOffset<ClassD,ClassA>());
82 PythonQt::self()->addParentClass("ClassD", "ClassB", PythonQtUpcastingOffset<ClassD,ClassB>());
82 PythonQt::self()->addParentClass("ClassD", "ClassB", PythonQtUpcastingOffset<ClassD,ClassB>());
83
83
84 PythonQtObjectPtr classA = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassA");
84 PythonQtObjectPtr classA = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassA");
85 PythonQtObjectPtr classB = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassB");
85 PythonQtObjectPtr classB = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassB");
86 PythonQtObjectPtr classC = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassC");
86 PythonQtObjectPtr classC = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassC");
87 PythonQtObjectPtr classD = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassD");
87 PythonQtObjectPtr classD = PythonQt::self()->getMainModule().getVariable("PythonQt.private.ClassD");
88 QVERIFY(classA);
88 QVERIFY(classA);
89 QVERIFY(classB);
89 QVERIFY(classB);
90 QVERIFY(classC);
90 QVERIFY(classC);
91 QVERIFY(classD);
91 QVERIFY(classD);
92
92
93 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
93 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
94 QEXPECT_FAIL("", "ClassB can not be converted to ClassA", Continue);
94 QEXPECT_FAIL("", "ClassB can not be converted to ClassA", Continue);
95 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
95 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
96 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
96 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
97 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
97 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassAPtr(a).getX()==1: obj.setPassed();\n"));
98
98
99 QEXPECT_FAIL("", "ClassA can not be converted to ClassB", Continue);
99 QEXPECT_FAIL("", "ClassA can not be converted to ClassB", Continue);
100 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
100 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
101 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
101 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
102 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
102 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
103 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
103 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassBPtr(a).getY()==2: obj.setPassed();\n"));
104
104
105 QEXPECT_FAIL("", "ClassA can not be converted to ClassC", Continue);
105 QEXPECT_FAIL("", "ClassA can not be converted to ClassC", Continue);
106 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
106 QVERIFY(_helper->runScript("a = PythonQt.private.ClassA();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
107 QEXPECT_FAIL("", "ClassB can not be converted to ClassC", Continue);
107 QEXPECT_FAIL("", "ClassB can not be converted to ClassC", Continue);
108 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
108 QVERIFY(_helper->runScript("a = PythonQt.private.ClassB();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
109 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
109 QVERIFY(_helper->runScript("a = PythonQt.private.ClassC();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
110 QEXPECT_FAIL("", "ClassD can not be converted to ClassC", Continue);
110 QEXPECT_FAIL("", "ClassD can not be converted to ClassC", Continue);
111 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
111 QVERIFY(_helper->runScript("a = PythonQt.private.ClassD();\nif obj.getClassCPtr(a).getX()==1: obj.setPassed();\n"));
112
112
113 QVERIFY(_helper->runScript("if type(obj.createClassA())==PythonQt.private.ClassA: obj.setPassed();\n"));
113 QVERIFY(_helper->runScript("if type(obj.createClassA())==PythonQt.private.ClassA: obj.setPassed();\n"));
114 QVERIFY(_helper->runScript("if type(obj.createClassB())==PythonQt.private.ClassB: obj.setPassed();\n"));
114 QVERIFY(_helper->runScript("if type(obj.createClassB())==PythonQt.private.ClassB: obj.setPassed();\n"));
115 QVERIFY(_helper->runScript("if type(obj.createClassCAsA())==PythonQt.private.ClassA: obj.setPassed();\n"));
115 QVERIFY(_helper->runScript("if type(obj.createClassCAsA())==PythonQt.private.ClassA: obj.setPassed();\n"));
116 QVERIFY(_helper->runScript("if type(obj.createClassCAsB())==PythonQt.private.ClassB: obj.setPassed();\n"));
116 QVERIFY(_helper->runScript("if type(obj.createClassCAsB())==PythonQt.private.ClassB: obj.setPassed();\n"));
117 QVERIFY(_helper->runScript("if type(obj.createClassD())==PythonQt.private.ClassD: obj.setPassed();\n"));
117 QVERIFY(_helper->runScript("if type(obj.createClassD())==PythonQt.private.ClassD: obj.setPassed();\n"));
118 QVERIFY(_helper->runScript("if type(obj.createClassDAsA())==PythonQt.private.ClassA: obj.setPassed();\n"));
118 QVERIFY(_helper->runScript("if type(obj.createClassDAsA())==PythonQt.private.ClassA: obj.setPassed();\n"));
119 QVERIFY(_helper->runScript("if type(obj.createClassDAsB())==PythonQt.private.ClassB: obj.setPassed();\n"));
119 QVERIFY(_helper->runScript("if type(obj.createClassDAsB())==PythonQt.private.ClassB: obj.setPassed();\n"));
120
120
121 PythonQt::self()->addPolymorphicHandler("ClassB", polymorphic_ClassB_Handler);
121 PythonQt::self()->addPolymorphicHandler("ClassB", polymorphic_ClassB_Handler);
122
122
123 QVERIFY(_helper->runScript("if type(obj.getClassBPtr(obj.createClassB()))==PythonQt.private.ClassB: obj.setPassed();\n"));
123 QVERIFY(_helper->runScript("if type(obj.getClassBPtr(obj.createClassB()))==PythonQt.private.ClassB: obj.setPassed();\n"));
124 QVERIFY(_helper->runScript("if type(obj.createClassCAsB())==PythonQt.private.ClassC: obj.setPassed();\n"));
124 QVERIFY(_helper->runScript("if type(obj.createClassCAsB())==PythonQt.private.ClassC: obj.setPassed();\n"));
125 QVERIFY(_helper->runScript("if type(obj.createClassDAsB())==PythonQt.private.ClassD: obj.setPassed();\n"));
125 QVERIFY(_helper->runScript("if type(obj.createClassDAsB())==PythonQt.private.ClassD: obj.setPassed();\n"));
126
126
127 }
127 }
128
128
129 void PythonQtTestSlotCalling::testAutoConversion() {
129 void PythonQtTestSlotCalling::testAutoConversion() {
130 QVERIFY(_helper->runScript("if obj.setAutoConvertColor(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
130 QVERIFY(_helper->runScript("if obj.setAutoConvertColor(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
131 QVERIFY(_helper->runScript("if obj.setAutoConvertBrush(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QBrush(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
131 QVERIFY(_helper->runScript("if obj.setAutoConvertBrush(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QBrush(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
132 QVERIFY(_helper->runScript("if obj.setAutoConvertPen(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QPen(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
132 QVERIFY(_helper->runScript("if obj.setAutoConvertPen(PythonQt.QtCore.Qt.red)==PythonQt.Qt.QPen(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
133 QVERIFY(_helper->runScript("if obj.setAutoConvertBrush(PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red))==PythonQt.Qt.QBrush(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
133 QVERIFY(_helper->runScript("if obj.setAutoConvertBrush(PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red))==PythonQt.Qt.QBrush(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
134 QVERIFY(_helper->runScript("if obj.setAutoConvertPen(PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red))==PythonQt.Qt.QPen(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
134 QVERIFY(_helper->runScript("if obj.setAutoConvertPen(PythonQt.Qt.QColor(PythonQt.QtCore.Qt.red))==PythonQt.Qt.QPen(PythonQt.QtCore.Qt.red): obj.setPassed();\n"));
135 QVERIFY(_helper->runScript("if obj.setAutoConvertCursor(PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor)).shape()==PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape(): obj.setPassed();\n"));
135 QVERIFY(_helper->runScript("if obj.setAutoConvertCursor(PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor)).shape()==PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape(): obj.setPassed();\n"));
136 QVERIFY(_helper->runScript("if obj.setAutoConvertCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape()==PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape(): obj.setPassed();\n"));
136 QVERIFY(_helper->runScript("if obj.setAutoConvertCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape()==PythonQt.Qt.QCursor(PythonQt.QtCore.Qt.UpArrowCursor).shape(): obj.setPassed();\n"));
137 }
137 }
138
138
139 void PythonQtTestSlotCalling::testNoArgSlotCall()
139 void PythonQtTestSlotCalling::testNoArgSlotCall()
140 {
140 {
141 QVERIFY(_helper->runScript("obj.testNoArg(); obj.setPassed();\n"));
141 QVERIFY(_helper->runScript("obj.testNoArg(); obj.setPassed();\n"));
142 }
142 }
143
143
144 void PythonQtTestSlotCalling::testOverloadedCall()
144 void PythonQtTestSlotCalling::testOverloadedCall()
145 {
145 {
146 QVERIFY(_helper->runScript("obj.overload(False); obj.setPassed();\n", 0));
146 QVERIFY(_helper->runScript("obj.overload(False); obj.setPassed();\n", 0));
147 QVERIFY(_helper->runScript("obj.overload(True); obj.setPassed();\n", 0));
147 QVERIFY(_helper->runScript("obj.overload(True); obj.setPassed();\n", 0));
148 QVERIFY(_helper->runScript("obj.overload(12.5); obj.setPassed();\n", 1));
148 QVERIFY(_helper->runScript("obj.overload(12.5); obj.setPassed();\n", 1));
149 QVERIFY(_helper->runScript("obj.overload(12); obj.setPassed();\n", 2));
149 QVERIFY(_helper->runScript("obj.overload(12); obj.setPassed();\n", 2));
150 QVERIFY(_helper->runScript("obj.overload('test'); obj.setPassed();\n", 3));
150 QVERIFY(_helper->runScript("obj.overload('test'); obj.setPassed();\n", 3));
151 QVERIFY(_helper->runScript("obj.overload(u'test'); obj.setPassed();\n", 3));
151 QVERIFY(_helper->runScript("obj.overload(u'test'); obj.setPassed();\n", 3));
152 QVERIFY(_helper->runScript("obj.overload(('test','test2')); obj.setPassed();\n", 4));
152 QVERIFY(_helper->runScript("obj.overload(('test','test2')); obj.setPassed();\n", 4));
153 QVERIFY(_helper->runScript("obj.overload(obj); obj.setPassed();\n", 5));
153 QVERIFY(_helper->runScript("obj.overload(obj); obj.setPassed();\n", 5));
154 QVERIFY(_helper->runScript("obj.overload(12,13); obj.setPassed();\n", 6));
154 QVERIFY(_helper->runScript("obj.overload(12,13); obj.setPassed();\n", 6));
155 }
155 }
156
156
157 void PythonQtTestSlotCalling::testPyObjectSlotCall()
157 void PythonQtTestSlotCalling::testPyObjectSlotCall()
158 {
158 {
159 QVERIFY(_helper->runScript("if obj.getPyObject(PythonQt)==PythonQt: obj.setPassed();\n"));
159 QVERIFY(_helper->runScript("if obj.getPyObject(PythonQt)==PythonQt: obj.setPassed();\n"));
160 QVERIFY(_helper->runScript("if obj.getPyObject('Hello')=='Hello': obj.setPassed();\n"));
160 QVERIFY(_helper->runScript("if obj.getPyObject('Hello')=='Hello': obj.setPassed();\n"));
161 QVERIFY(_helper->runScript("if obj.getPyObjectFromVariant(PythonQt)==PythonQt: obj.setPassed();\n"));
161 QVERIFY(_helper->runScript("if obj.getPyObjectFromVariant(PythonQt)==PythonQt: obj.setPassed();\n"));
162 QVERIFY(_helper->runScript("if obj.getPyObjectFromVariant2(PythonQt)==PythonQt: obj.setPassed();\n"));
162 QVERIFY(_helper->runScript("if obj.getPyObjectFromVariant2(PythonQt)==PythonQt: obj.setPassed();\n"));
163 // QVERIFY(_helper->runScript("if obj.getPyObjectFromPtr(PythonQt)==PythonQt: obj.setPassed();\n"));
163 // QVERIFY(_helper->runScript("if obj.getPyObjectFromPtr(PythonQt)==PythonQt: obj.setPassed();\n"));
164 }
164 }
165
165
166 void PythonQtTestSlotCalling::testCPPSlotCalls()
166 void PythonQtTestSlotCalling::testCPPSlotCalls()
167 {
167 {
168 // test QColor compare operation
168 // test QColor compare operation
169 QVERIFY(_helper->runScript("if PythonQt.QtGui.QColor(1,2,3)==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();obj.testNoArg()\n"));
169 QVERIFY(_helper->runScript("if PythonQt.QtGui.QColor(1,2,3)==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();obj.testNoArg()\n"));
170 QVERIFY(_helper->runScript("if PythonQt.QtGui.QColor(1,2,3)!=PythonQt.QtGui.QColor(3,2,1): obj.setPassed();obj.testNoArg()\n"));
170 QVERIFY(_helper->runScript("if PythonQt.QtGui.QColor(1,2,3)!=PythonQt.QtGui.QColor(3,2,1): obj.setPassed();obj.testNoArg()\n"));
171
171
172 // test passing/returning QColors
172 // test passing/returning QColors
173 QVERIFY(_helper->runScript("if obj.getQColor1(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
173 QVERIFY(_helper->runScript("if obj.getQColor1(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
174 QVERIFY(_helper->runScript("if obj.getQColor2(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
174 QVERIFY(_helper->runScript("if obj.getQColor2(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
175 QVERIFY(_helper->runScript("if obj.getQColor3(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
175 QVERIFY(_helper->runScript("if obj.getQColor3(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
176 QVERIFY(_helper->runScript("if obj.getQColor4(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
176 QVERIFY(_helper->runScript("if obj.getQColor4(PythonQt.QtGui.QColor(1,2,3))==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
177 QVERIFY(_helper->runScript("if obj.getQColor5()==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
177 QVERIFY(_helper->runScript("if obj.getQColor5()==PythonQt.QtGui.QColor(1,2,3): obj.setPassed();\n"));
178 }
178 }
179
179
180 void PythonQtTestSlotCalling::testPODSlotCalls()
180 void PythonQtTestSlotCalling::testPODSlotCalls()
181 {
181 {
182 QVERIFY(_helper->runScript("if obj.getBool(False)==False: obj.setPassed();\n"));
182 QVERIFY(_helper->runScript("if obj.getBool(False)==False: obj.setPassed();\n"));
183 QVERIFY(_helper->runScript("if obj.getBool(True)==True: obj.setPassed();\n"));
183 QVERIFY(_helper->runScript("if obj.getBool(True)==True: obj.setPassed();\n"));
184 QVERIFY(_helper->runScript("if obj.getInt(-42)==-42: obj.setPassed();\n"));
184 QVERIFY(_helper->runScript("if obj.getInt(-42)==-42: obj.setPassed();\n"));
185 QVERIFY(_helper->runScript("if obj.getUInt(42)==42: obj.setPassed();\n"));
185 QVERIFY(_helper->runScript("if obj.getUInt(42)==42: obj.setPassed();\n"));
186 QVERIFY(_helper->runScript("if obj.getShort(-43)==-43: obj.setPassed();\n"));
186 QVERIFY(_helper->runScript("if obj.getShort(-43)==-43: obj.setPassed();\n"));
187 QVERIFY(_helper->runScript("if obj.getUShort(43)==43: obj.setPassed();\n"));
187 QVERIFY(_helper->runScript("if obj.getUShort(43)==43: obj.setPassed();\n"));
188 QVERIFY(_helper->runScript("if obj.getChar(-12)==-12: obj.setPassed();\n"));
188 QVERIFY(_helper->runScript("if obj.getChar(-12)==-12: obj.setPassed();\n"));
189 QVERIFY(_helper->runScript("if obj.getUChar(12)==12: obj.setPassed();\n"));
189 QVERIFY(_helper->runScript("if obj.getUChar(12)==12: obj.setPassed();\n"));
190 QVERIFY(_helper->runScript("if obj.getLong(-256*256*256)==-256*256*256: obj.setPassed();\n"));
190 QVERIFY(_helper->runScript("if obj.getLong(-256*256*256)==-256*256*256: obj.setPassed();\n"));
191 QVERIFY(_helper->runScript("if obj.getULong(256*256*256)==256*256*256: obj.setPassed();\n"));
191 QVERIFY(_helper->runScript("if obj.getULong(256*256*256)==256*256*256: obj.setPassed();\n"));
192 QVERIFY(_helper->runScript("if obj.getLongLong(-42)==-42: obj.setPassed();\n"));
192 QVERIFY(_helper->runScript("if obj.getLongLong(-42)==-42: obj.setPassed();\n"));
193 QVERIFY(_helper->runScript("if obj.getULongLong(42)==42: obj.setPassed();\n"));
193 QVERIFY(_helper->runScript("if obj.getULongLong(42)==42: obj.setPassed();\n"));
194 QVERIFY(_helper->runScript("if obj.getQChar(4096)==4096: obj.setPassed();\n"));
194 QVERIFY(_helper->runScript("if obj.getQChar(4096)==4096: obj.setPassed();\n"));
195 QVERIFY(_helper->runScript("if obj.getDouble(47.12)==47.12: obj.setPassed();\n"));
195 QVERIFY(_helper->runScript("if obj.getDouble(47.12)==47.12: obj.setPassed();\n"));
196 QVERIFY(_helper->runScript("if abs(obj.getFloat(47.11)-47.11)<0.01: obj.setPassed();\n"));
196 QVERIFY(_helper->runScript("if abs(obj.getFloat(47.11)-47.11)<0.01: obj.setPassed();\n"));
197 QVERIFY(_helper->runScript("if obj.getQString('testStr')=='testStr': obj.setPassed();\n"));
197 QVERIFY(_helper->runScript("if obj.getQString('testStr')=='testStr': obj.setPassed();\n"));
198 QVERIFY(_helper->runScript("if obj.getQString('')=='': obj.setPassed();\n"));
198 QVERIFY(_helper->runScript("if obj.getQString('')=='': obj.setPassed();\n"));
199 QVERIFY(_helper->runScript("if obj.getQStringList(('test','test2'))==('test','test2'): obj.setPassed();\n"));
199 QVERIFY(_helper->runScript("if obj.getQStringList(('test','test2'))==('test','test2'): obj.setPassed();\n"));
200 }
200 }
201
201
202 void PythonQtTestSlotCalling::testQVariantSlotCalls()
202 void PythonQtTestSlotCalling::testQVariantSlotCalls()
203 {
203 {
204 QVERIFY(_helper->runScript("if obj.getQVariant(-42)==-42: obj.setPassed();\n"));
204 QVERIFY(_helper->runScript("if obj.getQVariant(-42)==-42: obj.setPassed();\n"));
205 QVERIFY(_helper->runScript("if obj.getQVariant('testStr')=='testStr': obj.setPassed();\n"));
205 QVERIFY(_helper->runScript("if obj.getQVariant('testStr')=='testStr': obj.setPassed();\n"));
206 QVERIFY(_helper->runScript("if obj.getQVariant(('test','test2'))==('test','test2'): obj.setPassed();\n"));
206 QVERIFY(_helper->runScript("if obj.getQVariant(('test','test2'))==('test','test2'): obj.setPassed();\n"));
207 QVERIFY(_helper->runScript("if obj.getQVariant(('test',12, 47.11))==('test',12, 47.11): obj.setPassed();\n"));
207 QVERIFY(_helper->runScript("if obj.getQVariant(('test',12, 47.11))==('test',12, 47.11): obj.setPassed();\n"));
208 QVERIFY(_helper->runScript("if obj.getQVariant({'test':'bla','test2':47.11})=={'test':'bla','test2':47.11}: obj.setPassed();\n"));
208 QVERIFY(_helper->runScript("if obj.getQVariant({'test':'bla','test2':47.11})=={'test':'bla','test2':47.11}: obj.setPassed();\n"));
209 QEXPECT_FAIL("", "Testing to pass a map and compare with a different map", Continue);
209 QEXPECT_FAIL("", "Testing to pass a map and compare with a different map", Continue);
210 QVERIFY(_helper->runScript("if obj.getQVariant({'test':'bla2','test2':47.11})=={'test':'bla','test2':47.11}: obj.setPassed();\n"));
210 QVERIFY(_helper->runScript("if obj.getQVariant({'test':'bla2','test2':47.11})=={'test':'bla','test2':47.11}: obj.setPassed();\n"));
211 QVERIFY(_helper->runScript("if obj.getQVariant(obj)==obj: obj.setPassed();\n"));
211 QVERIFY(_helper->runScript("if obj.getQVariant(obj)==obj: obj.setPassed();\n"));
212 }
212 }
213
213
214 void PythonQtTestSlotCalling::testObjectSlotCalls()
214 void PythonQtTestSlotCalling::testObjectSlotCalls()
215 {
215 {
216 QVERIFY(_helper->runScript("if obj.getQObject(obj)==obj: obj.setPassed();\n"));
216 QVERIFY(_helper->runScript("if obj.getQObject(obj)==obj: obj.setPassed();\n"));
217 QVERIFY(_helper->runScript("if obj.getTestObject(obj)==obj: obj.setPassed();\n"));
217 QVERIFY(_helper->runScript("if obj.getTestObject(obj)==obj: obj.setPassed();\n"));
218 QVERIFY(_helper->runScript("if obj.getNewObject().className()=='PythonQtTestSlotCallingHelper': obj.setPassed();\n"));
218 QVERIFY(_helper->runScript("if obj.getNewObject().className()=='PythonQtTestSlotCallingHelper': obj.setPassed();\n"));
219 QEXPECT_FAIL("", "Testing to pass a QObject when another object was expected", Continue);
219 QEXPECT_FAIL("", "Testing to pass a QObject when another object was expected", Continue);
220 QVERIFY(_helper->runScript("if obj.getQWidget(obj)==obj: obj.setPassed();\n"));
220 QVERIFY(_helper->runScript("if obj.getQWidget(obj)==obj: obj.setPassed();\n"));
221 }
221 }
222
222
223 void PythonQtTestSlotCalling::testCppFactory()
223 void PythonQtTestSlotCalling::testCppFactory()
224 {
224 {
225 PythonQtTestCppFactory* f = new PythonQtTestCppFactory;
225 PythonQtTestCppFactory* f = new PythonQtTestCppFactory;
226 PythonQt::self()->addInstanceDecorators(new PQCppObjectDecorator);
226 PythonQt::self()->addInstanceDecorators(new PQCppObjectDecorator);
227 // do not register, since we want to know if that works as well
227 // do not register, since we want to know if that works as well
228 //qRegisterMetaType<PQCppObjectNoWrap>("PQCppObjectNoWrap");
228 //qRegisterMetaType<PQCppObjectNoWrap>("PQCppObjectNoWrap");
229 PythonQt::self()->addDecorators(new PQCppObjectNoWrapDecorator);
229 PythonQt::self()->addDecorators(new PQCppObjectNoWrapDecorator);
230
230
231 PythonQt::self()->addWrapperFactory(f);
231 PythonQt::self()->addWrapperFactory(f);
232 QVERIFY(_helper->runScript("if obj.createPQCppObject(12).getHeight()==12: obj.setPassed();\n"));
232 QVERIFY(_helper->runScript("if obj.createPQCppObject(12).getHeight()==12: obj.setPassed();\n"));
233 QVERIFY(_helper->runScript("if obj.createPQCppObject(12).getH()==12: obj.setPassed();\n"));
233 QVERIFY(_helper->runScript("if obj.createPQCppObject(12).getH()==12: obj.setPassed();\n"));
234 QVERIFY(_helper->runScript("pq1 = obj.createPQCppObject(12);\n"
234 QVERIFY(_helper->runScript("pq1 = obj.createPQCppObject(12);\n"
235 "pq2 = obj.createPQCppObject(13);\n"
235 "pq2 = obj.createPQCppObject(13);\n"
236 "pq3 = obj.getPQCppObject(pq1);\n"
236 "pq3 = obj.getPQCppObject(pq1);\n"
237 "pq4 = obj.getPQCppObject(pq2);\n"
237 "pq4 = obj.getPQCppObject(pq2);\n"
238 "if pq3.getHeight()==12 and pq4.getHeight()==13: obj.setPassed();\n"
238 "if pq3.getHeight()==12 and pq4.getHeight()==13: obj.setPassed();\n"
239 ));
239 ));
240
240
241 QVERIFY(_helper->runScript("if obj.createPQCppObjectNoWrap(12).getH()==12: obj.setPassed();\n"));
241 QVERIFY(_helper->runScript("if obj.createPQCppObjectNoWrap(12).getH()==12: obj.setPassed();\n"));
242
242
243 QVERIFY(_helper->runScript("if obj.getPQCppObjectNoWrapAsValue().getH()==47: obj.setPassed();\n"));
243 QVERIFY(_helper->runScript("if obj.getPQCppObjectNoWrapAsValue().getH()==47: obj.setPassed();\n"));
244
244
245 qRegisterMetaType<PQUnknownButRegisteredValueObject>("PQUnknownButRegisteredValueObject");
245 qRegisterMetaType<PQUnknownButRegisteredValueObject>("PQUnknownButRegisteredValueObject");
246 QVERIFY(_helper->runScript("a = obj.getUnknownButRegisteredValueObjectAsPtr();print a;\nif a!=None: obj.setPassed();\n"));
246 QVERIFY(_helper->runScript("a = obj.getUnknownButRegisteredValueObjectAsPtr();print (a);\nif a!=None: obj.setPassed();\n"));
247 QVERIFY(_helper->runScript("a = obj.getUnknownButRegisteredValueObjectAsValue();print a;\nif a!=None: obj.setPassed();\n"));
247 QVERIFY(_helper->runScript("a = obj.getUnknownButRegisteredValueObjectAsValue();print (a);\nif a!=None: obj.setPassed();\n"));
248 QVERIFY(_helper->runScript("a = obj.getUnknownValueObjectAsPtr();print a;\nif a!=None: obj.setPassed();\n"));
248 QVERIFY(_helper->runScript("a = obj.getUnknownValueObjectAsPtr();print (a);\nif a!=None: obj.setPassed();\n"));
249 QEXPECT_FAIL("", "Testing by value return without the object being registered as QMetaType or having registered a default constructor decorator", Continue);
249 QEXPECT_FAIL("", "Testing by value return without the object being registered as QMetaType or having registered a default constructor decorator", Continue);
250 QVERIFY(_helper->runScript("a = obj.getUnknownValueObjectAsValue();print a;\nif a!=None: obj.setPassed();\n"));
250 QVERIFY(_helper->runScript("a = obj.getUnknownValueObjectAsValue();print (a);\nif a!=None: obj.setPassed();\n"));
251
251
252 // expect to get strict call to double overload
252 // expect to get strict call to double overload
253 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(22.2)\nif a.getH()==2: obj.setPassed();\n"));
253 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(22.2)\nif a.getH()==2: obj.setPassed();\n"));
254 // expect to get un-strict call to double overload
254 // expect to get un-strict call to double overload
255 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(22)\nif a.getH()==2: obj.setPassed();\n"));
255 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(22)\nif a.getH()==2: obj.setPassed();\n"));
256 // expect to get strict call to copy constructor overload
256 // expect to get strict call to copy constructor overload
257 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(PQCppObjectNoWrap())\nprint a.getH()\nif a.getH()==1: obj.setPassed();\n"));
257 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObjectNoWrap\na = PQCppObjectNoWrap(PQCppObjectNoWrap())\nprint (a.getH())\nif a.getH()==1: obj.setPassed();\n"));
258
258
259 // test decorated enums
259 // test decorated enums
260 // already registered by signals test
260 // already registered by signals test
261 //PythonQt::self()->registerCPPClass("PQCppObject2",NULL,NULL, PythonQtCreateObject<PQCppObject2Decorator>);
261 //PythonQt::self()->registerCPPClass("PQCppObject2",NULL,NULL, PythonQtCreateObject<PQCppObject2Decorator>);
262
262
263 // local enum (decorated)
263 // local enum (decorated)
264 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nprint a.testEnumFlag1\nif a.testEnumFlag1(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
264 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nprint (a.testEnumFlag1)\nif a.testEnumFlag1(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
265 // enum with namespace (decorated)
265 // enum with namespace (decorated)
266 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nif a.testEnumFlag2(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
266 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nif a.testEnumFlag2(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
267 // with int overload to check overloading
267 // with int overload to check overloading
268 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nif a.testEnumFlag3(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
268 QVERIFY(_helper->runScript("obj.testNoArg()\nfrom PythonQt.private import PQCppObject2\na = PQCppObject2()\nif a.testEnumFlag3(PQCppObject2.TestEnumValue2)==PQCppObject2.TestEnumValue2: obj.setPassed();\n"));
269
269
270 }
270 }
271
271
272 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag1(PQCppObject2* obj, PQCppObject2Decorator::TestEnumFlag flag) {
272 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag1(PQCppObject2* obj, PQCppObject2Decorator::TestEnumFlag flag) {
273 return flag;
273 return flag;
274 }
274 }
275
275
276 PQCppObject2::TestEnumFlag PQCppObject2Decorator::testEnumFlag2(PQCppObject2* obj, PQCppObject2::TestEnumFlag flag) {
276 PQCppObject2::TestEnumFlag PQCppObject2Decorator::testEnumFlag2(PQCppObject2* obj, PQCppObject2::TestEnumFlag flag) {
277 return flag;
277 return flag;
278 }
278 }
279
279
280 // with int overload
280 // with int overload
281 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag3(PQCppObject2* obj, int flag) {
281 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag3(PQCppObject2* obj, int flag) {
282 return (TestEnumFlag)-1;
282 return (TestEnumFlag)-1;
283 }
283 }
284 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag3(PQCppObject2* obj, PQCppObject2Decorator::TestEnumFlag flag) {
284 PQCppObject2Decorator::TestEnumFlag PQCppObject2Decorator::testEnumFlag3(PQCppObject2* obj, PQCppObject2Decorator::TestEnumFlag flag) {
285 return flag;
285 return flag;
286 }
286 }
287
287
288 void PythonQtTestSlotCalling::testMultiArgsSlotCall()
288 void PythonQtTestSlotCalling::testMultiArgsSlotCall()
289 {
289 {
290 QVERIFY(_helper->runScript("if obj.getMultiArgs(12,47.11,'test')==(12,47.11,'test'): obj.setPassed();\n"));
290 QVERIFY(_helper->runScript("if obj.getMultiArgs(12,47.11,'test')==(12,47.11,'test'): obj.setPassed();\n"));
291 }
291 }
292
292
293 bool PythonQtTestSlotCallingHelper::runScript(const char* script, int expectedOverload)
293 bool PythonQtTestSlotCallingHelper::runScript(const char* script, int expectedOverload)
294 {
294 {
295 _called = false;
295 _called = false;
296 _passed = false;
296 _passed = false;
297 _calledOverload = -1;
297 _calledOverload = -1;
298 PyRun_SimpleString(script);
298 PyRun_SimpleString(script);
299 return _called && _passed && _calledOverload==expectedOverload;
299 return _called && _passed && _calledOverload==expectedOverload;
300 }
300 }
301
301
302
302
303 void PythonQtTestSignalHandler::initTestCase()
303 void PythonQtTestSignalHandler::initTestCase()
304 {
304 {
305 _helper = new PythonQtTestSignalHandlerHelper(this);
305 _helper = new PythonQtTestSignalHandlerHelper(this);
306 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
306 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
307 PythonQt::self()->addObject(main, "obj", _helper);
307 PythonQt::self()->addObject(main, "obj", _helper);
308 }
308 }
309
309
310 void PythonQtTestSignalHandler::testSignalHandler()
310 void PythonQtTestSignalHandler::testSignalHandler()
311 {
311 {
312 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
312 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
313 PyRun_SimpleString("def testIntSignal(a):\n if a==12: obj.setPassed();\n");
313 PyRun_SimpleString("def testIntSignal(a):\n if a==12: obj.setPassed();\n");
314 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(intSignal(int)), main, "testIntSignal"));
314 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(intSignal(int)), main, "testIntSignal"));
315 QVERIFY(_helper->emitIntSignal(12));
315 QVERIFY(_helper->emitIntSignal(12));
316
316
317 PyRun_SimpleString("def testFloatSignal(a):\n if a==12: obj.setPassed();\n");
317 PyRun_SimpleString("def testFloatSignal(a):\n if a==12: obj.setPassed();\n");
318 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(floatSignal(float)), main, "testFloatSignal"));
318 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(floatSignal(float)), main, "testFloatSignal"));
319 QVERIFY(_helper->emitFloatSignal(12));
319 QVERIFY(_helper->emitFloatSignal(12));
320
320
321 // test decorated enums
321 // test decorated enums
322 PythonQt::self()->registerCPPClass("PQCppObject2",NULL,NULL, PythonQtCreateObject<PQCppObject2Decorator>);
322 PythonQt::self()->registerCPPClass("PQCppObject2",NULL,NULL, PythonQtCreateObject<PQCppObject2Decorator>);
323
323
324 PyRun_SimpleString("def testEnumSignal(a):\n if a==1: obj.setPassed();\n");
324 PyRun_SimpleString("def testEnumSignal(a):\n if a==1: obj.setPassed();\n");
325 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(enumSignal(PQCppObject2::TestEnumFlag)), main, "testEnumSignal"));
325 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(enumSignal(PQCppObject2::TestEnumFlag)), main, "testEnumSignal"));
326 QVERIFY(_helper->emitEnumSignal(PQCppObject2::TestEnumValue2));
326 QVERIFY(_helper->emitEnumSignal(PQCppObject2::TestEnumValue2));
327
327
328 PyRun_SimpleString("def testVariantSignal(a):\n if a==obj.expectedVariant(): obj.setPassed();\n");
328 PyRun_SimpleString("def testVariantSignal(a):\n if a==obj.expectedVariant(): obj.setPassed();\n");
329 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(variantSignal(QVariant)), main, "testVariantSignal"));
329 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(variantSignal(QVariant)), main, "testVariantSignal"));
330 _helper->setExpectedVariant(QString("Test"));
330 _helper->setExpectedVariant(QString("Test"));
331 QVERIFY(_helper->emitVariantSignal(QString("Test")));
331 QVERIFY(_helper->emitVariantSignal(QString("Test")));
332 _helper->setExpectedVariant(12);
332 _helper->setExpectedVariant(12);
333 QVERIFY(_helper->emitVariantSignal(12));
333 QVERIFY(_helper->emitVariantSignal(12));
334 _helper->setExpectedVariant(QStringList() << "test1" << "test2");
334 _helper->setExpectedVariant(QStringList() << "test1" << "test2");
335 QVERIFY(_helper->emitVariantSignal(QStringList() << "test1" << "test2"));
335 QVERIFY(_helper->emitVariantSignal(QStringList() << "test1" << "test2"));
336 _helper->setExpectedVariant(qVariantFromValue((QObject*)_helper));
336 _helper->setExpectedVariant(qVariantFromValue((QObject*)_helper));
337 QVERIFY(_helper->emitVariantSignal(qVariantFromValue((QObject*)_helper)));
337 QVERIFY(_helper->emitVariantSignal(qVariantFromValue((QObject*)_helper)));
338
338
339 PyRun_SimpleString("def testComplexSignal(a,b,l,o):\n if a==12 and b==13 and l==('test1','test2') and o == obj: obj.setPassed();\n");
339 PyRun_SimpleString("def testComplexSignal(a,b,l,o):\n if a==12 and b==13 and l==('test1','test2') and o == obj: obj.setPassed();\n");
340 // intentionally not normalized signal:
340 // intentionally not normalized signal:
341 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(complexSignal( int, float , const QStringList , QObject*)), main, "testComplexSignal"));
341 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(complexSignal( int, float , const QStringList , QObject*)), main, "testComplexSignal"));
342 QVERIFY(_helper->emitComplexSignal(12,13,QStringList() << "test1" << "test2", _helper));
342 QVERIFY(_helper->emitComplexSignal(12,13,QStringList() << "test1" << "test2", _helper));
343
343
344 // try removing the handler
344 // try removing the handler
345 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(complexSignal( int, float , const QStringList , QObject*)), main, "testComplexSignal"));
345 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(complexSignal( int, float , const QStringList , QObject*)), main, "testComplexSignal"));
346 // and emit the signal, which should fail because the handler was removed
346 // and emit the signal, which should fail because the handler was removed
347 QVERIFY(!_helper->emitComplexSignal(12,13,QStringList() << "test1" << "test2", _helper));
347 QVERIFY(!_helper->emitComplexSignal(12,13,QStringList() << "test1" << "test2", _helper));
348
348
349 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(intSignal(int)), main, "testIntSignal"));
349 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(intSignal(int)), main, "testIntSignal"));
350 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(floatSignal(float)), main, "testFloatSignal"));
350 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(floatSignal(float)), main, "testFloatSignal"));
351 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(variantSignal(QVariant)), main, "testVariantSignal"));
351 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(variantSignal(QVariant)), main, "testVariantSignal"));
352 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(enumSignal(PQCppObject2::TestEnumFlag)), main, "testEnumSignal"));
352 QVERIFY(PythonQt::self()->removeSignalHandler(_helper, SIGNAL(enumSignal(PQCppObject2::TestEnumFlag)), main, "testEnumSignal"));
353
353
354 }
354 }
355
355
356 void PythonQtTestSignalHandler::testRecursiveSignalHandler()
356 void PythonQtTestSignalHandler::testRecursiveSignalHandler()
357 {
357 {
358 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
358 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
359 PyRun_SimpleString("def testSignal1(a):\n obj.emitSignal2(a);\n");
359 PyRun_SimpleString("def testSignal1(a):\n obj.emitSignal2(a);\n");
360 PyRun_SimpleString("def testSignal2(a):\n obj.emitSignal3(float(a));\n");
360 PyRun_SimpleString("def testSignal2(a):\n obj.emitSignal3(float(a));\n");
361 PyRun_SimpleString("def testSignal3(a):\n if a==12: obj.setPassed();\n");
361 PyRun_SimpleString("def testSignal3(a):\n if a==12: obj.setPassed();\n");
362 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal1(int)), main, "testSignal1"));
362 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal1(int)), main, "testSignal1"));
363 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal2(const QString&)), main, "testSignal2"));
363 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal2(const QString&)), main, "testSignal2"));
364 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal3(float)), main, "testSignal3"));
364 QVERIFY(PythonQt::self()->addSignalHandler(_helper, SIGNAL(signal3(float)), main, "testSignal3"));
365 QVERIFY(_helper->emitSignal1(12));
365 QVERIFY(_helper->emitSignal1(12));
366 }
366 }
367
367
368
368
369 void PythonQtTestApi::initTestCase()
369 void PythonQtTestApi::initTestCase()
370 {
370 {
371 _helper = new PythonQtTestApiHelper();
371 _helper = new PythonQtTestApiHelper();
372 _main = PythonQt::self()->getMainModule();
372 _main = PythonQt::self()->getMainModule();
373 _main.evalScript("import PythonQt");
373 _main.evalScript("import PythonQt");
374 _main.addObject("obj", _helper);
374 _main.addObject("obj", _helper);
375 }
375 }
376
376
377 void PythonQtTestApi::testProperties()
377 void PythonQtTestApi::testProperties()
378 {
378 {
379 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
379 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
380 // check for name alias (for backward comp to Qt3)
380 // check for name alias (for backward comp to Qt3)
381 main.evalScript("obj.name = 'hello'");
381 main.evalScript("obj.name = 'hello'");
382 QVERIFY(QString("hello") == main.getVariable("obj.name").toString());
382 QVERIFY(QString("hello") == main.getVariable("obj.name").toString());
383
383
384 main.evalScript("obj.objectName = 'hello2'");
384 main.evalScript("obj.objectName = 'hello2'");
385 QVERIFY(QString("hello2") == main.getVariable("obj.objectName").toString());
385 QVERIFY(QString("hello2") == main.getVariable("obj.objectName").toString());
386
386
387 }
387 }
388
388
389 void PythonQtTestApi::testDynamicProperties()
389 void PythonQtTestApi::testDynamicProperties()
390 {
390 {
391 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
391 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
392
392
393 // this fails and should fail, but how could that be tested?
393 // this fails and should fail, but how could that be tested?
394 // main.evalScript("obj.testProp = 1");
394 // main.evalScript("obj.testProp = 1");
395
395
396 // create a new dynamic property
396 // create a new dynamic property
397 main.evalScript("obj.setProperty('testProp','testValue')");
397 main.evalScript("obj.setProperty('testProp','testValue')");
398
398
399 // read the property
399 // read the property
400 QVERIFY(QString("testValue") == main.getVariable("obj.testProp").toString());
400 QVERIFY(QString("testValue") == main.getVariable("obj.testProp").toString());
401 // modify and read again
401 // modify and read again
402 main.evalScript("obj.testProp = 12");
402 main.evalScript("obj.testProp = 12");
403 QVERIFY(12 == main.getVariable("obj.testProp").toInt());
403 QVERIFY(12 == main.getVariable("obj.testProp").toInt());
404
404
405 // check if dynamic property is in dict
405 // check if dynamic property is in dict
406 QVERIFY(12 == main.evalScript("obj.__dict__['testProp']", Py_eval_input).toInt());
406 QVERIFY(12 == main.evalScript("obj.__dict__['testProp']", Py_eval_input).toInt());
407
407
408 // check if dynamic property is in introspection
408 // check if dynamic property is in introspection
409 QStringList l = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), "obj", PythonQt::Anything);
409 QStringList l = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), "obj", PythonQt::Anything);
410 QVERIFY(l.contains("testProp"));
410 QVERIFY(l.contains("testProp"));
411
411
412 // check with None, previous value expected
412 // check with None, previous value expected
413 main.evalScript("obj.testProp = None");
413 main.evalScript("obj.testProp = None");
414 QVERIFY(12 == main.getVariable("obj.testProp").toInt());
414 QVERIFY(12 == main.getVariable("obj.testProp").toInt());
415
415
416 // remove the dynamic property
416 // remove the dynamic property
417 main.evalScript("obj.setProperty('testProp', None)");
417 main.evalScript("obj.setProperty('testProp', None)");
418
418
419 // check if dynamic property is really gone
419 // check if dynamic property is really gone
420 QStringList l2 = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), "obj", PythonQt::Anything);
420 QStringList l2 = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), "obj", PythonQt::Anything);
421 QVERIFY(!l2.contains("testProp"));
421 QVERIFY(!l2.contains("testProp"));
422
422
423 }
423 }
424
424
425
425
426 bool PythonQtTestApiHelper::call(const QString& function, const QVariantList& args, const QVariant& expectedResult) {
426 bool PythonQtTestApiHelper::call(const QString& function, const QVariantList& args, const QVariant& expectedResult) {
427 _passed = false;
427 _passed = false;
428 QVariant r = PythonQt::self()->call(PythonQt::self()->getMainModule(), function, args);
428 QVariant r = PythonQt::self()->call(PythonQt::self()->getMainModule(), function, args);
429 return _passed && expectedResult==r;
429 return _passed && expectedResult==r;
430 }
430 }
431
431
432 void PythonQtTestApi::testCall()
432 void PythonQtTestApi::testCall()
433 {
433 {
434 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
434 PythonQtObjectPtr main = PythonQt::self()->getMainModule();
435
435
436 QVERIFY(qvariant_cast<QObject*>(PythonQt::self()->getVariable(main, "obj"))==_helper);
436 QVERIFY(qvariant_cast<QObject*>(PythonQt::self()->getVariable(main, "obj"))==_helper);
437
437
438 PyRun_SimpleString("def testCallNoArgs():\n obj.setPassed();\n");
438 PyRun_SimpleString("def testCallNoArgs():\n obj.setPassed();\n");
439 QVERIFY(_helper->call("testCallNoArgs", QVariantList(), QVariant()));
439 QVERIFY(_helper->call("testCallNoArgs", QVariantList(), QVariant()));
440
440
441 PyRun_SimpleString("def testCall1(a):\n if a=='test': obj.setPassed();\n return 'test2';\n");
441 PyRun_SimpleString("def testCall1(a):\n if a=='test': obj.setPassed();\n return 'test2';\n");
442 QVERIFY(_helper->call("testCall1", QVariantList() << QVariant("test"), QVariant(QString("test2"))));
442 QVERIFY(_helper->call("testCall1", QVariantList() << QVariant("test"), QVariant(QString("test2"))));
443
443
444 PyRun_SimpleString("def testCall2(a, b):\n if a=='test' and b==obj: obj.setPassed();\n return obj;\n");
444 PyRun_SimpleString("def testCall2(a, b):\n if a=='test' and b==obj: obj.setPassed();\n return obj;\n");
445 QVariant r = PythonQt::self()->call(PythonQt::self()->getMainModule(), "testCall2", QVariantList() << QVariant("test") << qVariantFromValue((QObject*)_helper));
445 QVariant r = PythonQt::self()->call(PythonQt::self()->getMainModule(), "testCall2", QVariantList() << QVariant("test") << qVariantFromValue((QObject*)_helper));
446 QObject* p = qvariant_cast<QObject*>(r);
446 QObject* p = qvariant_cast<QObject*>(r);
447 QVERIFY(p==_helper);
447 QVERIFY(p==_helper);
448 }
448 }
449
449
450 void PythonQtTestApi::testVariables()
450 void PythonQtTestApi::testVariables()
451 {
451 {
452 PythonQt::self()->addObject(PythonQt::self()->getMainModule(), "someObject", _helper);
452 PythonQt::self()->addObject(PythonQt::self()->getMainModule(), "someObject", _helper);
453 QVariant v = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject");
453 QVariant v = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject");
454 QObject* p = qvariant_cast<QObject*>(v);
454 QObject* p = qvariant_cast<QObject*>(v);
455 QVERIFY(p==_helper);
455 QVERIFY(p==_helper);
456 // test for unset variable
456 // test for unset variable
457 QVariant v2 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject2");
457 QVariant v2 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject2");
458 QVERIFY(v2==QVariant());
458 QVERIFY(v2==QVariant());
459
459
460 PythonQt::self()->addVariable(PythonQt::self()->getMainModule(), "someValue", QStringList() << "test1" << "test2");
460 PythonQt::self()->addVariable(PythonQt::self()->getMainModule(), "someValue", QStringList() << "test1" << "test2");
461 QVariant v3 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someValue");
461 QVariant v3 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someValue");
462 QVERIFY(v3 == QVariant(QStringList() << "test1" << "test2"));
462 QVERIFY(v3 == QVariant(QStringList() << "test1" << "test2"));
463
463
464 QStringList l = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), QString::null, PythonQt::Variable);
464 QStringList l = PythonQt::self()->introspection(PythonQt::self()->getMainModule(), QString::null, PythonQt::Variable);
465 QSet<QString> s;
465 QSet<QString> s;
466 // check that at least these three variables are set
466 // check that at least these three variables are set
467 s << "obj" << "someObject" << "someValue";
467 s << "obj" << "someObject" << "someValue";
468 foreach (QString value, s) {
468 foreach (QString value, s) {
469 QVERIFY(l.indexOf(value)!=-1);
469 QVERIFY(l.indexOf(value)!=-1);
470 }
470 }
471
471
472 // insert a second time!
472 // insert a second time!
473 PythonQt::self()->addObject(PythonQt::self()->getMainModule(), "someObject", _helper);
473 PythonQt::self()->addObject(PythonQt::self()->getMainModule(), "someObject", _helper);
474 // and remove
474 // and remove
475 PythonQt::self()->removeVariable(PythonQt::self()->getMainModule(), "someObject");
475 PythonQt::self()->removeVariable(PythonQt::self()->getMainModule(), "someObject");
476 // we expect to find no variable
476 // we expect to find no variable
477 QVariant v4 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject");
477 QVariant v4 = PythonQt::self()->getVariable(PythonQt::self()->getMainModule(), "someObject");
478 QVERIFY(v4==QVariant());
478 QVERIFY(v4==QVariant());
479 }
479 }
480
480
481 void PythonQtTestApi::testImporter()
481 void PythonQtTestApi::testImporter()
482 {
482 {
483 PythonQt::self()->setImporter(_helper);
483 PythonQt::self()->setImporter(_helper);
484 PythonQt::self()->overwriteSysPath(QStringList() << "c:\\test");
484 PythonQt::self()->overwriteSysPath(QStringList() << "c:\\test");
485 PyRun_SimpleString("import bla\n");
485 PyRun_SimpleString("import bla\n");
486 }
486 }
487
487
488 void PythonQtTestApi::testQtNamespace()
488 void PythonQtTestApi::testQtNamespace()
489 {
489 {
490 QVERIFY(_main.getVariable("PythonQt.QtCore.Qt.red").toInt()==Qt::red);
490 QVERIFY(_main.getVariable("PythonQt.QtCore.Qt.red").toInt()==Qt::red);
491 QVERIFY(_main.getVariable("PythonQt.QtCore.Qt.FlatCap").toInt()==Qt::FlatCap);
491 QVERIFY(_main.getVariable("PythonQt.QtCore.Qt.FlatCap").toInt()==Qt::FlatCap);
492 #if( QT_VERSION < QT_VERSION_CHECK(5,0,0) )
492 #if( QT_VERSION < QT_VERSION_CHECK(5,0,0) )
493 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.escape")));
493 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.escape")));
494 #endif
494 #endif
495 // check for an enum type wrapper
495 // check for an enum type wrapper
496 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.AlignmentFlag")));
496 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.AlignmentFlag")));
497 // check for a flags type wrapper
497 // check for a flags type wrapper
498 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.Alignment")));
498 QVERIFY(PythonQtObjectPtr(_main.getVariable("PythonQt.QtCore.Qt.Alignment")));
499 }
499 }
500
500
501 void PythonQtTestApi::testConnects()
501 void PythonQtTestApi::testConnects()
502 {
502 {
503 // QVERIFY((qvariant_vast<QColor>(_main.evalScript("PythonQt.Qt.QColor(PythonQt.Qt.Qt.red)" ,Py_eval_input)) == QColor(Qt::red));
503 // QVERIFY((qvariant_vast<QColor>(_main.evalScript("PythonQt.Qt.QColor(PythonQt.Qt.Qt.red)" ,Py_eval_input)) == QColor(Qt::red));
504 //TODO: add signal/slot connect both with QObject.connect and connect
504 //TODO: add signal/slot connect both with QObject.connect and connect
505 }
505 }
506
506
507 void PythonQtTestApi::testQColorDecorators()
507 void PythonQtTestApi::testQColorDecorators()
508 {
508 {
509 PythonQtObjectPtr colorClass = _main.getVariable("PythonQt.QtGui.QColor");
509 PythonQtObjectPtr colorClass = _main.getVariable("PythonQt.QtGui.QColor");
510 QVERIFY(colorClass);
510 QVERIFY(colorClass);
511 // verify that the class is in the correct module
511 // verify that the class is in the correct module
512 QVERIFY(colorClass.getVariable("__module__") == "PythonQt.QtGui");
512 QVERIFY(colorClass.getVariable("__module__") == "PythonQt.QtGui");
513 // test on Qt module as well:
513 // test on Qt module as well:
514 colorClass = _main.getVariable("PythonQt.Qt.QColor");
514 colorClass = _main.getVariable("PythonQt.Qt.QColor");
515 QVERIFY(colorClass);
515 QVERIFY(colorClass);
516 // constructors
516 // constructors
517 QVERIFY(qvariant_cast<QColor>(colorClass.call(QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
517 QVERIFY(qvariant_cast<QColor>(colorClass.call(QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
518 QVERIFY(qvariant_cast<QColor>(colorClass.call()) == QColor());
518 QVERIFY(qvariant_cast<QColor>(colorClass.call()) == QColor());
519 QEXPECT_FAIL("", "Testing non-existing constructor", Continue);
519 QEXPECT_FAIL("", "Testing non-existing constructor", Continue);
520 QVERIFY(colorClass.call(QVariantList() << 1 << 2) != QVariant());
520 QVERIFY(colorClass.call(QVariantList() << 1 << 2) != QVariant());
521
521
522 // check that enum overload is taken over int
522 // check that enum overload is taken over int
523 QVERIFY(qvariant_cast<QColor>(_main.evalScript("PythonQt.Qt.QColor(PythonQt.Qt.Qt.red)" ,Py_eval_input)) == QColor(Qt::red));
523 QVERIFY(qvariant_cast<QColor>(_main.evalScript("PythonQt.Qt.QColor(PythonQt.Qt.Qt.red)" ,Py_eval_input)) == QColor(Qt::red));
524 // check that int overload is taken over enum
524 // check that int overload is taken over enum
525 QVERIFY(qvariant_cast<QColor>(_main.evalScript("PythonQt.Qt.QColor(0x112233)" ,Py_eval_input)) == QColor(0x112233));
525 QVERIFY(qvariant_cast<QColor>(_main.evalScript("PythonQt.Qt.QColor(0x112233)" ,Py_eval_input)) == QColor(0x112233));
526
526
527 // check for decorated Cmyk enum value
527 // check for decorated Cmyk enum value
528 QVERIFY(colorClass.getVariable("Cmyk").toInt() == QColor::Cmyk);
528 QVERIFY(colorClass.getVariable("Cmyk").toInt() == QColor::Cmyk);
529 PythonQtObjectPtr staticMethod = colorClass.getVariable("fromRgb");
529 PythonQtObjectPtr staticMethod = colorClass.getVariable("fromRgb");
530 QVERIFY(staticMethod);
530 QVERIFY(staticMethod);
531 // direct call of static method via class
531 // direct call of static method via class
532 QVERIFY(qvariant_cast<QColor>(colorClass.call("fromRgb", QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
532 QVERIFY(qvariant_cast<QColor>(colorClass.call("fromRgb", QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
533 // direct call of static method
533 // direct call of static method
534 QVERIFY(qvariant_cast<QColor>(staticMethod.call(QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
534 QVERIFY(qvariant_cast<QColor>(staticMethod.call(QVariantList() << 1 << 2 << 3)) == QColor(1,2,3));
535 PythonQtObjectPtr publicMethod = colorClass.getVariable("red");
535 PythonQtObjectPtr publicMethod = colorClass.getVariable("red");
536 QVERIFY(publicMethod);
536 QVERIFY(publicMethod);
537 // call with passing self in:
537 // call with passing self in:
538 QVERIFY(colorClass.call("red", QVariantList() << QColor(255,0,0)).toInt() == 255);
538 QVERIFY(colorClass.call("red", QVariantList() << QColor(255,0,0)).toInt() == 255);
539 }
539 }
540
540
541 QByteArray PythonQtTestApiHelper::readFileAsBytes(const QString& filename)
541 QByteArray PythonQtTestApiHelper::readFileAsBytes(const QString& filename)
542 {
542 {
543 QByteArray b;
543 QByteArray b;
544 return b;
544 return b;
545 }
545 }
546
546
547 QByteArray PythonQtTestApiHelper::readSourceFile(const QString& filename, bool& ok)
547 QByteArray PythonQtTestApiHelper::readSourceFile(const QString& filename, bool& ok)
548 {
548 {
549 QByteArray b;
549 QByteArray b;
550 ok = true;
550 ok = true;
551 return b;
551 return b;
552 }
552 }
553
553
554 bool PythonQtTestApiHelper::exists(const QString& filename)
554 bool PythonQtTestApiHelper::exists(const QString& filename)
555 {
555 {
556 return true;
556 return true;
557 }
557 }
558
558
559 QDateTime PythonQtTestApiHelper::lastModifiedDate(const QString& filename) {
559 QDateTime PythonQtTestApiHelper::lastModifiedDate(const QString& filename) {
560 return QDateTime::currentDateTime();
560 return QDateTime::currentDateTime();
561 }
561 }
562
562
563
563
564 void PythonQtTestApi::testRedirect()
564 void PythonQtTestApi::testRedirect()
565 {
565 {
566 connect(PythonQt::self(), SIGNAL(pythonStdOut(const QString&)), _helper, SLOT(stdOut(const QString&)));
566 connect(PythonQt::self(), SIGNAL(pythonStdOut(const QString&)), _helper, SLOT(stdOut(const QString&)));
567 connect(PythonQt::self(), SIGNAL(pythonStdErr(const QString&)), _helper, SLOT(stdErr(const QString&)));
567 connect(PythonQt::self(), SIGNAL(pythonStdErr(const QString&)), _helper, SLOT(stdErr(const QString&)));
568 PyRun_SimpleString("print 'test'\n");
568 PyRun_SimpleString("print ('test')\n");
569 }
569 }
570
570
571 void PythonQtTestApiHelper::stdOut(const QString& s)
571 void PythonQtTestApiHelper::stdOut(const QString& s)
572 {
572 {
573 outBuf.append(s);
574 QStringList x = outBuf.split("\n");
575 outBuf = x.takeLast();
576 foreach(QString s, x)
573 qDebug() << s;
577 qDebug() << s;
574 }
578 }
575
579
576 void PythonQtTestApiHelper::stdErr(const QString& s)
580 void PythonQtTestApiHelper::stdErr(const QString& s)
577 {
581 {
582 errBuf.append(s);
583 QStringList x = errBuf.split("\n");
584 errBuf = x.takeLast();
585 foreach(QString s, x)
578 qDebug() << s;
586 qDebug() << s;
579 }
587 }
580
588
581 QObject* PythonQtTestCppFactory::create(const QByteArray& name, void *ptr)
589 QObject* PythonQtTestCppFactory::create(const QByteArray& name, void *ptr)
582 {
590 {
583 if (name == "PQCppObject") {
591 if (name == "PQCppObject") {
584 return new PQCppObjectWrapper(ptr);
592 return new PQCppObjectWrapper(ptr);
585 }
593 }
586 return NULL;
594 return NULL;
587 }
595 }
@@ -1,515 +1,517
1 #ifndef _PYTHONQTTESTS_H
1 #ifndef _PYTHONQTTESTS_H
2 #define _PYTHONQTTESTS_H
2 #define _PYTHONQTTESTS_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
6 * Copyright (C) 2010 MeVis Medical Solutions AG 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 Medical Solutions AG, Universitaetsallee 29,
29 * Contact information: MeVis Medical Solutions AG, 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 PythonQtTests.h
38 // \file PythonQtTests.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 "PythonQt.h"
45 #include "PythonQt.h"
46 #include <QtTest/QtTest>
46 #include <QtTest/QtTest>
47 #include <QVariant>
47 #include <QVariant>
48 #include "PythonQtImportFileInterface.h"
48 #include "PythonQtImportFileInterface.h"
49 #include "PythonQtCppWrapperFactory.h"
49 #include "PythonQtCppWrapperFactory.h"
50
50
51 #include <QPen>
51 #include <QPen>
52 #include <QColor>
52 #include <QColor>
53 #include <QBrush>
53 #include <QBrush>
54 #include <QCursor>
54 #include <QCursor>
55
55
56 class PythonQtTestSlotCallingHelper;
56 class PythonQtTestSlotCallingHelper;
57 class PythonQtTestApiHelper;
57 class PythonQtTestApiHelper;
58 class QWidget;
58 class QWidget;
59
59
60 //! test the PythonQt api
60 //! test the PythonQt api
61 class PythonQtTestApi : public QObject
61 class PythonQtTestApi : public QObject
62 {
62 {
63 Q_OBJECT
63 Q_OBJECT
64
64
65 private slots:
65 private slots:
66 void initTestCase();
66 void initTestCase();
67 void testCall();
67 void testCall();
68 void testVariables();
68 void testVariables();
69 void testRedirect();
69 void testRedirect();
70 void testImporter();
70 void testImporter();
71 void testQColorDecorators();
71 void testQColorDecorators();
72 void testQtNamespace();
72 void testQtNamespace();
73 void testConnects();
73 void testConnects();
74
74
75 void testProperties();
75 void testProperties();
76 void testDynamicProperties();
76 void testDynamicProperties();
77
77
78 private:
78 private:
79 PythonQtTestApiHelper* _helper;
79 PythonQtTestApiHelper* _helper;
80 PythonQtObjectPtr _main;
80 PythonQtObjectPtr _main;
81
81
82 };
82 };
83
83
84 class ClassA {
84 class ClassA {
85 public:
85 public:
86 ClassA() { x = 1; }
86 ClassA() { x = 1; }
87 int x;
87 int x;
88 };
88 };
89
89
90 class ClassB {
90 class ClassB {
91 public:
91 public:
92 ClassB() { y = 2; }
92 ClassB() { y = 2; }
93 int y;
93 int y;
94
94
95 virtual int type() { return 2; }
95 virtual int type() { return 2; }
96 };
96 };
97
97
98 class ClassC : public ClassA, public ClassB {
98 class ClassC : public ClassA, public ClassB {
99 public:
99 public:
100 ClassC() { z = 3; }
100 ClassC() { z = 3; }
101 int z;
101 int z;
102
102
103 virtual int type() { return 3; }
103 virtual int type() { return 3; }
104 };
104 };
105
105
106 class ClassD : public QObject, public ClassA, public ClassB {
106 class ClassD : public QObject, public ClassA, public ClassB {
107 Q_OBJECT
107 Q_OBJECT
108 public:
108 public:
109 ClassD() { d = 4; }
109 ClassD() { d = 4; }
110 public slots:
110 public slots:
111 int getD() { return d; }
111 int getD() { return d; }
112 private:
112 private:
113 int d;
113 int d;
114
114
115 virtual int type() { return 4; }
115 virtual int type() { return 4; }
116 };
116 };
117
117
118 class ClassAWrapper : public QObject {
118 class ClassAWrapper : public QObject {
119 Q_OBJECT
119 Q_OBJECT
120 public slots:
120 public slots:
121 ClassA* new_ClassA() { return new ClassA; }
121 ClassA* new_ClassA() { return new ClassA; }
122 int getX(ClassA* o) { return o->x; }
122 int getX(ClassA* o) { return o->x; }
123 };
123 };
124
124
125 class ClassBWrapper : public QObject {
125 class ClassBWrapper : public QObject {
126 Q_OBJECT
126 Q_OBJECT
127 public slots:
127 public slots:
128 ClassB* new_ClassB() { return new ClassB; }
128 ClassB* new_ClassB() { return new ClassB; }
129 int getY(ClassB* o) { return o->y; }
129 int getY(ClassB* o) { return o->y; }
130 };
130 };
131
131
132 class ClassCWrapper : public QObject {
132 class ClassCWrapper : public QObject {
133 Q_OBJECT
133 Q_OBJECT
134 public slots:
134 public slots:
135 ClassC* new_ClassC() { return new ClassC; }
135 ClassC* new_ClassC() { return new ClassC; }
136 int getZ(ClassC* o) { return o->z; }
136 int getZ(ClassC* o) { return o->z; }
137 };
137 };
138
138
139 class ClassDWrapper : public QObject {
139 class ClassDWrapper : public QObject {
140 Q_OBJECT
140 Q_OBJECT
141 public slots:
141 public slots:
142 ClassD* new_ClassD() { return new ClassD; }
142 ClassD* new_ClassD() { return new ClassD; }
143 };
143 };
144
144
145
145
146 //! test the PythonQt api (helper)
146 //! test the PythonQt api (helper)
147 class PythonQtTestApiHelper : public QObject , public PythonQtImportFileInterface
147 class PythonQtTestApiHelper : public QObject , public PythonQtImportFileInterface
148 {
148 {
149 Q_OBJECT
149 Q_OBJECT
150 public:
150 public:
151 PythonQtTestApiHelper() {
151 PythonQtTestApiHelper() {
152 };
152 };
153
153
154 bool call(const QString& function, const QVariantList& args, const QVariant& expectedResult);
154 bool call(const QString& function, const QVariantList& args, const QVariant& expectedResult);
155
155
156 virtual QByteArray readFileAsBytes(const QString& filename);
156 virtual QByteArray readFileAsBytes(const QString& filename);
157
157
158 virtual QByteArray readSourceFile(const QString& filename, bool& ok);
158 virtual QByteArray readSourceFile(const QString& filename, bool& ok);
159
159
160 virtual bool exists(const QString& filename);
160 virtual bool exists(const QString& filename);
161
161
162 virtual QDateTime lastModifiedDate(const QString& filename);
162 virtual QDateTime lastModifiedDate(const QString& filename);
163
163
164 public slots:
164 public slots:
165
165
166 //! call to set that the test has passed (from Python!)
166 //! call to set that the test has passed (from Python!)
167 void setPassed() { _passed = true; }
167 void setPassed() { _passed = true; }
168
168
169 void stdOut(const QString&);
169 void stdOut(const QString&);
170 void stdErr(const QString&);
170 void stdErr(const QString&);
171
171
172 private:
172 private:
173 QString outBuf;
174 QString errBuf;
173 bool _passed;
175 bool _passed;
174 };
176 };
175
177
176
178
177 // test implementation of the wrapper factory
179 // test implementation of the wrapper factory
178 class PythonQtTestCppFactory : public PythonQtCppWrapperFactory
180 class PythonQtTestCppFactory : public PythonQtCppWrapperFactory
179 {
181 {
180 public:
182 public:
181 virtual QObject* create(const QByteArray& name, void *ptr);
183 virtual QObject* create(const QByteArray& name, void *ptr);
182 };
184 };
183
185
184 //! an cpp object to be wrapped
186 //! an cpp object to be wrapped
185 class PQCppObject {
187 class PQCppObject {
186
188
187 public:
189 public:
188 PQCppObject(int h) { _height = h; }
190 PQCppObject(int h) { _height = h; }
189
191
190 int getHeight() { return _height; }
192 int getHeight() { return _height; }
191 void setHeight(int h) { _height = h; }
193 void setHeight(int h) { _height = h; }
192
194
193 private:
195 private:
194 int _height;
196 int _height;
195 };
197 };
196
198
197 //! an qobject that wraps the existing cpp object
199 //! an qobject that wraps the existing cpp object
198 class PQCppObjectWrapper : public QObject {
200 class PQCppObjectWrapper : public QObject {
199 Q_OBJECT
201 Q_OBJECT
200 public:
202 public:
201 PQCppObjectWrapper(void* ptr) {
203 PQCppObjectWrapper(void* ptr) {
202 _ptr = (PQCppObject*)ptr;
204 _ptr = (PQCppObject*)ptr;
203 }
205 }
204
206
205 public slots:
207 public slots:
206 int getHeight() { return _ptr->getHeight(); }
208 int getHeight() { return _ptr->getHeight(); }
207 void setHeight(int h) { _ptr->setHeight(h); }
209 void setHeight(int h) { _ptr->setHeight(h); }
208
210
209 private:
211 private:
210 PQCppObject* _ptr;
212 PQCppObject* _ptr;
211 };
213 };
212
214
213 class PQCppObjectDecorator : public QObject {
215 class PQCppObjectDecorator : public QObject {
214 Q_OBJECT
216 Q_OBJECT
215 public slots:
217 public slots:
216 int getH(PQCppObject* obj) { return obj->getHeight(); }
218 int getH(PQCppObject* obj) { return obj->getHeight(); }
217
219
218 };
220 };
219
221
220 //! an cpp object to be wrapped by decorators only
222 //! an cpp object to be wrapped by decorators only
221 class PQCppObjectNoWrap {
223 class PQCppObjectNoWrap {
222
224
223 public:
225 public:
224 PQCppObjectNoWrap() { _height = 0; }
226 PQCppObjectNoWrap() { _height = 0; }
225 PQCppObjectNoWrap(int h) { _height = h; }
227 PQCppObjectNoWrap(int h) { _height = h; }
226
228
227 int getHeight() { return _height; }
229 int getHeight() { return _height; }
228 void setHeight(int h) { _height = h; }
230 void setHeight(int h) { _height = h; }
229
231
230 private:
232 private:
231 int _height;
233 int _height;
232 };
234 };
233
235
234 class PQCppObjectNoWrapDecorator : public QObject {
236 class PQCppObjectNoWrapDecorator : public QObject {
235 Q_OBJECT
237 Q_OBJECT
236
238
237 public slots:
239 public slots:
238 PQCppObjectNoWrap* new_PQCppObjectNoWrap() {
240 PQCppObjectNoWrap* new_PQCppObjectNoWrap() {
239 return new PQCppObjectNoWrap(0);
241 return new PQCppObjectNoWrap(0);
240 }
242 }
241 PQCppObjectNoWrap* new_PQCppObjectNoWrap(const PQCppObjectNoWrap& other) {
243 PQCppObjectNoWrap* new_PQCppObjectNoWrap(const PQCppObjectNoWrap& other) {
242 return new PQCppObjectNoWrap(1);
244 return new PQCppObjectNoWrap(1);
243 }
245 }
244 PQCppObjectNoWrap* new_PQCppObjectNoWrap(double value) {
246 PQCppObjectNoWrap* new_PQCppObjectNoWrap(double value) {
245 return new PQCppObjectNoWrap(2);
247 return new PQCppObjectNoWrap(2);
246 }
248 }
247
249
248 int getH(PQCppObjectNoWrap* obj) { return obj->getHeight(); }
250 int getH(PQCppObjectNoWrap* obj) { return obj->getHeight(); }
249
251
250 };
252 };
251
253
252
254
253 //! an cpp object that is to be wrapped by decorators only
255 //! an cpp object that is to be wrapped by decorators only
254 class PQCppObject2 {
256 class PQCppObject2 {
255
257
256 public:
258 public:
257 enum TestEnumFlag {
259 enum TestEnumFlag {
258 TestEnumValue1 = 0,
260 TestEnumValue1 = 0,
259 TestEnumValue2 = 1
261 TestEnumValue2 = 1
260 };
262 };
261
263
262 PQCppObject2() {}
264 PQCppObject2() {}
263
265
264 };
266 };
265
267
266 class PQCppObject2Decorator : public QObject {
268 class PQCppObject2Decorator : public QObject {
267 Q_OBJECT
269 Q_OBJECT
268
270
269 public:
271 public:
270 Q_ENUMS(TestEnumFlag)
272 Q_ENUMS(TestEnumFlag)
271 Q_FLAGS(TestEnum)
273 Q_FLAGS(TestEnum)
272
274
273 enum TestEnumFlag {
275 enum TestEnumFlag {
274 TestEnumValue1 = 0,
276 TestEnumValue1 = 0,
275 TestEnumValue2 = 1
277 TestEnumValue2 = 1
276 };
278 };
277
279
278 Q_DECLARE_FLAGS(TestEnum, TestEnumFlag)
280 Q_DECLARE_FLAGS(TestEnum, TestEnumFlag)
279
281
280 public slots:
282 public slots:
281 PQCppObject2* new_PQCppObject2() {
283 PQCppObject2* new_PQCppObject2() {
282 return new PQCppObject2();
284 return new PQCppObject2();
283 }
285 }
284
286
285 TestEnumFlag testEnumFlag1(PQCppObject2* obj, TestEnumFlag flag);
287 TestEnumFlag testEnumFlag1(PQCppObject2* obj, TestEnumFlag flag);
286
288
287 PQCppObject2::TestEnumFlag testEnumFlag2(PQCppObject2* obj, PQCppObject2::TestEnumFlag flag);
289 PQCppObject2::TestEnumFlag testEnumFlag2(PQCppObject2* obj, PQCppObject2::TestEnumFlag flag);
288
290
289 // with int overload
291 // with int overload
290 TestEnumFlag testEnumFlag3(PQCppObject2* obj, int flag);
292 TestEnumFlag testEnumFlag3(PQCppObject2* obj, int flag);
291 TestEnumFlag testEnumFlag3(PQCppObject2* obj, TestEnumFlag flag);
293 TestEnumFlag testEnumFlag3(PQCppObject2* obj, TestEnumFlag flag);
292
294
293 };
295 };
294
296
295 class PQUnknownValueObject
297 class PQUnknownValueObject
296 {
298 {
297 public:
299 public:
298 PQUnknownValueObject() {};
300 PQUnknownValueObject() {};
299 };
301 };
300
302
301 class PQUnknownButRegisteredValueObject
303 class PQUnknownButRegisteredValueObject
302 {
304 {
303 public:
305 public:
304 PQUnknownButRegisteredValueObject() {};
306 PQUnknownButRegisteredValueObject() {};
305 };
307 };
306
308
307 //! test the calling of slots
309 //! test the calling of slots
308 class PythonQtTestSlotCalling : public QObject
310 class PythonQtTestSlotCalling : public QObject
309 {
311 {
310 Q_OBJECT
312 Q_OBJECT
311
313
312 private slots:
314 private slots:
313 void initTestCase();
315 void initTestCase();
314 void init();
316 void init();
315
317
316 void testNoArgSlotCall();
318 void testNoArgSlotCall();
317 void testPODSlotCalls();
319 void testPODSlotCalls();
318 void testCPPSlotCalls();
320 void testCPPSlotCalls();
319 void testQVariantSlotCalls();
321 void testQVariantSlotCalls();
320 void testObjectSlotCalls();
322 void testObjectSlotCalls();
321 void testMultiArgsSlotCall();
323 void testMultiArgsSlotCall();
322 void testPyObjectSlotCall();
324 void testPyObjectSlotCall();
323 void testOverloadedCall();
325 void testOverloadedCall();
324 void testCppFactory();
326 void testCppFactory();
325 void testInheritance();
327 void testInheritance();
326 void testAutoConversion();
328 void testAutoConversion();
327
329
328 private:
330 private:
329 PythonQtTestSlotCallingHelper* _helper;
331 PythonQtTestSlotCallingHelper* _helper;
330
332
331 };
333 };
332
334
333 //! helper class for slot calling test
335 //! helper class for slot calling test
334 class PythonQtTestSlotCallingHelper : public QObject
336 class PythonQtTestSlotCallingHelper : public QObject
335 {
337 {
336 Q_OBJECT
338 Q_OBJECT
337 public:
339 public:
338 PythonQtTestSlotCallingHelper(PythonQtTestSlotCalling* test) {
340 PythonQtTestSlotCallingHelper(PythonQtTestSlotCalling* test) {
339 _test = test;
341 _test = test;
340 };
342 };
341
343
342 bool runScript(const char* script, int expectedOverload = -1);
344 bool runScript(const char* script, int expectedOverload = -1);
343
345
344 public slots:
346 public slots:
345
347
346 //! call to set that the test has passed (from Python!)
348 //! call to set that the test has passed (from Python!)
347 void setPassed() { _passed = true; }
349 void setPassed() { _passed = true; }
348
350
349 //! no arguments, no return value:
351 //! no arguments, no return value:
350 void testNoArg() { _called = true; }
352 void testNoArg() { _called = true; }
351
353
352 //! overload test!
354 //! overload test!
353 void overload(bool a) { _calledOverload = 0; _called = true; }
355 void overload(bool a) { _calledOverload = 0; _called = true; }
354 void overload(float a) { _calledOverload = 1; _called = true;}
356 void overload(float a) { _calledOverload = 1; _called = true;}
355 void overload(int a) { _calledOverload = 2; _called = true;}
357 void overload(int a) { _calledOverload = 2; _called = true;}
356 void overload(const QString& str) { _calledOverload = 3; _called = true;}
358 void overload(const QString& str) { _calledOverload = 3; _called = true;}
357 void overload(const QStringList& str) { _calledOverload = 4; _called = true;}
359 void overload(const QStringList& str) { _calledOverload = 4; _called = true;}
358 void overload(QObject* str) { _calledOverload = 5; _called = true;}
360 void overload(QObject* str) { _calledOverload = 5; _called = true;}
359 void overload(float a, int b) { _calledOverload = 6; _called = true;}
361 void overload(float a, int b) { _calledOverload = 6; _called = true;}
360
362
361 //! POD values:
363 //! POD values:
362 int getInt(int a) { _called = true; return a; }
364 int getInt(int a) { _called = true; return a; }
363 unsigned int getUInt(unsigned int a) { _called = true; return a; }
365 unsigned int getUInt(unsigned int a) { _called = true; return a; }
364 bool getBool(bool a) { _called = true; return a; }
366 bool getBool(bool a) { _called = true; return a; }
365 char getChar(char a) { _called = true; return a; }
367 char getChar(char a) { _called = true; return a; }
366 unsigned char getUChar(unsigned char a) { _called = true; return a; }
368 unsigned char getUChar(unsigned char a) { _called = true; return a; }
367 long getLong(long a) { _called = true; return a; }
369 long getLong(long a) { _called = true; return a; }
368 unsigned long getULong(unsigned long a) { _called = true; return a; }
370 unsigned long getULong(unsigned long a) { _called = true; return a; }
369 short getShort(short a) { _called = true; return a; }
371 short getShort(short a) { _called = true; return a; }
370 unsigned short getUShort(unsigned short a) { _called = true; return a; }
372 unsigned short getUShort(unsigned short a) { _called = true; return a; }
371 QChar getQChar(QChar a) { _called = true; return a; }
373 QChar getQChar(QChar a) { _called = true; return a; }
372 qint64 getLongLong(qint64 a) { _called = true; return a; }
374 qint64 getLongLong(qint64 a) { _called = true; return a; }
373 quint64 getULongLong(quint64 a) { _called = true; return a; }
375 quint64 getULongLong(quint64 a) { _called = true; return a; }
374 double getDouble(double d) { _called = true; return d; }
376 double getDouble(double d) { _called = true; return d; }
375 float getFloat(float d) { _called = true; return d; }
377 float getFloat(float d) { _called = true; return d; }
376
378
377 //! important qt types:
379 //! important qt types:
378 QString getQString(const QString& s) { _called = true; return s; }
380 QString getQString(const QString& s) { _called = true; return s; }
379 QStringList getQStringList(const QStringList& l) { _called = true; return l; }
381 QStringList getQStringList(const QStringList& l) { _called = true; return l; }
380 QVariant getQVariant(const QVariant& var) { _called = true; return var; }
382 QVariant getQVariant(const QVariant& var) { _called = true; return var; }
381
383
382 // QColor as representative for C++ value classes
384 // QColor as representative for C++ value classes
383 QColor getQColor1(const QColor& var) { _called = true; return var; }
385 QColor getQColor1(const QColor& var) { _called = true; return var; }
384 QColor getQColor2(QColor& var) { _called = true; return var; }
386 QColor getQColor2(QColor& var) { _called = true; return var; }
385 QColor getQColor3(QColor* col) { _called = true; return *col; }
387 QColor getQColor3(QColor* col) { _called = true; return *col; }
386 QColor getQColor4(const QVariant& color) { _called = true; return color.value<QColor>(); }
388 QColor getQColor4(const QVariant& color) { _called = true; return color.value<QColor>(); }
387 QColor* getQColor5() { _called = true; static QColor c(1,2,3); return &c; }
389 QColor* getQColor5() { _called = true; static QColor c(1,2,3); return &c; }
388
390
389 PyObject* getPyObject(PyObject* obj) { _called = true; return obj; }
391 PyObject* getPyObject(PyObject* obj) { _called = true; return obj; }
390 PyObject* getPyObjectFromVariant(const QVariant& val) { _called = true; return PythonQtObjectPtr(val); }
392 PyObject* getPyObjectFromVariant(const QVariant& val) { _called = true; return PythonQtObjectPtr(val); }
391 QVariant getPyObjectFromVariant2(const QVariant& val) { _called = true; return val; }
393 QVariant getPyObjectFromVariant2(const QVariant& val) { _called = true; return val; }
392 // this does not yet work but is not required to work:
394 // this does not yet work but is not required to work:
393 //PyObject* getPyObjectFromPtr(const PythonQtObjectPtr& val) { _called = true; return val; };
395 //PyObject* getPyObjectFromPtr(const PythonQtObjectPtr& val) { _called = true; return val; };
394
396
395 //! testing pointer passing
397 //! testing pointer passing
396 PythonQtTestSlotCallingHelper* getTestObject(PythonQtTestSlotCallingHelper* obj) { _called = true; return obj; }
398 PythonQtTestSlotCallingHelper* getTestObject(PythonQtTestSlotCallingHelper* obj) { _called = true; return obj; }
397 //! testing inheritance checking
399 //! testing inheritance checking
398 QObject* getQObject(QObject* obj) { _called = true; return obj; }
400 QObject* getQObject(QObject* obj) { _called = true; return obj; }
399 QWidget* getQWidget(QWidget* obj) { _called = true; return obj; }
401 QWidget* getQWidget(QWidget* obj) { _called = true; return obj; }
400 //! testing if an object that was not wrapped is wrapped earlier is wrapped correctly
402 //! testing if an object that was not wrapped is wrapped earlier is wrapped correctly
401 QObject* getNewObject() { _called = true; return new PythonQtTestSlotCallingHelper(NULL); }
403 QObject* getNewObject() { _called = true; return new PythonQtTestSlotCallingHelper(NULL); }
402
404
403 QVariantList getMultiArgs(int a, double b, const QString& str) { _called = true; return (QVariantList() << a << b << str); }
405 QVariantList getMultiArgs(int a, double b, const QString& str) { _called = true; return (QVariantList() << a << b << str); }
404
406
405 //! cpp wrapper factory test
407 //! cpp wrapper factory test
406 PQCppObject* createPQCppObject(int h) { _called = true; return new PQCppObject(h); }
408 PQCppObject* createPQCppObject(int h) { _called = true; return new PQCppObject(h); }
407
409
408 //! cpp wrapper factory test
410 //! cpp wrapper factory test
409 PQCppObject* getPQCppObject(PQCppObject* p) { _called = true; return p; }
411 PQCppObject* getPQCppObject(PQCppObject* p) { _called = true; return p; }
410
412
411 //! cpp wrapper factory test
413 //! cpp wrapper factory test
412 PQCppObjectNoWrap* createPQCppObjectNoWrap(int h) { _called = true; return new PQCppObjectNoWrap(h); }
414 PQCppObjectNoWrap* createPQCppObjectNoWrap(int h) { _called = true; return new PQCppObjectNoWrap(h); }
413
415
414 //! cpp wrapper factory test
416 //! cpp wrapper factory test
415 PQCppObjectNoWrap* getPQCppObjectNoWrap(PQCppObjectNoWrap* p) { _called = true; return p; }
417 PQCppObjectNoWrap* getPQCppObjectNoWrap(PQCppObjectNoWrap* p) { _called = true; return p; }
416
418
417 //! get a return by value PQCppObjectNoWrap
419 //! get a return by value PQCppObjectNoWrap
418 PQCppObjectNoWrap getPQCppObjectNoWrapAsValue() { _called = true; return PQCppObjectNoWrap(47); }
420 PQCppObjectNoWrap getPQCppObjectNoWrapAsValue() { _called = true; return PQCppObjectNoWrap(47); }
419
421
420 PQUnknownButRegisteredValueObject getUnknownButRegisteredValueObjectAsValue() { _called = true; return PQUnknownButRegisteredValueObject(); }
422 PQUnknownButRegisteredValueObject getUnknownButRegisteredValueObjectAsValue() { _called = true; return PQUnknownButRegisteredValueObject(); }
421 PQUnknownValueObject getUnknownValueObjectAsValue() { _called = true; return PQUnknownValueObject(); }
423 PQUnknownValueObject getUnknownValueObjectAsValue() { _called = true; return PQUnknownValueObject(); }
422
424
423 PQUnknownButRegisteredValueObject* getUnknownButRegisteredValueObjectAsPtr() { _called = true; return new PQUnknownButRegisteredValueObject(); }
425 PQUnknownButRegisteredValueObject* getUnknownButRegisteredValueObjectAsPtr() { _called = true; return new PQUnknownButRegisteredValueObject(); }
424 PQUnknownValueObject* getUnknownValueObjectAsPtr() { _called = true; return new PQUnknownValueObject(); }
426 PQUnknownValueObject* getUnknownValueObjectAsPtr() { _called = true; return new PQUnknownValueObject(); }
425
427
426 ClassA* getClassAPtr(ClassA* o) { _called = true; return o; }
428 ClassA* getClassAPtr(ClassA* o) { _called = true; return o; }
427 ClassB* getClassBPtr(ClassB* o) { _called = true; return o; }
429 ClassB* getClassBPtr(ClassB* o) { _called = true; return o; }
428 ClassC* getClassCPtr(ClassC* o) { _called = true; return o; }
430 ClassC* getClassCPtr(ClassC* o) { _called = true; return o; }
429 ClassD* getClassDPtr(ClassD* o) { _called = true; return o; }
431 ClassD* getClassDPtr(ClassD* o) { _called = true; return o; }
430
432
431 ClassA* createClassA() { _called = true; return new ClassA; }
433 ClassA* createClassA() { _called = true; return new ClassA; }
432 ClassB* createClassB() { _called = true; return new ClassB; }
434 ClassB* createClassB() { _called = true; return new ClassB; }
433 ClassC* createClassC() { _called = true; return new ClassC; }
435 ClassC* createClassC() { _called = true; return new ClassC; }
434 ClassD* createClassD() { _called = true; return new ClassD; }
436 ClassD* createClassD() { _called = true; return new ClassD; }
435 ClassA* createClassCAsA() { _called = true; return new ClassC; }
437 ClassA* createClassCAsA() { _called = true; return new ClassC; }
436 ClassB* createClassCAsB() { _called = true; return new ClassC; }
438 ClassB* createClassCAsB() { _called = true; return new ClassC; }
437 ClassA* createClassDAsA() { _called = true; return new ClassD; }
439 ClassA* createClassDAsA() { _called = true; return new ClassD; }
438 ClassB* createClassDAsB() { _called = true; return new ClassD; }
440 ClassB* createClassDAsB() { _called = true; return new ClassD; }
439
441
440 QColor setAutoConvertColor(const QColor& color) { _called = true; return color; };
442 QColor setAutoConvertColor(const QColor& color) { _called = true; return color; };
441 QBrush setAutoConvertBrush(const QBrush& brush) { _called = true; return brush; };
443 QBrush setAutoConvertBrush(const QBrush& brush) { _called = true; return brush; };
442 QPen setAutoConvertPen(const QPen& pen) { _called = true; return pen; };
444 QPen setAutoConvertPen(const QPen& pen) { _called = true; return pen; };
443 QCursor setAutoConvertCursor(const QCursor& cursor) { _called = true; return cursor; };
445 QCursor setAutoConvertCursor(const QCursor& cursor) { _called = true; return cursor; };
444
446
445 private:
447 private:
446 bool _passed;
448 bool _passed;
447 bool _called;
449 bool _called;
448 int _calledOverload;
450 int _calledOverload;
449 PythonQtTestSlotCalling* _test;
451 PythonQtTestSlotCalling* _test;
450 };
452 };
451
453
452 class PythonQtTestSignalHandlerHelper;
454 class PythonQtTestSignalHandlerHelper;
453
455
454 //! test the connection of signals to python
456 //! test the connection of signals to python
455 class PythonQtTestSignalHandler : public QObject
457 class PythonQtTestSignalHandler : public QObject
456 {
458 {
457 Q_OBJECT
459 Q_OBJECT
458
460
459 private slots:
461 private slots:
460 void initTestCase();
462 void initTestCase();
461
463
462 void testSignalHandler();
464 void testSignalHandler();
463 void testRecursiveSignalHandler();
465 void testRecursiveSignalHandler();
464
466
465 private:
467 private:
466 PythonQtTestSignalHandlerHelper* _helper;
468 PythonQtTestSignalHandlerHelper* _helper;
467
469
468 };
470 };
469
471
470 //! helper class for signal testing
472 //! helper class for signal testing
471 class PythonQtTestSignalHandlerHelper : public QObject
473 class PythonQtTestSignalHandlerHelper : public QObject
472 {
474 {
473 Q_OBJECT
475 Q_OBJECT
474
476
475 public:
477 public:
476 PythonQtTestSignalHandlerHelper(PythonQtTestSignalHandler* test) {
478 PythonQtTestSignalHandlerHelper(PythonQtTestSignalHandler* test) {
477 _test = test;
479 _test = test;
478 };
480 };
479
481
480 public slots:
482 public slots:
481 void setPassed() { _passed = true; }
483 void setPassed() { _passed = true; }
482
484
483 bool emitIntSignal(int a) { _passed = false; emit intSignal(a); return _passed; };
485 bool emitIntSignal(int a) { _passed = false; emit intSignal(a); return _passed; };
484 bool emitFloatSignal(float a) { _passed = false; emit floatSignal(a); return _passed; };
486 bool emitFloatSignal(float a) { _passed = false; emit floatSignal(a); return _passed; };
485 bool emitEnumSignal(PQCppObject2::TestEnumFlag flag) { _passed = false; emit enumSignal(flag); return _passed; };
487 bool emitEnumSignal(PQCppObject2::TestEnumFlag flag) { _passed = false; emit enumSignal(flag); return _passed; };
486
488
487 bool emitVariantSignal(const QVariant& v) { _passed = false; emit variantSignal(v); return _passed; };
489 bool emitVariantSignal(const QVariant& v) { _passed = false; emit variantSignal(v); return _passed; };
488 QVariant expectedVariant() { return _v; }
490 QVariant expectedVariant() { return _v; }
489 void setExpectedVariant(const QVariant& v) { _v = v; }
491 void setExpectedVariant(const QVariant& v) { _v = v; }
490
492
491 bool emitComplexSignal(int a, float b, const QStringList& l, QObject* obj) { _passed = false; emit complexSignal(a,b,l,obj); return _passed; };
493 bool emitComplexSignal(int a, float b, const QStringList& l, QObject* obj) { _passed = false; emit complexSignal(a,b,l,obj); return _passed; };
492
494
493 bool emitSignal1(int a) { _passed = false; emit signal1(a); return _passed; };
495 bool emitSignal1(int a) { _passed = false; emit signal1(a); return _passed; };
494 bool emitSignal2(const QString& s) { _passed = false; emit signal2(s); return _passed; };
496 bool emitSignal2(const QString& s) { _passed = false; emit signal2(s); return _passed; };
495 bool emitSignal3(float a) { _passed = false; emit signal3(a); return _passed; };
497 bool emitSignal3(float a) { _passed = false; emit signal3(a); return _passed; };
496
498
497 signals:
499 signals:
498 void intSignal(int);
500 void intSignal(int);
499 void floatSignal(float);
501 void floatSignal(float);
500 void variantSignal(const QVariant& v);
502 void variantSignal(const QVariant& v);
501 void complexSignal(int a, float b, const QStringList& l, QObject* obj);
503 void complexSignal(int a, float b, const QStringList& l, QObject* obj);
502 void enumSignal(PQCppObject2::TestEnumFlag flag);
504 void enumSignal(PQCppObject2::TestEnumFlag flag);
503
505
504 void signal1(int);
506 void signal1(int);
505 void signal2(const QString&);
507 void signal2(const QString&);
506 void signal3(float);
508 void signal3(float);
507
509
508 private:
510 private:
509 bool _passed;
511 bool _passed;
510 QVariant _v;
512 QVariant _v;
511
513
512 PythonQtTestSignalHandler* _test;
514 PythonQtTestSignalHandler* _test;
513 };
515 };
514
516
515 #endif
517 #endif
General Comments 0
You need to be logged in to leave comments. Login now