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