1/****************************************************************************
2**
3** Copyright (C) 2017-2015 Ford Motor Company
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtRemoteObjects module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <QtRemoteObjects/qremoteobjectnode.h>
41#include <QtRemoteObjects/qremoteobjectsettingsstore.h>
42#include <QtRemoteObjects/qremoteobjectpendingcall.h>
43#include <QTimer>
44#include <QQmlExtensionPlugin>
45#include <QJSValue>
46#include <QtQml/private/qjsvalue_p.h>
47#include <QtQml/qqmlengine.h>
48#include <qqmlinfo.h>
49#include <qqml.h>
50
51QT_BEGIN_NAMESPACE
52
53struct QtQmlRemoteObjectsResponse {
54 QJSValue promise;
55 QTimer *timer;
56};
57
58
59// documentation updates for this class can be made in remoteobjects-qml.qdoc
60class QtQmlRemoteObjects : public QObject
61{
62 Q_OBJECT
63public:
64 ~QtQmlRemoteObjects() {
65 auto i = m_callbacks.begin();
66 while (i != m_callbacks.end()) {
67 delete i.key();
68 delete i.value().timer;
69 i = m_callbacks.erase(it: i);
70 }
71 }
72
73 Q_INVOKABLE QJSValue watch(const QRemoteObjectPendingCall &reply, int timeout = 30000) {
74 if (m_accessiblePromise.isUndefined())
75 m_accessiblePromise = qmlEngine(this)->evaluate(program: "(function() { var obj = {}; obj.promise = new Promise(function(resolve, reject) { obj.resolve = resolve; obj.reject = reject; }); return obj; })");
76
77 QRemoteObjectPendingCallWatcher *watcher = new QRemoteObjectPendingCallWatcher(reply);
78
79 QJSValue promise = m_accessiblePromise.call();
80 QtQmlRemoteObjectsResponse response;
81 response.promise = promise;
82 response.timer = new QTimer();
83 response.timer->setSingleShot(true);
84 m_callbacks.insert(key: watcher, value: response);
85
86 // handle timeout
87 connect(sender: response.timer, signal: &QTimer::timeout, slot: [this, watcher]() {
88 auto i = m_callbacks.find(key: watcher);
89 if (i == m_callbacks.end()) {
90 qmlWarning(me: this) << "could not find callback for watcher.";
91 return;
92 }
93
94 QJSValue v(QLatin1String("timeout"));
95 i.value().promise.property(name: "reject").call(args: QJSValueList() << v);
96
97 delete i.key();
98 delete i.value().timer;
99 m_callbacks.erase(it: i);
100 });
101
102 // handle success
103 connect(sender: watcher, signal: &QRemoteObjectPendingCallWatcher::finished, slot: [this](QRemoteObjectPendingCallWatcher *self) {
104 auto i = m_callbacks.find(key: self);
105 if (i == m_callbacks.end()) {
106 qmlWarning(me: this) << "could not find callback for watcher.";
107 return;
108 }
109
110 QJSValue v;
111 QJSValuePrivate::setVariant(jsval: &v, v: self->returnValue());
112 i.value().promise.property(name: "resolve").call(args: QJSValueList() << v);
113
114 delete i.key();
115 delete i.value().timer;
116 m_callbacks.erase(it: i);
117 });
118
119 response.timer->start(msec: timeout);
120 return promise.property(name: "promise");
121 }
122
123private:
124 QHash<QRemoteObjectPendingCallWatcher*,QtQmlRemoteObjectsResponse> m_callbacks;
125 QJSValue m_accessiblePromise;
126};
127
128class QtRemoteObjectsPlugin : public QQmlExtensionPlugin
129{
130 Q_OBJECT
131 Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
132
133public:
134 void registerTypes(const char *uri) override
135 {
136 qmlRegisterModule(uri, versionMajor: 5, QT_VERSION_MINOR);
137
138 qmlRegisterUncreatableType<QRemoteObjectAbstractPersistedStore>(uri, versionMajor: 5, versionMinor: 12, qmlName: "PersistedStore", reason: "Cannot create PersistedStore");
139
140 qmlRegisterType<QRemoteObjectNode>(uri, versionMajor: 5, versionMinor: 12, qmlName: "Node");
141 qmlRegisterType<QRemoteObjectSettingsStore>(uri, versionMajor: 5, versionMinor: 12, qmlName: "SettingsStore");
142 qmlRegisterSingletonType<QtQmlRemoteObjects>(uri, versionMajor: 5, versionMinor: 14, typeName: "QtRemoteObjects", callback: [](QQmlEngine *, QJSEngine*){return new QtQmlRemoteObjects();});
143 qmlRegisterType<QRemoteObjectHost>(uri, versionMajor: 5, versionMinor: 15, qmlName: "Host");
144 qmlProtectModule(uri, majVersion: 5);
145 }
146};
147
148QT_END_NAMESPACE
149
150#include "plugin.moc"
151

source code of qtremoteobjects/src/imports/remoteobjects/plugin.cpp