@@ -149,12 +149,14 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName) | |||||
149 |
|
149 | |||
150 | _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr"); |
|
150 | _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr"); | |
151 |
|
151 | |||
|
152 | if (flags & PythonAlreadyInitialized == 0) { | |||
152 | Py_SetProgramName("PythonQt"); |
|
153 | Py_SetProgramName("PythonQt"); | |
153 | if (flags & IgnoreSiteModule) { |
|
154 | if (flags & IgnoreSiteModule) { | |
154 | // this prevents the automatic importing of Python site files |
|
155 | // this prevents the automatic importing of Python site files | |
155 | Py_NoSiteFlag = 1; |
|
156 | Py_NoSiteFlag = 1; | |
156 | } |
|
157 | } | |
157 | Py_Initialize(); |
|
158 | Py_Initialize(); | |
|
159 | } | |||
158 |
|
160 | |||
159 |
|
|
161 | // add our own python object types for qt object slots | |
160 | if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) { |
|
162 | if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) { | |
@@ -554,6 +556,14 PythonQtObjectPtr PythonQt::getMainModule() { | |||||
554 | return PyDict_GetItemString(dict, "__main__"); |
|
556 | return PyDict_GetItemString(dict, "__main__"); | |
555 | } |
|
557 | } | |
556 |
|
558 | |||
|
559 | PythonQtObjectPtr PythonQt::importModule(const QString& name) | |||
|
560 | { | |||
|
561 | PythonQtObjectPtr mod; | |||
|
562 | mod.setNewRef(PyImport_ImportModule(name.toLatin1().constData())); | |||
|
563 | return mod; | |||
|
564 | } | |||
|
565 | ||||
|
566 | ||||
557 | QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) { |
|
567 | QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) { | |
558 | QVariant result; |
|
568 | QVariant result; | |
559 | if (pycode) { |
|
569 | if (pycode) { |
@@ -84,16 +84,27 typedef QObject* PythonQtQObjectCreatorFunctionCB(); | |||||
84 | //! helper template to create a derived QObject class |
|
84 | //! helper template to create a derived QObject class | |
85 | template<class T> QObject* PythonQtCreateObject() { return new T(); }; |
|
85 | template<class T> QObject* PythonQtCreateObject() { return new T(); }; | |
86 |
|
86 | |||
87 |
//! |
|
87 | //! The main interface to the Python Qt binding, realized as a singleton | |
|
88 | /*! | |||
|
89 | Use PythonQt::init() to initialize the singleton and PythonQt::self() to access it. | |||
|
90 | While there can be only one PythonQt instance, you can have any number of Python context to do scripting in. | |||
|
91 | One possibility is to use createModuleFromFile(), createModuleFromScript() or createUniqueModule() to get a context | |||
|
92 | that is separated from the other contexts. Alternatively you can use Python dicts as contexts for script evaluation, | |||
|
93 | but you will need to populate the dict with the __builtins__ instance to have all Pythons available when running | |||
|
94 | code in the scope of a dict. | |||
|
95 | */ | |||
88 | class PYTHONQT_EXPORT PythonQt : public QObject { |
|
96 | class PYTHONQT_EXPORT PythonQt : public QObject { | |
89 |
|
97 | |||
90 | Q_OBJECT |
|
98 | Q_OBJECT | |
91 |
|
99 | |||
92 | public: |
|
100 | public: | |
|
101 | ||||
|
102 | //! flags that can be passed to PythonQt::init() | |||
93 | enum InitFlags { |
|
103 | enum InitFlags { | |
94 | RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals |
|
104 | RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals | |
95 | IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module |
|
105 | IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module | |
96 |
ExternalHelp = 4 |
|
106 | ExternalHelp = 4, //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal | |
|
107 | PythonAlreadyInitialized = 8 //!<< sets that PythonQt should not can PyInitialize, since it is already done | |||
97 | }; |
|
108 | }; | |
98 |
|
109 | |||
99 | //! flags that tell PythonQt which operators to expect on the registered type |
|
110 | //! flags that tell PythonQt which operators to expect on the registered type | |
@@ -132,19 +143,22 public: | |||||
132 |
|
143 | |||
133 | }; |
|
144 | }; | |
134 |
|
145 | |||
135 | //! initialize the python qt binding (flags are a or combination of InitFlags), if \c pythonQtModuleName is given |
|
146 | //--------------------------------------------------------------------------- | |
|
147 | //! \name Singleton Initialization | |||
|
148 | //@{ | |||
|
149 | ||||
|
150 | //! initialize the python qt binding (flags are a or combination of PythonQt::InitFlags), if \c pythonQtModuleName is given | |||
136 | //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used. |
|
151 | //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used. | |
137 | //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible. |
|
152 | //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible. | |
138 | static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray()); |
|
153 | static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray()); | |
139 |
|
154 | |||
140 | //! cleanup |
|
155 | //! cleanup of the singleton | |
141 | static void cleanup(); |
|
156 | static void cleanup(); | |
142 |
|
157 | |||
143 | //! get the singleton instance |
|
158 | //! get the singleton instance | |
144 | static PythonQt* self() { return _self; } |
|
159 | static PythonQt* self() { return _self; } | |
145 |
|
160 | |||
146 | //----------------------------------------------------------------------------- |
|
161 | //@} | |
147 | // Public API: |
|
|||
148 |
|
162 | |||
149 |
|
|
163 | //! defines the object types for introspection | |
150 | enum ObjectType { |
|
164 | enum ObjectType { | |
@@ -156,6 +170,39 public: | |||||
156 | CallOverloads |
|
170 | CallOverloads | |
157 | }; |
|
171 | }; | |
158 |
|
172 | |||
|
173 | //--------------------------------------------------------------------------- | |||
|
174 | //! \name Modules | |||
|
175 | //@{ | |||
|
176 | ||||
|
177 | //! get the __main__ module of python | |||
|
178 | PythonQtObjectPtr getMainModule(); | |||
|
179 | ||||
|
180 | //! import the given module and return a reference to it (useful to import e.g. "sys" and call something on it) | |||
|
181 | //! If a module is already imported, this returns the already imported module. | |||
|
182 | PythonQtObjectPtr importModule(const QString& name); | |||
|
183 | ||||
|
184 | //! creates the new module \c name and evaluates the given file in the context of that module | |||
|
185 | //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code | |||
|
186 | //! to a module later on. | |||
|
187 | //! The user needs to make sure that the \c name is unique in the python module dictionary. | |||
|
188 | PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename); | |||
|
189 | ||||
|
190 | //! creates the new module \c name and evaluates the given script in the context of that module. | |||
|
191 | //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code | |||
|
192 | //! to a module later on. | |||
|
193 | //! The user needs to make sure that the \c name is unique in the python module dictionary. | |||
|
194 | PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString()); | |||
|
195 | ||||
|
196 | //! create a uniquely named module, you can use evalFile or evalScript to populate the module with | |||
|
197 | //! script code | |||
|
198 | PythonQtObjectPtr createUniqueModule(); | |||
|
199 | ||||
|
200 | //@} | |||
|
201 | ||||
|
202 | //--------------------------------------------------------------------------- | |||
|
203 | //! \name Importing/Paths | |||
|
204 | //@{ | |||
|
205 | ||||
159 | //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path) |
|
206 | //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path) | |
160 | void overwriteSysPath(const QStringList& paths); |
|
207 | void overwriteSysPath(const QStringList& paths); | |
161 |
|
208 | |||
@@ -165,8 +212,11 public: | |||||
165 | //! sets the __path__ list of a module to the given list (important for local imports) |
|
212 | //! sets the __path__ list of a module to the given list (important for local imports) | |
166 | void setModuleImportPath(PyObject* module, const QStringList& paths); |
|
213 | void setModuleImportPath(PyObject* module, const QStringList& paths); | |
167 |
|
214 | |||
168 | //! get the __main__ module of python |
|
215 | //@} | |
169 | PythonQtObjectPtr getMainModule(); |
|
216 | ||
|
217 | //--------------------------------------------------------------------------- | |||
|
218 | //! \name Registering Classes | |||
|
219 | //@{ | |||
170 |
|
220 | |||
171 |
|
|
221 | //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well) | |
172 | /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject, |
|
222 | /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject, | |
@@ -196,6 +246,12 public: | |||||
196 | //! add a handler for polymorphic downcasting |
|
246 | //! add a handler for polymorphic downcasting | |
197 | void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb); |
|
247 | void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb); | |
198 |
|
248 | |||
|
249 | //@} | |||
|
250 | ||||
|
251 | //--------------------------------------------------------------------------- | |||
|
252 | //! \name Script Parsing and Evaluation | |||
|
253 | //@{ | |||
|
254 | ||||
199 |
|
|
255 | //! parses the given file and returns the python code object, this can then be used to call evalCode() | |
200 | PythonQtObjectPtr parseFile(const QString& filename); |
|
256 | PythonQtObjectPtr parseFile(const QString& filename); | |
201 |
|
257 | |||
@@ -209,23 +265,11 public: | |||||
209 | //! evaluates the given script code from file |
|
265 | //! evaluates the given script code from file | |
210 | void evalFile(PyObject* object, const QString& filename); |
|
266 | void evalFile(PyObject* object, const QString& filename); | |
211 |
|
267 | |||
212 | //! creates the new module \c name and evaluates the given file in the context of that module |
|
268 | //@} | |
213 | //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code |
|
|||
214 | //! to a module later on. |
|
|||
215 | //! The user needs to make sure that the \c name is unique in the python module dictionary. |
|
|||
216 | PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename); |
|
|||
217 |
|
||||
218 | //! creates the new module \c name and evaluates the given script in the context of that module. |
|
|||
219 | //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code |
|
|||
220 | //! to a module later on. |
|
|||
221 | //! The user needs to make sure that the \c name is unique in the python module dictionary. |
|
|||
222 | PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString()); |
|
|||
223 |
|
||||
224 | //! create a uniquely named module, you can use evalFile or evalScript to populate the module with |
|
|||
225 | //! script code |
|
|||
226 | PythonQtObjectPtr createUniqueModule(); |
|
|||
227 |
|
269 | |||
228 | //@{ Signal handlers |
|
270 | //--------------------------------------------------------------------------- | |
|
271 | //! \name Signal Handlers | |||
|
272 | //@{ | |||
229 |
|
273 | |||
230 | //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module |
|
274 | //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module | |
231 | bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname); |
|
275 | bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname); | |
@@ -241,7 +285,9 public: | |||||
241 |
|
285 | |||
242 | //@} |
|
286 | //@} | |
243 |
|
287 | |||
244 | //@{ Variable access |
|
288 | //--------------------------------------------------------------------------- | |
|
289 | //! \name Variable access | |||
|
290 | //@{ | |||
245 |
|
291 | |||
246 | //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable) |
|
292 | //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable) | |
247 | void addObject(PyObject* object, const QString& name, QObject* qObject); |
|
293 | void addObject(PyObject* object, const QString& name, QObject* qObject); | |
@@ -264,7 +310,9 public: | |||||
264 |
|
310 | |||
265 | //@} |
|
311 | //@} | |
266 |
|
312 | |||
267 | //@{ Calling of python callables |
|
313 | //--------------------------------------------------------------------------- | |
|
314 | //! \name Calling Python Objects | |||
|
315 | //@{ | |||
268 |
|
316 | |||
269 | //! call the given python \c callable in the scope of object, returns the result converted to a QVariant |
|
317 | //! call the given python \c callable in the scope of object, returns the result converted to a QVariant | |
270 | QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList()); |
|
318 | QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList()); | |
@@ -277,8 +325,9 public: | |||||
277 |
|
325 | |||
278 | //@} |
|
326 | //@} | |
279 |
|
327 | |||
280 | //@{ Decorations, constructors, wrappers... |
|
328 | //--------------------------------------------------------------------------- | |
281 |
|
329 | //! \name Decorations, Constructors, Wrappers... | ||
|
330 | //@{ | |||
282 |
|
331 | |||
283 | //! add an object whose slots will be used as decorator slots for |
|
332 | //! add an object whose slots will be used as decorator slots for | |
284 | //! other QObjects or CPP classes. The slots need to follow the |
|
333 | //! other QObjects or CPP classes. The slots need to follow the | |
@@ -333,7 +382,9 public: | |||||
333 |
|
382 | |||
334 | //@} |
|
383 | //@} | |
335 |
|
384 | |||
336 | //@{ Custom importer (to replace internal import implementation of python) |
|
385 | //--------------------------------------------------------------------------- | |
|
386 | //! \name Custom Importer | |||
|
387 | //@{ | |||
337 |
|
388 | |||
338 |
|
|
389 | //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files) | |
339 | //! (this method should be called directly after initialization of init() and before calling overwriteSysPath(). |
|
390 | //! (this method should be called directly after initialization of init() and before calling overwriteSysPath(). | |
@@ -360,14 +411,18 public: | |||||
360 | //! get paths that the importer should ignore |
|
411 | //! get paths that the importer should ignore | |
361 | const QStringList& getImporterIgnorePaths(); |
|
412 | const QStringList& getImporterIgnorePaths(); | |
362 |
|
413 | |||
|
414 | //! get access to the file importer (if set) | |||
|
415 | static PythonQtImportFileInterface* importInterface(); | |||
|
416 | ||||
363 | //@} |
|
417 | //@} | |
364 |
|
418 | |||
|
419 | //--------------------------------------------------------------------------- | |||
|
420 | //! \name Other Stuff | |||
|
421 | //@{ | |||
|
422 | ||||
365 | //! get access to internal data (should not be used on the public API, but is used by some C functions) |
|
423 | //! get access to internal data (should not be used on the public API, but is used by some C functions) | |
366 | static PythonQtPrivate* priv() { return _self->_p; } |
|
424 | static PythonQtPrivate* priv() { return _self->_p; } | |
367 |
|
425 | |||
368 | //! get access to the file importer (if set) |
|
|||
369 | static PythonQtImportFileInterface* importInterface(); |
|
|||
370 |
|
||||
371 | //! handle a python error, call this when a python function fails. If no error occurred, it returns false. |
|
426 | //! handle a python error, call this when a python function fails. If no error occurred, it returns false. | |
372 | //! The error is currently just output to the python stderr, future version might implement better trace printing |
|
427 | //! The error is currently just output to the python stderr, future version might implement better trace printing | |
373 | bool handleError(); |
|
428 | bool handleError(); | |
@@ -380,6 +435,15 public: | |||||
380 | //! call the callback if it is set |
|
435 | //! call the callback if it is set | |
381 | static void qObjectNoLongerWrappedCB(QObject* o); |
|
436 | static void qObjectNoLongerWrappedCB(QObject* o); | |
382 |
|
437 | |||
|
438 | //! called by internal help methods | |||
|
439 | PyObject* helpCalled(PythonQtClassInfo* info); | |||
|
440 | ||||
|
441 | //! returns the found object or NULL | |||
|
442 | //! @return new reference | |||
|
443 | PythonQtObjectPtr lookupObject(PyObject* module, const QString& name); | |||
|
444 | ||||
|
445 | //@} | |||
|
446 | ||||
383 | signals: |
|
447 | signals: | |
384 | //! emitted when python outputs something to stdout (and redirection is turned on) |
|
448 | //! emitted when python outputs something to stdout (and redirection is turned on) | |
385 | void pythonStdOut(const QString& str); |
|
449 | void pythonStdOut(const QString& str); | |
@@ -389,15 +453,6 signals: | |||||
389 | //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled |
|
453 | //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled | |
390 | void pythonHelpRequest(const QByteArray& cppClassName); |
|
454 | void pythonHelpRequest(const QByteArray& cppClassName); | |
391 |
|
455 | |||
392 |
|
||||
393 | public: |
|
|||
394 | //! called by internal help methods |
|
|||
395 | PyObject* helpCalled(PythonQtClassInfo* info); |
|
|||
396 |
|
||||
397 | //! returns the found object or NULL |
|
|||
398 | //! @return new reference |
|
|||
399 | PythonQtObjectPtr lookupObject(PyObject* module, const QString& name); |
|
|||
400 |
|
||||
401 | private: |
|
456 | private: | |
402 | void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName); |
|
457 | void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName); | |
403 |
|
458 |
General Comments 0
You need to be logged in to leave comments.
Login now