1// Copyright (C) 2017 Ford Motor Company
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QREMOTEOBJECTNODE_H
5#define QREMOTEOBJECTNODE_H
6
7#include <QtCore/qsharedpointer.h>
8#include <QtCore/qmetaobject.h>
9#include <QtRemoteObjects/qtremoteobjectglobal.h>
10#include <QtRemoteObjects/qremoteobjectregistry.h>
11#include <QtRemoteObjects/qremoteobjectdynamicreplica.h>
12
13#include <functional>
14
15QT_BEGIN_NAMESPACE
16
17class QRemoteObjectReplica;
18class SourceApiMap;
19class QAbstractItemModel;
20class QAbstractItemModelReplica;
21class QItemSelectionModel;
22class QRemoteObjectAbstractPersistedStorePrivate;
23class QRemoteObjectNodePrivate;
24class QRemoteObjectHostBasePrivate;
25class QRemoteObjectHostPrivate;
26class QRemoteObjectRegistryHostPrivate;
27
28class Q_REMOTEOBJECTS_EXPORT QRemoteObjectAbstractPersistedStore : public QObject
29{
30 Q_OBJECT
31
32public:
33 QRemoteObjectAbstractPersistedStore (QObject *parent = nullptr);
34 virtual ~QRemoteObjectAbstractPersistedStore();
35
36 virtual void saveProperties(const QString &repName, const QByteArray &repSig, const QVariantList &values) = 0;
37 virtual QVariantList restoreProperties(const QString &repName, const QByteArray &repSig) = 0;
38
39protected:
40 QRemoteObjectAbstractPersistedStore(QRemoteObjectAbstractPersistedStorePrivate &, QObject *parent);
41 Q_DECLARE_PRIVATE(QRemoteObjectAbstractPersistedStore)
42};
43
44class Q_REMOTEOBJECTS_EXPORT QRemoteObjectNode : public QObject
45{
46 Q_OBJECT
47 Q_PROPERTY(QUrl registryUrl READ registryUrl WRITE setRegistryUrl)
48 Q_PROPERTY(QRemoteObjectAbstractPersistedStore* persistedStore READ persistedStore WRITE setPersistedStore)
49 Q_PROPERTY(int heartbeatInterval READ heartbeatInterval WRITE setHeartbeatInterval NOTIFY heartbeatIntervalChanged)
50
51public:
52 enum ErrorCode{
53 NoError,
54 RegistryNotAcquired,
55 RegistryAlreadyHosted,
56 NodeIsNoServer,
57 ServerAlreadyCreated,
58 UnintendedRegistryHosting,
59 OperationNotValidOnClientNode,
60 SourceNotRegistered,
61 MissingObjectName,
62 HostUrlInvalid,
63 ProtocolMismatch,
64 ListenFailed
65 };
66 Q_ENUM(ErrorCode)
67
68 QRemoteObjectNode(QObject *parent = nullptr);
69 QRemoteObjectNode(const QUrl &registryAddress, QObject *parent = nullptr);
70 ~QRemoteObjectNode() override;
71
72 Q_INVOKABLE bool connectToNode(const QUrl &address);
73 void addClientSideConnection(QIODevice *ioDevice);
74 virtual void setName(const QString &name);
75 template < class ObjectType >
76 ObjectType *acquire(const QString &name = QString())
77 {
78 return new ObjectType(this, name);
79 }
80
81 template<typename T>
82 QStringList instances() const
83 {
84 const QMetaObject *mobj = &T::staticMetaObject;
85 const int index = mobj->indexOfClassInfo(QCLASSINFO_REMOTEOBJECT_TYPE);
86 if (index == -1)
87 return QStringList();
88
89 const QString typeName = QString::fromLatin1(ba: mobj->classInfo(index).value());
90 return instances(typeName);
91 }
92 QStringList instances(QStringView typeName) const;
93
94 QRemoteObjectDynamicReplica *acquireDynamic(const QString &name);
95 QAbstractItemModelReplica *acquireModel(const QString &name, QtRemoteObjects::InitialAction action = QtRemoteObjects::FetchRootSize, const QList<int> &rolesHint = {});
96 QUrl registryUrl() const;
97 virtual bool setRegistryUrl(const QUrl &registryAddress);
98 bool waitForRegistry(int timeout = 30000);
99 const QRemoteObjectRegistry *registry() const;
100
101 QRemoteObjectAbstractPersistedStore *persistedStore() const;
102 void setPersistedStore(QRemoteObjectAbstractPersistedStore *persistedStore);
103
104 ErrorCode lastError() const;
105
106 int heartbeatInterval() const;
107 void setHeartbeatInterval(int interval);
108
109 typedef std::function<void (QUrl)> RemoteObjectSchemaHandler;
110 void registerExternalSchema(const QString &schema, RemoteObjectSchemaHandler handler);
111
112Q_SIGNALS:
113 void remoteObjectAdded(const QRemoteObjectSourceLocation &);
114 void remoteObjectRemoved(const QRemoteObjectSourceLocation &);
115
116 void error(QRemoteObjectNode::ErrorCode errorCode);
117 void heartbeatIntervalChanged(int heartbeatInterval);
118
119protected:
120 QRemoteObjectNode(QRemoteObjectNodePrivate &, QObject *parent);
121
122 void timerEvent(QTimerEvent*) override;
123
124private:
125 void initializeReplica(QRemoteObjectReplica *instance, const QString &name = QString());
126 void persistProperties(const QString &repName, const QByteArray &repSig, const QVariantList &props);
127 QVariantList retrieveProperties(const QString &repName, const QByteArray &repSig);
128
129 Q_DECLARE_PRIVATE(QRemoteObjectNode)
130 friend class QRemoteObjectReplica;
131 friend class QConnectedReplicaImplementation;
132};
133
134class Q_REMOTEOBJECTS_EXPORT QRemoteObjectHostBase : public QRemoteObjectNode
135{
136 Q_OBJECT
137public:
138 enum AllowedSchemas { BuiltInSchemasOnly, AllowExternalRegistration };
139 Q_ENUM(AllowedSchemas)
140 ~QRemoteObjectHostBase() override;
141 void setName(const QString &name) override;
142
143 template <template <typename> class ApiDefinition, typename ObjectType>
144 bool enableRemoting(ObjectType *object)
145 {
146 ApiDefinition<ObjectType> *api = new ApiDefinition<ObjectType>(object);
147 return enableRemoting(object, api);
148 }
149 Q_INVOKABLE bool enableRemoting(QObject *object, const QString &name = QString());
150 bool enableRemoting(QAbstractItemModel *model, const QString &name, const QList<int> roles, QItemSelectionModel *selectionModel = nullptr);
151 Q_INVOKABLE bool disableRemoting(QObject *remoteObject);
152 void addHostSideConnection(QIODevice *ioDevice);
153
154 typedef std::function<bool(QStringView, QStringView)> RemoteObjectNameFilter;
155 bool proxy(const QUrl &registryUrl, const QUrl &hostUrl={},
156 RemoteObjectNameFilter filter=[](QStringView, QStringView) {return true; });
157 // TODO: Currently the reverse aspect requires the registry, so this is supported only for
158 // QRemoteObjectRegistryHost for now. Consider enabling it also for QRemoteObjectHost.
159 bool reverseProxy(RemoteObjectNameFilter filter=[](QStringView, QStringView) {return true; });
160
161protected:
162 virtual QUrl hostUrl() const;
163 virtual bool setHostUrl(const QUrl &hostAddress, AllowedSchemas allowedSchemas=BuiltInSchemasOnly);
164 QRemoteObjectHostBase(QRemoteObjectHostBasePrivate &, QObject *);
165
166private:
167 bool enableRemoting(QObject *object, const SourceApiMap *, QObject *adapter = nullptr);
168 Q_DECLARE_PRIVATE(QRemoteObjectHostBase)
169};
170
171class Q_REMOTEOBJECTS_EXPORT QRemoteObjectHost : public QRemoteObjectHostBase
172{
173 Q_OBJECT
174 Q_PROPERTY(QUrl hostUrl READ hostUrl WRITE setHostUrl NOTIFY hostUrlChanged)
175
176public:
177 QRemoteObjectHost(QObject *parent = nullptr);
178 QRemoteObjectHost(const QUrl &address, const QUrl &registryAddress = QUrl(),
179 AllowedSchemas allowedSchemas=BuiltInSchemasOnly, QObject *parent = nullptr);
180 QRemoteObjectHost(const QUrl &address, QObject *parent);
181 ~QRemoteObjectHost() override;
182 QUrl hostUrl() const override;
183 bool setHostUrl(const QUrl &hostAddress, AllowedSchemas allowedSchemas=BuiltInSchemasOnly) override;
184
185Q_SIGNALS:
186 void hostUrlChanged();
187
188protected:
189 QRemoteObjectHost(QRemoteObjectHostPrivate &, QObject *);
190
191private:
192 Q_DECLARE_PRIVATE(QRemoteObjectHost)
193};
194
195class Q_REMOTEOBJECTS_EXPORT QRemoteObjectRegistryHost : public QRemoteObjectHostBase
196{
197 Q_OBJECT
198public:
199 QRemoteObjectRegistryHost(const QUrl &registryAddress = QUrl(), QObject *parent = nullptr);
200 ~QRemoteObjectRegistryHost() override;
201 bool setRegistryUrl(const QUrl &registryUrl) override;
202
203protected:
204 QRemoteObjectRegistryHost(QRemoteObjectRegistryHostPrivate &, QObject *);
205
206private:
207 Q_DECLARE_PRIVATE(QRemoteObjectRegistryHost)
208};
209
210QT_END_NAMESPACE
211
212#endif
213

source code of qtremoteobjects/src/remoteobjects/qremoteobjectnode.h