diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2014-01-09 17:21:39 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-01-10 13:09:03 +0100 |
commit | 625c881cc74f2552e211b9ba81ac3b0ed30e9947 (patch) | |
tree | 246cf6d749138448423bf6b4da17a0306f8c1e0a /src | |
parent | b23442674f1b30d936fca43aee7b7d6dece15b2c (diff) | |
download | qtwebchannel-625c881cc74f2552e211b9ba81ac3b0ed30e9947.tar.gz |
Add declarative object-registration API to QML WebChannel.
The new registeredObjects list property is now preferred over the old
imparative registerObject/registerObjects API.
Items that are added to the list need an attached WebChannel.id property
which holds the identifier under which the object is published to remote
clients.
Change-Id: I96a8047b9a85e27f3fd48c900180c22ebd20eb35
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/webchannel/qmlwebchannel.cpp | 70 | ||||
-rw-r--r-- | src/imports/webchannel/qmlwebchannel.h | 30 | ||||
-rw-r--r-- | src/imports/webchannel/qmlwebchannelattached.cpp | 67 | ||||
-rw-r--r-- | src/imports/webchannel/qmlwebchannelattached.h | 67 | ||||
-rw-r--r-- | src/imports/webchannel/webchannel.pro | 6 | ||||
-rw-r--r-- | src/webchannel/qwebchannel.cpp | 6 | ||||
-rw-r--r-- | src/webchannel/qwebchannel.h | 3 |
7 files changed, 244 insertions, 5 deletions
diff --git a/src/imports/webchannel/qmlwebchannel.cpp b/src/imports/webchannel/qmlwebchannel.cpp index a7a6db0..22da1ac 100644 --- a/src/imports/webchannel/qmlwebchannel.cpp +++ b/src/imports/webchannel/qmlwebchannel.cpp @@ -45,6 +45,8 @@ #include "qwebchannel_p.h" #include "qmetaobjectpublisher_p.h" +#include <QtQml/QQmlContext> + QmlWebChannel::QmlWebChannel(QObject *parent) : QWebChannel(parent) { @@ -73,3 +75,71 @@ bool QmlWebChannel::test_clientIsIdle() const { return d->publisher->clientIsIdle; } + +void QmlWebChannel::objectIdChanged(const QString &newId) +{ + const QmlWebChannelAttached *const attached = qobject_cast<QmlWebChannelAttached*>(sender()); + Q_ASSERT(attached); + Q_ASSERT(attached->parent()); + Q_ASSERT(m_registeredObjects.contains(attached->parent())); + + QObject *const object = attached->parent(); + const QString &oldId = d->publisher->registeredObjectIds.value(object); + + if (!oldId.isEmpty()) { + deregisterObject(object); + } + + registerObject(newId, object); +} + +QmlWebChannelAttached *QmlWebChannel::qmlAttachedProperties(QObject *obj) +{ + return new QmlWebChannelAttached(obj); +} + +QQmlListProperty<QObject> QmlWebChannel::registeredObjects() +{ + return QQmlListProperty<QObject>(this, 0, + registeredObjects_append, + registeredObjects_count, + registeredObjects_at, + registeredObjects_clear); +} + +void QmlWebChannel::registeredObjects_append(QQmlListProperty<QObject> *prop, QObject *object) +{ + const QmlWebChannelAttached *const attached = qobject_cast<QmlWebChannelAttached*>( + qmlAttachedPropertiesObject<QmlWebChannel>(object, false /* don't create */)); + if (!attached) { + const QQmlContext *const context = qmlContext(object); + qWarning() << "Cannot register object" << context->nameForObject(object) << '(' << object << ") without attached WebChannel.id property. Did you forget to set it?"; + return; + } + QmlWebChannel *channel = static_cast<QmlWebChannel*>(prop->object); + if (!attached->id().isEmpty()) { + // TODO: warning in such cases? + channel->registerObject(attached->id(), object); + } + channel->m_registeredObjects.append(object); + connect(attached, SIGNAL(idChanged(QString)), channel, SLOT(objectIdChanged(QString))); +} + +int QmlWebChannel::registeredObjects_count(QQmlListProperty<QObject> *prop) +{ + return static_cast<QmlWebChannel*>(prop->object)->m_registeredObjects.size(); +} + +QObject *QmlWebChannel::registeredObjects_at(QQmlListProperty<QObject> *prop, int index) +{ + return static_cast<QmlWebChannel*>(prop->object)->m_registeredObjects.at(index); +} + +void QmlWebChannel::registeredObjects_clear(QQmlListProperty<QObject> *prop) +{ + QmlWebChannel *channel = static_cast<QmlWebChannel*>(prop->object); + foreach (QObject *object, channel->m_registeredObjects) { + channel->deregisterObject(object); + } + return channel->m_registeredObjects.clear(); +} diff --git a/src/imports/webchannel/qmlwebchannel.h b/src/imports/webchannel/qmlwebchannel.h index b52bc8b..9e25b45 100644 --- a/src/imports/webchannel/qmlwebchannel.h +++ b/src/imports/webchannel/qmlwebchannel.h @@ -45,19 +45,45 @@ #include <qwebchannel.h> +#include "qmlwebchannelattached.h" + +#include <QVector> + +#include <QtQml/qqml.h> +#include <QtQml/QQmlListProperty> + +class QmlWebChannelAttached; + class QmlWebChannel : public QWebChannel { Q_OBJECT + Q_PROPERTY( QQmlListProperty<QObject> registeredObjects READ registeredObjects ) public: QmlWebChannel(QObject *parent = 0); virtual ~QmlWebChannel(); - // TODO: replace by list property - Q_INVOKABLE void registerObjects(const QVariantMap &objects); + Q_INVOKABLE void registerObjects(const QVariantMap& objects); + QQmlListProperty<QObject> registeredObjects(); // TODO: remove this by replacing QML with C++ tests Q_INVOKABLE bool test_clientIsIdle() const; + + static QmlWebChannelAttached* qmlAttachedProperties(QObject *obj); + +private slots: + void objectIdChanged(const QString &newId); + +private: + static void registeredObjects_append(QQmlListProperty<QObject> *prop, QObject* item); + static int registeredObjects_count(QQmlListProperty<QObject> *prop); + static QObject *registeredObjects_at(QQmlListProperty<QObject> *prop, int index); + static void registeredObjects_clear(QQmlListProperty<QObject> *prop); + + QVector<QObject*> m_registeredObjects; }; +QML_DECLARE_TYPE( QmlWebChannel ) +QML_DECLARE_TYPEINFO( QmlWebChannel, QML_HAS_ATTACHED_PROPERTIES ) + #endif // QMLWEBCHANNEL_H diff --git a/src/imports/webchannel/qmlwebchannelattached.cpp b/src/imports/webchannel/qmlwebchannelattached.cpp new file mode 100644 index 0000000..9a413fc --- /dev/null +++ b/src/imports/webchannel/qmlwebchannelattached.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +** Contact: http://www.qt-project.org/legal +* +** This file is part of the QtWebChannel module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlwebchannelattached.h" + +QmlWebChannelAttached::QmlWebChannelAttached(QObject *parent) + : QObject(parent) +{ + +} + +QmlWebChannelAttached::~QmlWebChannelAttached() +{ + +} + +QString QmlWebChannelAttached::id() const +{ + return m_id; +} + +void QmlWebChannelAttached::setId(const QString &id) +{ + if (id != m_id) { + m_id = id; + emit idChanged(id); + } +} diff --git a/src/imports/webchannel/qmlwebchannelattached.h b/src/imports/webchannel/qmlwebchannelattached.h new file mode 100644 index 0000000..c705c25 --- /dev/null +++ b/src/imports/webchannel/qmlwebchannelattached.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +** Contact: http://www.qt-project.org/legal +* +** This file is part of the QtWebChannel module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLWEBCHANNELATTACHED_H +#define QMLWEBCHANNELATTACHED_H + +#include <QObject> + +class QmlWebChannelAttached : public QObject +{ + Q_OBJECT + + Q_PROPERTY( QString id READ id WRITE setId NOTIFY idChanged FINAL ) +public: + explicit QmlWebChannelAttached(QObject *parent = 0); + virtual ~QmlWebChannelAttached(); + + QString id() const; + void setId(const QString &id); + +signals: + void idChanged(const QString &id); + +private: + QString m_id; +}; + +#endif // QMLWEBCHANNELATTACHED_H diff --git a/src/imports/webchannel/webchannel.pro b/src/imports/webchannel/webchannel.pro index 3051077..c1959f5 100644 --- a/src/imports/webchannel/webchannel.pro +++ b/src/imports/webchannel/webchannel.pro @@ -5,9 +5,11 @@ VPATH += ../../webchannel SOURCES += \ plugin.cpp \ - qmlwebchannel.cpp + qmlwebchannel.cpp \ + qmlwebchannelattached.cpp HEADERS += \ - qmlwebchannel.h + qmlwebchannel.h \ + qmlwebchannelattached.h load(qml_plugin) diff --git a/src/webchannel/qwebchannel.cpp b/src/webchannel/qwebchannel.cpp index f7a2c5f..70c8f35 100644 --- a/src/webchannel/qwebchannel.cpp +++ b/src/webchannel/qwebchannel.cpp @@ -123,6 +123,12 @@ void QWebChannel::registerObject(const QString &id, QObject *object) d->publisher->registerObject(id, object); } +void QWebChannel::deregisterObject(QObject *object) +{ + // handling of deregistration is analogously to handling of a destroyed signal + d->publisher->signalEmitted(object, s_destroyedSignalIndex, QVariantList() << QVariant::fromValue(object)); +} + bool QWebChannel::blockUpdates() const { return d->publisher->blockUpdates; diff --git a/src/webchannel/qwebchannel.h b/src/webchannel/qwebchannel.h index 22d87a7..4f464b3 100644 --- a/src/webchannel/qwebchannel.h +++ b/src/webchannel/qwebchannel.h @@ -77,7 +77,8 @@ public: * TODO: This must be called, before clients are initialized. */ void registerObjects(const QHash<QString, QObject*> &objects); - void registerObject(const QString &id, QObject *object); + Q_INVOKABLE void registerObject(const QString &id, QObject *object); + Q_INVOKABLE void deregisterObject(QObject *object); /** * @return true when property updates are blocked, false otherwise. |