##// END OF EJS Templates
florianlink -
r163:349fb638ffe0
parent child
Show More
@@ -0,0 +1,55
1 /*
2 *
3 * Copyright (C) 2011 MeVis Medical Solutions AG All Rights Reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
28 *
29 * http://www.mevis.de
30 *
31 */
32
33 #ifndef __PythonQtPythonInclude_h
34 #define __PythonQtPythonInclude_h
35
36 // Undefine macros that Python.h defines to avoid redefinition warning.
37 #undef _POSIX_C_SOURCE
38 #undef _POSIX_THREADS
39 #undef _XOPEN_SOURCE
40
41 // If PYTHONQT_USE_RELEASE_PYTHON_FALLBACK is enabled, try to link
42 // release Python DLL if it is available by undefining _DEBUG while
43 // including Python.h
44 #if defined(PYTHONQT_USE_RELEASE_PYTHON_FALLBACK) && defined(_DEBUG)
45 #undef _DEBUG
46 #if defined(_MSC_VER) && _MSC_VER >= 1400
47 #define _CRT_NOFORCE_MANIFEST 1
48 #endif
49 #include <Python.h>
50 #define _DEBUG
51 #else
52 #include <Python.h>
53 #endif
54
55 #endif
@@ -0,0 +1,114
1 /*
2 *
3 * Copyright (C) 2011 MeVis Medical Solutions AG All Rights Reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
28 *
29 * http://www.mevis.de
30 *
31 */
32
33 //----------------------------------------------------------------------------------
34 /*!
35 // \file PythonQtStdIn.cpp
36 // \author Jean-Christophe Fillion-Robin
37 // \author Last changed by $Author: jcfr $
38 // \date 2011
39 */
40 //----------------------------------------------------------------------------------
41
42 #include "PythonQtStdIn.h"
43
44 static PyObject *PythonQtStdInRedirect_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
45 {
46 PythonQtStdInRedirect *self;
47 self = (PythonQtStdInRedirect *)type->tp_alloc(type, 0);
48 self->_cb = NULL;
49 self->_callData = NULL;
50
51 return (PyObject *)self;
52 }
53
54 static PyObject *PythonQtStdInRedirect_readline(PyObject * self, PyObject * args)
55 {
56 PythonQtStdInRedirect* s = (PythonQtStdInRedirect*)self;
57 QString string;
58 if (s->_cb) {
59 string = (*s->_cb)(s->_callData);
60 }
61 return Py_BuildValue(const_cast<char*>("s"), const_cast<char*>(string.toAscii().data()));
62 }
63
64 static PyMethodDef PythonQtStdInRedirect_methods[] = {
65 {"readline", (PyCFunction)PythonQtStdInRedirect_readline, METH_VARARGS,
66 "read input line"},
67 {NULL, NULL, 0 , NULL} /* sentinel */
68 };
69
70 static PyMemberDef PythonQtStdInRedirect_members[] = {
71 {NULL} /* Sentinel */
72 };
73
74 PyTypeObject PythonQtStdInRedirectType = {
75 PyObject_HEAD_INIT(NULL)
76 0, /*ob_size*/
77 "PythonQtStdInRedirect", /*tp_name*/
78 sizeof(PythonQtStdInRedirect), /*tp_basicsize*/
79 0, /*tp_itemsize*/
80 0, /*tp_dealloc*/
81 0, /*tp_print*/
82 0, /*tp_getattr*/
83 0, /*tp_setattr*/
84 0, /*tp_compare*/
85 0, /*tp_repr*/
86 0, /*tp_as_number*/
87 0, /*tp_as_sequence*/
88 0, /*tp_as_mapping*/
89 0, /*tp_hash */
90 0, /*tp_call*/
91 0, /*tp_str*/
92 0, /*tp_getattro*/
93 0, /*tp_setattro*/
94 0, /*tp_as_buffer*/
95 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
96 "PythonQtStdInRedirect", /* tp_doc */
97 0, /* tp_traverse */
98 0, /* tp_clear */
99 0, /* tp_richcompare */
100 0, /* tp_weaklistoffset */
101 0, /* tp_iter */
102 0, /* tp_iternext */
103 PythonQtStdInRedirect_methods, /* tp_methods */
104 PythonQtStdInRedirect_members, /* tp_members */
105 0, /* tp_getset */
106 0, /* tp_base */
107 0, /* tp_dict */
108 0, /* tp_descr_get */
109 0, /* tp_descr_set */
110 0, /* tp_dictoffset */
111 0, /* tp_init */
112 0, /* tp_alloc */
113 PythonQtStdInRedirect_new, /* tp_new */
114 };
@@ -0,0 +1,63
1 #ifndef _PYTHONQTSTDIN_H
2 #define _PYTHONQTSTDIN_H
3
4 /*
5 *
6 * Copyright (C) 2011 MeVis Medical Solutions AG All Rights Reserved.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
31 *
32 * http://www.mevis.de
33 *
34 */
35
36 //----------------------------------------------------------------------------------
37 /*!
38 // \file PythonQtStdIn.h
39 // \author Jean-Christophe Fillion-Robin
40 // \author Last changed by $Author: jcfr $
41 // \date 2011
42 */
43 //----------------------------------------------------------------------------------
44
45
46 #include "PythonQtPythonInclude.h"
47 #include "structmember.h"
48 #include <QString>
49
50 //! declares the type of the stdout redirection class
51 extern PyTypeObject PythonQtStdInRedirectType;
52
53 //! declares the callback that is called from the write() function
54 typedef QString PythonQtInputChangedCB(void* callData);
55
56 //! declares the stdin redirection class
57 typedef struct {
58 PyObject_HEAD
59 PythonQtInputChangedCB* _cb;
60 void * _callData;
61 } PythonQtStdInRedirect;
62
63 #endif
@@ -1,675 +1,675
1 #ifndef _PYTHONQT_H
1 #ifndef _PYTHONQT_H
2 #define _PYTHONQT_H
2 #define _PYTHONQT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 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 PythonQt.h
38 // \file PythonQt.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include "PythonQtInstanceWrapper.h"
46 #include "PythonQtInstanceWrapper.h"
47 #include "PythonQtClassWrapper.h"
47 #include "PythonQtClassWrapper.h"
48 #include "PythonQtSlot.h"
48 #include "PythonQtSlot.h"
49 #include "PythonQtObjectPtr.h"
49 #include "PythonQtObjectPtr.h"
50 #include "PythonQtStdIn.h"
50 #include "PythonQtStdIn.h"
51 #include <QObject>
51 #include <QObject>
52 #include <QVariant>
52 #include <QVariant>
53 #include <QList>
53 #include <QList>
54 #include <QHash>
54 #include <QHash>
55 #include <QByteArray>
55 #include <QByteArray>
56 #include <QStringList>
56 #include <QStringList>
57 #include <QtDebug>
57 #include <QtDebug>
58 #include <iostream>
58 #include <iostream>
59
59
60
60
61 class PythonQtClassInfo;
61 class PythonQtClassInfo;
62 class PythonQtPrivate;
62 class PythonQtPrivate;
63 class PythonQtMethodInfo;
63 class PythonQtMethodInfo;
64 class PythonQtSignalReceiver;
64 class PythonQtSignalReceiver;
65 class PythonQtImportFileInterface;
65 class PythonQtImportFileInterface;
66 class PythonQtCppWrapperFactory;
66 class PythonQtCppWrapperFactory;
67 class PythonQtQFileImporter;
67 class PythonQtQFileImporter;
68
68
69 typedef void PythonQtQObjectWrappedCB(QObject* object);
69 typedef void PythonQtQObjectWrappedCB(QObject* object);
70 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
70 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
71 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
71 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name);
72
72
73 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
73 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
74
74
75 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
75 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) {
76 (reinterpret_cast<T*>(object))->_wrapper = wrapper;
76 (reinterpret_cast<T*>(object))->_wrapper = wrapper;
77 }
77 }
78
78
79 //! returns the offset that needs to be added to upcast an object of type T1 to T2
79 //! returns the offset that needs to be added to upcast an object of type T1 to T2
80 template<class T1, class T2> int PythonQtUpcastingOffset() {
80 template<class T1, class T2> int PythonQtUpcastingOffset() {
81 return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
81 return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100))))
82 - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
82 - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100))));
83 }
83 }
84
84
85 //! callback to create a QObject lazily
85 //! callback to create a QObject lazily
86 typedef QObject* PythonQtQObjectCreatorFunctionCB();
86 typedef QObject* PythonQtQObjectCreatorFunctionCB();
87
87
88 //! helper template to create a derived QObject class
88 //! helper template to create a derived QObject class
89 template<class T> QObject* PythonQtCreateObject() { return new T(); };
89 template<class T> QObject* PythonQtCreateObject() { return new T(); };
90
90
91 //! The main interface to the Python Qt binding, realized as a singleton
91 //! The main interface to the Python Qt binding, realized as a singleton
92 /*!
92 /*!
93 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
93 Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it.
94 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
94 While there can be only one PythonQt instance, you can have any number of Python context to do scripting in.
95 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
95 One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context
96 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
96 that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation,
97 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
97 but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running
98 code in the scope of a dict.
98 code in the scope of a dict.
99 */
99 */
100 class PYTHONQT_EXPORT PythonQt : public QObject {
100 class PYTHONQT_EXPORT PythonQt : public QObject {
101
101
102 Q_OBJECT
102 Q_OBJECT
103
103
104 public:
104 public:
105
105
106 //! flags that can be passed to PythonQt::init()
106 //! flags that can be passed to PythonQt::init()
107 enum InitFlags {
107 enum InitFlags {
108 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
108 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
109 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
109 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
110 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
110 ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
111 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
111 PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done
112 };
112 };
113
113
114 //! flags that tell PythonQt which operators to expect on the registered type
114 //! flags that tell PythonQt which operators to expect on the registered type
115 enum TypeSlots {
115 enum TypeSlots {
116 Type_Add = 1,
116 Type_Add = 1,
117 Type_Subtract = 1 << 1,
117 Type_Subtract = 1 << 1,
118 Type_Multiply = 1 << 2,
118 Type_Multiply = 1 << 2,
119 Type_Divide = 1 << 3,
119 Type_Divide = 1 << 3,
120 Type_Mod = 1 << 4,
120 Type_Mod = 1 << 4,
121 Type_And = 1 << 5,
121 Type_And = 1 << 5,
122 Type_Or = 1 << 6,
122 Type_Or = 1 << 6,
123 Type_Xor = 1 << 7,
123 Type_Xor = 1 << 7,
124 Type_LShift = 1 << 8,
124 Type_LShift = 1 << 8,
125 Type_RShift = 1 << 9,
125 Type_RShift = 1 << 9,
126
126
127 Type_InplaceAdd = 1 << 10,
127 Type_InplaceAdd = 1 << 10,
128 Type_InplaceSubtract = 1 << 11,
128 Type_InplaceSubtract = 1 << 11,
129 Type_InplaceMultiply = 1 << 12,
129 Type_InplaceMultiply = 1 << 12,
130 Type_InplaceDivide = 1 << 13,
130 Type_InplaceDivide = 1 << 13,
131 Type_InplaceMod = 1 << 14,
131 Type_InplaceMod = 1 << 14,
132 Type_InplaceAnd = 1 << 15,
132 Type_InplaceAnd = 1 << 15,
133 Type_InplaceOr = 1 << 16,
133 Type_InplaceOr = 1 << 16,
134 Type_InplaceXor = 1 << 17,
134 Type_InplaceXor = 1 << 17,
135 Type_InplaceLShift = 1 << 18,
135 Type_InplaceLShift = 1 << 18,
136 Type_InplaceRShift = 1 << 19,
136 Type_InplaceRShift = 1 << 19,
137
137
138 // Not yet needed/nicely mappable/generated...
138 // Not yet needed/nicely mappable/generated...
139 //Type_Positive = 1 << 29,
139 //Type_Positive = 1 << 29,
140 //Type_Negative = 1 << 29,
140 //Type_Negative = 1 << 29,
141 //Type_Abs = 1 << 29,
141 //Type_Abs = 1 << 29,
142 //Type_Hash = 1 << 29,
142 //Type_Hash = 1 << 29,
143
143
144 Type_Invert = 1 << 29,
144 Type_Invert = 1 << 29,
145 Type_RichCompare = 1 << 30,
145 Type_RichCompare = 1 << 30,
146 Type_NonZero = 1 << 31,
146 Type_NonZero = 1 << 31,
147
147
148 };
148 };
149
149
150 //! enum for profiling callback
150 //! enum for profiling callback
151 enum ProfilingCallbackState {
151 enum ProfilingCallbackState {
152 Enter = 1,
152 Enter = 1,
153 Leave = 2
153 Leave = 2
154 };
154 };
155
155
156 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
156 //! callback for profiling. className and methodName are only passed when state == Enter, otherwise
157 //! they are NULL.
157 //! they are NULL.
158 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
158 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName);
159
159
160 //---------------------------------------------------------------------------
160 //---------------------------------------------------------------------------
161 //! \name Singleton Initialization
161 //! \name Singleton Initialization
162 //@{
162 //@{
163
163
164 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
164 //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given
165 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
165 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
166 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
166 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
167 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
167 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
168
168
169 //! cleanup of the singleton
169 //! cleanup of the singleton
170 static void cleanup();
170 static void cleanup();
171
171
172 //! get the singleton instance
172 //! get the singleton instance
173 static PythonQt* self();
173 static PythonQt* self();
174
174
175 //@}
175 //@}
176
176
177 //! defines the object types for introspection
177 //! defines the object types for introspection
178 enum ObjectType {
178 enum ObjectType {
179 Class,
179 Class,
180 Function,
180 Function,
181 Variable,
181 Variable,
182 Module,
182 Module,
183 Anything,
183 Anything,
184 CallOverloads
184 CallOverloads
185 };
185 };
186
186
187
187
188 //---------------------------------------------------------------------------
188 //---------------------------------------------------------------------------
189 //! \name Standard input handling
189 //! \name Standard input handling
190 //@{
190 //@{
191
191
192 //! Overwrite default handling of stdin using a custom callback. It internally backup
192 //! Overwrite default handling of stdin using a custom callback. It internally backup
193 //! the original 'sys.stdin' into 'sys.pythonqt_original_stdin'
193 //! the original 'sys.stdin' into 'sys.pythonqt_original_stdin'
194 void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
194 void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0);
195
195
196 //! Enable or disable stdin custom callback. It resets 'sys.stdin' using either 'sys.pythonqt_stdin'
196 //! Enable or disable stdin custom callback. It resets 'sys.stdin' using either 'sys.pythonqt_stdin'
197 //! or 'sys.pythonqt_original_stdin'
197 //! or 'sys.pythonqt_original_stdin'
198 void setRedirectStdInCallbackEnabled(bool enabled);
198 void setRedirectStdInCallbackEnabled(bool enabled);
199
199
200 //@}
200 //@}
201
201
202 //---------------------------------------------------------------------------
202 //---------------------------------------------------------------------------
203 //! \name Modules
203 //! \name Modules
204 //@{
204 //@{
205
205
206 //! get the __main__ module of python
206 //! get the __main__ module of python
207 PythonQtObjectPtr getMainModule();
207 PythonQtObjectPtr getMainModule();
208
208
209 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
209 //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it)
210 //! If a module is already imported, this returns the already imported module.
210 //! If a module is already imported, this returns the already imported module.
211 PythonQtObjectPtr importModule(const QString& name);
211 PythonQtObjectPtr importModule(const QString& name);
212
212
213 //! creates the new module \c name and evaluates the given file in the context of that module
213 //! creates the new module \c name and evaluates the given file in the context of that module
214 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
214 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
215 //! to a module later on.
215 //! to a module later on.
216 //! The user needs to make sure that the \c name is unique in the python module dictionary.
216 //! The user needs to make sure that the \c name is unique in the python module dictionary.
217 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
217 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
218
218
219 //! creates the new module \c name and evaluates the given script in the context of that module.
219 //! creates the new module \c name and evaluates the given script in the context of that module.
220 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
220 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
221 //! to a module later on.
221 //! to a module later on.
222 //! The user needs to make sure that the \c name is unique in the python module dictionary.
222 //! The user needs to make sure that the \c name is unique in the python module dictionary.
223 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
223 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
224
224
225 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
225 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
226 //! script code
226 //! script code
227 PythonQtObjectPtr createUniqueModule();
227 PythonQtObjectPtr createUniqueModule();
228
228
229 //@}
229 //@}
230
230
231 //---------------------------------------------------------------------------
231 //---------------------------------------------------------------------------
232 //! \name Importing/Paths
232 //! \name Importing/Paths
233 //@{
233 //@{
234
234
235 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
235 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
236 void overwriteSysPath(const QStringList& paths);
236 void overwriteSysPath(const QStringList& paths);
237
237
238 //! prepend a path to sys.path to allow importing from it
238 //! prepend a path to sys.path to allow importing from it
239 void addSysPath(const QString& path);
239 void addSysPath(const QString& path);
240
240
241 //! sets the __path__ list of a module to the given list (important for local imports)
241 //! sets the __path__ list of a module to the given list (important for local imports)
242 void setModuleImportPath(PyObject* module, const QStringList& paths);
242 void setModuleImportPath(PyObject* module, const QStringList& paths);
243
243
244 //@}
244 //@}
245
245
246 //---------------------------------------------------------------------------
246 //---------------------------------------------------------------------------
247 //! \name Registering Classes
247 //! \name Registering Classes
248 //@{
248 //@{
249
249
250 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
250 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
251 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
251 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
252 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
252 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
253 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
253 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
254
254
255 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
255 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
256 //! (ownership of wrapper is passed to PythonQt)
256 //! (ownership of wrapper is passed to PythonQt)
257 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
257 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
258
258
259 This will add a wrapper object that is used to make calls to the given classname \c typeName.
259 This will add a wrapper object that is used to make calls to the given classname \c typeName.
260 All slots that take a pointer to typeName as the first argument will be callable from Python on
260 All slots that take a pointer to typeName as the first argument will be callable from Python on
261 a variant object that contains such a type.
261 a variant object that contains such a type.
262 */
262 */
263 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
263 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
264
264
265 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
265 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
266 //! and it will register the classes when it first sees a pointer to such a derived class
266 //! and it will register the classes when it first sees a pointer to such a derived class
267 void registerQObjectClassNames(const QStringList& names);
267 void registerQObjectClassNames(const QStringList& names);
268
268
269 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
269 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
270 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
270 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
271 //! type is really derived from parentType.
271 //! type is really derived from parentType.
272 //! Returns false if the typeName was not yet registered.
272 //! Returns false if the typeName was not yet registered.
273 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
273 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
274
274
275 //! add a handler for polymorphic downcasting
275 //! add a handler for polymorphic downcasting
276 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
276 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
277
277
278 //@}
278 //@}
279
279
280 //---------------------------------------------------------------------------
280 //---------------------------------------------------------------------------
281 //! \name Script Parsing and Evaluation
281 //! \name Script Parsing and Evaluation
282 //@{
282 //@{
283
283
284 //! parses the given file and returns the python code object, this can then be used to call evalCode()
284 //! parses the given file and returns the python code object, this can then be used to call evalCode()
285 PythonQtObjectPtr parseFile(const QString& filename);
285 PythonQtObjectPtr parseFile(const QString& filename);
286
286
287 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
287 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
288 //! If pycode is NULL, a python error is printed.
288 //! If pycode is NULL, a python error is printed.
289 QVariant evalCode(PyObject* object, PyObject* pycode);
289 QVariant evalCode(PyObject* object, PyObject* pycode);
290
290
291 //! evaluates the given script code and returns the result value
291 //! evaluates the given script code and returns the result value
292 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
292 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
293
293
294 //! evaluates the given script code from file
294 //! evaluates the given script code from file
295 void evalFile(PyObject* object, const QString& filename);
295 void evalFile(PyObject* object, const QString& filename);
296
296
297 //@}
297 //@}
298
298
299 //---------------------------------------------------------------------------
299 //---------------------------------------------------------------------------
300 //! \name Signal Handlers
300 //! \name Signal Handlers
301 //@{
301 //@{
302
302
303 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
303 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
304 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
304 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
305
305
306 //! remove a signal handler from the given \c signal of \c obj
306 //! remove a signal handler from the given \c signal of \c obj
307 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
307 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
308
308
309 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
309 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
310 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
310 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
311
311
312 //! remove a signal handler from the given \c signal of \c obj
312 //! remove a signal handler from the given \c signal of \c obj
313 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
313 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
314
314
315 //@}
315 //@}
316
316
317 //---------------------------------------------------------------------------
317 //---------------------------------------------------------------------------
318 //! \name Variable access
318 //! \name Variable access
319 //@{
319 //@{
320
320
321 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
321 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
322 void addObject(PyObject* object, const QString& name, QObject* qObject);
322 void addObject(PyObject* object, const QString& name, QObject* qObject);
323
323
324 //! add the given variable to the object
324 //! add the given variable to the object
325 void addVariable(PyObject* object, const QString& name, const QVariant& v);
325 void addVariable(PyObject* object, const QString& name, const QVariant& v);
326
326
327 //! remove the given variable
327 //! remove the given variable
328 void removeVariable(PyObject* module, const QString& name);
328 void removeVariable(PyObject* module, const QString& name);
329
329
330 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
330 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
331 QVariant getVariable(PyObject* object, const QString& name);
331 QVariant getVariable(PyObject* object, const QString& name);
332
332
333 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
333 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
334 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
334 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
335
335
336 //! returns the found callable object or NULL
336 //! returns the found callable object or NULL
337 //! @return new reference
337 //! @return new reference
338 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
338 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
339
339
340 //@}
340 //@}
341
341
342 //---------------------------------------------------------------------------
342 //---------------------------------------------------------------------------
343 //! \name Calling Python Objects
343 //! \name Calling Python Objects
344 //@{
344 //@{
345
345
346 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
346 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
347 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
347 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
348
348
349 //! call the given python object, returns the result converted to a QVariant
349 //! call the given python object, returns the result converted to a QVariant
350 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
350 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
351
351
352 //! call the given python object, returns the result as new PyObject
352 //! call the given python object, returns the result as new PyObject
353 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
353 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
354
354
355 //@}
355 //@}
356
356
357 //---------------------------------------------------------------------------
357 //---------------------------------------------------------------------------
358 //! \name Decorations, Constructors, Wrappers...
358 //! \name Decorations, Constructors, Wrappers...
359 //@{
359 //@{
360
360
361 //! add an object whose slots will be used as decorator slots for
361 //! add an object whose slots will be used as decorator slots for
362 //! other QObjects or CPP classes. The slots need to follow the
362 //! other QObjects or CPP classes. The slots need to follow the
363 //! convention that the first argument is a pointer to the wrapped object.
363 //! convention that the first argument is a pointer to the wrapped object.
364 //! (ownership is passed to PythonQt)
364 //! (ownership is passed to PythonQt)
365 /*!
365 /*!
366 Example:
366 Example:
367
367
368 A slot with the signature
368 A slot with the signature
369
369
370 \code
370 \code
371 bool doSomething(QWidget* w, int a)
371 bool doSomething(QWidget* w, int a)
372 \endcode
372 \endcode
373
373
374 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
374 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
375 that will be called with the concrete instance as first argument.
375 that will be called with the concrete instance as first argument.
376 So in Python you can now e.g. call
376 So in Python you can now e.g. call
377
377
378 \code
378 \code
379 someWidget.doSomething(12)
379 someWidget.doSomething(12)
380 \endcode
380 \endcode
381
381
382 without QWidget really having this method. This allows to easily make normal methods
382 without QWidget really having this method. This allows to easily make normal methods
383 of Qt classes callable by forwarding them with such decorator slots
383 of Qt classes callable by forwarding them with such decorator slots
384 or to make CPP classes (which are not derived from QObject) callable from Python.
384 or to make CPP classes (which are not derived from QObject) callable from Python.
385 */
385 */
386 void addInstanceDecorators(QObject* o);
386 void addInstanceDecorators(QObject* o);
387
387
388 //! add an object whose slots will be used as decorator slots for
388 //! add an object whose slots will be used as decorator slots for
389 //! class objects (ownership is passed to PythonQt)
389 //! class objects (ownership is passed to PythonQt)
390 /*!
390 /*!
391 The slots need to follow the following convention:
391 The slots need to follow the following convention:
392 - SomeClass* new_SomeClass(...)
392 - SomeClass* new_SomeClass(...)
393 - QVariant new_SomeClass(...)
393 - QVariant new_SomeClass(...)
394 - void delete_SomeClass(SomeClass*)
394 - void delete_SomeClass(SomeClass*)
395 - ... static_SomeClass_someName(...)
395 - ... static_SomeClass_someName(...)
396
396
397 This will add:
397 This will add:
398 - a constructor
398 - a constructor
399 - a constructor which generates a QVariant
399 - a constructor which generates a QVariant
400 - a destructor (only useful for CPP objects)
400 - a destructor (only useful for CPP objects)
401 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
401 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
402
402
403 */
403 */
404 void addClassDecorators(QObject* o);
404 void addClassDecorators(QObject* o);
405
405
406 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
406 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
407 void addDecorators(QObject* o);
407 void addDecorators(QObject* o);
408
408
409 //! add the given factory to PythonQt (ownership stays with caller)
409 //! add the given factory to PythonQt (ownership stays with caller)
410 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
410 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
411
411
412 //@}
412 //@}
413
413
414 //---------------------------------------------------------------------------
414 //---------------------------------------------------------------------------
415 //! \name Custom Importer
415 //! \name Custom Importer
416 //@{
416 //@{
417
417
418 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
418 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
419 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
419 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
420 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
420 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
421 //! This is not reversible, so even setting setImporter(NULL) afterwards will
421 //! This is not reversible, so even setting setImporter(NULL) afterwards will
422 //! keep the custom PythonQt importer with a QFile default import interface.
422 //! keep the custom PythonQt importer with a QFile default import interface.
423 //! Subsequent python import calls will make use of the passed importInterface
423 //! Subsequent python import calls will make use of the passed importInterface
424 //! which forwards all import calls to the given \c importInterface.
424 //! which forwards all import calls to the given \c importInterface.
425 //! Passing NULL will install a default QFile importer.
425 //! Passing NULL will install a default QFile importer.
426 //! (\c importInterface ownership stays with caller)
426 //! (\c importInterface ownership stays with caller)
427 void setImporter(PythonQtImportFileInterface* importInterface);
427 void setImporter(PythonQtImportFileInterface* importInterface);
428
428
429 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
429 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
430 //! (without calling setImporter or installDefaultImporter at least once, the default python import
430 //! (without calling setImporter or installDefaultImporter at least once, the default python import
431 //! mechanism is in place)
431 //! mechanism is in place)
432 //! the default importer allows to import files from anywhere QFile can read from,
432 //! the default importer allows to import files from anywhere QFile can read from,
433 //! including the Qt resource system using ":". Keep in mind that you need to extend
433 //! including the Qt resource system using ":". Keep in mind that you need to extend
434 //! "sys.path" with ":" to be able to import from the Qt resources.
434 //! "sys.path" with ":" to be able to import from the Qt resources.
435 void installDefaultImporter() { setImporter(NULL); }
435 void installDefaultImporter() { setImporter(NULL); }
436
436
437 //! set paths that the importer should ignore
437 //! set paths that the importer should ignore
438 void setImporterIgnorePaths(const QStringList& paths);
438 void setImporterIgnorePaths(const QStringList& paths);
439
439
440 //! get paths that the importer should ignore
440 //! get paths that the importer should ignore
441 const QStringList& getImporterIgnorePaths();
441 const QStringList& getImporterIgnorePaths();
442
442
443 //! get access to the file importer (if set)
443 //! get access to the file importer (if set)
444 static PythonQtImportFileInterface* importInterface();
444 static PythonQtImportFileInterface* importInterface();
445
445
446 //@}
446 //@}
447
447
448 //---------------------------------------------------------------------------
448 //---------------------------------------------------------------------------
449 //! \name Other Stuff
449 //! \name Other Stuff
450 //@{
450 //@{
451
451
452 //! get access to internal data (should not be used on the public API, but is used by some C functions)
452 //! get access to internal data (should not be used on the public API, but is used by some C functions)
453 static PythonQtPrivate* priv() { return _self->_p; }
453 static PythonQtPrivate* priv() { return _self->_p; }
454
454
455 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
455 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
456 //! The error is currently just output to the python stderr, future version might implement better trace printing
456 //! The error is currently just output to the python stderr, future version might implement better trace printing
457 bool handleError();
457 bool handleError();
458
458
459 //! clear all NotFound entries on all class infos, to ensure that
459 //! clear all NotFound entries on all class infos, to ensure that
460 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
460 //! newly loaded wrappers can add methods even when the object was wrapped by PythonQt before the wrapper was loaded
461 void clearNotFoundCachedMembers();
461 void clearNotFoundCachedMembers();
462
462
463 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
463 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
464 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
464 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
465 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
465 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
466 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
466 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
467
467
468 //! call the callback if it is set
468 //! call the callback if it is set
469 static void qObjectNoLongerWrappedCB(QObject* o);
469 static void qObjectNoLongerWrappedCB(QObject* o);
470
470
471 //! called by internal help methods
471 //! called by internal help methods
472 PyObject* helpCalled(PythonQtClassInfo* info);
472 PyObject* helpCalled(PythonQtClassInfo* info);
473
473
474 //! returns the found object or NULL
474 //! returns the found object or NULL
475 //! @return new reference
475 //! @return new reference
476 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
476 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
477
477
478 //! sets a callback that is called before and after function calls for profiling
478 //! sets a callback that is called before and after function calls for profiling
479 void setProfilingCallback(ProfilingCB* cb);
479 void setProfilingCallback(ProfilingCB* cb);
480
480
481 //@}
481 //@}
482
482
483 signals:
483 signals:
484 //! emitted when python outputs something to stdout (and redirection is turned on)
484 //! emitted when python outputs something to stdout (and redirection is turned on)
485 void pythonStdOut(const QString& str);
485 void pythonStdOut(const QString& str);
486 //! emitted when python outputs something to stderr (and redirection is turned on)
486 //! emitted when python outputs something to stderr (and redirection is turned on)
487 void pythonStdErr(const QString& str);
487 void pythonStdErr(const QString& str);
488
488
489 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
489 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
490 void pythonHelpRequest(const QByteArray& cppClassName);
490 void pythonHelpRequest(const QByteArray& cppClassName);
491
491
492 private:
492 private:
493 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
493 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
494
494
495 //! callback for stdout redirection, emits pythonStdOut signal
495 //! callback for stdout redirection, emits pythonStdOut signal
496 static void stdOutRedirectCB(const QString& str);
496 static void stdOutRedirectCB(const QString& str);
497 //! callback for stderr redirection, emits pythonStdErr signal
497 //! callback for stderr redirection, emits pythonStdErr signal
498 static void stdErrRedirectCB(const QString& str);
498 static void stdErrRedirectCB(const QString& str);
499
499
500 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
500 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
501 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
501 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
502
502
503 PythonQt(int flags, const QByteArray& pythonQtModuleName);
503 PythonQt(int flags, const QByteArray& pythonQtModuleName);
504 ~PythonQt();
504 ~PythonQt();
505
505
506 static PythonQt* _self;
506 static PythonQt* _self;
507 static int _uniqueModuleCount;
507 static int _uniqueModuleCount;
508
508
509 PythonQtPrivate* _p;
509 PythonQtPrivate* _p;
510
510
511 };
511 };
512
512
513 //! internal PythonQt details
513 //! internal PythonQt details
514 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
514 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
515
515
516 Q_OBJECT
516 Q_OBJECT
517
517
518 public:
518 public:
519 PythonQtPrivate();
519 PythonQtPrivate();
520 ~PythonQtPrivate();
520 ~PythonQtPrivate();
521
521
522 enum DecoratorTypes {
522 enum DecoratorTypes {
523 StaticDecorator = 1,
523 StaticDecorator = 1,
524 ConstructorDecorator = 2,
524 ConstructorDecorator = 2,
525 DestructorDecorator = 4,
525 DestructorDecorator = 4,
526 InstanceDecorator = 8,
526 InstanceDecorator = 8,
527 AllDecorators = 0xffff
527 AllDecorators = 0xffff
528 };
528 };
529
529
530 //! get the suffixes that are used for shared libraries
530 //! get the suffixes that are used for shared libraries
531 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
531 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
532
532
533 //! returns if the id is the id for PythonQtObjectPtr
533 //! returns if the id is the id for PythonQtObjectPtr
534 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
534 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
535
535
536 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
536 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
537 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
537 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
538 //! remove the wrapper ptr again
538 //! remove the wrapper ptr again
539 void removeWrapperPointer(void* obj);
539 void removeWrapperPointer(void* obj);
540
540
541 //! add parent class relation
541 //! add parent class relation
542 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
542 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
543
543
544 //! add a handler for polymorphic downcasting
544 //! add a handler for polymorphic downcasting
545 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
545 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
546
546
547 //! lookup existing classinfo and return new if not yet present
547 //! lookup existing classinfo and return new if not yet present
548 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
548 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
549
549
550 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
550 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
551 void removeSignalEmitter(QObject* obj);
551 void removeSignalEmitter(QObject* obj);
552
552
553 //! wrap the given QObject into a Python object (or return existing wrapper!)
553 //! wrap the given QObject into a Python object (or return existing wrapper!)
554 PyObject* wrapQObject(QObject* obj);
554 PyObject* wrapQObject(QObject* obj);
555
555
556 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
556 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
557 PyObject* wrapPtr(void* ptr, const QByteArray& name);
557 PyObject* wrapPtr(void* ptr, const QByteArray& name);
558
558
559 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
559 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
560 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
560 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
561 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
561 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
562 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
562 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
563
563
564 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
564 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
565 //! (ownership of wrapper is passed to PythonQt)
565 //! (ownership of wrapper is passed to PythonQt)
566 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
566 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
567
567
568 This will add a wrapper object that is used to make calls to the given classname \c typeName.
568 This will add a wrapper object that is used to make calls to the given classname \c typeName.
569 All slots that take a pointer to typeName as the first argument will be callable from Python on
569 All slots that take a pointer to typeName as the first argument will be callable from Python on
570 a variant object that contains such a type.
570 a variant object that contains such a type.
571 */
571 */
572 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
572 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
573
573
574 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
574 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
575 //! and it will register the classes when it first sees a pointer to such a derived class
575 //! and it will register the classes when it first sees a pointer to such a derived class
576 void registerQObjectClassNames(const QStringList& names);
576 void registerQObjectClassNames(const QStringList& names);
577
577
578 //! add a decorator object
578 //! add a decorator object
579 void addDecorators(QObject* o, int decoTypes);
579 void addDecorators(QObject* o, int decoTypes);
580
580
581 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
581 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
582 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
582 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
583
583
584 //! create a new instance of the given enum type with given value (returns a new reference)
584 //! create a new instance of the given enum type with given value (returns a new reference)
585 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
585 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
586
586
587 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
587 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
588 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
588 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
589
589
590 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
590 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
591 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
591 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
592
592
593 //! get the class info for a meta object (if available)
593 //! get the class info for a meta object (if available)
594 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
594 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
595
595
596 //! get the class info for a meta object (if available)
596 //! get the class info for a meta object (if available)
597 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
597 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
598
598
599 //! creates the new module from the given pycode
599 //! creates the new module from the given pycode
600 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
600 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
601
601
602 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
602 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
603 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
603 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
604
604
605 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
605 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
606 static PyObject* dummyTuple();
606 static PyObject* dummyTuple();
607
607
608 //! called by virtual overloads when a python return value can not be converted to the required Qt type
608 //! called by virtual overloads when a python return value can not be converted to the required Qt type
609 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
609 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
610
610
611 //! get access to the PythonQt module
611 //! get access to the PythonQt module
612 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
612 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
613
613
614 //! returns the profiling callback, which may be NULL
614 //! returns the profiling callback, which may be NULL
615 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
615 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; }
616
616
617 private:
617 private:
618 //! Setup the shared library suffixes by getting them from the "imp" module.
618 //! Setup the shared library suffixes by getting them from the "imp" module.
619 void setupSharedLibrarySuffixes();
619 void setupSharedLibrarySuffixes();
620
620
621 //! create a new pythonqt class wrapper and place it in the pythonqt module
621 //! create a new pythonqt class wrapper and place it in the pythonqt module
622 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
622 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
623
623
624 //! get/create new package module (the returned object is a borrowed reference)
624 //! get/create new package module (the returned object is a borrowed reference)
625 PyObject* packageByName(const char* name);
625 PyObject* packageByName(const char* name);
626
626
627 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
627 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
628 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
628 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
629
629
630 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
630 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
631 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
631 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
632
632
633 //! stores the meta info of known Qt classes
633 //! stores the meta info of known Qt classes
634 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
634 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
635
635
636 //! names of qobject derived classes that can be casted to qobject savely
636 //! names of qobject derived classes that can be casted to qobject savely
637 QHash<QByteArray, bool> _knownQObjectClassNames;
637 QHash<QByteArray, bool> _knownQObjectClassNames;
638
638
639 //! stores signal receivers for QObjects
639 //! stores signal receivers for QObjects
640 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
640 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
641
641
642 //! the PythonQt python module
642 //! the PythonQt python module
643 PythonQtObjectPtr _pythonQtModule;
643 PythonQtObjectPtr _pythonQtModule;
644
644
645 //! the name of the PythonQt python module
645 //! the name of the PythonQt python module
646 QByteArray _pythonQtModuleName;
646 QByteArray _pythonQtModuleName;
647
647
648 //! the importer interface (if set)
648 //! the importer interface (if set)
649 PythonQtImportFileInterface* _importInterface;
649 PythonQtImportFileInterface* _importInterface;
650
650
651 //! the default importer
651 //! the default importer
652 PythonQtQFileImporter* _defaultImporter;
652 PythonQtQFileImporter* _defaultImporter;
653
653
654 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
654 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
655 PythonQtQObjectWrappedCB* _wrappedCB;
655 PythonQtQObjectWrappedCB* _wrappedCB;
656
656
657 QStringList _importIgnorePaths;
657 QStringList _importIgnorePaths;
658 QStringList _sharedLibrarySuffixes;
658 QStringList _sharedLibrarySuffixes;
659
659
660 //! the cpp object wrapper factories
660 //! the cpp object wrapper factories
661 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
661 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
662
662
663 QHash<QByteArray, PyObject*> _packages;
663 QHash<QByteArray, PyObject*> _packages;
664
664
665 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
665 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
666
666
667 PythonQt::ProfilingCB* _profilingCB;
667 PythonQt::ProfilingCB* _profilingCB;
668
668
669 int _initFlags;
669 int _initFlags;
670 int _PythonQtObjectPtr_metaId;
670 int _PythonQtObjectPtr_metaId;
671
671
672 friend class PythonQt;
672 friend class PythonQt;
673 };
673 };
674
674
675 #endif
675 #endif
@@ -1,868 +1,868
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 "PythonQtClassInfo.h"
42 #include "PythonQtClassInfo.h"
43 #include "PythonQtMethodInfo.h"
43 #include "PythonQtMethodInfo.h"
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include <QMetaMethod>
45 #include <QMetaMethod>
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaEnum>
47 #include <QMetaEnum>
48
48
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
50
50
51 PythonQtClassInfo::PythonQtClassInfo() {
51 PythonQtClassInfo::PythonQtClassInfo() {
52 _meta = NULL;
52 _meta = NULL;
53 _constructors = NULL;
53 _constructors = NULL;
54 _destructor = NULL;
54 _destructor = NULL;
55 _decoratorProvider = NULL;
55 _decoratorProvider = NULL;
56 _decoratorProviderCB = NULL;
56 _decoratorProviderCB = NULL;
57 _pythonQtClassWrapper = NULL;
57 _pythonQtClassWrapper = NULL;
58 _shellSetInstanceWrapperCB = NULL;
58 _shellSetInstanceWrapperCB = NULL;
59 _metaTypeId = -1;
59 _metaTypeId = -1;
60 _typeSlots = 0;
60 _typeSlots = 0;
61 _isQObject = false;
61 _isQObject = false;
62 _enumsCreated = false;
62 _enumsCreated = false;
63 }
63 }
64
64
65 PythonQtClassInfo::~PythonQtClassInfo()
65 PythonQtClassInfo::~PythonQtClassInfo()
66 {
66 {
67 clearCachedMembers();
67 clearCachedMembers();
68
68
69 if (_constructors) {
69 if (_constructors) {
70 _constructors->deleteOverloadsAndThis();
70 _constructors->deleteOverloadsAndThis();
71 }
71 }
72 if (_destructor) {
72 if (_destructor) {
73 _destructor->deleteOverloadsAndThis();
73 _destructor->deleteOverloadsAndThis();
74 }
74 }
75 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
76 info->deleteOverloadsAndThis();
76 info->deleteOverloadsAndThis();
77 }
77 }
78 }
78 }
79
79
80 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
81 {
81 {
82 // _wrappedClassName is already set earlier in the class setup
82 // _wrappedClassName is already set earlier in the class setup
83 _isQObject = true;
83 _isQObject = true;
84 _meta = meta;
84 _meta = meta;
85 }
85 }
86
86
87 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
88 {
88 {
89 _isQObject = false;
89 _isQObject = false;
90 _wrappedClassName = classname;
90 _wrappedClassName = classname;
91 _metaTypeId = QMetaType::type(classname);
91 _metaTypeId = QMetaType::type(classname);
92 }
92 }
93
93
94 void PythonQtClassInfo::clearCachedMembers()
94 void PythonQtClassInfo::clearCachedMembers()
95 {
95 {
96 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
97 while (i.hasNext()) {
97 while (i.hasNext()) {
98 PythonQtMemberInfo member = i.next().value();
98 PythonQtMemberInfo member = i.next().value();
99 if (member._type== PythonQtMemberInfo::Slot) {
99 if (member._type== PythonQtMemberInfo::Slot) {
100 PythonQtSlotInfo* info = member._slot;
100 PythonQtSlotInfo* info = member._slot;
101 while (info) {
101 while (info) {
102 PythonQtSlotInfo* next = info->nextInfo();
102 PythonQtSlotInfo* next = info->nextInfo();
103 delete info;
103 delete info;
104 info = next;
104 info = next;
105 }
105 }
106 }
106 }
107 }
107 }
108 }
108 }
109
109
110 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
111 {
111 {
112 const char* sigEnd = sigStart;
112 const char* sigEnd = sigStart;
113 char c;
113 char c;
114 do {
114 do {
115 c = *sigEnd++;
115 c = *sigEnd++;
116 } while (c!=someChar && c!=0);
116 } while (c!=someChar && c!=0);
117 return sigEnd-sigStart-1;
117 return sigEnd-sigStart-1;
118 }
118 }
119
119
120 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
121 {
121 {
122 if (!_meta) return false;
122 if (!_meta) return false;
123
123
124 bool found = false;
124 bool found = false;
125 bool nameMapped = false;
125 bool nameMapped = false;
126 const char* attributeName = memberName;
126 const char* attributeName = memberName;
127 // look for properties
127 // look for properties
128 int i = _meta->indexOfProperty(attributeName);
128 int i = _meta->indexOfProperty(attributeName);
129 if (i==-1) {
129 if (i==-1) {
130 // try to map name to objectName
130 // try to map name to objectName
131 if (qstrcmp(attributeName, "name")==0) {
131 if (qstrcmp(attributeName, "name")==0) {
132 attributeName = "objectName";
132 attributeName = "objectName";
133 nameMapped = true;
133 nameMapped = true;
134 i = _meta->indexOfProperty(attributeName);
134 i = _meta->indexOfProperty(attributeName);
135 }
135 }
136 }
136 }
137 if (i!=-1) {
137 if (i!=-1) {
138 PythonQtMemberInfo newInfo(_meta->property(i));
138 PythonQtMemberInfo newInfo(_meta->property(i));
139 _cachedMembers.insert(attributeName, newInfo);
139 _cachedMembers.insert(attributeName, newInfo);
140 if (nameMapped) {
140 if (nameMapped) {
141 _cachedMembers.insert(memberName, newInfo);
141 _cachedMembers.insert(memberName, newInfo);
142 }
142 }
143 #ifdef PYTHONQT_DEBUG
143 #ifdef PYTHONQT_DEBUG
144 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
144 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
145 #endif
145 #endif
146 found = true;
146 found = true;
147 }
147 }
148 return found;
148 return found;
149 }
149 }
150
150
151 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
151 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
152 {
152 {
153 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
153 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
154 foreach(const ParentClassInfo& info, _parentClasses) {
154 foreach(const ParentClassInfo& info, _parentClasses) {
155 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
155 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
156 }
156 }
157 return inputInfo;
157 return inputInfo;
158 }
158 }
159
159
160 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
160 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
161 QObject* decoratorProvider = decorator();
161 QObject* decoratorProvider = decorator();
162 int memberNameLen = strlen(memberName);
162 int memberNameLen = static_cast<int>(strlen(memberName));
163 if (decoratorProvider) {
163 if (decoratorProvider) {
164 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
164 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
165 const QMetaObject* meta = decoratorProvider->metaObject();
165 const QMetaObject* meta = decoratorProvider->metaObject();
166 int numMethods = meta->methodCount();
166 int numMethods = meta->methodCount();
167 int startFrom = QObject::staticMetaObject.methodCount();
167 int startFrom = QObject::staticMetaObject.methodCount();
168 for (int i = startFrom; i < numMethods; i++) {
168 for (int i = startFrom; i < numMethods; i++) {
169 QMetaMethod m = meta->method(i);
169 QMetaMethod m = meta->method(i);
170 if ((m.methodType() == QMetaMethod::Method ||
170 if ((m.methodType() == QMetaMethod::Method ||
171 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
171 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
172
172
173 const char* sigStart = m.signature();
173 const char* sigStart = m.signature();
174 bool isClassDeco = false;
174 bool isClassDeco = false;
175 if (qstrncmp(sigStart, "static_", 7)==0) {
175 if (qstrncmp(sigStart, "static_", 7)==0) {
176 // skip the static_classname_ part of the string
176 // skip the static_classname_ part of the string
177 sigStart += 7 + 1 + strlen(className());
177 sigStart += 7 + 1 + strlen(className());
178 isClassDeco = true;
178 isClassDeco = true;
179 } else if (qstrncmp(sigStart, "new_", 4)==0) {
179 } else if (qstrncmp(sigStart, "new_", 4)==0) {
180 isClassDeco = true;
180 isClassDeco = true;
181 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
181 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
182 isClassDeco = true;
182 isClassDeco = true;
183 }
183 }
184 // find the first '('
184 // find the first '('
185 int offset = findCharOffset(sigStart, '(');
185 int offset = findCharOffset(sigStart, '(');
186
186
187 // XXX no checking is currently done if the slots have correct first argument or not...
187 // XXX no checking is currently done if the slots have correct first argument or not...
188
188
189 // check if same length and same name
189 // check if same length and same name
190 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
190 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
191 found = true;
191 found = true;
192 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
192 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
193 info->setUpcastingOffset(upcastingOffset);
193 info->setUpcastingOffset(upcastingOffset);
194 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
194 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
195 if (tail) {
195 if (tail) {
196 tail->setNextInfo(info);
196 tail->setNextInfo(info);
197 } else {
197 } else {
198 PythonQtMemberInfo newInfo(info);
198 PythonQtMemberInfo newInfo(info);
199 memberCache.insert(memberName, newInfo);
199 memberCache.insert(memberName, newInfo);
200 }
200 }
201 tail = info;
201 tail = info;
202 }
202 }
203 }
203 }
204 }
204 }
205 }
205 }
206
206
207 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
207 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
208
208
209 return tail;
209 return tail;
210 }
210 }
211
211
212 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
212 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
213 {
213 {
214 bool found = false;
214 bool found = false;
215 int memberNameLen = strlen(memberName);
215 int memberNameLen = static_cast<int>(strlen(memberName));
216 PythonQtSlotInfo* tail = NULL;
216 PythonQtSlotInfo* tail = NULL;
217 if (_meta) {
217 if (_meta) {
218 int numMethods = _meta->methodCount();
218 int numMethods = _meta->methodCount();
219 for (int i = 0; i < numMethods; i++) {
219 for (int i = 0; i < numMethods; i++) {
220 QMetaMethod m = _meta->method(i);
220 QMetaMethod m = _meta->method(i);
221 if (((m.methodType() == QMetaMethod::Method ||
221 if (((m.methodType() == QMetaMethod::Method ||
222 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
222 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
223 || m.methodType()==QMetaMethod::Signal) {
223 || m.methodType()==QMetaMethod::Signal) {
224
224
225 const char* sigStart = m.signature();
225 const char* sigStart = m.signature();
226 // find the first '('
226 // find the first '('
227 int offset = findCharOffset(sigStart, '(');
227 int offset = findCharOffset(sigStart, '(');
228
228
229 // check if same length and same name
229 // check if same length and same name
230 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
230 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
231 found = true;
231 found = true;
232 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
232 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
233 if (tail) {
233 if (tail) {
234 tail->setNextInfo(info);
234 tail->setNextInfo(info);
235 } else {
235 } else {
236 PythonQtMemberInfo newInfo(info);
236 PythonQtMemberInfo newInfo(info);
237 _cachedMembers.insert(memberName, newInfo);
237 _cachedMembers.insert(memberName, newInfo);
238 }
238 }
239 tail = info;
239 tail = info;
240 }
240 }
241 }
241 }
242 }
242 }
243 }
243 }
244
244
245 // look for dynamic decorators in this class and in derived classes
245 // look for dynamic decorators in this class and in derived classes
246 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
246 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
247
247
248 return found;
248 return found;
249 }
249 }
250
250
251 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
251 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
252 {
252 {
253 bool found = false;
253 bool found = false;
254 // look for enum values
254 // look for enum values
255 int enumCount = meta->enumeratorCount();
255 int enumCount = meta->enumeratorCount();
256 for (int i=0;i<enumCount; i++) {
256 for (int i=0;i<enumCount; i++) {
257 QMetaEnum e = meta->enumerator(i);
257 QMetaEnum e = meta->enumerator(i);
258 // we do not want flags, they will cause our values to appear two times
258 // we do not want flags, they will cause our values to appear two times
259 if (e.isFlag()) continue;
259 if (e.isFlag()) continue;
260
260
261 for (int j=0; j < e.keyCount(); j++) {
261 for (int j=0; j < e.keyCount(); j++) {
262 if (qstrcmp(e.key(j), memberName)==0) {
262 if (qstrcmp(e.key(j), memberName)==0) {
263 PyObject* enumType = findEnumWrapper(e.name());
263 PyObject* enumType = findEnumWrapper(e.name());
264 if (enumType) {
264 if (enumType) {
265 PythonQtObjectPtr enumValuePtr;
265 PythonQtObjectPtr enumValuePtr;
266 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
266 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
267 PythonQtMemberInfo newInfo(enumValuePtr);
267 PythonQtMemberInfo newInfo(enumValuePtr);
268 _cachedMembers.insert(memberName, newInfo);
268 _cachedMembers.insert(memberName, newInfo);
269 #ifdef PYTHONQT_DEBUG
269 #ifdef PYTHONQT_DEBUG
270 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
270 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
271 #endif
271 #endif
272 found = true;
272 found = true;
273 break;
273 break;
274 } else {
274 } else {
275 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
275 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
276 }
276 }
277 }
277 }
278 }
278 }
279 }
279 }
280 return found;
280 return found;
281 }
281 }
282
282
283 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
283 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
284 {
284 {
285 PythonQtMemberInfo info = _cachedMembers.value(memberName);
285 PythonQtMemberInfo info = _cachedMembers.value(memberName);
286 if (info._type != PythonQtMemberInfo::Invalid) {
286 if (info._type != PythonQtMemberInfo::Invalid) {
287 return info;
287 return info;
288 } else {
288 } else {
289 bool found = false;
289 bool found = false;
290
290
291 found = lookForPropertyAndCache(memberName);
291 found = lookForPropertyAndCache(memberName);
292 if (!found) {
292 if (!found) {
293 found = lookForMethodAndCache(memberName);
293 found = lookForMethodAndCache(memberName);
294 }
294 }
295 if (!found) {
295 if (!found) {
296 if (_meta) {
296 if (_meta) {
297 // check enums in our meta object directly
297 // check enums in our meta object directly
298 found = lookForEnumAndCache(_meta, memberName);
298 found = lookForEnumAndCache(_meta, memberName);
299 }
299 }
300 if (!found) {
300 if (!found) {
301 // check enums in the class hierachy of CPP classes
301 // check enums in the class hierachy of CPP classes
302 // look for dynamic decorators in this class and in derived classes
302 // look for dynamic decorators in this class and in derived classes
303 QList<QObject*> decoObjects;
303 QList<QObject*> decoObjects;
304 recursiveCollectDecoratorObjects(decoObjects);
304 recursiveCollectDecoratorObjects(decoObjects);
305 foreach(QObject* deco, decoObjects) {
305 foreach(QObject* deco, decoObjects) {
306 // call on ourself for caching, but with different metaObject():
306 // call on ourself for caching, but with different metaObject():
307 found = lookForEnumAndCache(deco->metaObject(), memberName);
307 found = lookForEnumAndCache(deco->metaObject(), memberName);
308 if (found) {
308 if (found) {
309 break;
309 break;
310 }
310 }
311 }
311 }
312 }
312 }
313 }
313 }
314 if (!found) {
314 if (!found) {
315 // maybe it is an enum wrapper?
315 // maybe it is an enum wrapper?
316 PyObject* p = findEnumWrapper(memberName);
316 PyObject* p = findEnumWrapper(memberName);
317 if (p) {
317 if (p) {
318 info._type = PythonQtMemberInfo::EnumWrapper;
318 info._type = PythonQtMemberInfo::EnumWrapper;
319 info._enumWrapper = p;
319 info._enumWrapper = p;
320 _cachedMembers.insert(memberName, info);
320 _cachedMembers.insert(memberName, info);
321 found = true;
321 found = true;
322 }
322 }
323 }
323 }
324 if (!found) {
324 if (!found) {
325 // since python keywords can not be looked up, we check if the name contains a single trailing _
325 // since python keywords can not be looked up, we check if the name contains a single trailing _
326 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
326 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
327 QByteArray mbrName(memberName);
327 QByteArray mbrName(memberName);
328 if ((mbrName.length()>2) &&
328 if ((mbrName.length()>2) &&
329 (mbrName.at(mbrName.length()-1) == '_') &&
329 (mbrName.at(mbrName.length()-1) == '_') &&
330 (mbrName.at(mbrName.length()-2) != '_')) {
330 (mbrName.at(mbrName.length()-2) != '_')) {
331 mbrName = mbrName.mid(0,mbrName.length()-1);
331 mbrName = mbrName.mid(0,mbrName.length()-1);
332 found = lookForMethodAndCache(mbrName.constData());
332 found = lookForMethodAndCache(mbrName.constData());
333 if (found) {
333 if (found) {
334 return _cachedMembers.value(mbrName);
334 return _cachedMembers.value(mbrName);
335 }
335 }
336 }
336 }
337 }
337 }
338 if (!found) {
338 if (!found) {
339 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
339 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
340 info._type = PythonQtMemberInfo::NotFound;
340 info._type = PythonQtMemberInfo::NotFound;
341 _cachedMembers.insert(memberName, info);
341 _cachedMembers.insert(memberName, info);
342 }
342 }
343 }
343 }
344
344
345 return _cachedMembers.value(memberName);
345 return _cachedMembers.value(memberName);
346 }
346 }
347
347
348 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
348 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
349 QObject* deco = decorator();
349 QObject* deco = decorator();
350 if (deco) {
350 if (deco) {
351 decoratorObjects.append(deco);
351 decoratorObjects.append(deco);
352 }
352 }
353 foreach(const ParentClassInfo& info, _parentClasses) {
353 foreach(const ParentClassInfo& info, _parentClasses) {
354 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
354 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
355 }
355 }
356 }
356 }
357
357
358 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
358 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
359 classInfoObjects.append(this);
359 classInfoObjects.append(this);
360 foreach(const ParentClassInfo& info, _parentClasses) {
360 foreach(const ParentClassInfo& info, _parentClasses) {
361 info._parent->recursiveCollectClassInfos(classInfoObjects);
361 info._parent->recursiveCollectClassInfos(classInfoObjects);
362 }
362 }
363 }
363 }
364
364
365 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
365 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
366 {
366 {
367 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
367 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
368 while (it.hasNext()) {
368 while (it.hasNext()) {
369
369
370 PythonQtSlotInfo* infoOrig = it.next();
370 PythonQtSlotInfo* infoOrig = it.next();
371
371
372 const char* sigStart = infoOrig->metaMethod()->signature();
372 const char* sigStart = infoOrig->metaMethod()->signature();
373 if (qstrncmp("static_", sigStart, 7)==0) {
373 if (qstrncmp("static_", sigStart, 7)==0) {
374 sigStart += 7;
374 sigStart += 7;
375 sigStart += findCharOffset(sigStart, '_')+1;
375 sigStart += findCharOffset(sigStart, '_')+1;
376 }
376 }
377 int offset = findCharOffset(sigStart, '(');
377 int offset = findCharOffset(sigStart, '(');
378 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
378 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
379 //make a copy, otherwise we will have trouble on overloads!
379 //make a copy, otherwise we will have trouble on overloads!
380 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
380 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
381 info->setUpcastingOffset(upcastingOffset);
381 info->setUpcastingOffset(upcastingOffset);
382 found = true;
382 found = true;
383 if (tail) {
383 if (tail) {
384 tail->setNextInfo(info);
384 tail->setNextInfo(info);
385 } else {
385 } else {
386 PythonQtMemberInfo newInfo(info);
386 PythonQtMemberInfo newInfo(info);
387 memberCache.insert(memberName, newInfo);
387 memberCache.insert(memberName, newInfo);
388 }
388 }
389 tail = info;
389 tail = info;
390 }
390 }
391 }
391 }
392 return tail;
392 return tail;
393 }
393 }
394
394
395 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
395 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
396 QObject* decoratorProvider = decorator();
396 QObject* decoratorProvider = decorator();
397 if (decoratorProvider) {
397 if (decoratorProvider) {
398 const QMetaObject* meta = decoratorProvider->metaObject();
398 const QMetaObject* meta = decoratorProvider->metaObject();
399 int numMethods = meta->methodCount();
399 int numMethods = meta->methodCount();
400 int startFrom = QObject::staticMetaObject.methodCount();
400 int startFrom = QObject::staticMetaObject.methodCount();
401 for (int i = startFrom; i < numMethods; i++) {
401 for (int i = startFrom; i < numMethods; i++) {
402 QMetaMethod m = meta->method(i);
402 QMetaMethod m = meta->method(i);
403 if ((m.methodType() == QMetaMethod::Method ||
403 if ((m.methodType() == QMetaMethod::Method ||
404 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
404 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
405
405
406 const char* sigStart = m.signature();
406 const char* sigStart = m.signature();
407 bool isClassDeco = false;
407 bool isClassDeco = false;
408 if (qstrncmp(sigStart, "static_", 7)==0) {
408 if (qstrncmp(sigStart, "static_", 7)==0) {
409 // skip the static_classname_ part of the string
409 // skip the static_classname_ part of the string
410 sigStart += 7 + 1 + strlen(className());
410 sigStart += 7 + 1 + strlen(className());
411 isClassDeco = true;
411 isClassDeco = true;
412 } else if (qstrncmp(sigStart, "new_", 4)==0) {
412 } else if (qstrncmp(sigStart, "new_", 4)==0) {
413 continue;
413 continue;
414 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
414 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
415 continue;
415 continue;
416 } else if (qstrncmp(sigStart, "py_", 3)==0) {
416 } else if (qstrncmp(sigStart, "py_", 3)==0) {
417 // hide everything that starts with py_
417 // hide everything that starts with py_
418 continue;
418 continue;
419 }
419 }
420 // find the first '('
420 // find the first '('
421 int offset = findCharOffset(sigStart, '(');
421 int offset = findCharOffset(sigStart, '(');
422
422
423 // XXX no checking is currently done if the slots have correct first argument or not...
423 // XXX no checking is currently done if the slots have correct first argument or not...
424 if (!metaOnly || isClassDeco) {
424 if (!metaOnly || isClassDeco) {
425 list << QString::fromLatin1(sigStart, offset);
425 list << QString::fromLatin1(sigStart, offset);
426 }
426 }
427 }
427 }
428 }
428 }
429 }
429 }
430
430
431 // look for global decorator slots
431 // look for global decorator slots
432 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
432 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
433 while (it.hasNext()) {
433 while (it.hasNext()) {
434 PythonQtSlotInfo* slot = it.next();
434 PythonQtSlotInfo* slot = it.next();
435 if (metaOnly) {
435 if (metaOnly) {
436 if (slot->isClassDecorator()) {
436 if (slot->isClassDecorator()) {
437 QByteArray first = slot->slotName();
437 QByteArray first = slot->slotName();
438 if (first.startsWith("static_")) {
438 if (first.startsWith("static_")) {
439 int idx = first.indexOf('_');
439 int idx = first.indexOf('_');
440 idx = first.indexOf('_', idx+1);
440 idx = first.indexOf('_', idx+1);
441 first = first.mid(idx+1);
441 first = first.mid(idx+1);
442 }
442 }
443 list << first;
443 list << first;
444 }
444 }
445 } else {
445 } else {
446 list << slot->slotName();
446 list << slot->slotName();
447 }
447 }
448 }
448 }
449 }
449 }
450
450
451 QStringList PythonQtClassInfo::propertyList()
451 QStringList PythonQtClassInfo::propertyList()
452 {
452 {
453 QStringList l;
453 QStringList l;
454 if (_isQObject && _meta) {
454 if (_isQObject && _meta) {
455 int i;
455 int i;
456 int numProperties = _meta->propertyCount();
456 int numProperties = _meta->propertyCount();
457 for (i = 0; i < numProperties; i++) {
457 for (i = 0; i < numProperties; i++) {
458 QMetaProperty p = _meta->property(i);
458 QMetaProperty p = _meta->property(i);
459 l << QString(p.name());
459 l << QString(p.name());
460 }
460 }
461 }
461 }
462 return l;
462 return l;
463 }
463 }
464
464
465 QStringList PythonQtClassInfo::memberList(bool metaOnly)
465 QStringList PythonQtClassInfo::memberList(bool metaOnly)
466 {
466 {
467 decorator();
467 decorator();
468
468
469 QStringList l;
469 QStringList l;
470 QString h;
470 QString h;
471 if (_isQObject && _meta && !metaOnly) {
471 if (_isQObject && _meta && !metaOnly) {
472 l = propertyList();
472 l = propertyList();
473 }
473 }
474
474
475 // normal slots of QObject (or wrapper QObject)
475 // normal slots of QObject (or wrapper QObject)
476 if (!metaOnly && _meta) {
476 if (!metaOnly && _meta) {
477 int numMethods = _meta->methodCount();
477 int numMethods = _meta->methodCount();
478 bool skipQObj = !_isQObject;
478 bool skipQObj = !_isQObject;
479 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
479 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
480 QMetaMethod m = _meta->method(i);
480 QMetaMethod m = _meta->method(i);
481 if (((m.methodType() == QMetaMethod::Method ||
481 if (((m.methodType() == QMetaMethod::Method ||
482 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
482 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
483 || m.methodType()==QMetaMethod::Signal) {
483 || m.methodType()==QMetaMethod::Signal) {
484 QByteArray signa(m.signature());
484 QByteArray signa(m.signature());
485 signa = signa.left(signa.indexOf('('));
485 signa = signa.left(signa.indexOf('('));
486 l << signa;
486 l << signa;
487 }
487 }
488 }
488 }
489 }
489 }
490
490
491 {
491 {
492 // look for dynamic decorators in this class and in derived classes
492 // look for dynamic decorators in this class and in derived classes
493 QList<PythonQtClassInfo*> infos;
493 QList<PythonQtClassInfo*> infos;
494 recursiveCollectClassInfos(infos);
494 recursiveCollectClassInfos(infos);
495 foreach(PythonQtClassInfo* info, infos) {
495 foreach(PythonQtClassInfo* info, infos) {
496 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
496 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
497 }
497 }
498 }
498 }
499
499
500 // List enumerator keys...
500 // List enumerator keys...
501 QList<const QMetaObject*> enumMetaObjects;
501 QList<const QMetaObject*> enumMetaObjects;
502 if (_meta) {
502 if (_meta) {
503 enumMetaObjects << _meta;
503 enumMetaObjects << _meta;
504 }
504 }
505 // check enums in the class hierachy of CPP classes
505 // check enums in the class hierachy of CPP classes
506 QList<QObject*> decoObjects;
506 QList<QObject*> decoObjects;
507 recursiveCollectDecoratorObjects(decoObjects);
507 recursiveCollectDecoratorObjects(decoObjects);
508 foreach(QObject* deco, decoObjects) {
508 foreach(QObject* deco, decoObjects) {
509 enumMetaObjects << deco->metaObject();
509 enumMetaObjects << deco->metaObject();
510 }
510 }
511
511
512 foreach(const QMetaObject* meta, enumMetaObjects) {
512 foreach(const QMetaObject* meta, enumMetaObjects) {
513 for (int i = 0; i<meta->enumeratorCount(); i++) {
513 for (int i = 0; i<meta->enumeratorCount(); i++) {
514 QMetaEnum e = meta->enumerator(i);
514 QMetaEnum e = meta->enumerator(i);
515 l << e.name();
515 l << e.name();
516 // we do not want flags, they will cause our values to appear two times
516 // we do not want flags, they will cause our values to appear two times
517 if (e.isFlag()) continue;
517 if (e.isFlag()) continue;
518
518
519 for (int j=0; j < e.keyCount(); j++) {
519 for (int j=0; j < e.keyCount(); j++) {
520 l << QString(e.key(j));
520 l << QString(e.key(j));
521 }
521 }
522 }
522 }
523 }
523 }
524
524
525 return QSet<QString>::fromList(l).toList();
525 return QSet<QString>::fromList(l).toList();
526 }
526 }
527
527
528 const char* PythonQtClassInfo::className()
528 const char* PythonQtClassInfo::className()
529 {
529 {
530 return _wrappedClassName.constData();
530 return _wrappedClassName.constData();
531 }
531 }
532
532
533 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
533 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
534 {
534 {
535 if (ptr==NULL) {
535 if (ptr==NULL) {
536 return NULL;
536 return NULL;
537 }
537 }
538 if (_wrappedClassName == classname) {
538 if (_wrappedClassName == classname) {
539 return ptr;
539 return ptr;
540 }
540 }
541 foreach(const ParentClassInfo& info, _parentClasses) {
541 foreach(const ParentClassInfo& info, _parentClasses) {
542 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
542 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
543 if (result) {
543 if (result) {
544 return result;
544 return result;
545 }
545 }
546 }
546 }
547 return NULL;
547 return NULL;
548 }
548 }
549
549
550 bool PythonQtClassInfo::inherits(const char* name)
550 bool PythonQtClassInfo::inherits(const char* name)
551 {
551 {
552 if (_wrappedClassName == name) {
552 if (_wrappedClassName == name) {
553 return true;
553 return true;
554 }
554 }
555 foreach(const ParentClassInfo& info, _parentClasses) {
555 foreach(const ParentClassInfo& info, _parentClasses) {
556 if (info._parent->inherits(name)) {
556 if (info._parent->inherits(name)) {
557 return true;
557 return true;
558 }
558 }
559 }
559 }
560 return false;
560 return false;
561 }
561 }
562
562
563 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
563 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
564 {
564 {
565 if (classInfo == this) {
565 if (classInfo == this) {
566 return true;
566 return true;
567 }
567 }
568 foreach(const ParentClassInfo& info, _parentClasses) {
568 foreach(const ParentClassInfo& info, _parentClasses) {
569 if (info._parent->inherits(classInfo)) {
569 if (info._parent->inherits(classInfo)) {
570 return true;
570 return true;
571 }
571 }
572 }
572 }
573 return false;
573 return false;
574 }
574 }
575
575
576 QString PythonQtClassInfo::help()
576 QString PythonQtClassInfo::help()
577 {
577 {
578 decorator();
578 decorator();
579 QString h;
579 QString h;
580 h += QString("--- ") + QString(className()) + QString(" ---\n");
580 h += QString("--- ") + QString(className()) + QString(" ---\n");
581
581
582 if (_isQObject) {
582 if (_isQObject) {
583 h += "Properties:\n";
583 h += "Properties:\n";
584
584
585 int i;
585 int i;
586 int numProperties = _meta->propertyCount();
586 int numProperties = _meta->propertyCount();
587 for (i = 0; i < numProperties; i++) {
587 for (i = 0; i < numProperties; i++) {
588 QMetaProperty p = _meta->property(i);
588 QMetaProperty p = _meta->property(i);
589 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
589 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
590 }
590 }
591 }
591 }
592
592
593 if (constructors()) {
593 if (constructors()) {
594 h += "Constructors:\n";
594 h += "Constructors:\n";
595 PythonQtSlotInfo* constr = constructors();
595 PythonQtSlotInfo* constr = constructors();
596 while (constr) {
596 while (constr) {
597 h += constr->fullSignature() + "\n";
597 h += constr->fullSignature() + "\n";
598 constr = constr->nextInfo();
598 constr = constr->nextInfo();
599 }
599 }
600 }
600 }
601
601
602 h += "Slots:\n";
602 h += "Slots:\n";
603 h += "QString help()\n";
603 h += "QString help()\n";
604 h += "QString className()\n";
604 h += "QString className()\n";
605
605
606 if (_meta) {
606 if (_meta) {
607 int numMethods = _meta->methodCount();
607 int numMethods = _meta->methodCount();
608 for (int i = 0; i < numMethods; i++) {
608 for (int i = 0; i < numMethods; i++) {
609 QMetaMethod m = _meta->method(i);
609 QMetaMethod m = _meta->method(i);
610 if ((m.methodType() == QMetaMethod::Method ||
610 if ((m.methodType() == QMetaMethod::Method ||
611 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
611 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
612 PythonQtSlotInfo slot(this, m, i);
612 PythonQtSlotInfo slot(this, m, i);
613 h += slot.fullSignature()+ "\n";
613 h += slot.fullSignature()+ "\n";
614 }
614 }
615 }
615 }
616 }
616 }
617
617
618 // TODO xxx : decorators and enums from decorator() are missing...
618 // TODO xxx : decorators and enums from decorator() are missing...
619 // maybe we can reuse memberlist()?
619 // maybe we can reuse memberlist()?
620
620
621 if (_meta && _meta->enumeratorCount()) {
621 if (_meta && _meta->enumeratorCount()) {
622 h += "Enums:\n";
622 h += "Enums:\n";
623 for (int i = 0; i<_meta->enumeratorCount(); i++) {
623 for (int i = 0; i<_meta->enumeratorCount(); i++) {
624 QMetaEnum e = _meta->enumerator(i);
624 QMetaEnum e = _meta->enumerator(i);
625 h += QString(e.name()) + " {";
625 h += QString(e.name()) + " {";
626 for (int j=0; j < e.keyCount(); j++) {
626 for (int j=0; j < e.keyCount(); j++) {
627 if (j) { h+= ", "; }
627 if (j) { h+= ", "; }
628 h += e.key(j);
628 h += e.key(j);
629 }
629 }
630 h += " }\n";
630 h += " }\n";
631 }
631 }
632 }
632 }
633
633
634 if (_isQObject && _meta) {
634 if (_isQObject && _meta) {
635 int numMethods = _meta->methodCount();
635 int numMethods = _meta->methodCount();
636 if (numMethods>0) {
636 if (numMethods>0) {
637 h += "Signals:\n";
637 h += "Signals:\n";
638 for (int i = 0; i < numMethods; i++) {
638 for (int i = 0; i < numMethods; i++) {
639 QMetaMethod m = _meta->method(i);
639 QMetaMethod m = _meta->method(i);
640 if (m.methodType() == QMetaMethod::Signal) {
640 if (m.methodType() == QMetaMethod::Signal) {
641 h += QString(m.signature()) + "\n";
641 h += QString(m.signature()) + "\n";
642 }
642 }
643 }
643 }
644 }
644 }
645 }
645 }
646 return h;
646 return h;
647 }
647 }
648
648
649 PythonQtSlotInfo* PythonQtClassInfo::constructors()
649 PythonQtSlotInfo* PythonQtClassInfo::constructors()
650 {
650 {
651 if (!_constructors) {
651 if (!_constructors) {
652 // force creation of lazy decorator, which will register the decorators
652 // force creation of lazy decorator, which will register the decorators
653 decorator();
653 decorator();
654 }
654 }
655 return _constructors;
655 return _constructors;
656 }
656 }
657
657
658 PythonQtSlotInfo* PythonQtClassInfo::destructor()
658 PythonQtSlotInfo* PythonQtClassInfo::destructor()
659 {
659 {
660 if (!_destructor) {
660 if (!_destructor) {
661 // force creation of lazy decorator, which will register the decorators
661 // force creation of lazy decorator, which will register the decorators
662 decorator();
662 decorator();
663 }
663 }
664 return _destructor;
664 return _destructor;
665 }
665 }
666
666
667 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
667 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
668 {
668 {
669 PythonQtSlotInfo* prev = constructors();
669 PythonQtSlotInfo* prev = constructors();
670 if (prev) {
670 if (prev) {
671 info->setNextInfo(prev->nextInfo());
671 info->setNextInfo(prev->nextInfo());
672 prev->setNextInfo(info);
672 prev->setNextInfo(info);
673 } else {
673 } else {
674 _constructors = info;
674 _constructors = info;
675 }
675 }
676 }
676 }
677
677
678 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
678 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
679 {
679 {
680 _decoratorSlots.append(info);
680 _decoratorSlots.append(info);
681 }
681 }
682
682
683 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
683 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
684 {
684 {
685 if (_destructor) {
685 if (_destructor) {
686 _destructor->deleteOverloadsAndThis();
686 _destructor->deleteOverloadsAndThis();
687 }
687 }
688 _destructor = info;
688 _destructor = info;
689 }
689 }
690
690
691 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
691 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
692 {
692 {
693 _meta = meta;
693 _meta = meta;
694 clearCachedMembers();
694 clearCachedMembers();
695 }
695 }
696
696
697 QObject* PythonQtClassInfo::decorator()
697 QObject* PythonQtClassInfo::decorator()
698 {
698 {
699 if (!_decoratorProvider && _decoratorProviderCB) {
699 if (!_decoratorProvider && _decoratorProviderCB) {
700 _decoratorProvider = (*_decoratorProviderCB)();
700 _decoratorProvider = (*_decoratorProviderCB)();
701 if (_decoratorProvider) {
701 if (_decoratorProvider) {
702 _decoratorProvider->setParent(PythonQt::priv());
702 _decoratorProvider->setParent(PythonQt::priv());
703 // setup enums early, since they might be needed by the constructor decorators:
703 // setup enums early, since they might be needed by the constructor decorators:
704 if (!_enumsCreated) {
704 if (!_enumsCreated) {
705 createEnumWrappers();
705 createEnumWrappers();
706 }
706 }
707 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
707 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
708 }
708 }
709 }
709 }
710 // check if enums need to be created and create them if they are not yet created
710 // check if enums need to be created and create them if they are not yet created
711 if (!_enumsCreated) {
711 if (!_enumsCreated) {
712 createEnumWrappers();
712 createEnumWrappers();
713 }
713 }
714 return _decoratorProvider;
714 return _decoratorProvider;
715 }
715 }
716
716
717 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
717 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
718 {
718 {
719 PythonQtMemberInfo info = member("py_hasOwner");
719 PythonQtMemberInfo info = member("py_hasOwner");
720 if (info._type == PythonQtMemberInfo::Slot) {
720 if (info._type == PythonQtMemberInfo::Slot) {
721 void* obj = object;
721 void* obj = object;
722 bool result = false;
722 bool result = false;
723 void* args[2];
723 void* args[2];
724 args[0] = &result;
724 args[0] = &result;
725 args[1] = &obj;
725 args[1] = &obj;
726 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
726 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
727 return !result;
727 return !result;
728 } else {
728 } else {
729 return false;
729 return false;
730 }
730 }
731 }
731 }
732
732
733 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
733 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, const char** resultClassName)
734 {
734 {
735 if (!_polymorphicHandlers.isEmpty()) {
735 if (!_polymorphicHandlers.isEmpty()) {
736 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
736 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
737 void* resultPtr = (*cb)(ptr, resultClassName);
737 void* resultPtr = (*cb)(ptr, resultClassName);
738 if (resultPtr) {
738 if (resultPtr) {
739 return resultPtr;
739 return resultPtr;
740 }
740 }
741 }
741 }
742 }
742 }
743 foreach(const ParentClassInfo& info, _parentClasses) {
743 foreach(const ParentClassInfo& info, _parentClasses) {
744 if (!info._parent->isQObject()) {
744 if (!info._parent->isQObject()) {
745 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
745 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
746 if (resultPtr) {
746 if (resultPtr) {
747 return resultPtr;
747 return resultPtr;
748 }
748 }
749 }
749 }
750 }
750 }
751 return NULL;
751 return NULL;
752 }
752 }
753
753
754 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
754 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
755 {
755 {
756 char* className;
756 const char* className;
757 // this would do downcasting recursively...
757 // this would do downcasting recursively...
758 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
758 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
759
759
760 // we only do downcasting on the base object, not on the whole inheritance tree...
760 // we only do downcasting on the base object, not on the whole inheritance tree...
761 void* resultPtr = NULL;
761 void* resultPtr = NULL;
762 if (!_polymorphicHandlers.isEmpty()) {
762 if (!_polymorphicHandlers.isEmpty()) {
763 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
763 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
764 resultPtr = (*cb)(ptr, &className);
764 resultPtr = (*cb)(ptr, &className);
765 if (resultPtr) {
765 if (resultPtr) {
766 break;
766 break;
767 }
767 }
768 }
768 }
769 }
769 }
770 if (resultPtr) {
770 if (resultPtr) {
771 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
771 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
772 } else {
772 } else {
773 *resultClassInfo = this;
773 *resultClassInfo = this;
774 resultPtr = ptr;
774 resultPtr = ptr;
775 }
775 }
776 return resultPtr;
776 return resultPtr;
777 }
777 }
778
778
779 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
779 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
780 {
780 {
781 if (isLocalEnum) {
781 if (isLocalEnum) {
782 *isLocalEnum = true;
782 *isLocalEnum = true;
783 }
783 }
784 int scopePos = name.lastIndexOf("::");
784 int scopePos = name.lastIndexOf("::");
785 if (scopePos != -1) {
785 if (scopePos != -1) {
786 if (isLocalEnum) {
786 if (isLocalEnum) {
787 *isLocalEnum = false;
787 *isLocalEnum = false;
788 }
788 }
789 // split into scope and enum name
789 // split into scope and enum name
790 QByteArray enumScope = name.mid(0,scopePos);
790 QByteArray enumScope = name.mid(0,scopePos);
791 QByteArray enumName = name.mid(scopePos+2);
791 QByteArray enumName = name.mid(scopePos+2);
792 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
792 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
793 if (info) {
793 if (info) {
794 return info->findEnumWrapper(enumName);
794 return info->findEnumWrapper(enumName);
795 } else{
795 } else{
796 return NULL;
796 return NULL;
797 }
797 }
798 }
798 }
799 if (localScope) {
799 if (localScope) {
800 return localScope->findEnumWrapper(name);
800 return localScope->findEnumWrapper(name);
801 } else {
801 } else {
802 return NULL;
802 return NULL;
803 }
803 }
804 }
804 }
805
805
806 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
806 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
807 {
807 {
808 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
808 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
809 QMetaEnum e = meta->enumerator(i);
809 QMetaEnum e = meta->enumerator(i);
810 PythonQtObjectPtr p;
810 PythonQtObjectPtr p;
811 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
811 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
812 _enumWrappers.append(p);
812 _enumWrappers.append(p);
813 }
813 }
814 }
814 }
815
815
816 void PythonQtClassInfo::createEnumWrappers()
816 void PythonQtClassInfo::createEnumWrappers()
817 {
817 {
818 if (!_enumsCreated) {
818 if (!_enumsCreated) {
819 _enumsCreated = true;
819 _enumsCreated = true;
820 if (_meta) {
820 if (_meta) {
821 createEnumWrappers(_meta);
821 createEnumWrappers(_meta);
822 }
822 }
823 if (decorator()) {
823 if (decorator()) {
824 createEnumWrappers(decorator()->metaObject());
824 createEnumWrappers(decorator()->metaObject());
825 }
825 }
826 foreach(const ParentClassInfo& info, _parentClasses) {
826 foreach(const ParentClassInfo& info, _parentClasses) {
827 info._parent->createEnumWrappers();
827 info._parent->createEnumWrappers();
828 }
828 }
829 }
829 }
830 }
830 }
831
831
832 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
832 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
833 // force enum creation
833 // force enum creation
834 if (!_enumsCreated) {
834 if (!_enumsCreated) {
835 createEnumWrappers();
835 createEnumWrappers();
836 }
836 }
837 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
837 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
838 const char* className = ((PyTypeObject*)p.object())->tp_name;
838 const char* className = ((PyTypeObject*)p.object())->tp_name;
839 if (qstrcmp(className, name)==0) {
839 if (qstrcmp(className, name)==0) {
840 return p.object();
840 return p.object();
841 }
841 }
842 }
842 }
843 foreach(const ParentClassInfo& info, _parentClasses) {
843 foreach(const ParentClassInfo& info, _parentClasses) {
844 PyObject* p = info._parent->findEnumWrapper(name);
844 PyObject* p = info._parent->findEnumWrapper(name);
845 if (p) return p;
845 if (p) return p;
846 }
846 }
847 return NULL;
847 return NULL;
848 }
848 }
849
849
850 void PythonQtClassInfo::setDecoratorProvider( PythonQtQObjectCreatorFunctionCB* cb )
850 void PythonQtClassInfo::setDecoratorProvider( PythonQtQObjectCreatorFunctionCB* cb )
851 {
851 {
852 _decoratorProviderCB = cb;
852 _decoratorProviderCB = cb;
853 _decoratorProvider = NULL;
853 _decoratorProvider = NULL;
854 _enumsCreated = false;
854 _enumsCreated = false;
855 }
855 }
856
856
857 void PythonQtClassInfo::clearNotFoundCachedMembers()
857 void PythonQtClassInfo::clearNotFoundCachedMembers()
858 {
858 {
859 // remove all not found entries, since a new decorator means new slots,
859 // remove all not found entries, since a new decorator means new slots,
860 // which might have been cached as "NotFound" already.
860 // which might have been cached as "NotFound" already.
861 QMutableHashIterator<QByteArray, PythonQtMemberInfo> it(_cachedMembers);
861 QMutableHashIterator<QByteArray, PythonQtMemberInfo> it(_cachedMembers);
862 while (it.hasNext()) {
862 while (it.hasNext()) {
863 it.next();
863 it.next();
864 if (it.value()._type == PythonQtMemberInfo::NotFound) {
864 if (it.value()._type == PythonQtMemberInfo::NotFound) {
865 it.remove();
865 it.remove();
866 }
866 }
867 }
867 }
868 }
868 }
@@ -1,265 +1,265
1 #ifndef _PYTHONQTCLASSINFO_H
1 #ifndef _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_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 #include <QMetaObject>
36 #include <QMetaObject>
37 #include <QMetaMethod>
37 #include <QMetaMethod>
38 #include <QHash>
38 #include <QHash>
39 #include <QByteArray>
39 #include <QByteArray>
40 #include <QList>
40 #include <QList>
41 #include "PythonQt.h"
41 #include "PythonQt.h"
42
42
43 class PythonQtSlotInfo;
43 class PythonQtSlotInfo;
44
44
45 struct PythonQtMemberInfo {
45 struct PythonQtMemberInfo {
46 enum Type {
46 enum Type {
47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
48 };
48 };
49
49
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
51
51
52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
53 _type = Slot;
53 _type = Slot;
54 _slot = info;
54 _slot = info;
55 _enumValue = NULL;
55 _enumValue = NULL;
56 }
56 }
57
57
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
59 _type = EnumValue;
59 _type = EnumValue;
60 _slot = NULL;
60 _slot = NULL;
61 _enumValue = enumValue;
61 _enumValue = enumValue;
62 _enumWrapper = NULL;
62 _enumWrapper = NULL;
63 }
63 }
64
64
65 PythonQtMemberInfo(const QMetaProperty& prop) {
65 PythonQtMemberInfo(const QMetaProperty& prop) {
66 _type = Property;
66 _type = Property;
67 _slot = NULL;
67 _slot = NULL;
68 _enumValue = NULL;
68 _enumValue = NULL;
69 _property = prop;
69 _property = prop;
70 _enumWrapper = NULL;
70 _enumWrapper = NULL;
71 }
71 }
72
72
73 Type _type;
73 Type _type;
74
74
75 // TODO: this could be a union...
75 // TODO: this could be a union...
76 PythonQtSlotInfo* _slot;
76 PythonQtSlotInfo* _slot;
77 PyObject* _enumWrapper;
77 PyObject* _enumWrapper;
78 PythonQtObjectPtr _enumValue;
78 PythonQtObjectPtr _enumValue;
79 QMetaProperty _property;
79 QMetaProperty _property;
80 };
80 };
81
81
82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
83 /*! for fast lookup of slots when calling the object from Python
83 /*! for fast lookup of slots when calling the object from Python
84 */
84 */
85 class PYTHONQT_EXPORT PythonQtClassInfo {
85 class PYTHONQT_EXPORT PythonQtClassInfo {
86
86
87 public:
87 public:
88 PythonQtClassInfo();
88 PythonQtClassInfo();
89 ~PythonQtClassInfo();
89 ~PythonQtClassInfo();
90
90
91 //! store information about parent classes
91 //! store information about parent classes
92 struct ParentClassInfo {
92 struct ParentClassInfo {
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
94 {};
94 {};
95
95
96 PythonQtClassInfo* _parent;
96 PythonQtClassInfo* _parent;
97 int _upcastingOffset;
97 int _upcastingOffset;
98 };
98 };
99
99
100
100
101 //! setup as a QObject, taking the meta object as meta information about the QObject
101 //! setup as a QObject, taking the meta object as meta information about the QObject
102 void setupQObject(const QMetaObject* meta);
102 void setupQObject(const QMetaObject* meta);
103
103
104 //! setup as a CPP (non-QObject), taking the classname
104 //! setup as a CPP (non-QObject), taking the classname
105 void setupCPPObject(const QByteArray& classname);
105 void setupCPPObject(const QByteArray& classname);
106
106
107 //! set the type capabilities
107 //! set the type capabilities
108 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
108 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
109 //! get the type capabilities
109 //! get the type capabilities
110 int typeSlots() const { return _typeSlots; }
110 int typeSlots() const { return _typeSlots; }
111
111
112 //! get the Python method definition for a given slot name (without return type and signature)
112 //! get the Python method definition for a given slot name (without return type and signature)
113 PythonQtMemberInfo member(const char* member);
113 PythonQtMemberInfo member(const char* member);
114
114
115 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
115 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
116 PythonQtSlotInfo* constructors();
116 PythonQtSlotInfo* constructors();
117
117
118 //! get access to the destructor slot
118 //! get access to the destructor slot
119 PythonQtSlotInfo* destructor();
119 PythonQtSlotInfo* destructor();
120
120
121 //! add a constructor, ownership is passed to classinfo
121 //! add a constructor, ownership is passed to classinfo
122 void addConstructor(PythonQtSlotInfo* info);
122 void addConstructor(PythonQtSlotInfo* info);
123
123
124 //! set a destructor, ownership is passed to classinfo
124 //! set a destructor, ownership is passed to classinfo
125 void setDestructor(PythonQtSlotInfo* info);
125 void setDestructor(PythonQtSlotInfo* info);
126
126
127 //! add a decorator slot, ownership is passed to classinfo
127 //! add a decorator slot, ownership is passed to classinfo
128 void addDecoratorSlot(PythonQtSlotInfo* info);
128 void addDecoratorSlot(PythonQtSlotInfo* info);
129
129
130 //! get the classname (either of the QObject or of the wrapped CPP object)
130 //! get the classname (either of the QObject or of the wrapped CPP object)
131 const char* className();
131 const char* className();
132
132
133 //! returns if the QObject
133 //! returns if the QObject
134 bool isQObject() { return _isQObject; }
134 bool isQObject() { return _isQObject; }
135
135
136 //! returns if the class is a CPP wrapper
136 //! returns if the class is a CPP wrapper
137 bool isCPPWrapper() { return !_isQObject; }
137 bool isCPPWrapper() { return !_isQObject; }
138
138
139 //! get the meta object
139 //! get the meta object
140 const QMetaObject* metaObject() { return _meta; }
140 const QMetaObject* metaObject() { return _meta; }
141
141
142 //! set the meta object, this will reset the caching
142 //! set the meta object, this will reset the caching
143 void setMetaObject(const QMetaObject* meta);
143 void setMetaObject(const QMetaObject* meta);
144
144
145 //! returns if this class inherits from the given classname
145 //! returns if this class inherits from the given classname
146 bool inherits(const char* classname);
146 bool inherits(const char* classname);
147
147
148 //! returns if this class inherits from the given classinfo
148 //! returns if this class inherits from the given classinfo
149 bool inherits(PythonQtClassInfo* info);
149 bool inherits(PythonQtClassInfo* info);
150
150
151 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
151 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
152 //! which might be different to \c ptr due to C++ multiple inheritance
152 //! which might be different to \c ptr due to C++ multiple inheritance
153 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
153 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
154 void* castTo(void* ptr, const char* classname);
154 void* castTo(void* ptr, const char* classname);
155
155
156 //! get help string for the metaobject
156 //! get help string for the metaobject
157 QString help();
157 QString help();
158
158
159 //! get list of all properties (on QObjects only, otherwise the list is empty)
159 //! get list of all properties (on QObjects only, otherwise the list is empty)
160 QStringList propertyList();
160 QStringList propertyList();
161
161
162 //! get list of all members
162 //! get list of all members
163 QStringList memberList(bool metaOnly = false);
163 QStringList memberList(bool metaOnly = false);
164
164
165 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
165 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
166 int metaTypeId() { return _metaTypeId; }
166 int metaTypeId() { return _metaTypeId; }
167
167
168 //! set an additional decorator provider that offers additional decorator slots for this class
168 //! set an additional decorator provider that offers additional decorator slots for this class
169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb);
169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb);
170
170
171 //! get the decorator qobject instance
171 //! get the decorator qobject instance
172 QObject* decorator();
172 QObject* decorator();
173
173
174 //! add the parent class info of a CPP object
174 //! add the parent class info of a CPP object
175 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
175 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
176
176
177 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
177 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
178 bool hasOwnerMethodButNoOwner(void* object);
178 bool hasOwnerMethodButNoOwner(void* object);
179
179
180 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
180 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
181 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
181 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
182
182
183 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
183 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
184 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
184 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
185
185
186 //! set the shell set instance wrapper cb
186 //! set the shell set instance wrapper cb
187 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
187 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
188 _shellSetInstanceWrapperCB = cb;
188 _shellSetInstanceWrapperCB = cb;
189 }
189 }
190
190
191 //! get the shell set instance wrapper cb
191 //! get the shell set instance wrapper cb
192 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
192 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
193 return _shellSetInstanceWrapperCB;
193 return _shellSetInstanceWrapperCB;
194 }
194 }
195
195
196 //! add a handler for polymorphic downcasting
196 //! add a handler for polymorphic downcasting
197 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
197 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
198
198
199 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
199 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
200 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
200 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
201
201
202 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
202 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
203 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
203 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
204
204
205 //! clear all members that where cached as "NotFound"
205 //! clear all members that where cached as "NotFound"
206 void clearNotFoundCachedMembers();
206 void clearNotFoundCachedMembers();
207
207
208 private:
208 private:
209 void createEnumWrappers();
209 void createEnumWrappers();
210 void createEnumWrappers(const QMetaObject* meta);
210 void createEnumWrappers(const QMetaObject* meta);
211 PyObject* findEnumWrapper(const char* name);
211 PyObject* findEnumWrapper(const char* name);
212
212
213 //! clear all cached members
213 //! clear all cached members
214 void clearCachedMembers();
214 void clearCachedMembers();
215
215
216 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
216 void* recursiveCastDownIfPossible(void* ptr, const char** resultClassName);
217
217
218 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
218 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
219 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
219 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
220 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
220 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
221
221
222 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
222 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
223 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
223 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
224
224
225 bool lookForPropertyAndCache(const char* memberName);
225 bool lookForPropertyAndCache(const char* memberName);
226 bool lookForMethodAndCache(const char* memberName);
226 bool lookForMethodAndCache(const char* memberName);
227 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
227 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
228
228
229 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
229 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
230 int findCharOffset(const char* sigStart, char someChar);
230 int findCharOffset(const char* sigStart, char someChar);
231
231
232 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
232 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
233
233
234 PythonQtSlotInfo* _constructors;
234 PythonQtSlotInfo* _constructors;
235 PythonQtSlotInfo* _destructor;
235 PythonQtSlotInfo* _destructor;
236 QList<PythonQtSlotInfo*> _decoratorSlots;
236 QList<PythonQtSlotInfo*> _decoratorSlots;
237
237
238 QList<PythonQtObjectPtr> _enumWrappers;
238 QList<PythonQtObjectPtr> _enumWrappers;
239
239
240 const QMetaObject* _meta;
240 const QMetaObject* _meta;
241
241
242 QByteArray _wrappedClassName;
242 QByteArray _wrappedClassName;
243 QList<ParentClassInfo> _parentClasses;
243 QList<ParentClassInfo> _parentClasses;
244
244
245 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
245 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
246
246
247 QObject* _decoratorProvider;
247 QObject* _decoratorProvider;
248 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
248 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
249
249
250 PyObject* _pythonQtClassWrapper;
250 PyObject* _pythonQtClassWrapper;
251
251
252 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
252 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
253
253
254 int _metaTypeId;
254 int _metaTypeId;
255 int _typeSlots;
255 int _typeSlots;
256
256
257 bool _isQObject;
257 bool _isQObject;
258 bool _enumsCreated;
258 bool _enumsCreated;
259
259
260 };
260 };
261
261
262 //---------------------------------------------------------------
262 //---------------------------------------------------------------
263
263
264
264
265 #endif
265 #endif
@@ -1,61 +1,62
1 #ifndef _PYTHONQTCPPWRAPPERFACTORY_H
1 #ifndef _PYTHONQTCPPWRAPPERFACTORY_H
2 #define _PYTHONQTCPPWRAPPERFACTORY_H
2 #define _PYTHONQTCPPWRAPPERFACTORY_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 PythonQtCppWrapperFactory.h
38 // \file PythonQtCppWrapperFactory.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-06
41 // \date 2006-06
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 //! Factory interface for C++ classes that can be wrapped by QObject objects
45 //! Factory interface for C++ classes that can be wrapped by QObject objects
46 /*! To create your own factory, derive PythonQtCppWrapperFactory and implement
46 /*! To create your own factory, derive PythonQtCppWrapperFactory and implement
47 the create() method.
47 the create() method.
48 A factory can be added to PythonQt by PythonQt::addCppWrapperFactory().
48 A factory can be added to PythonQt by PythonQt::addCppWrapperFactory().
49 */
49 */
50 class PYTHONQT_EXPORT PythonQtCppWrapperFactory
50 class PYTHONQT_EXPORT PythonQtCppWrapperFactory
51 {
51 {
52 public:
52 public:
53 PythonQtCppWrapperFactory() {};
53 PythonQtCppWrapperFactory() {};
54 virtual ~PythonQtCppWrapperFactory() {};
54 virtual ~PythonQtCppWrapperFactory() {};
55
55
56 //! create a wrapper for the given object
56 //! create a wrapper for the given object
57 virtual QObject* create(const QByteArray& name, void *ptr) = 0;
57 virtual QObject* create(const QByteArray& name, void *ptr) = 0;
58
58
59 };
59 };
60
60
61 #endif
61 #endif
62
@@ -1,75 +1,76
1 #ifndef _PYTHONQTIMPORTFILEINTERFACE_H
1 #ifndef _PYTHONQTIMPORTFILEINTERFACE_H
2 #define _PYTHONQTIMPORTFILEINTERFACE_H
2 #define _PYTHONQTIMPORTFILEINTERFACE_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 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 PythonQtImportFileInterface.h
38 // \file PythonQtImportFileInterface.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include <QDateTime>
45 #include <QDateTime>
46 #include <QString>
46 #include <QString>
47 #include <QByteArray>
47 #include <QByteArray>
48
48
49 //! Defines an abstract interface to file access for the Python import statement.
49 //! Defines an abstract interface to file access for the Python import statement.
50 //! see PythonQt::setImporter()
50 //! see PythonQt::setImporter()
51 class PythonQtImportFileInterface {
51 class PythonQtImportFileInterface {
52
52
53 public:
53 public:
54 // get rid of warnings
54 // get rid of warnings
55 virtual ~PythonQtImportFileInterface() {}
55 virtual ~PythonQtImportFileInterface() {}
56
56
57 //! read the given file as byte array, without doing any linefeed translations
57 //! read the given file as byte array, without doing any linefeed translations
58 virtual QByteArray readFileAsBytes(const QString& filename) = 0;
58 virtual QByteArray readFileAsBytes(const QString& filename) = 0;
59
59
60 //! read a source file, expects a readable Python text file with translated line feeds.
60 //! read a source file, expects a readable Python text file with translated line feeds.
61 //! If the file can not be load OR it can not be verified, ok is set to false
61 //! If the file can not be load OR it can not be verified, ok is set to false
62 virtual QByteArray readSourceFile(const QString& filename, bool& ok) = 0;
62 virtual QByteArray readSourceFile(const QString& filename, bool& ok) = 0;
63
63
64 //! returns if the file exists
64 //! returns if the file exists
65 virtual bool exists(const QString& filename) = 0;
65 virtual bool exists(const QString& filename) = 0;
66
66
67 //! get the last modified data of a file
67 //! get the last modified data of a file
68 virtual QDateTime lastModifiedDate(const QString& filename) = 0;
68 virtual QDateTime lastModifiedDate(const QString& filename) = 0;
69
69
70 //! indicates that *.py files which are newer than their corresponding *.pyc files
70 //! indicates that *.py files which are newer than their corresponding *.pyc files
71 //! are ignored
71 //! are ignored
72 virtual bool ignoreUpdatedPythonSourceFiles() { return false; }
72 virtual bool ignoreUpdatedPythonSourceFiles() { return false; }
73 };
73 };
74
74
75 #endif
75 #endif
76
@@ -1,350 +1,350
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 PythonQtMethodInfo.cpp
35 // \file PythonQtMethodInfo.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 "PythonQtMethodInfo.h"
42 #include "PythonQtMethodInfo.h"
43 #include "PythonQtClassInfo.h"
43 #include "PythonQtClassInfo.h"
44 #include <iostream>
44 #include <iostream>
45
45
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
46 QHash<QByteArray, PythonQtMethodInfo*> PythonQtMethodInfo::_cachedSignatures;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
47 QHash<QByteArray, QByteArray> PythonQtMethodInfo::_parameterNameAliases;
48
48
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
49 PythonQtMethodInfo::PythonQtMethodInfo(const QMetaMethod& meta, PythonQtClassInfo* classInfo)
50 {
50 {
51 #ifdef PYTHONQT_DEBUG
51 #ifdef PYTHONQT_DEBUG
52 QByteArray sig(meta.signature());
52 QByteArray sig(meta.signature());
53 sig = sig.mid(sig.indexOf('('));
53 sig = sig.mid(sig.indexOf('('));
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
54 QByteArray fullSig = QByteArray(meta.typeName()) + " " + sig;
55 std::cout << "caching " << fullSig.data() << std::endl;
55 std::cout << "caching " << fullSig.data() << std::endl;
56 #endif
56 #endif
57
57
58 ParameterInfo type;
58 ParameterInfo type;
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
59 fillParameterInfo(type, QByteArray(meta.typeName()), classInfo);
60 _parameters.append(type);
60 _parameters.append(type);
61 QList<QByteArray> names = meta.parameterTypes();
61 QList<QByteArray> names = meta.parameterTypes();
62 foreach (const QByteArray& name, names) {
62 foreach (const QByteArray& name, names) {
63 fillParameterInfo(type, name, classInfo);
63 fillParameterInfo(type, name, classInfo);
64 _parameters.append(type);
64 _parameters.append(type);
65 }
65 }
66 }
66 }
67
67
68 PythonQtMethodInfo::PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args)
68 PythonQtMethodInfo::PythonQtMethodInfo(const QByteArray& typeName, const QList<QByteArray>& args)
69 {
69 {
70 ParameterInfo type;
70 ParameterInfo type;
71 fillParameterInfo(type, typeName, NULL);
71 fillParameterInfo(type, typeName, NULL);
72 _parameters.append(type);
72 _parameters.append(type);
73 foreach (const QByteArray& name, args) {
73 foreach (const QByteArray& name, args) {
74 fillParameterInfo(type, name, NULL);
74 fillParameterInfo(type, name, NULL);
75 _parameters.append(type);
75 _parameters.append(type);
76 }
76 }
77 }
77 }
78
78
79 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
79 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfo(const QMetaMethod& signal, PythonQtClassInfo* classInfo)
80 {
80 {
81 QByteArray sig(signal.signature());
81 QByteArray sig(signal.signature());
82 sig = sig.mid(sig.indexOf('('));
82 sig = sig.mid(sig.indexOf('('));
83 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
83 QByteArray fullSig = QByteArray(signal.typeName()) + " " + sig;
84 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
84 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
85 if (!result) {
85 if (!result) {
86 result = new PythonQtMethodInfo(signal, classInfo);
86 result = new PythonQtMethodInfo(signal, classInfo);
87 _cachedSignatures.insert(fullSig, result);
87 _cachedSignatures.insert(fullSig, result);
88 }
88 }
89 return result;
89 return result;
90 }
90 }
91
91
92 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(int numArgs, const char** args)
92 const PythonQtMethodInfo* PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(int numArgs, const char** args)
93 {
93 {
94 QByteArray typeName = args[0];
94 QByteArray typeName = args[0];
95 QList<QByteArray> arguments;
95 QList<QByteArray> arguments;
96 QByteArray fullSig = typeName;
96 QByteArray fullSig = typeName;
97 fullSig += "(";
97 fullSig += "(";
98 for (int i =1;i<numArgs; i++) {
98 for (int i =1;i<numArgs; i++) {
99 if (i>1) {
99 if (i>1) {
100 fullSig += ",";
100 fullSig += ",";
101 }
101 }
102 arguments << QByteArray(args[i]);
102 arguments << QByteArray(args[i]);
103 }
103 }
104 fullSig += ")";
104 fullSig += ")";
105 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
105 PythonQtMethodInfo* result = _cachedSignatures.value(fullSig);
106 if (!result) {
106 if (!result) {
107 result = new PythonQtMethodInfo(typeName, arguments);
107 result = new PythonQtMethodInfo(typeName, arguments);
108 _cachedSignatures.insert(fullSig, result);
108 _cachedSignatures.insert(fullSig, result);
109 }
109 }
110 return result;
110 return result;
111 }
111 }
112
112
113 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
113 void PythonQtMethodInfo::fillParameterInfo(ParameterInfo& type, const QByteArray& orgName, PythonQtClassInfo* classInfo)
114 {
114 {
115 QByteArray name = orgName;
115 QByteArray name = orgName;
116
116
117 type.enumWrapper = NULL;
117 type.enumWrapper = NULL;
118
118
119 int len = name.length();
119 int len = name.length();
120 if (len>0) {
120 if (len>0) {
121 if (strncmp(name.constData(), "const ", 6)==0) {
121 if (strncmp(name.constData(), "const ", 6)==0) {
122 name = name.mid(6);
122 name = name.mid(6);
123 len -= 6;
123 len -= 6;
124 type.isConst = true;
124 type.isConst = true;
125 } else {
125 } else {
126 type.isConst = false;
126 type.isConst = false;
127 }
127 }
128 char pointerCount = 0;
128 char pointerCount = 0;
129 bool hadReference = false;
129 bool hadReference = false;
130 // remove * and & from the end of the string, handle & and * the same way
130 // remove * and & from the end of the string, handle & and * the same way
131 while (name.at(len-1) == '*') {
131 while (name.at(len-1) == '*') {
132 len--;
132 len--;
133 pointerCount++;
133 pointerCount++;
134 }
134 }
135 while (name.at(len-1) == '&') {
135 while (name.at(len-1) == '&') {
136 len--;
136 len--;
137 hadReference = true;
137 hadReference = true;
138 }
138 }
139 if (len!=name.length()) {
139 if (len!=name.length()) {
140 name = name.left(len);
140 name = name.left(len);
141 }
141 }
142 type.pointerCount = pointerCount;
142 type.pointerCount = pointerCount;
143
143
144 QByteArray alias = _parameterNameAliases.value(name);
144 QByteArray alias = _parameterNameAliases.value(name);
145 if (!alias.isEmpty()) {
145 if (!alias.isEmpty()) {
146 name = alias;
146 name = alias;
147 }
147 }
148
148
149 type.typeId = nameToType(name);
149 type.typeId = nameToType(name);
150 if ((type.pointerCount == 0) && type.typeId == Unknown) {
150 if ((type.pointerCount == 0) && type.typeId == Unknown) {
151 type.typeId = QMetaType::type(name.constData());
151 type.typeId = QMetaType::type(name.constData());
152 if (type.typeId == QMetaType::Void) {
152 if (type.typeId == QMetaType::Void) {
153 type.typeId = Unknown;
153 type.typeId = Unknown;
154 }
154 }
155 }
155 }
156 type.name = name;
156 type.name = name;
157
157
158 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
158 if (type.typeId == PythonQtMethodInfo::Unknown || type.typeId >= QMetaType::User) {
159 bool isLocalEnum;
159 bool isLocalEnum;
160 // TODOXXX: make use of this flag!
160 // TODOXXX: make use of this flag!
161 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
161 type.enumWrapper = PythonQtClassInfo::findEnumWrapper(type.name, classInfo, &isLocalEnum);
162 }
162 }
163 } else {
163 } else {
164 type.typeId = QMetaType::Void;
164 type.typeId = QMetaType::Void;
165 type.pointerCount = 0;
165 type.pointerCount = 0;
166 type.isConst = false;
166 type.isConst = false;
167 }
167 }
168 }
168 }
169
169
170 int PythonQtMethodInfo::nameToType(const char* name)
170 int PythonQtMethodInfo::nameToType(const char* name)
171 {
171 {
172 if (_parameterTypeDict.isEmpty()) {
172 if (_parameterTypeDict.isEmpty()) {
173 // we could also use QMetaType::nameToType, but that does a string compare search
173 // we could also use QMetaType::nameToType, but that does a string compare search
174 // and does not support QVariant
174 // and does not support QVariant
175
175
176 // QMetaType names
176 // QMetaType names
177 _parameterTypeDict.insert("long", QMetaType::Long);
177 _parameterTypeDict.insert("long", QMetaType::Long);
178 _parameterTypeDict.insert("int", QMetaType::Int);
178 _parameterTypeDict.insert("int", QMetaType::Int);
179 _parameterTypeDict.insert("short", QMetaType::Short);
179 _parameterTypeDict.insert("short", QMetaType::Short);
180 _parameterTypeDict.insert("char", QMetaType::Char);
180 _parameterTypeDict.insert("char", QMetaType::Char);
181 _parameterTypeDict.insert("ulong", QMetaType::ULong);
181 _parameterTypeDict.insert("ulong", QMetaType::ULong);
182 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
182 _parameterTypeDict.insert("unsigned long", QMetaType::ULong);
183 _parameterTypeDict.insert("uint", QMetaType::UInt);
183 _parameterTypeDict.insert("uint", QMetaType::UInt);
184 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
184 _parameterTypeDict.insert("unsigned int", QMetaType::UInt);
185 _parameterTypeDict.insert("ushort", QMetaType::UShort);
185 _parameterTypeDict.insert("ushort", QMetaType::UShort);
186 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
186 _parameterTypeDict.insert("unsigned short", QMetaType::UShort);
187 _parameterTypeDict.insert("uchar", QMetaType::UChar);
187 _parameterTypeDict.insert("uchar", QMetaType::UChar);
188 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
188 _parameterTypeDict.insert("unsigned char", QMetaType::UChar);
189 _parameterTypeDict.insert("bool", QMetaType::Bool);
189 _parameterTypeDict.insert("bool", QMetaType::Bool);
190 _parameterTypeDict.insert("float", QMetaType::Float);
190 _parameterTypeDict.insert("float", QMetaType::Float);
191 _parameterTypeDict.insert("double", QMetaType::Double);
191 _parameterTypeDict.insert("double", QMetaType::Double);
192 _parameterTypeDict.insert("qreal", QMetaType::Double);
192 _parameterTypeDict.insert("qreal", QMetaType::Double);
193 _parameterTypeDict.insert("QChar", QMetaType::QChar);
193 _parameterTypeDict.insert("QChar", QMetaType::QChar);
194 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
194 _parameterTypeDict.insert("QByteArray", QMetaType::QByteArray);
195 _parameterTypeDict.insert("QString", QMetaType::QString);
195 _parameterTypeDict.insert("QString", QMetaType::QString);
196 _parameterTypeDict.insert("", QMetaType::Void);
196 _parameterTypeDict.insert("", QMetaType::Void);
197 _parameterTypeDict.insert("void", QMetaType::Void);
197 _parameterTypeDict.insert("void", QMetaType::Void);
198 // QVariant names
198 // QVariant names
199 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
199 _parameterTypeDict.insert("Q_LLONG", QMetaType::LongLong);
200 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
200 _parameterTypeDict.insert("Q_ULLONG", QMetaType::ULongLong);
201 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
201 _parameterTypeDict.insert("qlonglong", QMetaType::LongLong);
202 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
202 _parameterTypeDict.insert("qulonglong", QMetaType::ULongLong);
203 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
203 _parameterTypeDict.insert("qint64", QMetaType::LongLong);
204 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
204 _parameterTypeDict.insert("quint64", QMetaType::ULongLong);
205 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
205 _parameterTypeDict.insert("QVariantMap", QMetaType::QVariantMap);
206 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
206 _parameterTypeDict.insert("QVariantList", QMetaType::QVariantList);
207 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
207 _parameterTypeDict.insert("QMap<QString,QVariant>", QMetaType::QVariantMap);
208 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
208 _parameterTypeDict.insert("QList<QVariant>", QMetaType::QVariantList);
209 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
209 _parameterTypeDict.insert("QStringList", QMetaType::QStringList);
210 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
210 _parameterTypeDict.insert("QBitArray", QMetaType::QBitArray);
211 _parameterTypeDict.insert("QDate", QMetaType::QDate);
211 _parameterTypeDict.insert("QDate", QMetaType::QDate);
212 _parameterTypeDict.insert("QTime", QMetaType::QTime);
212 _parameterTypeDict.insert("QTime", QMetaType::QTime);
213 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
213 _parameterTypeDict.insert("QDateTime", QMetaType::QDateTime);
214 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
214 _parameterTypeDict.insert("QUrl", QMetaType::QUrl);
215 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
215 _parameterTypeDict.insert("QLocale", QMetaType::QLocale);
216 _parameterTypeDict.insert("QRect", QMetaType::QRect);
216 _parameterTypeDict.insert("QRect", QMetaType::QRect);
217 _parameterTypeDict.insert("QRectF", QMetaType::QRectF);
217 _parameterTypeDict.insert("QRectF", QMetaType::QRectF);
218 _parameterTypeDict.insert("QSize", QMetaType::QSize);
218 _parameterTypeDict.insert("QSize", QMetaType::QSize);
219 _parameterTypeDict.insert("QSizeF", QMetaType::QSizeF);
219 _parameterTypeDict.insert("QSizeF", QMetaType::QSizeF);
220 _parameterTypeDict.insert("QLine", QMetaType::QLine);
220 _parameterTypeDict.insert("QLine", QMetaType::QLine);
221 _parameterTypeDict.insert("QLineF", QMetaType::QLineF);
221 _parameterTypeDict.insert("QLineF", QMetaType::QLineF);
222 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
222 _parameterTypeDict.insert("QPoint", QMetaType::QPoint);
223 _parameterTypeDict.insert("QPointF", QMetaType::QPointF);
223 _parameterTypeDict.insert("QPointF", QMetaType::QPointF);
224 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
224 _parameterTypeDict.insert("QRegExp", QMetaType::QRegExp);
225 _parameterTypeDict.insert("QFont", QMetaType::QFont);
225 _parameterTypeDict.insert("QFont", QMetaType::QFont);
226 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
226 _parameterTypeDict.insert("QPixmap", QMetaType::QPixmap);
227 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
227 _parameterTypeDict.insert("QBrush", QMetaType::QBrush);
228 _parameterTypeDict.insert("QColor", QMetaType::QColor);
228 _parameterTypeDict.insert("QColor", QMetaType::QColor);
229 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
229 _parameterTypeDict.insert("QCursor", QMetaType::QCursor);
230 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
230 _parameterTypeDict.insert("QPalette", QMetaType::QPalette);
231 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
231 _parameterTypeDict.insert("QIcon", QMetaType::QIcon);
232 _parameterTypeDict.insert("QImage", QMetaType::QImage);
232 _parameterTypeDict.insert("QImage", QMetaType::QImage);
233 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
233 _parameterTypeDict.insert("QRegion", QMetaType::QRegion);
234 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
234 _parameterTypeDict.insert("QBitmap", QMetaType::QBitmap);
235 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
235 _parameterTypeDict.insert("QSizePolicy", QMetaType::QSizePolicy);
236 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
236 _parameterTypeDict.insert("QKeySequence", QMetaType::QKeySequence);
237 _parameterTypeDict.insert("QPen", QMetaType::QPen);
237 _parameterTypeDict.insert("QPen", QMetaType::QPen);
238 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
238 _parameterTypeDict.insert("QTextLength", QMetaType::QTextLength);
239 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
239 _parameterTypeDict.insert("QTextFormat", QMetaType::QTextFormat);
240 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
240 _parameterTypeDict.insert("QMatrix", QMetaType::QMatrix);
241 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
241 _parameterTypeDict.insert("QVariant", PythonQtMethodInfo::Variant);
242 // own special types... (none so far, could be e.g. ObjectList
242 // own special types... (none so far, could be e.g. ObjectList
243 }
243 }
244 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
244 QHash<QByteArray, int>::const_iterator it = _parameterTypeDict.find(name);
245 if (it!=_parameterTypeDict.end()) {
245 if (it!=_parameterTypeDict.end()) {
246 return it.value();
246 return it.value();
247 } else {
247 } else {
248 return PythonQtMethodInfo::Unknown;
248 return PythonQtMethodInfo::Unknown;
249 }
249 }
250 }
250 }
251
251
252 void PythonQtMethodInfo::cleanupCachedMethodInfos()
252 void PythonQtMethodInfo::cleanupCachedMethodInfos()
253 {
253 {
254 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
254 QHashIterator<QByteArray, PythonQtMethodInfo *> i(_cachedSignatures);
255 while (i.hasNext()) {
255 while (i.hasNext()) {
256 delete i.next().value();
256 delete i.next().value();
257 }
257 }
258 }
258 }
259
259
260 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
260 void PythonQtMethodInfo::addParameterTypeAlias(const QByteArray& alias, const QByteArray& name)
261 {
261 {
262 _parameterNameAliases.insert(alias, name);
262 _parameterNameAliases.insert(alias, name);
263 }
263 }
264
264
265 //-------------------------------------------------------------------------------------------------
265 //-------------------------------------------------------------------------------------------------
266
266
267 void PythonQtSlotInfo::deleteOverloadsAndThis()
267 void PythonQtSlotInfo::deleteOverloadsAndThis()
268 {
268 {
269 PythonQtSlotInfo* cur = this;
269 PythonQtSlotInfo* cur = this;
270 while(cur->nextInfo()) {
270 while(cur->nextInfo()) {
271 PythonQtSlotInfo* next = cur->nextInfo();
271 PythonQtSlotInfo* next = cur->nextInfo();
272 delete cur;
272 delete cur;
273 cur = next;
273 cur = next;
274 }
274 }
275 }
275 }
276
276
277
277
278 QString PythonQtSlotInfo::fullSignature()
278 QString PythonQtSlotInfo::fullSignature()
279 {
279 {
280 bool skipFirstArg = isInstanceDecorator();
280 bool skipFirstArg = isInstanceDecorator();
281 QString result = _meta.typeName();
281 QString result = _meta.typeName();
282 QByteArray sig = slotName();
282 QByteArray sig = slotName();
283 QList<QByteArray> names = _meta.parameterNames();
283 QList<QByteArray> names = _meta.parameterNames();
284
284
285 bool isStatic = false;
285 bool isStatic = false;
286 bool isConstructor = false;
286 bool isConstructor = false;
287 bool isDestructor = false;
287 bool isDestructor = false;
288
288
289 if (_type == ClassDecorator) {
289 if (_type == ClassDecorator) {
290 if (sig.startsWith("new_")) {
290 if (sig.startsWith("new_")) {
291 sig = sig.mid(strlen("new_"));
291 sig = sig.mid(4);
292 isConstructor = true;
292 isConstructor = true;
293 } else if (sig.startsWith("delete_")) {
293 } else if (sig.startsWith("delete_")) {
294 sig = sig.mid(strlen("delete_"));
294 sig = sig.mid(7);
295 isDestructor = true;
295 isDestructor = true;
296 } else if(sig.startsWith("static_")) {
296 } else if(sig.startsWith("static_")) {
297 isStatic = true;
297 isStatic = true;
298 sig = sig.mid(strlen("static_"));
298 sig = sig.mid(7);
299 int idx = sig.indexOf("_");
299 int idx = sig.indexOf("_");
300 if (idx>=0) {
300 if (idx>=0) {
301 sig = sig.mid(idx+1);
301 sig = sig.mid(idx+1);
302 }
302 }
303 }
303 }
304 }
304 }
305
305
306 result += QByteArray(" ") + sig;
306 result += QByteArray(" ") + sig;
307 result += "(";
307 result += "(";
308
308
309 int lastEntry = _parameters.count()-1;
309 int lastEntry = _parameters.count()-1;
310 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
310 for (int i = skipFirstArg?2:1; i<_parameters.count(); i++) {
311 if (_parameters.at(i).isConst) {
311 if (_parameters.at(i).isConst) {
312 result += "const ";
312 result += "const ";
313 }
313 }
314 result += _parameters.at(i).name;
314 result += _parameters.at(i).name;
315 if (_parameters.at(i).pointerCount) {
315 if (_parameters.at(i).pointerCount) {
316 QByteArray stars;
316 QByteArray stars;
317 stars.fill('*', _parameters.at(i).pointerCount);
317 stars.fill('*', _parameters.at(i).pointerCount);
318 result += stars;
318 result += stars;
319 }
319 }
320 if (!names.at(i-1).isEmpty()) {
320 if (!names.at(i-1).isEmpty()) {
321 result += " ";
321 result += " ";
322 result += names.at(i-1);
322 result += names.at(i-1);
323 }
323 }
324 if (i!=lastEntry) {
324 if (i!=lastEntry) {
325 result += ", ";
325 result += ", ";
326 }
326 }
327 }
327 }
328 result += ")";
328 result += ")";
329
329
330 if (isStatic) {
330 if (isStatic) {
331 result = QString("static ") + result;
331 result = QString("static ") + result;
332 }
332 }
333 if (isConstructor) {
333 if (isConstructor) {
334 // result = QString("constructor ") + result;
334 // result = QString("constructor ") + result;
335 }
335 }
336 if (isDestructor) {
336 if (isDestructor) {
337 result = QString("~") + result;
337 result = QString("~") + result;
338 }
338 }
339 return result;
339 return result;
340 }
340 }
341
341
342
342
343 QByteArray PythonQtSlotInfo::slotName()
343 QByteArray PythonQtSlotInfo::slotName()
344 {
344 {
345 QByteArray sig(_meta.signature());
345 QByteArray sig(_meta.signature());
346 int idx = sig.indexOf('(');
346 int idx = sig.indexOf('(');
347 sig = sig.left(idx);
347 sig = sig.left(idx);
348 return sig;
348 return sig;
349 }
349 }
350
350
@@ -1,43 +1,45
1 DEFINES += PYTHONQT_EXPORTS
1 DEFINES += PYTHONQT_EXPORTS
2
2
3 HEADERS += \
3 HEADERS += \
4 $$PWD/PythonQt.h \
4 $$PWD/PythonQt.h \
5 $$PWD/PythonQtStdDecorators.h \
5 $$PWD/PythonQtStdDecorators.h \
6 $$PWD/PythonQtClassInfo.h \
6 $$PWD/PythonQtClassInfo.h \
7 $$PWD/PythonQtImporter.h \
7 $$PWD/PythonQtImporter.h \
8 $$PWD/PythonQtObjectPtr.h \
8 $$PWD/PythonQtObjectPtr.h \
9 $$PWD/PythonQtSlot.h \
9 $$PWD/PythonQtSlot.h \
10 $$PWD/PythonQtStdIn.h \
10 $$PWD/PythonQtStdOut.h \
11 $$PWD/PythonQtStdOut.h \
11 $$PWD/PythonQtMisc.h \
12 $$PWD/PythonQtMisc.h \
12 $$PWD/PythonQtMethodInfo.h \
13 $$PWD/PythonQtMethodInfo.h \
13 $$PWD/PythonQtImportFileInterface.h \
14 $$PWD/PythonQtImportFileInterface.h \
14 $$PWD/PythonQtConversion.h \
15 $$PWD/PythonQtConversion.h \
15 $$PWD/PythonQtSignalReceiver.h \
16 $$PWD/PythonQtSignalReceiver.h \
16 $$PWD/PythonQtInstanceWrapper.h \
17 $$PWD/PythonQtInstanceWrapper.h \
17 $$PWD/PythonQtClassWrapper.h \
18 $$PWD/PythonQtClassWrapper.h \
18 $$PWD/PythonQtCppWrapperFactory.h \
19 $$PWD/PythonQtCppWrapperFactory.h \
19 $$PWD/PythonQtQFileImporter.h \
20 $$PWD/PythonQtQFileImporter.h \
20 $$PWD/PythonQtQFileImporter.h \
21 $$PWD/PythonQtQFileImporter.h \
21 $$PWD/PythonQtVariants.h \
22 $$PWD/PythonQtVariants.h \
22 $$PWD/gui/PythonQtScriptingConsole.h \
23 $$PWD/gui/PythonQtScriptingConsole.h \
23 $$PWD/PythonQtSystem.h
24 $$PWD/PythonQtSystem.h
24
25
25 SOURCES += \
26 SOURCES += \
26 $$PWD/PythonQtStdDecorators.cpp \
27 $$PWD/PythonQtStdDecorators.cpp \
27 $$PWD/PythonQt.cpp \
28 $$PWD/PythonQt.cpp \
28 $$PWD/PythonQtClassInfo.cpp \
29 $$PWD/PythonQtClassInfo.cpp \
29 $$PWD/PythonQtImporter.cpp \
30 $$PWD/PythonQtImporter.cpp \
30 $$PWD/PythonQtObjectPtr.cpp \
31 $$PWD/PythonQtObjectPtr.cpp \
32 $$PWD/PythonQtStdIn.cpp \
31 $$PWD/PythonQtStdOut.cpp \
33 $$PWD/PythonQtStdOut.cpp \
32 $$PWD/PythonQtSlot.cpp \
34 $$PWD/PythonQtSlot.cpp \
33 $$PWD/PythonQtMisc.cpp \
35 $$PWD/PythonQtMisc.cpp \
34 $$PWD/PythonQtMethodInfo.cpp \
36 $$PWD/PythonQtMethodInfo.cpp \
35 $$PWD/PythonQtConversion.cpp \
37 $$PWD/PythonQtConversion.cpp \
36 $$PWD/PythonQtSignalReceiver.cpp \
38 $$PWD/PythonQtSignalReceiver.cpp \
37 $$PWD/PythonQtInstanceWrapper.cpp \
39 $$PWD/PythonQtInstanceWrapper.cpp \
38 $$PWD/PythonQtQFileImporter.cpp \
40 $$PWD/PythonQtQFileImporter.cpp \
39 $$PWD/PythonQtClassWrapper.cpp \
41 $$PWD/PythonQtClassWrapper.cpp \
40 $$PWD/gui/PythonQtScriptingConsole.cpp \
42 $$PWD/gui/PythonQtScriptingConsole.cpp \
41
43
42 include($$PWD/../generated_cpp/com_trolltech_qt_core_builtin/com_trolltech_qt_core_builtin.pri)
44 include($$PWD/../generated_cpp/com_trolltech_qt_core_builtin/com_trolltech_qt_core_builtin.pri)
43 include($$PWD/../generated_cpp/com_trolltech_qt_gui_builtin/com_trolltech_qt_gui_builtin.pri)
45 include($$PWD/../generated_cpp/com_trolltech_qt_gui_builtin/com_trolltech_qt_gui_builtin.pri)
General Comments 0
You need to be logged in to leave comments. Login now