mirror of
https://github.com/thp/pyotherside.git
synced 2025-01-17 23:22:53 +08:00
Add API documentation using Doxygen
This commit is contained in:
parent
0c8bd9e07a
commit
ad62b4dc2b
@ -17,12 +17,12 @@
|
||||
**/
|
||||
|
||||
#include "pyotherside_plugin.h"
|
||||
#include "qpython.h"
|
||||
#include "qpython_priv.h"
|
||||
|
||||
static void
|
||||
pyotherside_atexit()
|
||||
{
|
||||
QPython::closing();
|
||||
QPythonPriv::closing();
|
||||
}
|
||||
|
||||
PyOtherSideExtensionPlugin::PyOtherSideExtensionPlugin()
|
||||
|
@ -26,6 +26,25 @@
|
||||
#include <QJSEngine>
|
||||
|
||||
|
||||
class QPythonWorker : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QPythonWorker(QPython *qpython);
|
||||
~QPythonWorker();
|
||||
|
||||
public slots:
|
||||
void process(QString func, QVariant args, QJSValue callback);
|
||||
void import(QString func, QJSValue callback);
|
||||
|
||||
signals:
|
||||
void finished(QVariant result, QJSValue callback);
|
||||
void imported(bool result, QJSValue callback);
|
||||
|
||||
private:
|
||||
QPython *qpython;
|
||||
};
|
||||
|
||||
QPythonWorker::QPythonWorker(QPython *qpython)
|
||||
: QObject()
|
||||
, qpython(qpython)
|
||||
@ -55,7 +74,7 @@ QPython::priv = NULL;
|
||||
|
||||
QPython::QPython(QObject *parent)
|
||||
: QObject(parent)
|
||||
, worker(this)
|
||||
, worker(new QPythonWorker(this))
|
||||
, thread()
|
||||
, handlers()
|
||||
{
|
||||
@ -63,20 +82,20 @@ QPython::QPython(QObject *parent)
|
||||
priv = new QPythonPriv;
|
||||
}
|
||||
|
||||
worker.moveToThread(&thread);
|
||||
worker->moveToThread(&thread);
|
||||
|
||||
QObject::connect(priv, SIGNAL(receive(QVariant)),
|
||||
this, SLOT(receive(QVariant)));
|
||||
|
||||
QObject::connect(this, SIGNAL(process(QString,QVariant,QJSValue)),
|
||||
&worker, SLOT(process(QString,QVariant,QJSValue)));
|
||||
QObject::connect(&worker, SIGNAL(finished(QVariant,QJSValue)),
|
||||
this, SLOT(finished(QVariant,QJSValue)));
|
||||
worker, SLOT(process(QString,QVariant,QJSValue)));
|
||||
QObject::connect(worker, SIGNAL(finished(QVariant,QJSValue)),
|
||||
this, SLOT(finished(QVariant,QJSValue)));
|
||||
|
||||
QObject::connect(this, SIGNAL(import(QString,QJSValue)),
|
||||
&worker, SLOT(import(QString,QJSValue)));
|
||||
QObject::connect(&worker, SIGNAL(imported(bool,QJSValue)),
|
||||
this, SLOT(imported(bool,QJSValue)));
|
||||
worker, SLOT(import(QString,QJSValue)));
|
||||
QObject::connect(worker, SIGNAL(imported(bool,QJSValue)),
|
||||
this, SLOT(imported(bool,QJSValue)));
|
||||
|
||||
thread.start();
|
||||
}
|
||||
@ -85,6 +104,8 @@ QPython::~QPython()
|
||||
{
|
||||
thread.quit();
|
||||
thread.wait();
|
||||
|
||||
delete worker;
|
||||
}
|
||||
|
||||
void
|
||||
@ -242,12 +263,3 @@ QPython::imported(bool result, QJSValue callback)
|
||||
callback.call(args);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPython::closing()
|
||||
{
|
||||
priv->enter();
|
||||
priv->closing();
|
||||
priv->leave();
|
||||
}
|
||||
|
||||
|
222
src/qpython.h
222
src/qpython.h
@ -30,68 +30,238 @@
|
||||
|
||||
class QPython;
|
||||
class QPythonPriv;
|
||||
|
||||
class QPythonWorker : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QPythonWorker(QPython *qpython);
|
||||
~QPythonWorker();
|
||||
|
||||
public slots:
|
||||
void process(QString func, QVariant args, QJSValue callback);
|
||||
void import(QString func, QJSValue callback);
|
||||
|
||||
signals:
|
||||
void finished(QVariant result, QJSValue callback);
|
||||
void imported(bool result, QJSValue callback);
|
||||
|
||||
private:
|
||||
QPython *qpython;
|
||||
};
|
||||
class QPythonWorker;
|
||||
|
||||
class QPython : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* \brief Create a new Python instance
|
||||
*
|
||||
* A new Python instance can be created in QML as follows:
|
||||
*
|
||||
* \code
|
||||
* import io.thp.pyotherside 1.0
|
||||
*
|
||||
* Python {
|
||||
* id: py
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \arg parent The parent QObject
|
||||
**/
|
||||
QPython(QObject *parent=NULL);
|
||||
|
||||
virtual ~QPython();
|
||||
|
||||
/**
|
||||
* \brief Add a local filesystem path to Python's sys.path.
|
||||
*
|
||||
* The import path will be added synchronously. After the call
|
||||
* returns, the new import path will already be in effect.
|
||||
*
|
||||
* \arg path Directory that will be added to the search path
|
||||
**/
|
||||
Q_INVOKABLE void
|
||||
addImportPath(QString path);
|
||||
|
||||
/**
|
||||
* \brief Add a handler for events sent with \c pyotherside.send()
|
||||
*
|
||||
* The provided \a callback will be called whenever the first argument
|
||||
* to \c pyotherside.send() matches the \a event argument.
|
||||
*
|
||||
* For example, when the Python code contains a call like this:
|
||||
*
|
||||
* \code
|
||||
* import pyotherside
|
||||
*
|
||||
* pyotherside.call('new-entries', 100, 123)
|
||||
* \endcode
|
||||
*
|
||||
* The event can be captured in QML like this:
|
||||
*
|
||||
* \code
|
||||
* Python {
|
||||
* id: py
|
||||
*
|
||||
* Component.onCompleted: {
|
||||
* py.setHandler('new-entries', function(first, last) {
|
||||
* console.log('New entries from ' + first + ' to ' + last);
|
||||
* });
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* All events for which no handler was set will be sent to the
|
||||
* received() signal.
|
||||
*
|
||||
* If a handler for that specific \a event already exist, the
|
||||
* new \a callback will replace the old one.
|
||||
*
|
||||
* \arg event The event name (first argument to pyotherside.send())
|
||||
* \arg callback The JS callback to be called when the event occurs
|
||||
**/
|
||||
Q_INVOKABLE void
|
||||
setHandler(QString event, QJSValue callback);
|
||||
|
||||
/**
|
||||
* \brief Evaluate a Python expression synchronously
|
||||
*
|
||||
* Evaluate the string \a expr as Python expression and return the
|
||||
* result as Qt data type. The evaluation happens synchronously.
|
||||
*
|
||||
* \code
|
||||
* Python {
|
||||
* Component.onCompleted: {
|
||||
* console.log('Squares: ' + evaluate('[x for x in range(10)]'));
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \arg expr Python expression to be evaluated
|
||||
* \result The result of the expression as Qt data type
|
||||
**/
|
||||
Q_INVOKABLE QVariant
|
||||
evaluate(QString expr);
|
||||
|
||||
/* Need a callback, as the module can only be used after import */
|
||||
/**
|
||||
* \brief Asynchronously import a Python module
|
||||
*
|
||||
* Imports a Python module by name asynchronously. The function
|
||||
* will return immediately. If the module is successfully imported,
|
||||
* the supplied \a callback will be called. Only then will the
|
||||
* imported module be available:
|
||||
*
|
||||
* \code
|
||||
* Python {
|
||||
* Component.onCompleted: {
|
||||
* importModule('os', function() {
|
||||
* // You can use the "os" module here
|
||||
* });
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* If an error occurs while trying to import, the signal error()
|
||||
* will be emitted with detailed information about the error.
|
||||
*
|
||||
* \arg name The name of the Python module to import
|
||||
* \arg callback The JS callback to be called when the module is
|
||||
* successfully imported
|
||||
**/
|
||||
Q_INVOKABLE void
|
||||
importModule(QString name, QJSValue callback);
|
||||
|
||||
/**
|
||||
* \brief Synchronously import a Python module
|
||||
*
|
||||
* Imports a Python module by name synchronously. This function
|
||||
* will block until the module is imported and available. In
|
||||
* general, you should use importModule() instead of this function
|
||||
* to avoid blocking the QML UI thread. Example use:
|
||||
*
|
||||
* \code
|
||||
* Python {
|
||||
* Component.onCompleted: {
|
||||
* var success = importModule_sync('os');
|
||||
* if (success) {
|
||||
* // You can use the "os" module here
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \arg name The name of the Python module to import
|
||||
* \result \c true if the import was successful, \c false otherwise
|
||||
**/
|
||||
Q_INVOKABLE bool
|
||||
importModule_sync(QString name);
|
||||
|
||||
/**
|
||||
* \brief Asynchronously call a Python function
|
||||
*
|
||||
* Call a Python function asynchronously and call back into QML
|
||||
* when the result is available:
|
||||
*
|
||||
* \code
|
||||
* Python {
|
||||
* Component.onCompleted: {
|
||||
* importModule('os', function() {
|
||||
* call('os.getcwd', [], function (result) {
|
||||
* console.log('Working directory: ' + result);
|
||||
* call('os.chdir', ['/'], function (result) {
|
||||
* console.log('Working directory changed.');
|
||||
* }););
|
||||
* });
|
||||
* });
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \arg func The Python function to call
|
||||
* \arg args A list of arguments, or \c [] for no arguments
|
||||
* \arg callback A callback that receives the function call result
|
||||
**/
|
||||
Q_INVOKABLE void
|
||||
call(QString func,
|
||||
QVariant args=QVariantList(),
|
||||
QJSValue callback=QJSValue());
|
||||
|
||||
|
||||
/**
|
||||
* \brief Synchronously call a Python function
|
||||
*
|
||||
* This is the synchronous variant of call(). In general, you should
|
||||
* use call() instead of this function to avoid blocking the QML UI
|
||||
* thread. Example usage:
|
||||
*
|
||||
* \code
|
||||
* Python {
|
||||
* Component.onCompleted: {
|
||||
* importModule_sync('os');
|
||||
* var cwd = call_sync('os.getcwd', []);
|
||||
* console.log('Working directory: ' + cwd);
|
||||
* call_sync('os.chdir', ['/']);
|
||||
* console.log('Working directory changed.');
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \arg func The Python function to call
|
||||
* \arg args A list of arguments, or \c [] for no arguments
|
||||
* \result The return value of the Python call as Qt data type
|
||||
**/
|
||||
Q_INVOKABLE QVariant
|
||||
call_sync(QString func, QVariant args=QVariantList());
|
||||
|
||||
static void
|
||||
closing();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* \brief Default event handler for \c pyotherside.send()
|
||||
*
|
||||
* This signal will be emitted for all events from Python for
|
||||
* which no specific handler (see setHandler()) is configured.
|
||||
*
|
||||
* \arg data The argument list of \c pyotherside.send()
|
||||
**/
|
||||
void received(QVariant data);
|
||||
|
||||
/**
|
||||
* \brief Error handler for errors from Python
|
||||
*
|
||||
* This signal will be emitted when an error happens in the
|
||||
* Python interpreter that isn't caught. For example, errors
|
||||
* in evaluate(), importModule() and call() will be reported
|
||||
* with this signal.
|
||||
*
|
||||
* \arg traceback A string describing the error
|
||||
**/
|
||||
void error(QString traceback);
|
||||
|
||||
private slots:
|
||||
void process(QString func, QVariant args, QJSValue callback);
|
||||
void import(QString name, QJSValue callback);
|
||||
|
||||
private slots:
|
||||
void receive(QVariant data);
|
||||
|
||||
void finished(QVariant result, QJSValue callback);
|
||||
@ -100,7 +270,7 @@ class QPython : public QObject {
|
||||
private:
|
||||
static QPythonPriv *priv;
|
||||
|
||||
QPythonWorker worker;
|
||||
QPythonWorker *worker;
|
||||
QThread thread;
|
||||
QMap<QString,QJSValue> handlers;
|
||||
};
|
||||
|
@ -192,6 +192,7 @@ QPythonPriv::eval(QString expr)
|
||||
void
|
||||
QPythonPriv::closing()
|
||||
{
|
||||
enter();
|
||||
if (priv->atexit_callback != NULL) {
|
||||
PyObject *args = PyTuple_New(0);
|
||||
PyObject *result = PyObject_Call(priv->atexit_callback, args, NULL);
|
||||
@ -201,5 +202,6 @@ QPythonPriv::closing()
|
||||
Py_DECREF(priv->atexit_callback);
|
||||
priv->atexit_callback = NULL;
|
||||
}
|
||||
leave();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user