diff --git a/docs/conf.py b/docs/conf.py index 2e250c8..dff1a2e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,9 +48,9 @@ copyright = u'2014, Thomas Perl' # built documents. # # The short X.Y version. -version = '1.3' +version = '1.4' # The full version, including alpha/beta/rc tags. -release = '1.3.0' +release = '1.4.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/index.rst b/docs/index.rst index a915748..dd90c5f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -28,7 +28,7 @@ This section describes the QML API exposed by the *PyOtherSide* QML Plugin. Import Versions --------------- -The current QML API version of PyOtherSide is 1.3. When new features are +The current QML API version of PyOtherSide is 1.4. When new features are introduced, or behavior is changed, the API version will be bumped and documented here. @@ -67,7 +67,7 @@ To use the ``Python`` element in a QML file, you have to import the plugin using .. code-block:: javascript - import io.thp.pyotherside 1.3 + import io.thp.pyotherside 1.4 Signals ``````` @@ -150,12 +150,16 @@ imported modules using: If a JavaScript exception occurs in the callback, the :func:`error` signal is emitted with ``traceback`` containing the exception info. +.. versionadded:: 1.4.0 + Attributes on Python objects can be accessed using :func:`getattr`: .. function:: getattr(obj, string attr) -> var Get the attribute ``attr`` of the Python object ``obj``. +.. versionadded:: 1.4.0 + For some of these methods, there also exist synchronous variants, but it is highly recommended to use the asynchronous variants instead to avoid blocking the QML UI thread: @@ -176,6 +180,8 @@ the QML UI thread: Call a Python method. Returns the return value of the Python method. +.. versionadded:: 1.4.0 + The following functions allow access to the version of the running PyOtherSide plugin and Python interpreter. @@ -355,6 +361,8 @@ between Python and QML (and vice versa): +--------------------+------------+-----------------------------+ | iterable | JS Array | since PyOtherSide 1.3.0 | +--------------------+------------+-----------------------------+ +| object | (opaque) | since PyOtherSide 1.4.0 | ++--------------------+------------+-----------------------------+ Trying to pass in other types than the ones listed here is undefined behavior and will usually result in an error. @@ -679,7 +687,7 @@ Using this function from QML is straightforward: .. code-block:: javascript import QtQuick 2.0 - import io.thp.pyotherside 1.3 + import io.thp.pyotherside 1.4 Rectangle { color: 'black' @@ -775,7 +783,7 @@ This module can now be imported in QML and used as ``source`` in the QML .. code-block:: javascript import QtQuick 2.0 - import io.thp.pyotherside 1.3 + import io.thp.pyotherside 1.4 Image { id: image @@ -918,6 +926,12 @@ Known Problems: ChangeLog ========= +Version 1.4.0 (UNRELEASED) +-------------------------- + +* Support for passing Python objects to QML and keeping references there +* Add :func:`callMethod`, :func:`callMethod_sync` and :func:`getattr` + Version 1.3.0 (2014-07-24) -------------------------- diff --git a/examples/helloworld.qml b/examples/helloworld.qml index 187833c..03c5627 100644 --- a/examples/helloworld.qml +++ b/examples/helloworld.qml @@ -1,5 +1,5 @@ import QtQuick 2.0 -import io.thp.pyotherside 1.0 +import io.thp.pyotherside 1.4 Rectangle { width: 200 diff --git a/pyotherside.pri b/pyotherside.pri index 5fdc4e3..338a554 100644 --- a/pyotherside.pri +++ b/pyotherside.pri @@ -1,2 +1,2 @@ PROJECTNAME = pyotherside -VERSION = 1.3.0 +VERSION = 1.4.0 diff --git a/src/pyotherside_plugin.cpp b/src/pyotherside_plugin.cpp index 33afc4e..0ea9537 100644 --- a/src/pyotherside_plugin.cpp +++ b/src/pyotherside_plugin.cpp @@ -61,4 +61,5 @@ PyOtherSideExtensionPlugin::registerTypes(const char *uri) // There is no PyOtherSide 1.1 import, as it's the same as 1.0 qmlRegisterType(uri, 1, 2, PYOTHERSIDE_QPYTHON_NAME); qmlRegisterType(uri, 1, 3, PYOTHERSIDE_QPYTHON_NAME); + qmlRegisterType(uri, 1, 4, PYOTHERSIDE_QPYTHON_NAME); } diff --git a/src/qpython.cpp b/src/qpython.cpp index 3989ff8..17b8c60 100644 --- a/src/qpython.cpp +++ b/src/qpython.cpp @@ -257,6 +257,11 @@ QPython::call_sync(QString func, QVariant args) void QPython::callMethod(QVariant obj, QString method, QVariant args, QJSValue callback) { + if (!SINCE_API_VERSION(1, 4)) { + emit error(QString("Import PyOtherSide 1.4 or newer to use callMethod()")); + return; + } + QJSValue *cb = 0; if (!callback.isNull() && !callback.isUndefined() && callback.isCallable()) { cb = new QJSValue(callback); @@ -267,6 +272,11 @@ QPython::callMethod(QVariant obj, QString method, QVariant args, QJSValue callba QVariant QPython::callMethod_sync(QVariant obj, QString method, QVariant args) { + if (!SINCE_API_VERSION(1, 4)) { + emit error(QString("Import PyOtherSide 1.4 or newer to use callMethod_sync()")); + return QVariant(); + } + ENSURE_GIL_STATE; PyObject *pyobj = convertQVariantToPyObject(obj); @@ -299,6 +309,11 @@ QPython::callMethod_sync(QVariant obj, QString method, QVariant args) QVariant QPython::getattr(QVariant obj, QString attr) { + if (!SINCE_API_VERSION(1, 4)) { + emit error(QString("Import PyOtherSide 1.4 or newer to use getattr()")); + return QVariant(); + } + ENSURE_GIL_STATE; PyObject *pyobj = convertQVariantToPyObject(obj); diff --git a/src/qpython.h b/src/qpython.h index 190e3ce..b25148d 100644 --- a/src/qpython.h +++ b/src/qpython.h @@ -418,4 +418,13 @@ public: } }; +class QPython14 : public QPython { +Q_OBJECT +public: + QPython14(QObject *parent=0) + : QPython(parent, 1, 4) + { + } +}; + #endif /* PYOTHERSIDE_QPYTHON_H */ diff --git a/tests/test_added_in_14/test_added_in_14.qml b/tests/test_added_in_14/test_added_in_14.qml new file mode 100644 index 0000000..463a069 --- /dev/null +++ b/tests/test_added_in_14/test_added_in_14.qml @@ -0,0 +1,24 @@ +import QtQuick 2.0 +// Note that we import 1.3 here instead of >= 1.4 +import io.thp.pyotherside 1.3 + +Python { + Component.onCompleted: { + var foo = undefined; + + // qml: Received error: Import PyOtherSide 1.4 or newer to use getattr() + getattr(foo, 'test'); + + // qml: Received error: Import PyOtherSide 1.4 or newer to use callMethod() + callMethod(foo, 'something', [], function (result) {}); + + // qml: Received error: Import PyOtherSide 1.4 or newer to use callMethod_sync() + var result = callMethod_sync(foo, 'something', []); + + Qt.quit(); + } + + onError: { + console.log('Received error: ' + traceback); + } +}