##// END OF EJS Templates
updated docs and exported class info...
florianlink -
r139:ad60447f50bd
parent child
Show More
@@ -1,262 +1,262
1 1 #ifndef _PYTHONQTCLASSINFO_H
2 2 #define _PYTHONQTCLASSINFO_H
3 3
4 4 /*
5 5 *
6 6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 7 *
8 8 * This library is free software; you can redistribute it and/or
9 9 * modify it under the terms of the GNU Lesser General Public
10 10 * License as published by the Free Software Foundation; either
11 11 * version 2.1 of the License, or (at your option) any later version.
12 12 *
13 13 * This library is distributed in the hope that it will be useful,
14 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 16 * Lesser General Public License for more details.
17 17 *
18 18 * Further, this software is distributed without any warranty that it is
19 19 * free of the rightful claim of any third person regarding infringement
20 20 * or the like. Any license provided herein, whether implied or
21 21 * otherwise, applies only to this software file. Patent licenses, if
22 22 * any, provided herein do not apply to combinations of this program with
23 23 * other software, or any other product whatsoever.
24 24 *
25 25 * You should have received a copy of the GNU Lesser General Public
26 26 * License along with this library; if not, write to the Free Software
27 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 28 *
29 29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 30 * 28359 Bremen, Germany or:
31 31 *
32 32 * http://www.mevis.de
33 33 *
34 34 */
35 35
36 36 #include <QMetaObject>
37 37 #include <QMetaMethod>
38 38 #include <QHash>
39 39 #include <QByteArray>
40 40 #include <QList>
41 41 #include "PythonQt.h"
42 42
43 43 class PythonQtSlotInfo;
44 44
45 45 struct PythonQtMemberInfo {
46 46 enum Type {
47 47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
48 48 };
49 49
50 50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
51 51
52 52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
53 53 _type = Slot;
54 54 _slot = info;
55 55 _enumValue = NULL;
56 56 }
57 57
58 58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
59 59 _type = EnumValue;
60 60 _slot = NULL;
61 61 _enumValue = enumValue;
62 62 _enumWrapper = NULL;
63 63 }
64 64
65 65 PythonQtMemberInfo(const QMetaProperty& prop) {
66 66 _type = Property;
67 67 _slot = NULL;
68 68 _enumValue = NULL;
69 69 _property = prop;
70 70 _enumWrapper = NULL;
71 71 }
72 72
73 73 Type _type;
74 74
75 75 // TODO: this could be a union...
76 76 PythonQtSlotInfo* _slot;
77 77 PyObject* _enumWrapper;
78 78 PythonQtObjectPtr _enumValue;
79 79 QMetaProperty _property;
80 80 };
81 81
82 82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
83 83 /*! for fast lookup of slots when calling the object from Python
84 84 */
85 class PythonQtClassInfo {
85 class PYTHONQT_EXPORT PythonQtClassInfo {
86 86
87 87 public:
88 88 PythonQtClassInfo();
89 89 ~PythonQtClassInfo();
90 90
91 91 //! store information about parent classes
92 92 struct ParentClassInfo {
93 93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
94 94 {};
95 95
96 96 PythonQtClassInfo* _parent;
97 97 int _upcastingOffset;
98 98 };
99 99
100 100
101 101 //! setup as a QObject, taking the meta object as meta information about the QObject
102 102 void setupQObject(const QMetaObject* meta);
103 103
104 104 //! setup as a CPP (non-QObject), taking the classname
105 105 void setupCPPObject(const QByteArray& classname);
106 106
107 107 //! set the type capabilities
108 108 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
109 109 //! get the type capabilities
110 110 int typeSlots() const { return _typeSlots; }
111 111
112 112 //! get the Python method definition for a given slot name (without return type and signature)
113 113 PythonQtMemberInfo member(const char* member);
114 114
115 115 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
116 116 PythonQtSlotInfo* constructors();
117 117
118 118 //! get access to the destructor slot
119 119 PythonQtSlotInfo* destructor();
120 120
121 121 //! add a constructor, ownership is passed to classinfo
122 122 void addConstructor(PythonQtSlotInfo* info);
123 123
124 124 //! set a destructor, ownership is passed to classinfo
125 125 void setDestructor(PythonQtSlotInfo* info);
126 126
127 127 //! add a decorator slot, ownership is passed to classinfo
128 128 void addDecoratorSlot(PythonQtSlotInfo* info);
129 129
130 130 //! get the classname (either of the QObject or of the wrapped CPP object)
131 131 const char* className();
132 132
133 133 //! returns if the QObject
134 134 bool isQObject() { return _isQObject; }
135 135
136 136 //! returns if the class is a CPP wrapper
137 137 bool isCPPWrapper() { return !_isQObject; }
138 138
139 139 //! get the meta object
140 140 const QMetaObject* metaObject() { return _meta; }
141 141
142 142 //! set the meta object, this will reset the caching
143 143 void setMetaObject(const QMetaObject* meta);
144 144
145 145 //! returns if this class inherits from the given classname
146 146 bool inherits(const char* classname);
147 147
148 148 //! returns if this class inherits from the given classinfo
149 149 bool inherits(PythonQtClassInfo* info);
150 150
151 151 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
152 152 //! which might be different to \c ptr due to C++ multiple inheritance
153 153 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
154 154 void* castTo(void* ptr, const char* classname);
155 155
156 156 //! get help string for the metaobject
157 157 QString help();
158 158
159 159 //! get list of all properties (on QObjects only, otherwise the list is empty)
160 160 QStringList propertyList();
161 161
162 162 //! get list of all members
163 163 QStringList memberList(bool metaOnly = false);
164 164
165 165 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
166 166 int metaTypeId() { return _metaTypeId; }
167 167
168 168 //! set an additional decorator provider that offers additional decorator slots for this class
169 169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb) { _decoratorProviderCB = cb; _decoratorProvider = NULL; }
170 170
171 171 //! get the decorator qobject instance
172 172 QObject* decorator();
173 173
174 174 //! add the parent class info of a CPP object
175 175 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
176 176
177 177 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
178 178 bool hasOwnerMethodButNoOwner(void* object);
179 179
180 180 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
181 181 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
182 182
183 183 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
184 184 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
185 185
186 186 //! set the shell set instance wrapper cb
187 187 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
188 188 _shellSetInstanceWrapperCB = cb;
189 189 }
190 190
191 191 //! get the shell set instance wrapper cb
192 192 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
193 193 return _shellSetInstanceWrapperCB;
194 194 }
195 195
196 196 //! add a handler for polymorphic downcasting
197 197 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
198 198
199 199 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
200 200 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
201 201
202 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 203 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
204 204
205 205 private:
206 206 void createEnumWrappers();
207 207 void createEnumWrappers(const QMetaObject* meta);
208 208 PyObject* findEnumWrapper(const char* name);
209 209
210 210 //! clear all cached members
211 211 void clearCachedMembers();
212 212
213 213 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
214 214
215 215 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
216 216 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
217 217 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
218 218
219 219 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
220 220 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
221 221
222 222 bool lookForPropertyAndCache(const char* memberName);
223 223 bool lookForMethodAndCache(const char* memberName);
224 224 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
225 225
226 226 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
227 227 int findCharOffset(const char* sigStart, char someChar);
228 228
229 229 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
230 230
231 231 PythonQtSlotInfo* _constructors;
232 232 PythonQtSlotInfo* _destructor;
233 233 QList<PythonQtSlotInfo*> _decoratorSlots;
234 234
235 235 QList<PythonQtObjectPtr> _enumWrappers;
236 236
237 237 const QMetaObject* _meta;
238 238
239 239 QByteArray _wrappedClassName;
240 240 QList<ParentClassInfo> _parentClasses;
241 241
242 242 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
243 243
244 244 QObject* _decoratorProvider;
245 245 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
246 246
247 247 PyObject* _pythonQtClassWrapper;
248 248
249 249 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
250 250
251 251 int _metaTypeId;
252 252 int _typeSlots;
253 253
254 254 bool _isQObject;
255 255 bool _enumsCreated;
256 256
257 257 };
258 258
259 259 //---------------------------------------------------------------
260 260
261 261
262 262 #endif
@@ -1,509 +1,512
1 1 #ifndef _PYTHONQTDOC_H
2 2 #define _PYTHONQTDOC_H
3 3
4 4 /*
5 5 *
6 6 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
7 7 *
8 8 * This library is free software; you can redistribute it and/or
9 9 * modify it under the terms of the GNU Lesser General Public
10 10 * License as published by the Free Software Foundation; either
11 11 * version 2.1 of the License, or (at your option) any later version.
12 12 *
13 13 * This library is distributed in the hope that it will be useful,
14 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 16 * Lesser General Public License for more details.
17 17 *
18 18 * Further, this software is distributed without any warranty that it is
19 19 * free of the rightful claim of any third person regarding infringement
20 20 * or the like. Any license provided herein, whether implied or
21 21 * otherwise, applies only to this software file. Patent licenses, if
22 22 * any, provided herein do not apply to combinations of this program with
23 23 * other software, or any other product whatsoever.
24 24 *
25 25 * You should have received a copy of the GNU Lesser General Public
26 26 * License along with this library; if not, write to the Free Software
27 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 28 *
29 29 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
30 30 * 28359 Bremen, Germany or:
31 31 *
32 32 * http://www.mevis.de
33 33 *
34 34 */
35 35
36 36 //----------------------------------------------------------------------------------
37 37 /*!
38 38 // \file PythonQtDoc.h
39 39 // \author Florian Link
40 40 // \author Last changed by $Author: florian $
41 41 // \date 2006-10
42 42 */
43 43 //----------------------------------------------------------------------------------
44 44
45 45 /*!
46 46 \if USE_GLOBAL_DOXYGEN_DOC
47 47 \page PythonQtPage PythonQt Overview
48 48 \else
49 49 \mainpage PythonQt Overview
50 50 \endif
51 51
52 52 \section Introduction
53 53
54 54 \b PythonQt is a dynamic Python (http://www.python.org) binding for the Qt framework (http://qt.nokia.com).
55 55 It offers an easy way to embed the Python scripting language into
56 56 your C++ Qt applications. It makes heavy use of the QMetaObject system and thus requires Qt 4.x.
57 57
58 58 The focus of PythonQt is on embedding Python into an existing C++ application, not on writing the whole
59 59 application completely in Python. If you want to write your whole application in Python,
60 60 you should use <a href="http://www.riverbankcomputing.co.uk/pyqt/">PyQt</a> or <a href="http://www.pyside.org">PySide</a> instead.
61 61
62 62 If you are looking for a simple way to embed Python objects into your C++/Qt Application
63 63 and to script parts of your application via Python, PythonQt is the way to go!
64 64
65 65 PythonQt is a stable library that was developed to make the
66 66 Image Processing and Visualization platform MeVisLab (http://www.mevislab.de)
67 67 scriptable from Python.
68 68
69 69 \section Download
70 70
71 71 PythonQt is hosted on SourceForge at http://sourceforge.net/projects/pythonqt , you can access it via SVN
72 72 or download a tarball.
73 73
74 74 \section Licensing
75 75
76 76 PythonQt is distributed under the LGPL license, so it pairs well with the LGPL of the Qt 4.5 release and allows
77 77 to be used in commercial applications when following the LGPL 2.1 obligations.
78 78
79 79 \section LicensingWrapper Licensing of Wrapper Generator
80 80
81 81 The build system of PythonQt makes use of a modified version of the LGPL'ed QtScript generator,
82 82 located in the "generator" directory.
83 83
84 84 See http://qt.gitorious.org/qt-labs/qtscriptgenerator for details on the original project.
85 85 Thanks a lot to the QtJambi guys and the QtScript Generator project for the C++ parser and
86 86 Qt typesystem files!
87 87
88 88 The PythonQt wrappers generated by the generator located in the "generated_cpp" directory are free to be used without any licensing restrictions.
89 89
90 90 The generated wrappers are pre-generated and checked-in for Qt 4.6.1, so you only need to build and run the
91 91 generator when you want to build additional wrappers or you want to upgrade/downgrade to another Qt version.
92 92 You may use the generator to generate C++ bindings for your own C++ classes (e.g., to make them inheritable in Python),
93 93 , but this is currently not documented and involves creating your own typesystem files (although the Qt Jambi examples might help you).
94 94
95 95 \section Features
96 96
97 97 The following are the built-in features of the PythonQt library:
98 98
99 99 - Access all \b slots, \b properties, children and registered enums of any QObject derived class from Python
100 100 - Connecting Qt Signals to Python functions (both from within Python and from C++)
101 101 - Easy wrapping of Python objects from C++ with smart, reference-counting PythonQtObjectPtr.
102 102 - Convenient conversions to/from QVariant for PythonQtObjectPtr.
103 103 - Wrapping of C++ objects (which are not derived from QObject) via PythonQtCppWrapperFactory
104 104 - Extending C++ and QObject derived classes with additional slots, static methods and constructors (see Decorators)
105 105 - StdOut/Err redirection to Qt signals instead of cout
106 106 - Interface for creating your own \c import replacement, so that Python scripts can be e.g. signed/verified before they are executed (PythonQtImportFileInterface)
107 107 - Mapping of plain-old-datatypes and ALL QVariant types to and from Python
108 108 - Support for wrapping of user QVariant types which are registerd via QMetaType
109 109 - Support for Qt namespace (with all enumerators)
110 110 - All PythonQt wrapped objects support the dir() statement, so that you can see easily which attributes a QObject, CPP object or QVariant has
111 111 - No preprocessing/wrapping tool needs to be started, PythonQt can script any QObject without prior knowledge about it (except for the MetaObject information from the \b moc)
112 112 - Multiple inheritance for C++ objects (e.g. a QWidget is derived from QObject and QPaintDevice, PythonQt will automatically cast a QWidget to a QPaintDevice when needed)
113 113 - Polymorphic downcasting (if e.g. PythonQt sees a QEvent, it can downcast it depending on the type(), so the Python e.g. sees a QPaintEvent instead of a plain QEvent)
114 114 - Deriving C++ objects from Python and overwriting virtual method with a Python implementation (requires usage of wrapper generator or manual work!)
115 115 - Extensible handler for Python/C++ conversion of complex types, e.g. mapping of QVector<SomeObject> to/from a Python array
116 - Setting of dynamic QObject properties via setProperty(), dynamic properties can be accessed for reading and writing like normal Python attributes (but creating a new property needs to be done with setProperty(), to distinguish from normal Python attributes)
116 117
117 118 \section FeaturesQtAll Features (with PythonQt_QtAll linked in)
118 119
119 120 Thanks to the new wrapper generator, PythonQt now offers the additional PythonQt_QtAll library which wraps the complete Qt API, including all C++ classes and all non-slots on QObject derived classes.
120 121 This offers the following features:
121 122
122 123 - Complete Qt API wrapped and accessible
123 124 - The following modules are available as submodules of the PythonQt module:
124 125 - QtCore
125 126 - QtGui
126 127 - QtNetwork
127 128 - QtOpenGL
128 129 - QtSql
129 130 - QtSvg
130 131 - QtUiTools
131 132 - QtWebKit
132 133 - QtXml
133 - QtXmlPatterns
134 - (phonon, QtHelp, assistant, designer are currently not supported, this would require some additional effort on the code generator)
134 - (QtXmlPatterns, QtScript, QtHelp, phonon, assistant, designer are currently not supported, this would require some additional effort on the code generator)
135 135 - For convenience, all classes are also available in the PythonQt.Qt module, for people who do not care in which module a class is located
136 - Any Qt class that has virtual methods can be easily derived from Python and the virtual methods can be reimplemented in Python
136 - Any Qt class that has virtual methods can be easily derived from Python and the virtual methods can be reimplemented in Python (this feature is considered experimental!)
137 137 - Polymorphic downcasting on QEvent, QGraphicsItem, QStyleOption, ...
138 138 - Multiple inheritance support (e.g., QGraphicsTextItem is a QObject AND a QGraphicsItem, PythonQt will handle this well)
139 139
140 140 \section Comparision Comparision with PyQt/PySide
141 141
142 - PythonQt is not as Pythonic as PyQt in many details (e.g. buffer protocol, pickling, translation support, ...) and it is mainly thought for embedding and intercommunication between Qt/Cpp and Python
142 - PythonQt is not as pythonic as PyQt in many details (e.g. buffer protocol, pickling, translation support, ...) and it is mainly thought for embedding and intercommunication between Qt/Cpp and Python
143 143 - PythonQt allows to communicate in both directions, e.g., calling a Python object from C++ AND calling a C++ method from Python, while PyQt only handles the Python->C++ direction
144 144 - PythonQt offers properties as Python attributes, while PyQt offers them as setter/getter methods (e.g. QWidget.width is a property in PythonQt and a method in PyQt)
145 - PythonQt does not support instanceof checks for Qt classes, except for the exact match and derived Python classes
146 - QObject.emit to emit Qt signals from Python is not yet implemented but PythonQt allows to just emit a signal by calling it
147 - PythonQt does not (yet) offer to add new signals to Python/C++ objects
148 - Ownership of objects is a bit different in PythonQt, currently Python classes derived from a C++ class need to be manually referenced in Python to not get deleted too early (this will be fixed)
149 - QStrings are always converted to unicode Python objects (PyQt returns QString instead), we prefered to return Python strings.
145 - PythonQt currently does not support instanceof checks for Qt classes, except for the exact match and derived Python classes
146 - QObject.emit to emit Qt signals from Python is not yet implemented but PythonQt allows to just emit a signal by calling it like a normal slot
147 - PythonQt does not (yet) offer to add new signals to Python/C++ objects and it does not yet support the newstyle PyQt signals (so you need to connect via C++ string signatures)
148 - Ownership of objects is a bit different in PythonQt, currently Python classes derived from a C++ class need to be manually referenced in Python to not get deleted too early (this will be fixed in a future version)
149 - QStrings are always converted to unicode Python objects, QByteArray always stays a QByteArray and can be converted using str()
150 - There are many details in the generated wrappers that could need some polishing, e.g., methods that use pointer arguments for additional return values could return a results tuple.
151 - Not all types of QList/QVector/QHash templates are supported, some Qt methods use those as arguments/return values (but you can add your own handlers to handle them if you need them).
150 152 - Probably there are lots of details that differ, I do not know PyQt that well to list them all.
153 - In the long run, PythonQt will consider using/extending PySide with the features of PythonQt to get rid of its own generator and typesystem files, alternatively the KDE Smoke generator might be used in the future (this has not yet been decided, the current PythonQt generator works well and there is no hurry to switch).
151 154
152 155 \section Interface
153 156
154 157 The main interface to PythonQt is the PythonQt singleton.
155 158 PythonQt needs to be initialized via PythonQt::init() once.
156 159 Afterwards you communicate with the singleton via PythonQt::self().
157 160 PythonQt offers a complete Qt binding, which
158 161 needs to be enabled via PythonQt_QtAll::init().
159 162
160 163
161 164 \section Datatype Datatype Mapping
162 165
163 166 The following table shows the mapping between Python and Qt objects:
164 167 <table>
165 168 <tr><th>Qt/C++</th><th>Python</th></tr>
166 169 <tr><td>bool</td><td>bool</td></tr>
167 170 <tr><td>double</td><td>float</td></tr>
168 171 <tr><td>float</td><td>float</td></tr>
169 172 <tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
170 173 <tr><td>long</td><td>integer</td></tr>
171 174 <tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
172 175 <tr><td>QString</td><td>unicode string</td></tr>
173 176 <tr><td>QByteArray</td><td>str</td></tr>
174 177 <tr><td>char*</td><td>str</td></tr>
175 178 <tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
176 179 <tr><td>QVariantList</td><td>tuple of objects</td></tr>
177 180 <tr><td>QVariantMap</td><td>dict of objects</td></tr>
178 181 <tr><td>QVariant</td><td>depends on type, see below</td></tr>
179 182 <tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant wrapper that supports complete API of the respective Qt classes</td></tr>
180 183 <tr><td>OwnRegisteredMetaType</td><td>C++ wrapper, optionally with additional information/wrapping provided by registerCPPClass()</td></tr>
181 184 <tr><td>QList<AnyObject*></td><td>converts to a list of CPP wrappers</td></tr>
182 185 <tr><td>EnumType</td><td>integer (all enums that are known via the moc and the Qt namespace are supported)</td></tr>
183 186 <tr><td>QObject (and derived classes)</td><td>QObject wrapper</td></tr>
184 187 <tr><td>C++ object</td><td>CPP wrapper, either wrapped via PythonQtCppWrapperFactory or just decorated with decorators</td></tr>
185 188 <tr><td>PyObject</td><td>PyObject</td></tr>
186 189 </table>
187 190
188 191 PyObject is passed as simple pointer, which allows to pass/return any Python Object directly to/from
189 192 a Qt slot.
190 193 QVariants are mapped recursively as given above, e.g. a dictionary can
191 194 contain lists of dictionaries of doubles.
192 195 For example a QVariant of type "String" is mapped to a python unicode string.
193 196 All Qt QVariant types are implemented, PythonQt supports the complete Qt API for these object.
194 197
195 198 \section QObject QObject Wrapping
196 199
197 200 All classes derived from QObject are automatically wrapped with a python wrapper class
198 201 when they become visible to the Python interpreter. This can happen via
199 202 - the PythonQt::addObject() method
200 203 - when a Qt \b slot returns a QObject derived object to python
201 204 - when a Qt \b signal contains a QObject and is connected to a python function
202 205
203 206 It is important that you call PythonQt::registerClass() for any QObject derived class
204 207 that may become visible to Python, except when you add it via PythonQt::addObject().
205 208 This will register the complete parent hierachy of the registered class, so that
206 209 when you register e.g. a QPushButton, QWidget will be registered as well (and all intermediate
207 210 parents).
208 211
209 212 From Python, you can talk to the returned QObjects in a natural way by calling
210 213 their slots and receiving the return values. You can also read/write all
211 214 properties of the objects as if they where normal python properties.
212 215
213 216 In addition to this, the wrapped objects support
214 217 - className() - returns a string that reprents the classname of the QObject
215 218 - help() - shows all properties, slots, enums, decorator slots and constructors of the object, in a printable form
216 219 - delete() - deletes the object (use with care, especially if you passed the ownership to C++)
217 220 - connect(signal, function) - connect the signal of the given object to a python function
218 221 - connect(signal, qobject, slot) - connect the signal of the given object to a slot of another QObject
219 222 - disconnect(signal, function) - disconnect the signal of the given object from a python function
220 223 - disconnect(signal, qobject, slot) - disconnect the signal of the given object from a slot of another QObject
221 224 - children() - returns the children of the object
222 225 - setParent(QObject) - set the parent
223 226 - QObject* parent() - get the parent
224 227
225 228 The below example shows how to connect signals in Python:
226 229
227 230 \code
228 231 # define a signal handler function
229 232 def someFunction(flag):
230 233 print flag
231 234
232 235 # button1 is a QPushButton that has been added to Python via addObject()
233 236 # connect the clicked signal to a python function:
234 237 button1.connect("clicked(bool)", someFunction)
235 238
236 239 \endcode
237 240
238 241 \section CPP CPP Wrapping
239 242
240 243 You can create dedicated wrapper QObjects for any C++ class. This is done by deriving from PythonQtCppWrapperFactory
241 244 and adding your factory via addWrapperFactory().
242 245 Whenever PythonQt encounters a CPP pointer (e.g. on a slot or signal)
243 246 and it does not known it as a QObject derived class, it will create a generic CPP wrapper. So even unknown C++ objects
244 247 can be passed through Python. If the wrapper factory supports the CPP class, a QObject wrapper will be created for each
245 248 instance that enters Python. An alternative to a complete wrapper via the wrapper factory are decorators, see \ref Decorators
246 249
247 250 \section MetaObject Meta Object/Class access
248 251
249 252 For each known C++ class, PythonQt provides a Python class. These classes are visible
250 253 inside of the "PythonQt" python module or in subpackages if a package is given when the class is registered.
251 254
252 255 A Meta class supports:
253 256
254 257 - access to all declared enum values
255 258 - constructors
256 259 - static methods
257 260 - unbound non-static methods
258 261 - help() and className()
259 262
260 263 From within Python, you can import the module "PythonQt" to access these classes and the Qt namespace.
261 264
262 265 \code
263 266 from PythonQt import QtCore
264 267
265 268 # namespace access:
266 269 print QtCore.Qt.AlignLeft
267 270
268 271 # constructors
269 272 a = QtCore.QSize(12,13)
270 273 b = QtCore.QFont()
271 274
272 275 # static method
273 276 QtCore.QDate.currentDate()
274 277
275 278 # enum value
276 279 QtCore.QFont.UltraCondensed
277 280
278 281 \endcode
279 282
280 283 \section Decorators Decorator slots
281 284
282 285 PythonQt introduces a new generic approach to extend any wrapped QObject or CPP object with
283 286
284 287 - constructors
285 288 - destructors (for CPP objects)
286 289 - additional slots
287 290 - static slots (callable on both the Meta object and the instances)
288 291
289 292 The idea behind decorators is that we wanted to make it as easy as possible to extend
290 293 wrapped objects. Since we already have an implementation for invoking any Qt Slot from
291 294 Python, it looked promising to use this approach for the extension of wrapped objects as well.
292 295 This avoids that the PythonQt user needs to care about how Python arguments are mapped from/to
293 296 Qt when he wants to create static methods, constructors and additional member functions.
294 297
295 298 The basic idea about decorators is to create a QObject derived class that implements slots
296 299 which take one of the above roles (e.g. constructor, destructor etc.) via a naming convention.
297 300 These slots are then assigned to other classes via the naming convention.
298 301
299 302 - SomeClassName* new_SomeClassName(...) - defines a constructor for "SomeClassName" that returns a new object of type SomeClassName (where SomeClassName can be any CPP class, not just QObject classes)
300 303 - void delete_SomeClassName(SomeClassName* o) - defines a destructor, which should delete the passed in object o
301 304 - anything static_SomeClassName_someMethodName(...) - defines a static method that is callable on instances and the meta class
302 305 - anything someMethodName(SomeClassName* o, ...) - defines a slot that will be available on SomeClassName instances (and derived instances). When such a slot is called the first argument is the pointer to the instance and the rest of the arguments can be used to make a call on the instance.
303 306
304 307 The below example shows all kinds of decorators in action:
305 308
306 309 \code
307 310
308 311 // an example CPP object
309 312 class YourCPPObject {
310 313 public:
311 314 YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
312 315
313 316 float doSomething(int arg1) { return arg1*a*b; };
314 317
315 318 private:
316 319
317 320 int a;
318 321 float b;
319 322 };
320 323
321 324 // an example decorator
322 325 class ExampleDecorator : public QObject
323 326 {
324 327 Q_OBJECT
325 328
326 329 public slots:
327 330 // add a constructor to QSize that takes a QPoint
328 331 QSize* new_QSize(const QPoint& p) { return new QSize(p.x(), p.y()); }
329 332
330 333 // add a constructor for QPushButton that takes a text and a parent widget
331 334 QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) { return new QPushButton(text, parent); }
332 335
333 336 // add a constructor for a CPP object
334 337 YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new YourCPPObject(arg1, arg2); }
335 338
336 339 // add a destructor for a CPP object
337 340 void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
338 341
339 342 // add a static method to QWidget
340 343 QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
341 344
342 345 // add an additional slot to QWidget (make move() callable, which is not declared as a slot in QWidget)
343 346 void move(QWidget* w, const QPoint& p) { w->move(p); }
344 347
345 348 // add an additional slot to QWidget, overloading the above move method
346 349 void move(QWidget* w, int x, int y) { w->move(x,y); }
347 350
348 351 // add a method to your own CPP object
349 352 int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1); }
350 353 };
351 354
352 355 ...
353 356
354 357 PythonQt::self()->addDecorators(new ExampleDecorator());
355 358 PythonQt::self()->registerCPPClass("YourCPPObject");
356 359
357 360 \endcode
358 361
359 362 After you have registered an instance of the above ExampleDecorator, you can do the following from Python
360 363 (all these calls are mapped to the above decorator slots):
361 364
362 365 \code
363 366 from PythonQt import QtCore, QtGui, YourCPPObject
364 367
365 368 # call our new constructor of QSize
366 369 size = QtCore.QSize(QPoint(1,2));
367 370
368 371 # call our new QPushButton constructor
369 372 button = QtGui.QPushButton("sometext");
370 373
371 374 # call the move slot (overload1)
372 375 button.move(QPoint(0,0))
373 376
374 377 # call the move slot (overload2)
375 378 button.move(0,0)
376 379
377 380 # call the static method
378 381 grabber = QtGui.QWidget.mouseWrapper();
379 382
380 383 # create a CPP object via constructor
381 384 yourCpp = YourCPPObject(1,11.5)
382 385
383 386 # call the wrapped method on CPP object
384 387 print yourCpp.doSomething(1);
385 388
386 389 # destructor will be called:
387 390 yourCpp = None
388 391
389 392 \endcode
390 393
391 394 \section Building
392 395
393 396 PythonQt requires at least Qt 4.6.1 (for earlier Qt versions, you will need to run the pythonqt_gerenator, Qt 4.3 is the absolute minimum) and Python 2.5.x or 2.6.x on Windows, Linux and MacOS X. It has not yet been tested with Python 3.x, but it should only require minor changes.
394 397 To compile PythonQt, you will need a python developer installation which includes Python's header files and
395 398 the python2x.[lib | dll | so | dynlib].
396 399 The build scripts a currently set to use Python 2.6.
397 400 You may need to tweak the \b build/python.prf file to set the correct Python includes and libs on your system.
398 401
399 402 \subsection Windows
400 403
401 404 On Windows, the (non-source) Python Windows installer can be used.
402 405 Make sure that you use the same compiler, the current Python distribution is built
403 406 with Visual Studio 2003. If you want to use another compiler, you will need to build
404 407 Python yourself, using your compiler.
405 408
406 409 To build PythonQt, you need to set the environment variable \b PYTHON_PATH to point to the root
407 410 dir of the python installation and \b PYTHON_LIB to point to
408 411 the directory where the python lib file is located.
409 412
410 413 When using the prebuild Python installer, this will be:
411 414
412 415 \code
413 416 > set PYTHON_PATH = c:\Python25
414 417 > set PYTHON_LIB = c:\Python25\libs
415 418 \endcode
416 419
417 420 When using the python sources, this will be something like:
418 421
419 422 \code
420 423 > set PYTHON_PATH = c:\yourDir\Python-2.5.1\
421 424 > set PYTHON_LIB = c:\yourDir\Python-2.5.1\PCbuild8\Win32
422 425 \endcode
423 426
424 427 To build all, do the following (after setting the above variables):
425 428
426 429 \code
427 430 > cd PythonQtRoot
428 431 > vcvars32
429 432 > qmake
430 433 > nmake
431 434 \endcode
432 435
433 436 This should build everything. If Python can not be linked or include files can not be found,
434 437 you probably need to tweak \b build/python.prf
435 438
436 439 The tests and examples are located in PythonQt/lib.
437 440
438 441 \subsection Linux
439 442
440 443 On Linux, you need to install a Python-dev package.
441 444 If Python can not be linked or include files can not be found,
442 445 you probably need to tweak \b build/python.prf
443 446
444 447 To build PythonQt, just do a:
445 448
446 449 \code
447 450 > cd PythonQtRoot
448 451 > qmake
449 452 > make all
450 453 \endcode
451 454
452 455 The tests and examples are located in PythonQt/lib.
453 456 You should add PythonQt/lib to your LD_LIBRARY_PATH so that the runtime
454 457 linker can find the *.so files.
455 458
456 459 \subsection MacOsX
457 460
458 461 On Mac, Python is installed as a Framework, so you should not need to install it.
459 462 To build PythonQt, just do a:
460 463
461 464 \code
462 465 > cd PythonQtRoot
463 466 > qmake
464 467 > make all
465 468 \endcode
466 469
467 470 \section Tests
468 471
469 472 There is a unit test that tests most features of PythonQt, see the \b tests subdirectory for details.
470 473
471 474 \section Examples
472 475
473 476 Examples are available in the \b examples directory. The PyScriptingConsole implements a simple
474 477 interactive scripting console that shows how to script a simple application.
475 478
476 479 The following shows how to integrate PythonQt into you Qt application:
477 480
478 481 \code
479 482 #include "PythonQt.h"
480 483 #include <QApplication>
481 484 ...
482 485
483 486 int main( int argc, char **argv )
484 487 {
485 488
486 489 QApplication qapp(argc, argv);
487 490
488 491 // init PythonQt and Python itself
489 492 PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
490 493
491 494
492 495 // get a smart pointer to the __main__ module of the Python interpreter
493 496 PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
494 497
495 498 // add a QObject as variable of name "example" to the namespace of the __main__ module
496 499 PyExampleObject example;
497 500 PythonQt::self()->addObject(mainContext, "example", &example);
498 501
499 502 // do something
500 503 PythonQt::self()->runScript(mainContext, "print example\n");
501 504 PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return a*b;\n");
502 505 QVariantList args;
503 506 args << 42 << 47;
504 507 QVariant result = PythonQt::self()->call(mainContext,"multiply", args);
505 508 ...
506 509 \endcode
507 510
508 511
509 512 */
General Comments 0
You need to be logged in to leave comments. Login now