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 "pyotherside_plugin.h"
|
||||||
#include "qpython.h"
|
#include "qpython_priv.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pyotherside_atexit()
|
pyotherside_atexit()
|
||||||
{
|
{
|
||||||
QPython::closing();
|
QPythonPriv::closing();
|
||||||
}
|
}
|
||||||
|
|
||||||
PyOtherSideExtensionPlugin::PyOtherSideExtensionPlugin()
|
PyOtherSideExtensionPlugin::PyOtherSideExtensionPlugin()
|
||||||
|
@ -26,6 +26,25 @@
|
|||||||
#include <QJSEngine>
|
#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)
|
QPythonWorker::QPythonWorker(QPython *qpython)
|
||||||
: QObject()
|
: QObject()
|
||||||
, qpython(qpython)
|
, qpython(qpython)
|
||||||
@ -55,7 +74,7 @@ QPython::priv = NULL;
|
|||||||
|
|
||||||
QPython::QPython(QObject *parent)
|
QPython::QPython(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, worker(this)
|
, worker(new QPythonWorker(this))
|
||||||
, thread()
|
, thread()
|
||||||
, handlers()
|
, handlers()
|
||||||
{
|
{
|
||||||
@ -63,20 +82,20 @@ QPython::QPython(QObject *parent)
|
|||||||
priv = new QPythonPriv;
|
priv = new QPythonPriv;
|
||||||
}
|
}
|
||||||
|
|
||||||
worker.moveToThread(&thread);
|
worker->moveToThread(&thread);
|
||||||
|
|
||||||
QObject::connect(priv, SIGNAL(receive(QVariant)),
|
QObject::connect(priv, SIGNAL(receive(QVariant)),
|
||||||
this, SLOT(receive(QVariant)));
|
this, SLOT(receive(QVariant)));
|
||||||
|
|
||||||
QObject::connect(this, SIGNAL(process(QString,QVariant,QJSValue)),
|
QObject::connect(this, SIGNAL(process(QString,QVariant,QJSValue)),
|
||||||
&worker, SLOT(process(QString,QVariant,QJSValue)));
|
worker, SLOT(process(QString,QVariant,QJSValue)));
|
||||||
QObject::connect(&worker, SIGNAL(finished(QVariant,QJSValue)),
|
QObject::connect(worker, SIGNAL(finished(QVariant,QJSValue)),
|
||||||
this, SLOT(finished(QVariant,QJSValue)));
|
this, SLOT(finished(QVariant,QJSValue)));
|
||||||
|
|
||||||
QObject::connect(this, SIGNAL(import(QString,QJSValue)),
|
QObject::connect(this, SIGNAL(import(QString,QJSValue)),
|
||||||
&worker, SLOT(import(QString,QJSValue)));
|
worker, SLOT(import(QString,QJSValue)));
|
||||||
QObject::connect(&worker, SIGNAL(imported(bool,QJSValue)),
|
QObject::connect(worker, SIGNAL(imported(bool,QJSValue)),
|
||||||
this, SLOT(imported(bool,QJSValue)));
|
this, SLOT(imported(bool,QJSValue)));
|
||||||
|
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
@ -85,6 +104,8 @@ QPython::~QPython()
|
|||||||
{
|
{
|
||||||
thread.quit();
|
thread.quit();
|
||||||
thread.wait();
|
thread.wait();
|
||||||
|
|
||||||
|
delete worker;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -242,12 +263,3 @@ QPython::imported(bool result, QJSValue callback)
|
|||||||
callback.call(args);
|
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 QPython;
|
||||||
class QPythonPriv;
|
class QPythonPriv;
|
||||||
|
class QPythonWorker;
|
||||||
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 QPython : public QObject {
|
class QPython : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
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);
|
QPython(QObject *parent=NULL);
|
||||||
|
|
||||||
virtual ~QPython();
|
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
|
Q_INVOKABLE void
|
||||||
addImportPath(QString path);
|
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
|
Q_INVOKABLE void
|
||||||
setHandler(QString event, QJSValue callback);
|
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
|
Q_INVOKABLE QVariant
|
||||||
evaluate(QString expr);
|
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
|
Q_INVOKABLE void
|
||||||
importModule(QString name, QJSValue callback);
|
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
|
Q_INVOKABLE bool
|
||||||
importModule_sync(QString name);
|
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
|
Q_INVOKABLE void
|
||||||
call(QString func,
|
call(QString func,
|
||||||
QVariant args=QVariantList(),
|
QVariant args=QVariantList(),
|
||||||
QJSValue callback=QJSValue());
|
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
|
Q_INVOKABLE QVariant
|
||||||
call_sync(QString func, QVariant args=QVariantList());
|
call_sync(QString func, QVariant args=QVariantList());
|
||||||
|
|
||||||
static void
|
|
||||||
closing();
|
|
||||||
|
|
||||||
signals:
|
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);
|
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);
|
void error(QString traceback);
|
||||||
|
|
||||||
|
private slots:
|
||||||
void process(QString func, QVariant args, QJSValue callback);
|
void process(QString func, QVariant args, QJSValue callback);
|
||||||
void import(QString name, QJSValue callback);
|
void import(QString name, QJSValue callback);
|
||||||
|
|
||||||
private slots:
|
|
||||||
void receive(QVariant data);
|
void receive(QVariant data);
|
||||||
|
|
||||||
void finished(QVariant result, QJSValue callback);
|
void finished(QVariant result, QJSValue callback);
|
||||||
@ -100,7 +270,7 @@ class QPython : public QObject {
|
|||||||
private:
|
private:
|
||||||
static QPythonPriv *priv;
|
static QPythonPriv *priv;
|
||||||
|
|
||||||
QPythonWorker worker;
|
QPythonWorker *worker;
|
||||||
QThread thread;
|
QThread thread;
|
||||||
QMap<QString,QJSValue> handlers;
|
QMap<QString,QJSValue> handlers;
|
||||||
};
|
};
|
||||||
|
@ -192,6 +192,7 @@ QPythonPriv::eval(QString expr)
|
|||||||
void
|
void
|
||||||
QPythonPriv::closing()
|
QPythonPriv::closing()
|
||||||
{
|
{
|
||||||
|
enter();
|
||||||
if (priv->atexit_callback != NULL) {
|
if (priv->atexit_callback != NULL) {
|
||||||
PyObject *args = PyTuple_New(0);
|
PyObject *args = PyTuple_New(0);
|
||||||
PyObject *result = PyObject_Call(priv->atexit_callback, args, NULL);
|
PyObject *result = PyObject_Call(priv->atexit_callback, args, NULL);
|
||||||
@ -201,5 +202,6 @@ QPythonPriv::closing()
|
|||||||
Py_DECREF(priv->atexit_callback);
|
Py_DECREF(priv->atexit_callback);
|
||||||
priv->atexit_callback = NULL;
|
priv->atexit_callback = NULL;
|
||||||
}
|
}
|
||||||
|
leave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user