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 | |
15 | QT_BEGIN_NAMESPACE |
16 | |
17 | class QRemoteObjectReplica; |
18 | class SourceApiMap; |
19 | class QAbstractItemModel; |
20 | class QAbstractItemModelReplica; |
21 | class QItemSelectionModel; |
22 | class QRemoteObjectAbstractPersistedStorePrivate; |
23 | class QRemoteObjectNodePrivate; |
24 | class QRemoteObjectHostBasePrivate; |
25 | class QRemoteObjectHostPrivate; |
26 | class QRemoteObjectRegistryHostPrivate; |
27 | |
28 | class Q_REMOTEOBJECTS_EXPORT QRemoteObjectAbstractPersistedStore : public QObject |
29 | { |
30 | Q_OBJECT |
31 | |
32 | public: |
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 | |
39 | protected: |
40 | QRemoteObjectAbstractPersistedStore(QRemoteObjectAbstractPersistedStorePrivate &, QObject *parent); |
41 | Q_DECLARE_PRIVATE(QRemoteObjectAbstractPersistedStore) |
42 | }; |
43 | |
44 | class 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 | |
51 | public: |
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 ®istryAddress, 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 ®istryAddress); |
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 | |
112 | Q_SIGNALS: |
113 | void remoteObjectAdded(const QRemoteObjectSourceLocation &); |
114 | void remoteObjectRemoved(const QRemoteObjectSourceLocation &); |
115 | |
116 | void error(QRemoteObjectNode::ErrorCode errorCode); |
117 | void heartbeatIntervalChanged(int heartbeatInterval); |
118 | |
119 | protected: |
120 | QRemoteObjectNode(QRemoteObjectNodePrivate &, QObject *parent); |
121 | |
122 | void timerEvent(QTimerEvent*) override; |
123 | |
124 | private: |
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 | |
134 | class Q_REMOTEOBJECTS_EXPORT QRemoteObjectHostBase : public QRemoteObjectNode |
135 | { |
136 | Q_OBJECT |
137 | public: |
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 ®istryUrl, 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 | |
161 | protected: |
162 | virtual QUrl hostUrl() const; |
163 | virtual bool setHostUrl(const QUrl &hostAddress, AllowedSchemas allowedSchemas=BuiltInSchemasOnly); |
164 | QRemoteObjectHostBase(QRemoteObjectHostBasePrivate &, QObject *); |
165 | |
166 | private: |
167 | bool enableRemoting(QObject *object, const SourceApiMap *, QObject *adapter = nullptr); |
168 | Q_DECLARE_PRIVATE(QRemoteObjectHostBase) |
169 | }; |
170 | |
171 | class Q_REMOTEOBJECTS_EXPORT QRemoteObjectHost : public QRemoteObjectHostBase |
172 | { |
173 | Q_OBJECT |
174 | Q_PROPERTY(QUrl hostUrl READ hostUrl WRITE setHostUrl NOTIFY hostUrlChanged) |
175 | |
176 | public: |
177 | QRemoteObjectHost(QObject *parent = nullptr); |
178 | QRemoteObjectHost(const QUrl &address, const QUrl ®istryAddress = 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 | |
185 | Q_SIGNALS: |
186 | void hostUrlChanged(); |
187 | |
188 | protected: |
189 | QRemoteObjectHost(QRemoteObjectHostPrivate &, QObject *); |
190 | |
191 | private: |
192 | Q_DECLARE_PRIVATE(QRemoteObjectHost) |
193 | }; |
194 | |
195 | class Q_REMOTEOBJECTS_EXPORT QRemoteObjectRegistryHost : public QRemoteObjectHostBase |
196 | { |
197 | Q_OBJECT |
198 | public: |
199 | QRemoteObjectRegistryHost(const QUrl ®istryAddress = QUrl(), QObject *parent = nullptr); |
200 | ~QRemoteObjectRegistryHost() override; |
201 | bool setRegistryUrl(const QUrl ®istryUrl) override; |
202 | |
203 | protected: |
204 | QRemoteObjectRegistryHost(QRemoteObjectRegistryHostPrivate &, QObject *); |
205 | |
206 | private: |
207 | Q_DECLARE_PRIVATE(QRemoteObjectRegistryHost) |
208 | }; |
209 | |
210 | QT_END_NAMESPACE |
211 | |
212 | #endif |
213 | |