Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/PythonQt/src/PythonQtDoc.h
3206 views
1
#ifndef _PYTHONQTDOC_H
2
#define _PYTHONQTDOC_H
3
4
/*
5
*
6
* Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
7
*
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2.1 of the License, or (at your option) any later version.
12
*
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
17
*
18
* Further, this software is distributed without any warranty that it is
19
* free of the rightful claim of any third person regarding infringement
20
* or the like. Any license provided herein, whether implied or
21
* otherwise, applies only to this software file. Patent licenses, if
22
* any, provided herein do not apply to combinations of this program with
23
* other software, or any other product whatsoever.
24
*
25
* You should have received a copy of the GNU Lesser General Public
26
* License along with this library; if not, write to the Free Software
27
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
*
29
* Contact information: MeVis Research GmbH, Universitaetsallee 29,
30
* 28359 Bremen, Germany or:
31
*
32
* http://www.mevis.de
33
*
34
*/
35
36
//----------------------------------------------------------------------------------
37
/*!
38
// \file PythonQtDoc.h
39
// \author Florian Link
40
// \author Last changed by $Author: florian $
41
// \date 2006-10
42
*/
43
//----------------------------------------------------------------------------------
44
45
/*!
46
\mainpage
47
48
\section Introduction
49
50
\b PythonQt is a dynamic Python (http://www.python.org) binding for Qt
51
(http://www.trolltech.com). It offers an easy way to embed the Python scripting
52
language into your Qt applications. It makes heavy use of the QMetaObject system
53
and thus requires Qt4.x.
54
55
In contrast to <a href="http://www.riverbankcomputing.co.uk/pyqt/">PyQt</a> ,
56
PythonQt is \b not a complete Python wrapper around the complete Qt
57
functionality. So if you are looking for a way to write complete applications in
58
Python using the Qt GUI, you should use PyQt.
59
60
If you are looking for a simple way to embed the Python language into your Qt
61
Application and to script parts of your application via Python, PythonQt is the
62
way to go!
63
64
PythonQt is a stable library that was developed to make the Image Processing
65
and Visualization platform MeVisLab (http://www.mevislab.de) scriptable from
66
Python.
67
68
\section Licensing
69
70
PythonQt is distributed under the LGPL license.
71
72
\section Download
73
74
PythonQt is hosted on SourceForge at http://sourceforge.net/projects/pythonqt ,
75
you can access it via SVN or download a tarball.
76
77
\section Features
78
79
- Access all \b slots, \b properties, children and registered enums of any
80
QObject derived class from Python
81
- Connecting Qt Signals to Python functions (both from within Python and from
82
C++)
83
- Wrapping of C++ objects (which are not derived from QObject) via
84
PythonQtCPPWrapperFactory
85
- Extending C++ and QObject derived classes with additional slots, static
86
methods and constructors (see Decorators)
87
- StdOut/Err redirection to Qt signals instead of cout
88
- Interface for creating your own \c import replacement, so that Python scripts
89
can be e.g. signed/verified before they are executed (PythonQtImportInterface)
90
- Mapping of plain-old-datatypes and ALL QVariant types to and from Python
91
- Support for wrapping of user QVariant types which are registered via
92
QMetaType
93
- Support for Qt namespace (with all enumerators)
94
- All PythonQt wrapped objects support the dir() statement, so that you can see
95
easily which attributes a QObject, CPP object or QVariant has
96
- No preprocessing/wrapping tool needs to be started, PythonQt can script any
97
QObject without prior knowledge about it (except for the MetaObject information
98
from the \b moc)
99
100
\section Non-Features
101
102
Features that PythonQt does NOT support (and will not support):
103
104
- you can not derive from QObjects inside of Python, this would require wrapper
105
generation like PyQt does
106
- you can only script QObject derived classes, for normal C++ classes you need
107
to create a PythonQtCPPWrapperFactory and adequate wrapper classes or add
108
decorator slots
109
- you can not access normal member functions of QObjects, only slots and
110
properties, because the \b moc does not store normal member functions in the
111
MetaObject system
112
113
\section Interface
114
115
The main interface to PythonQt is the PythonQt singleton.
116
PythonQt needs to be initialized via PythonQt::init() once.
117
Afterwards you communicate with the singleton via PythonQt::self().
118
PythonQt offers a default binding for the complete QWidget set, which
119
needs to be enabled via PythonQtGui::init().
120
121
122
\section Datatype Datatype Mapping
123
124
The following table shows the mapping between Python and Qt objects:
125
<table>
126
<tr><th>Qt/C++</th><th>Python</th></tr>
127
<tr><td>bool</td><td>bool</td></tr>
128
<tr><td>double</td><td>float</td></tr>
129
<tr><td>float</td><td>float</td></tr>
130
<tr><td>char/uchar,int/uint,short,ushort,QChar</td><td>integer</td></tr>
131
<tr><td>long</td><td>integer</td></tr>
132
<tr><td>ulong,longlong,ulonglong</td><td>long</td></tr>
133
<tr><td>QString</td><td>unicode string</td></tr>
134
<tr><td>QByteArray</td><td>str</td></tr>
135
<tr><td>char*</td><td>str</td></tr>
136
<tr><td>QStringList</td><td>tuple of unicode strings</td></tr>
137
<tr><td>QVariantList</td><td>tuple of objects</td></tr>
138
<tr><td>QVariantMap</td><td>dict of objects</td></tr>
139
<tr><td>QVariant</td><td>depends on type, see below</td></tr>
140
<tr><td>QSize, QRect and all other standard Qt QVariants</td><td>variant
141
wrapper that supports complete API of the respective Qt classes</td></tr>
142
<tr><td>OwnRegisteredMetaType</td><td>variant wrapper, optionally with a
143
wrapper provided by addVariantWrapper()</td></tr>
144
<tr><td>EnumType</td><td>integer (all enums that are known via the moc and the
145
Qt namespace are supported)</td></tr> <tr><td>QObject (and derived
146
classes)</td><td>QObject wrapper</td></tr> <tr><td>C++ object</td><td>CPP
147
wrapper, either wrapped via PythonQtCPPWrapperFactory or just decorated with
148
decorators</td></tr> <tr><td>PyObject</td><td>PyObject</td></tr>
149
</table>
150
151
PyObject is passed as simple pointer, which allows to pass/return any Python
152
Object directly to/from a Qt slot. QVariants are mapped recursively as given
153
above, e.g. a dictionary can contain lists of dictionaries of doubles. For
154
example a QVariant of type "String" is mapped to a python unicode string. All Qt
155
QVariant types are implemented, PythonQt supports the complete Qt API for these
156
object.
157
158
\section QObject QObject Wrapping
159
160
All classes derived from QObject are automatically wrapped with a python
161
wrapper class when they become visible to the Python interpreter. This can
162
happen via
163
- the PythonQt::addObject() method
164
- when a Qt \b slot returns a QObject derived object to python
165
- when a Qt \b signal contains a QObject and is connected to a python function
166
167
It is important that you call PythonQt::registerClass() for any QObject derived
168
class that may become visible to Python, except when you add it via
169
PythonQt::addObject(). This will register the complete parent hierarchy of the
170
registered class, so that when you register e.g. a QPushButton, QWidget will be
171
registered as well (and all intermediate parents).
172
173
From Python, you can talk to the returned QObjects in a natural way by calling
174
their slots and receiving the return values. You can also read/write all
175
properties of the objects as if they where normal python properties.
176
177
In addition to this, the wrapped objects support
178
- className() - returns a string that represents the classname of the QObject
179
- help() - shows all properties, slots, enums, decorator slots and constructors
180
of the object, in a printable form
181
- connect(signal, function) - connect the signal of the given object to a
182
python function
183
- connect(signal, qobject, slot) - connect the signal of the given object to a
184
slot of another QObject
185
- disconnect(signal, function) - disconnect the signal of the given object from
186
a python function
187
- disconnect(signal, qobject, slot) - disconnect the signal of the given object
188
from a slot of another QObject
189
- children() - returns the children of the object
190
- setParent(QObject) - set the parent
191
- QObject* parent() - get the parent
192
193
The below example shows how to connect signals in Python:
194
195
\code
196
# define a signal handler function
197
def someFunction(flag):
198
print flag
199
200
# button1 is a QPushButton that has been added to Python via addObject()
201
# connect the clicked signal to a python function:
202
button1.connect("clicked(bool)", someFunction)
203
204
\endcode
205
206
\section CPP CPP Wrapping
207
208
You can create dedicated wrapper QObject for any C++ class. This is done by
209
deriving from PythonQtCPPWrapperFactory and adding your factory via
210
addWrapperFactory(). Whenever PythonQt encounters a CPP pointer (e.g. on a slot
211
or signal) and it does not known it as a QObject derived class, it will create a
212
generic CPP wrapper. So even unknown C++ objects can be passed through Python.
213
If the wrapper factory supports the CPP class, a QObject wrapper will be created
214
for each instance that enters Python. An alternative to a complete wrapper via
215
the wrapper factory are decorators, see \ref Decorators
216
217
\section MetaObject Meta Object/Class access
218
219
For each known CPP class, QObject derived class and QVariant type, PythonQt
220
provides a Meta class. These meta classes are visible inside of the "PythonQt"
221
python module.
222
223
A Meta class supports:
224
225
- access to all declared enum values
226
- constructors
227
- static decorator slots
228
- help() and className()
229
230
From within Python, you can import the module "PythonQt" to access these meta
231
objects and the Qt namespace.
232
233
\code
234
from PythonQt import *
235
236
# namespace access:
237
print Qt.AlignLeft
238
239
# constructors
240
a = QSize(12,13)
241
b = QFont()
242
243
# static method
244
QDate.currentDate()
245
246
# enum value
247
QFont.UltraCondensed
248
249
\endcode
250
251
\section Decorators Decorator slots
252
253
PythonQt introduces a new generic approach to extend any wrapped QObject or CPP
254
object with
255
256
- constructors
257
- destructors (for CPP objects)
258
- additional slots
259
- static slots (callable on both the Meta object and the instances)
260
261
The idea behind decorators is that we wanted to make it as easy as possible to
262
extend wrapped objects. Since we already have an implementation for invoking any
263
Qt Slot from Python, it looked promising to use this approach for the extension
264
of wrapped objects as well. This avoids that the PythonQt user needs to care
265
about how Python arguments are mapped from/to Qt when he wants to create static
266
methods, constructors and additional member functions.
267
268
The basic idea about decorators is to create a QObject derived class that
269
implements slots which take one of the above roles (e.g. constructor, destructor
270
etc.) via a naming convention. These slots are then assigned to other classes
271
via the naming convention.
272
273
- QVariant new_SomeClassName(...) - defines a constructor for "SomeClassName"
274
that returns a QVariant
275
- SomeClassName* new_SomeClassName(...) - defines a constructor for
276
"SomeClassName" that returns a new object of type SomeClassName (where
277
SomeClassName can be any CPP class, not just QObject classes)
278
- void delete_SomeClassName(SomeClassName* o) - defines a destructor, which
279
should delete the passed in object o
280
- anything static_SomeClassName_someMethodName(...) - defines a static method
281
that is callable on instances and the meta class
282
- anything someMethodName(SomeClassName* o, ...) - defines a slot that will be
283
available on SomeClassName instances (and derived instances). When such a slot
284
is called the first argument is the pointer to the instance and the rest of the
285
arguments can be used to make a call on the instance.
286
287
The below example shows all kinds of decorators in action:
288
289
\code
290
291
// an example CPP object
292
class YourCPPObject {
293
public:
294
YourCPPObject(int arg1, float arg2) { a = arg1; b = arg2; }
295
296
float doSomething(int arg1) { return arg1*a*b; };
297
298
private:
299
300
int a;
301
float b;
302
};
303
304
// an example decorator
305
class ExampleDecorator : public QObject
306
{
307
Q_OBJECT
308
309
public slots:
310
// add a constructor to QSize variant that takes a QPoint
311
QVariant new_QSize(const QPoint& p) { return QSize(p.x(), p.y()); }
312
313
// add a constructor for QPushButton that takes a text and a parent widget
314
QPushButton* new_QPushButton(const QString& text, QWidget* parent=NULL) {
315
return new QPushButton(text, parent); }
316
317
// add a constructor for a CPP object
318
YourCPPObject* new_YourCPPObject(int arg1, float arg2) { return new
319
YourCPPObject(arg1, arg2); }
320
321
// add a destructor for a CPP object
322
void delete_YourCPPObject(YourCPPObject* obj) { delete obj; }
323
324
// add a static method to QWidget
325
QWidget* static_QWidget_mouseGrabber() { return QWidget::mouseGrabber(); }
326
327
// add an additional slot to QWidget (make move() callable, which is not
328
declared as a slot in QWidget) void move(QWidget* w, const QPoint& p) {
329
w->move(p); }
330
331
// add an additional slot to QWidget, overloading the above move method
332
void move(QWidget* w, int x, int y) { w->move(x,y); }
333
334
// add a method to your own CPP object
335
int doSomething(YourCPPObject* obj, int arg1) { return obj->doSomething(arg1);
336
}
337
};
338
339
...
340
341
PythonQt::self()->addDecorators(new ExampleDecorator());
342
PythonQt::self()->registerClass(&QPushButton::staticMetaObject);
343
PythonQt::self()->registerCPPClassNames(QStringList() << "YourCPPObject");
344
345
\endcode
346
347
After you have registered an instance of the above ExampleDecorator, you can do
348
the following from Python (all these calls are mapped to the above decorator
349
slots):
350
351
\code
352
from PythonQt import *
353
354
# call our new constructor of QSize
355
size = QSize(QPoint(1,2));
356
357
# call our new QPushButton constructor
358
button = QPushButton("sometext");
359
360
# call the move slot (overload1)
361
button.move(QPoint(0,0))
362
363
# call the move slot (overload2)
364
button.move(0,0)
365
366
# call the static method
367
grabber = QWidget.mouseWrapper();
368
369
# create a CPP object via constructor
370
yourCpp = YourCPPObject(1,11.5)
371
372
# call the wrapped method on CPP object
373
print yourCpp.doSomething(1);
374
375
# destructor will be called:
376
yourCpp = None
377
378
\endcode
379
380
\section Building
381
382
PythonQt requires at least Qt 4.2.2 (or higher) and Python 2.3, 2.4 and 2.5 on
383
Windows, Linux and MacOS X. To compile PythonQt, you will need a python
384
developer installation which includes Python's header files and the
385
python2x.[lib | dll | so | dynlib].
386
387
For building PythonQt, you will need to set some environment variables:
388
\b PYTHON_ROOT should point to the Python sources/headers.
389
\b PYTHON_LIB should point to where the Python library files are located.
390
\b PYTHONQT_ROOT should point to the root directory of PythonQt.
391
392
Run qmake on PythonQt.pro to generate a project file for your system and then
393
build it.
394
395
\section Tests
396
397
There is a unit test that tests most features of PythonQt, see the \b tests
398
subdirectory for details.
399
400
\section Examples
401
402
Examples are available in the \b examples directory. The PyScriptingConsole
403
implements a simple interactive scripting console that shows how to script a
404
simple application.
405
406
The following shows how to integrate PythonQt into you Qt application:
407
408
\code
409
#include "PythonQt.h"
410
#include <QApplication>
411
...
412
413
int main( int argc, char **argv )
414
{
415
416
QApplication qapp(argc, argv);
417
418
// init PythonQt and Python itself
419
PythonQt::init(PythonQt::IgnoreSiteModule | PythonQt::RedirectStdOut);
420
421
// get a smart pointer to the __main__ module of the Python interpreter
422
PythonQtObjectPtr mainContext = PythonQt::self()->getMainModule();
423
424
// add a QObject as variable of name "example" to the namespace of the
425
__main__ module PyExampleObject example;
426
PythonQt::self()->addObject(mainContext, "example", &example);
427
428
// register all other QObjects that you want to script and that are returned
429
by your API PythonQt::self()->registerClass(&QMainWindow::staticMetaObject);
430
PythonQt::self()->registerClass(&QPushButton::staticMetaObject);
431
...
432
433
// do something
434
PythonQt::self()->runScript(mainContext, "print example\n");
435
PythonQt::self()->runScript(mainContext, "def multiply(a,b):\n return
436
a*b;\n"); QVariantList args; args << 42 << 47; QVariant result =
437
PythonQt::self()->call(mainContext,"multiply", args);
438
...
439
\endcode
440
441
442
\section TODOs
443
444
- improve qmake profiles for non mevis users
445
- add more information on how to distribute an application that uses PythonQt,
446
including the Python distribution
447
448
*/
449
450