summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--.qmake.conf2
-rw-r--r--examples/remoteobjects/modelviewclient/main.cpp1
-rw-r--r--examples/remoteobjects/modelviewclient/modelviewclient.pro1
-rw-r--r--examples/remoteobjects/modelviewserver/modelviewserver.pro1
-rw-r--r--examples/remoteobjects/plugins/plugin.cpp6
-rw-r--r--examples/remoteobjects/server/timemodel.h6
-rw-r--r--examples/remoteobjects/simpleswitch/directconnectclient/client.h2
-rw-r--r--examples/remoteobjects/simpleswitch/directconnectdynamicclient/dynamicclient.h2
-rw-r--r--examples/remoteobjects/simpleswitch/directconnectserver/simpleswitch.h4
-rw-r--r--examples/remoteobjects/simpleswitch/registryconnectedclient/dynamicclient.h2
-rw-r--r--examples/remoteobjects/simpleswitch/registryconnectedserver/simpleswitch.h4
-rw-r--r--src/imports/remoteobjects/plugin.cpp6
-rw-r--r--src/imports/remoteobjects/plugins.qmltypes74
-rw-r--r--src/remoteobjects/doc/snippets/doc_src_remoteobjects.cpp4
-rw-r--r--src/remoteobjects/doc/src/remoteobjects-index.qdoc2
-rw-r--r--src/remoteobjects/doc/src/remoteobjects-interaction.qdoc2
-rw-r--r--src/remoteobjects/doc/src/remoteobjects-nodes.qdoc2
-rw-r--r--src/remoteobjects/doc/src/remoteobjects-registry.qdoc2
-rw-r--r--src/remoteobjects/doc/src/remoteobjects-repc.qdoc4
-rw-r--r--src/remoteobjects/doc/src/remoteobjects-replica.qdoc2
-rw-r--r--src/remoteobjects/doc/src/remoteobjects-source.qdoc2
-rw-r--r--src/remoteobjects/doc/src/remoteobjects-troubleshooting.qdoc2
-rw-r--r--src/remoteobjects/doc/src/remoteobjects-use.qdoc2
-rw-r--r--src/remoteobjects/qconnection_local_backend.cpp33
-rw-r--r--src/remoteobjects/qconnection_local_backend_p.h13
-rw-r--r--src/remoteobjects/qconnection_qnx_backend.cpp35
-rw-r--r--src/remoteobjects/qconnection_qnx_backend_p.h9
-rw-r--r--src/remoteobjects/qconnection_tcpip_backend.cpp32
-rw-r--r--src/remoteobjects/qconnection_tcpip_backend_p.h13
-rw-r--r--src/remoteobjects/qconnectionfactories.cpp13
-rw-r--r--src/remoteobjects/qconnectionfactories.h228
-rw-r--r--src/remoteobjects/qconnectionfactories_p.h185
-rw-r--r--src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp40
-rw-r--r--src/remoteobjects/qremoteobjectabstractitemmodeladapter_p.h116
-rw-r--r--src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp146
-rw-r--r--src/remoteobjects/qremoteobjectabstractitemmodelreplica.h10
-rw-r--r--src/remoteobjects/qremoteobjectabstractitemmodelreplica_p.h42
-rw-r--r--src/remoteobjects/qremoteobjectabstractitemmodeltypes.h28
-rw-r--r--src/remoteobjects/qremoteobjectdynamicreplica.cpp24
-rw-r--r--src/remoteobjects/qremoteobjectdynamicreplica.h2
-rw-r--r--src/remoteobjects/qremoteobjectnode.cpp307
-rw-r--r--src/remoteobjects/qremoteobjectnode.h47
-rw-r--r--src/remoteobjects/qremoteobjectnode_p.h34
-rw-r--r--src/remoteobjects/qremoteobjectpacket.cpp89
-rw-r--r--src/remoteobjects/qremoteobjectpacket_p.h6
-rw-r--r--src/remoteobjects/qremoteobjectpendingcall.cpp14
-rw-r--r--src/remoteobjects/qremoteobjectpendingcall.h5
-rw-r--r--src/remoteobjects/qremoteobjectpendingcall_p.h6
-rw-r--r--src/remoteobjects/qremoteobjectregistry.cpp36
-rw-r--r--src/remoteobjects/qremoteobjectregistry.h12
-rw-r--r--src/remoteobjects/qremoteobjectregistrysource_p.h2
-rw-r--r--src/remoteobjects/qremoteobjectreplica.cpp183
-rw-r--r--src/remoteobjects/qremoteobjectreplica.h12
-rw-r--r--src/remoteobjects/qremoteobjectreplica_p.h46
-rw-r--r--src/remoteobjects/qremoteobjectsettingsstore.cpp94
-rw-r--r--src/remoteobjects/qremoteobjectsettingsstore.h66
-rw-r--r--src/remoteobjects/qremoteobjectsource.cpp88
-rw-r--r--src/remoteobjects/qremoteobjectsource.h30
-rw-r--r--src/remoteobjects/qremoteobjectsource_p.h21
-rw-r--r--src/remoteobjects/qremoteobjectsourceio.cpp28
-rw-r--r--src/remoteobjects/qremoteobjectsourceio_p.h14
-rw-r--r--src/remoteobjects/qtremoteobjectglobal.h13
-rw-r--r--src/remoteobjects/remoteobjects.pro52
-rw-r--r--src/repparser/parser.g47
-rw-r--r--tests/auto/auto.pro19
-rw-r--r--tests/auto/benchmarks/tst_benchmarkstest.cpp4
-rw-r--r--tests/auto/integration/engine.h2
-rw-r--r--tests/auto/integration/integration.pro3
-rw-r--r--tests/auto/integration/local/local.pro3
-rw-r--r--tests/auto/integration/qnx/qnx.pro3
-rw-r--r--tests/auto/integration/speedometer.h2
-rw-r--r--tests/auto/integration/tcp/tcp.pro3
-rw-r--r--tests/auto/integration/template.pri4
-rw-r--r--tests/auto/integration/tst_integration.cpp84
-rw-r--r--tests/auto/integration_multiprocess/MyInterface.rep5
-rw-r--r--tests/auto/integration_multiprocess/client/main.cpp121
-rw-r--r--tests/auto/integration_multiprocess/server/main.cpp14
-rw-r--r--tests/auto/integration_multiprocess/server/mytestserver.cpp13
-rw-r--r--tests/auto/integration_multiprocess/server/mytestserver.h7
-rw-r--r--tests/auto/integration_multiprocess/tst/tst_integration_multiprocess.cpp14
-rw-r--r--tests/auto/modelreplica/tst_modelreplicatest.cpp21
-rw-r--r--tests/auto/modelview/modelview.pro1
-rw-r--r--tests/auto/modelview/tst_modelview.cpp58
-rw-r--r--tests/auto/qml/integration/data/tst_integration.qml56
-rw-r--r--tests/auto/qml/integration/integration.pro12
-rw-r--r--tests/auto/qml/integration/tst_integration.cpp30
-rw-r--r--tests/auto/qml/qml.pro5
-rw-r--r--tests/auto/qml/usertypes/data/complex.qml9
-rw-r--r--tests/auto/qml/usertypes/data/extraprop.qml12
-rw-r--r--tests/auto/qml/usertypes/data/model.qml9
-rw-r--r--tests/auto/qml/usertypes/data/subObject.qml17
-rw-r--r--tests/auto/qml/usertypes/tst_usertypes.cpp168
-rw-r--r--tests/auto/qml/usertypes/usertypes.pro14
-rw-r--r--tests/auto/qml/usertypes/usertypes.rep25
-rw-r--r--tests/auto/repc/signature/signatureTests/tst_signature.cpp20
-rw-r--r--tests/auto/repc/signature/state/main.cpp4
-rw-r--r--tests/auto/repcodegenerator/classwithreadonlypropertytest.rep4
-rw-r--r--tests/auto/repcodegenerator/repcodegenerator.pro1
-rw-r--r--tests/auto/repparser/tst_parser.cpp43
-rw-r--r--tests/auto/subclassreplica/class.rep9
-rw-r--r--tests/auto/subclassreplica/subclassreplica.pro15
-rw-r--r--tests/auto/subclassreplica/tst_subclassreplicatest.cpp94
-rw-r--r--tests/shared/testutils.h51
-rw-r--r--tools/repc/repc.pro1
-rw-r--r--tools/repc/repcodegenerator.cpp586
-rw-r--r--tools/repc/repcodegenerator.h2
107 files changed, 2876 insertions, 1052 deletions
diff --git a/.gitignore b/.gitignore
index 0a51ada..6c583d0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -77,3 +77,7 @@ rep_*_replica.h
/tools/repc/rep_grammar_p.h
/tools/repc/repparser.cpp
/tools/repc/repparser.h
+
+# Compiled QML/JS code
+*.qmlc
+*.jsc
diff --git a/.qmake.conf b/.qmake.conf
index e97c141..53985fb 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,6 +1,6 @@
load(qt_build_config)
CONFIG += qt_example_installs
-MODULE_VERSION = 5.9.5
+MODULE_VERSION = 5.11.0
QTRO_SOURCE_TREE = $$PWD
diff --git a/examples/remoteobjects/modelviewclient/main.cpp b/examples/remoteobjects/modelviewclient/main.cpp
index a62531f..7848198 100644
--- a/examples/remoteobjects/modelviewclient/main.cpp
+++ b/examples/remoteobjects/modelviewclient/main.cpp
@@ -66,6 +66,7 @@ int main(int argc, char **argv)
QRemoteObjectNode node(QUrl(QStringLiteral("local:registry")));
+ node.setHeartbeatInterval(1000);
QTreeView view;
view.setWindowTitle(QStringLiteral("RemoteView"));
view.resize(640,480);
diff --git a/examples/remoteobjects/modelviewclient/modelviewclient.pro b/examples/remoteobjects/modelviewclient/modelviewclient.pro
index f2ab294..473f38f 100644
--- a/examples/remoteobjects/modelviewclient/modelviewclient.pro
+++ b/examples/remoteobjects/modelviewclient/modelviewclient.pro
@@ -7,3 +7,4 @@ target.path = $$[QT_INSTALL_EXAMPLES]/remoteobjects/modelviewclient
INSTALLS += target
QT += widgets remoteobjects
+requires(qtConfig(treeview))
diff --git a/examples/remoteobjects/modelviewserver/modelviewserver.pro b/examples/remoteobjects/modelviewserver/modelviewserver.pro
index 53abb6b..d2fc6c4 100644
--- a/examples/remoteobjects/modelviewserver/modelviewserver.pro
+++ b/examples/remoteobjects/modelviewserver/modelviewserver.pro
@@ -1,4 +1,5 @@
QT += widgets remoteobjects
+requires(qtConfig(treeview))
TEMPLATE = app
diff --git a/examples/remoteobjects/plugins/plugin.cpp b/examples/remoteobjects/plugins/plugin.cpp
index 7e91afa..9590d26 100644
--- a/examples/remoteobjects/plugins/plugin.cpp
+++ b/examples/remoteobjects/plugins/plugin.cpp
@@ -83,7 +83,7 @@ public:
connect(d_ptr.data(), SIGNAL(sendCustom(PresetInfo)), this, SLOT(testCustom(PresetInfo)));
}
- ~TimeModel()
+ ~TimeModel() override
{
}
@@ -120,7 +120,7 @@ class QExampleQmlPlugin : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
public:
- void initializeEngine(QQmlEngine *engine, const char *uri)
+ void initializeEngine(QQmlEngine *engine, const char *uri) override
{
Q_UNUSED(engine);
Q_UNUSED(uri);
@@ -128,7 +128,7 @@ public:
engine->addImportPath(QStringLiteral("qrc:/qml"));
m_client.setRegistryUrl(QUrl(QStringLiteral("local:registry")));
}
- void registerTypes(const char *uri)
+ void registerTypes(const char *uri) override
{
Q_ASSERT(uri == QLatin1String("TimeExample"));
qmlRegisterType<TimeModel>(uri, 1, 0, "Time");
diff --git a/examples/remoteobjects/server/timemodel.h b/examples/remoteobjects/server/timemodel.h
index f03a18f..09c594a 100644
--- a/examples/remoteobjects/server/timemodel.h
+++ b/examples/remoteobjects/server/timemodel.h
@@ -56,13 +56,13 @@ class MinuteTimer : public MinuteTimerSimpleSource
Q_OBJECT
public:
MinuteTimer(QObject *parent = nullptr);
- virtual ~MinuteTimer();
+ ~MinuteTimer() override;
public slots:
- virtual void SetTimeZone(const int &zn);
+ void SetTimeZone(const int &zn) override;
protected:
- void timerEvent(QTimerEvent *);
+ void timerEvent(QTimerEvent *) override;
private:
QTime time;
diff --git a/examples/remoteobjects/simpleswitch/directconnectclient/client.h b/examples/remoteobjects/simpleswitch/directconnectclient/client.h
index 09d1bd6..9d86b74 100644
--- a/examples/remoteobjects/simpleswitch/directconnectclient/client.h
+++ b/examples/remoteobjects/simpleswitch/directconnectclient/client.h
@@ -61,7 +61,7 @@ class Client : public QObject
Q_OBJECT
public:
Client(QSharedPointer<SimpleSwitchReplica> ptr);
- ~Client();
+ ~Client() override;
void initConnections();// function connect signals and slots of source and client
Q_SIGNALS:
diff --git a/examples/remoteobjects/simpleswitch/directconnectdynamicclient/dynamicclient.h b/examples/remoteobjects/simpleswitch/directconnectdynamicclient/dynamicclient.h
index 9003fa5..ad948a9 100644
--- a/examples/remoteobjects/simpleswitch/directconnectdynamicclient/dynamicclient.h
+++ b/examples/remoteobjects/simpleswitch/directconnectdynamicclient/dynamicclient.h
@@ -62,7 +62,7 @@ class DynamicClient : public QObject
Q_OBJECT
public:
DynamicClient(QSharedPointer<QRemoteObjectDynamicReplica> ptr);
- ~DynamicClient();
+ ~DynamicClient() override;
Q_SIGNALS:
void echoSwitchState(bool switchState);// this signal is connected with server_slot(..) slot of source object and echoes back switch state received from source
diff --git a/examples/remoteobjects/simpleswitch/directconnectserver/simpleswitch.h b/examples/remoteobjects/simpleswitch/directconnectserver/simpleswitch.h
index c10f91e..48ea61c 100644
--- a/examples/remoteobjects/simpleswitch/directconnectserver/simpleswitch.h
+++ b/examples/remoteobjects/simpleswitch/directconnectserver/simpleswitch.h
@@ -58,8 +58,8 @@ class SimpleSwitch : public SimpleSwitchSimpleSource
Q_OBJECT
public:
SimpleSwitch(QObject *parent = nullptr);
- ~SimpleSwitch();
- virtual void server_slot(bool clientState);
+ ~SimpleSwitch() override;
+ void server_slot(bool clientState) override;
public Q_SLOTS:
void timeout_slot();
private:
diff --git a/examples/remoteobjects/simpleswitch/registryconnectedclient/dynamicclient.h b/examples/remoteobjects/simpleswitch/registryconnectedclient/dynamicclient.h
index 9003fa5..ad948a9 100644
--- a/examples/remoteobjects/simpleswitch/registryconnectedclient/dynamicclient.h
+++ b/examples/remoteobjects/simpleswitch/registryconnectedclient/dynamicclient.h
@@ -62,7 +62,7 @@ class DynamicClient : public QObject
Q_OBJECT
public:
DynamicClient(QSharedPointer<QRemoteObjectDynamicReplica> ptr);
- ~DynamicClient();
+ ~DynamicClient() override;
Q_SIGNALS:
void echoSwitchState(bool switchState);// this signal is connected with server_slot(..) slot of source object and echoes back switch state received from source
diff --git a/examples/remoteobjects/simpleswitch/registryconnectedserver/simpleswitch.h b/examples/remoteobjects/simpleswitch/registryconnectedserver/simpleswitch.h
index c10f91e..48ea61c 100644
--- a/examples/remoteobjects/simpleswitch/registryconnectedserver/simpleswitch.h
+++ b/examples/remoteobjects/simpleswitch/registryconnectedserver/simpleswitch.h
@@ -58,8 +58,8 @@ class SimpleSwitch : public SimpleSwitchSimpleSource
Q_OBJECT
public:
SimpleSwitch(QObject *parent = nullptr);
- ~SimpleSwitch();
- virtual void server_slot(bool clientState);
+ ~SimpleSwitch() override;
+ void server_slot(bool clientState) override;
public Q_SLOTS:
void timeout_slot();
private:
diff --git a/src/imports/remoteobjects/plugin.cpp b/src/imports/remoteobjects/plugin.cpp
index 47c4869..a4fbdd9 100644
--- a/src/imports/remoteobjects/plugin.cpp
+++ b/src/imports/remoteobjects/plugin.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include <QtRemoteObjects/qremoteobjectnode.h>
+#include <QtRemoteObjects/qremoteobjectsettingsstore.h>
#include <QQmlExtensionPlugin>
#include <qqml.h>
@@ -49,9 +50,12 @@ class QtQmlRemoteObjectsPlugin : public QQmlExtensionPlugin
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtQml.RemoteObjects/1.0")
public:
- void registerTypes(const char *uri)
+ void registerTypes(const char *uri) override
{
+ qmlRegisterUncreatableType<QRemoteObjectAbstractPersistedStore>(uri, 1, 0, "PersistedStore", "Cannot create PersistedStore");
+
qmlRegisterType<QRemoteObjectNode>(uri, 1, 0, "Node");
+ qmlRegisterType<QRemoteObjectSettingsStore>(uri, 1, 0, "SettingsStore");
qmlProtectModule(uri, 1);
}
};
diff --git a/src/imports/remoteobjects/plugins.qmltypes b/src/imports/remoteobjects/plugins.qmltypes
new file mode 100644
index 0000000..4839d3a
--- /dev/null
+++ b/src/imports/remoteobjects/plugins.qmltypes
@@ -0,0 +1,74 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtQml.RemoteObjects 1.0'
+
+Module {
+ dependencies: ["QtQuick 2.8"]
+ Component {
+ name: "QRemoteObjectAbstractPersistedStore"
+ prototype: "QObject"
+ exports: ["QtQml.RemoteObjects/PersistedStore 1.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ }
+ Component {
+ name: "QRemoteObjectNode"
+ prototype: "QObject"
+ exports: ["QtQml.RemoteObjects/Node 1.0"]
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "ErrorCode"
+ values: {
+ "NoError": 0,
+ "RegistryNotAcquired": 1,
+ "RegistryAlreadyHosted": 2,
+ "NodeIsNoServer": 3,
+ "ServerAlreadyCreated": 4,
+ "UnintendedRegistryHosting": 5,
+ "OperationNotValidOnClientNode": 6,
+ "SourceNotRegistered": 7,
+ "MissingObjectName": 8,
+ "HostUrlInvalid": 9,
+ "ProtocolMismatch": 10
+ }
+ }
+ Property { name: "registryUrl"; type: "QUrl" }
+ Property {
+ name: "persistedStore"
+ type: "QRemoteObjectAbstractPersistedStore"
+ isPointer: true
+ }
+ Property { name: "heartbeatInterval"; type: "int" }
+ Signal {
+ name: "remoteObjectAdded"
+ Parameter { type: "QRemoteObjectSourceLocation" }
+ }
+ Signal {
+ name: "remoteObjectRemoved"
+ Parameter { type: "QRemoteObjectSourceLocation" }
+ }
+ Signal {
+ name: "error"
+ Parameter { name: "errorCode"; type: "QRemoteObjectNode::ErrorCode" }
+ }
+ Signal {
+ name: "heartbeatIntervalChanged"
+ Parameter { name: "heartbeatInterval"; type: "int" }
+ }
+ Method {
+ name: "connectToNode"
+ type: "bool"
+ Parameter { name: "address"; type: "QUrl" }
+ }
+ }
+ Component {
+ name: "QRemoteObjectSettingsStore"
+ prototype: "QRemoteObjectAbstractPersistedStore"
+ exports: ["QtQml.RemoteObjects/SettingsStore 1.0"]
+ exportMetaObjectRevisions: [0]
+ }
+}
diff --git a/src/remoteobjects/doc/snippets/doc_src_remoteobjects.cpp b/src/remoteobjects/doc/snippets/doc_src_remoteobjects.cpp
index a549ab7..3ab3280 100644
--- a/src/remoteobjects/doc/snippets/doc_src_remoteobjects.cpp
+++ b/src/remoteobjects/doc/snippets/doc_src_remoteobjects.cpp
@@ -73,7 +73,7 @@ hostNode.enableRemoting<MinuteTimerSourceAPI>(&timer);
//! [create_replica]
#include "rep_TimeModel_replica.h"
-QScopedPointer<MinuteTimerReplica> d_ptr;
+QScopedPointer<MinuteTimerReplica> d_impl;
//! [create_replica]
//! [dynamic_replica]
@@ -81,7 +81,7 @@ QRemoteObjectDynamicReplica *dynamicRep;
//! [dynamic_replica]
//! [acquire_replica]
-d_ptr->reset(clientNode.acquire("MinuteTimer"));
+d_impl->reset(clientNode.acquire("MinuteTimer"));
*dynamicRep = clientNode.acquire("MinuteTimer");
//! [acquire_replica]
diff --git a/src/remoteobjects/doc/src/remoteobjects-index.qdoc b/src/remoteobjects/doc/src/remoteobjects-index.qdoc
index cdcba51..e2ce60f 100644
--- a/src/remoteobjects/doc/src/remoteobjects-index.qdoc
+++ b/src/remoteobjects/doc/src/remoteobjects-index.qdoc
@@ -102,7 +102,7 @@ QT += remoteobjects
\li \l {Qt Remote Objects Registry}
\li \l {Qt Remote Objects Compiler}
\li \l {Remote Object Interaction}
- \li \l {Using Qt RemoteObjects}
+ \li \l {Using Qt Remote Objects}
\li \l {Troubleshooting Qt Remote Objects}
\endlist
diff --git a/src/remoteobjects/doc/src/remoteobjects-interaction.qdoc b/src/remoteobjects/doc/src/remoteobjects-interaction.qdoc
index caa4c2c..6f980b6 100644
--- a/src/remoteobjects/doc/src/remoteobjects-interaction.qdoc
+++ b/src/remoteobjects/doc/src/remoteobjects-interaction.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Ford Motor Company
+** Copyright (C) 2018 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtRemoteObjects module of the Qt Toolkit.
diff --git a/src/remoteobjects/doc/src/remoteobjects-nodes.qdoc b/src/remoteobjects/doc/src/remoteobjects-nodes.qdoc
index 881b656..907460b 100644
--- a/src/remoteobjects/doc/src/remoteobjects-nodes.qdoc
+++ b/src/remoteobjects/doc/src/remoteobjects-nodes.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Ford Motor Company
+** Copyright (C) 2018 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtRemoteObjects module of the Qt Toolkit.
diff --git a/src/remoteobjects/doc/src/remoteobjects-registry.qdoc b/src/remoteobjects/doc/src/remoteobjects-registry.qdoc
index 06912d1..67a4fe3 100644
--- a/src/remoteobjects/doc/src/remoteobjects-registry.qdoc
+++ b/src/remoteobjects/doc/src/remoteobjects-registry.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Ford Motor Company
+** Copyright (C) 2018 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtRemoteObjects module of the Qt Toolkit.
diff --git a/src/remoteobjects/doc/src/remoteobjects-repc.qdoc b/src/remoteobjects/doc/src/remoteobjects-repc.qdoc
index 49c731a..cf32c80 100644
--- a/src/remoteobjects/doc/src/remoteobjects-repc.qdoc
+++ b/src/remoteobjects/doc/src/remoteobjects-repc.qdoc
@@ -218,10 +218,10 @@
property value has to be allowed to change during initialization. For
READONLY, the Source will have neither a setter nor a push slot, and the
replica side will not have a push slot generated. Adding the PERSISTED
- trait to a PROP will have the PROP use the \l QRemoteObjectPersistedStore
+ trait to a PROP will have the PROP use the \l QRemoteObjectAbstractPersistedStore
instance set on a Node (if any) to save/restore PROP values.
- \sa QRemoteObjectPersistedStore
+ \sa QRemoteObjectAbstractPersistedStore
\section3 SIGNAL
diff --git a/src/remoteobjects/doc/src/remoteobjects-replica.qdoc b/src/remoteobjects/doc/src/remoteobjects-replica.qdoc
index 980df98..ae1253d 100644
--- a/src/remoteobjects/doc/src/remoteobjects-replica.qdoc
+++ b/src/remoteobjects/doc/src/remoteobjects-replica.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Ford Motor Company
+** Copyright (C) 2018 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtRemoteObjects module of the Qt Toolkit.
diff --git a/src/remoteobjects/doc/src/remoteobjects-source.qdoc b/src/remoteobjects/doc/src/remoteobjects-source.qdoc
index ed12627..0a788f8 100644
--- a/src/remoteobjects/doc/src/remoteobjects-source.qdoc
+++ b/src/remoteobjects/doc/src/remoteobjects-source.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Ford Motor Company
+** Copyright (C) 2018 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtRemoteObjects module of the Qt Toolkit.
diff --git a/src/remoteobjects/doc/src/remoteobjects-troubleshooting.qdoc b/src/remoteobjects/doc/src/remoteobjects-troubleshooting.qdoc
index 5ed7a69..51a6cf1 100644
--- a/src/remoteobjects/doc/src/remoteobjects-troubleshooting.qdoc
+++ b/src/remoteobjects/doc/src/remoteobjects-troubleshooting.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Ford Motor Company
+** Copyright (C) 2018 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtRemoteObjects module of the Qt Toolkit.
diff --git a/src/remoteobjects/doc/src/remoteobjects-use.qdoc b/src/remoteobjects/doc/src/remoteobjects-use.qdoc
index 0dd0e1e..ae557c5 100644
--- a/src/remoteobjects/doc/src/remoteobjects-use.qdoc
+++ b/src/remoteobjects/doc/src/remoteobjects-use.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Ford Motor Company
+** Copyright (C) 2018 Ford Motor Company
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtRemoteObjects module of the Qt Toolkit.
diff --git a/src/remoteobjects/qconnection_local_backend.cpp b/src/remoteobjects/qconnection_local_backend.cpp
index 40723b5..4332095 100644
--- a/src/remoteobjects/qconnection_local_backend.cpp
+++ b/src/remoteobjects/qconnection_local_backend.cpp
@@ -43,10 +43,11 @@ QT_BEGIN_NAMESPACE
LocalClientIo::LocalClientIo(QObject *parent)
: ClientIoDevice(parent)
+ , m_socket(new QLocalSocket(this))
{
- connect(&m_socket, &QLocalSocket::readyRead, this, &ClientIoDevice::readyRead);
- connect(&m_socket, static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), this, &LocalClientIo::onError);
- connect(&m_socket, &QLocalSocket::stateChanged, this, &LocalClientIo::onStateChanged);
+ connect(m_socket, &QLocalSocket::readyRead, this, &ClientIoDevice::readyRead);
+ connect(m_socket, static_cast<void (QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), this, &LocalClientIo::onError);
+ connect(m_socket, &QLocalSocket::stateChanged, this, &LocalClientIo::onStateChanged);
}
LocalClientIo::~LocalClientIo()
@@ -54,35 +55,41 @@ LocalClientIo::~LocalClientIo()
close();
}
-QIODevice *LocalClientIo::connection()
+QIODevice *LocalClientIo::connection() const
{
- return &m_socket;
+ return m_socket;
}
void LocalClientIo::doClose()
{
- if (m_socket.isOpen()) {
- connect(&m_socket, &QLocalSocket::disconnected, this, &QObject::deleteLater);
- m_socket.disconnectFromServer();
+ if (m_socket->isOpen()) {
+ connect(m_socket, &QLocalSocket::disconnected, this, &QObject::deleteLater);
+ m_socket->disconnectFromServer();
} else {
this->deleteLater();
}
}
+void LocalClientIo::doDisconnectFromServer()
+{
+ m_socket->disconnectFromServer();
+}
+
void LocalClientIo::connectToServer()
{
if (!isOpen())
- m_socket.connectToServer(url().path());
+ m_socket->connectToServer(url().path());
}
-bool LocalClientIo::isOpen()
+bool LocalClientIo::isOpen() const
{
- return !isClosing() && m_socket.isOpen();
+ return !isClosing() && (m_socket->state() == QLocalSocket::ConnectedState
+ || m_socket->state() == QLocalSocket::ConnectingState);
}
void LocalClientIo::onError(QLocalSocket::LocalSocketError error)
{
- qCDebug(QT_REMOTEOBJECT) << "onError" << error << m_socket.serverName();
+ qCDebug(QT_REMOTEOBJECT) << "onError" << error << m_socket->serverName();
switch (error) {
case QLocalSocket::ServerNotFoundError:
@@ -105,7 +112,7 @@ void LocalClientIo::onError(QLocalSocket::LocalSocketError error)
void LocalClientIo::onStateChanged(QLocalSocket::LocalSocketState state)
{
if (state == QLocalSocket::ClosingState && !isClosing()) {
- m_socket.abort();
+ m_socket->abort();
emit shouldReconnect(this);
}
if (state == QLocalSocket::ConnectedState) {
diff --git a/src/remoteobjects/qconnection_local_backend_p.h b/src/remoteobjects/qconnection_local_backend_p.h
index 51a804e..4db2880 100644
--- a/src/remoteobjects/qconnection_local_backend_p.h
+++ b/src/remoteobjects/qconnection_local_backend_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include "qconnectionfactories.h"
+#include "qconnectionfactories_p.h"
#include <QLocalServer>
#include <QLocalSocket>
@@ -64,11 +64,11 @@ class LocalClientIo : public ClientIoDevice
public:
explicit LocalClientIo(QObject *parent = nullptr);
- ~LocalClientIo();
+ ~LocalClientIo() override;
- QIODevice *connection() override;
+ QIODevice *connection() const override;
void connectToServer() override;
- bool isOpen() override;
+ bool isOpen() const override;
public Q_SLOTS:
void onError(QLocalSocket::LocalSocketError error);
@@ -76,8 +76,9 @@ public Q_SLOTS:
protected:
void doClose() override;
+ void doDisconnectFromServer() override;
private:
- QLocalSocket m_socket;
+ QLocalSocket* m_socket;
};
class LocalServerIo : public ServerIoDevice
@@ -101,7 +102,7 @@ class LocalServerImpl : public QConnectionAbstractServer
public:
explicit LocalServerImpl(QObject *parent);
- ~LocalServerImpl();
+ ~LocalServerImpl() override;
bool hasPendingConnections() const override;
ServerIoDevice *configureNewConnection() override;
diff --git a/src/remoteobjects/qconnection_qnx_backend.cpp b/src/remoteobjects/qconnection_qnx_backend.cpp
index 549be45..a4f6375 100644
--- a/src/remoteobjects/qconnection_qnx_backend.cpp
+++ b/src/remoteobjects/qconnection_qnx_backend.cpp
@@ -43,13 +43,14 @@ QT_BEGIN_NAMESPACE
QnxClientIo::QnxClientIo(QObject *parent)
: ClientIoDevice(parent)
+ , m_socket(new QQnxNativeIo(this))
{
- connect(&m_socket, &QQnxNativeIo::readyRead, this, &ClientIoDevice::readyRead);
- connect(&m_socket,
+ connect(m_socket, &QQnxNativeIo::readyRead, this, &ClientIoDevice::readyRead);
+ connect(m_socket,
static_cast<void(QQnxNativeIo::*)(QAbstractSocket::SocketError)>(&QQnxNativeIo::error),
this,
&QnxClientIo::onError);
- connect(&m_socket, &QQnxNativeIo::stateChanged, this, &QnxClientIo::onStateChanged);
+ connect(m_socket, &QQnxNativeIo::stateChanged, this, &QnxClientIo::onStateChanged);
}
QnxClientIo::~QnxClientIo()
@@ -57,39 +58,45 @@ QnxClientIo::~QnxClientIo()
close();
}
-QIODevice *QnxClientIo::connection()
+QIODevice *QnxClientIo::connection() const
{
- return &m_socket;
+ return m_socket;
}
void QnxClientIo::doClose()
{
- if (m_socket.isOpen()) {
- connect(&m_socket, &QQnxNativeIo::disconnected, this, &QObject::deleteLater);
- m_socket.disconnectFromServer();
+ if (m_socket->isOpen()) {
+ connect(m_socket, &QQnxNativeIo::disconnected, this, &QObject::deleteLater);
+ m_socket->disconnectFromServer();
} else {
deleteLater();
}
}
+void QnxClientIo::doDisconnectFromServer()
+{
+ m_socket->disconnectFromServer();
+}
+
void QnxClientIo::connectToServer()
{
if (!isOpen())
- m_socket.connectToServer(url().path());
+ m_socket->connectToServer(url().path());
}
-bool QnxClientIo::isOpen()
+bool QnxClientIo::isOpen() const
{
- return !isClosing() && m_socket.isOpen();
+ return !isClosing() && (m_socket->state() == QAbstractSocket::ConnectedState
+ || m_socket->state() == QAbstractSocket::ConnectingState);
}
void QnxClientIo::onError(QAbstractSocket::SocketError error)
{
- qCDebug(QT_REMOTEOBJECT) << "onError" << error << m_socket.serverName();
+ qCDebug(QT_REMOTEOBJECT) << "onError" << error << m_socket->serverName();
switch (error) {
case QAbstractSocket::RemoteHostClosedError:
- m_socket.close();
+ m_socket->close();
qCWarning(QT_REMOTEOBJECT) << "RemoteHostClosedError";
case QAbstractSocket::HostNotFoundError: //Host not there, wait and try again
case QAbstractSocket::AddressInUseError:
@@ -105,7 +112,7 @@ void QnxClientIo::onError(QAbstractSocket::SocketError error)
void QnxClientIo::onStateChanged(QAbstractSocket::SocketState state)
{
if (state == QAbstractSocket::ClosingState && !isClosing()) {
- m_socket.abort();
+ m_socket->abort();
emit shouldReconnect(this);
} else if (state == QAbstractSocket::ConnectedState) {
m_dataStream.setDevice(connection());
diff --git a/src/remoteobjects/qconnection_qnx_backend_p.h b/src/remoteobjects/qconnection_qnx_backend_p.h
index 454cc55..0e0d714 100644
--- a/src/remoteobjects/qconnection_qnx_backend_p.h
+++ b/src/remoteobjects/qconnection_qnx_backend_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QtRemoteObjects/qconnectionfactories.h>
+#include "qconnectionfactories_p.h"
#include "qconnection_qnx_qiodevices.h"
#include "qconnection_qnx_server.h"
@@ -101,9 +101,9 @@ public:
explicit QnxClientIo(QObject *parent = nullptr);
~QnxClientIo();
- QIODevice *connection() override;
+ QIODevice *connection() const override;
void connectToServer() override;
- bool isOpen() override;
+ bool isOpen() const override;
public Q_SLOTS:
void onError(QAbstractSocket::SocketError error);
@@ -111,8 +111,9 @@ public Q_SLOTS:
protected:
void doClose() override;
+ void doDisconnectFromServer() override;
private:
- QQnxNativeIo m_socket;
+ QQnxNativeIo *m_socket;
};
class QnxServerIo : public ServerIoDevice
diff --git a/src/remoteobjects/qconnection_tcpip_backend.cpp b/src/remoteobjects/qconnection_tcpip_backend.cpp
index 050cfb3..71706b6 100644
--- a/src/remoteobjects/qconnection_tcpip_backend.cpp
+++ b/src/remoteobjects/qconnection_tcpip_backend.cpp
@@ -45,10 +45,11 @@ QT_BEGIN_NAMESPACE
TcpClientIo::TcpClientIo(QObject *parent)
: ClientIoDevice(parent)
+ , m_socket(new QTcpSocket(this))
{
- connect(&m_socket, &QTcpSocket::readyRead, this, &ClientIoDevice::readyRead);
- connect(&m_socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), this, &TcpClientIo::onError);
- connect(&m_socket, &QTcpSocket::stateChanged, this, &TcpClientIo::onStateChanged);
+ connect(m_socket, &QTcpSocket::readyRead, this, &ClientIoDevice::readyRead);
+ connect(m_socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), this, &TcpClientIo::onError);
+ connect(m_socket, &QTcpSocket::stateChanged, this, &TcpClientIo::onStateChanged);
}
TcpClientIo::~TcpClientIo()
@@ -56,21 +57,26 @@ TcpClientIo::~TcpClientIo()
close();
}
-QIODevice *TcpClientIo::connection()
+QIODevice *TcpClientIo::connection() const
{
- return &m_socket;
+ return m_socket;
}
void TcpClientIo::doClose()
{
- if (m_socket.isOpen()) {
- connect(&m_socket, &QTcpSocket::disconnected, this, &QObject::deleteLater);
- m_socket.disconnectFromHost();
+ if (m_socket->isOpen()) {
+ connect(m_socket, &QTcpSocket::disconnected, this, &QObject::deleteLater);
+ m_socket->disconnectFromHost();
} else {
this->deleteLater();
}
}
+void TcpClientIo::doDisconnectFromServer()
+{
+ m_socket->disconnectFromHost();
+}
+
void TcpClientIo::connectToServer()
{
if (isOpen())
@@ -82,13 +88,13 @@ void TcpClientIo::connectToServer()
address = addresses.first();
}
- m_socket.connectToHost(address, url().port());
+ m_socket->connectToHost(address, url().port());
}
-bool TcpClientIo::isOpen()
+bool TcpClientIo::isOpen() const
{
- return (!isClosing() && (m_socket.state() == QAbstractSocket::ConnectedState
- || m_socket.state() == QAbstractSocket::ConnectingState));
+ return (!isClosing() && (m_socket->state() == QAbstractSocket::ConnectedState
+ || m_socket->state() == QAbstractSocket::ConnectingState));
}
void TcpClientIo::onError(QAbstractSocket::SocketError error)
@@ -111,7 +117,7 @@ void TcpClientIo::onError(QAbstractSocket::SocketError error)
void TcpClientIo::onStateChanged(QAbstractSocket::SocketState state)
{
if (state == QAbstractSocket::ClosingState && !isClosing()) {
- m_socket.abort();
+ m_socket->abort();
emit shouldReconnect(this);
}
if (state == QAbstractSocket::ConnectedState) {
diff --git a/src/remoteobjects/qconnection_tcpip_backend_p.h b/src/remoteobjects/qconnection_tcpip_backend_p.h
index 7f393d7..a36692a 100644
--- a/src/remoteobjects/qconnection_tcpip_backend_p.h
+++ b/src/remoteobjects/qconnection_tcpip_backend_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include "qconnectionfactories.h"
+#include "qconnectionfactories_p.h"
#include <QTcpServer>
#include <QTcpSocket>
@@ -64,11 +64,11 @@ class TcpClientIo : public ClientIoDevice
public:
explicit TcpClientIo(QObject *parent = nullptr);
- ~TcpClientIo();
+ ~TcpClientIo() override;
- QIODevice *connection() override;
+ QIODevice *connection() const override;
void connectToServer() override;
- bool isOpen() override;
+ bool isOpen() const override;
public Q_SLOTS:
void onError(QAbstractSocket::SocketError error);
@@ -76,9 +76,10 @@ public Q_SLOTS:
protected:
void doClose() override;
+ void doDisconnectFromServer() override;
private:
- QTcpSocket m_socket;
+ QTcpSocket *m_socket;
};
class TcpServerIo : public ServerIoDevice
@@ -102,7 +103,7 @@ class TcpServerImpl : public QConnectionAbstractServer
public:
explicit TcpServerImpl(QObject *parent);
- ~TcpServerImpl();
+ ~TcpServerImpl() override;
bool hasPendingConnections() const override;
ServerIoDevice *configureNewConnection() override;
diff --git a/src/remoteobjects/qconnectionfactories.cpp b/src/remoteobjects/qconnectionfactories.cpp
index 6be1e17..583f800 100644
--- a/src/remoteobjects/qconnectionfactories.cpp
+++ b/src/remoteobjects/qconnectionfactories.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "qconnectionfactories.h"
+#include "qconnectionfactories_p.h"
#include "qconnectionfactories_p.h"
// BEGIN: Backends
@@ -67,6 +67,7 @@ inline bool fromDataStream(QDataStream &in, QRemoteObjectPacketTypeEnum &type, Q
in >> _type;
type = Invalid;
switch (_type) {
+ case Handshake: type = Handshake; break;
case InitPacket: type = InitPacket; break;
case InitDynamicPacket: type = InitDynamicPacket; break;
case AddObject: type = AddObject; break;
@@ -75,6 +76,8 @@ inline bool fromDataStream(QDataStream &in, QRemoteObjectPacketTypeEnum &type, Q
case InvokeReplyPacket: type = InvokeReplyPacket; break;
case PropertyChangePacket: type = PropertyChangePacket; break;
case ObjectList: type = ObjectList; break;
+ case Ping: type = Ping; break;
+ case Pong: type = Pong; break;
default:
qCWarning(QT_REMOTEOBJECT_IO) << "Invalid packet received" << type;
}
@@ -104,6 +107,12 @@ void ClientIoDevice::close()
doClose();
}
+void ClientIoDevice::disconnectFromServer()
+{
+ doDisconnectFromServer();
+ emit shouldReconnect(this);
+}
+
bool ClientIoDevice::read(QRemoteObjectPacketTypeEnum &type, QString &name)
{
qCDebug(QT_REMOTEOBJECT_IO) << "ClientIODevice::read()" << m_curReadSize << bytesAvailable();
@@ -134,7 +143,7 @@ void ClientIoDevice::write(const QByteArray &data, qint64 size)
connection()->write(data.data(), size);
}
-qint64 ClientIoDevice::bytesAvailable()
+qint64 ClientIoDevice::bytesAvailable() const
{
return connection()->bytesAvailable();
}
diff --git a/src/remoteobjects/qconnectionfactories.h b/src/remoteobjects/qconnectionfactories.h
deleted file mode 100644
index bf35327..0000000
--- a/src/remoteobjects/qconnectionfactories.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017-2015 Ford Motor Company
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtRemoteObjects 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QCONNECTIONFACTORIES_H
-#define QCONNECTIONFACTORIES_H
-
-#include <QAbstractSocket>
-#include <QDataStream>
-#include <QtRemoteObjects/qtremoteobjectglobal.h>
-
-QT_BEGIN_NAMESPACE
-
-//The Qt servers create QIODevice derived classes from handleConnection.
-//The problem is that they behave differently, so this class adds some
-//consistency.
-class Q_REMOTEOBJECTS_EXPORT ServerIoDevice : public QObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(ServerIoDevice)
-
-public:
- explicit ServerIoDevice(QObject *parent = nullptr);
- virtual ~ServerIoDevice();
-
- bool read(QtRemoteObjects::QRemoteObjectPacketTypeEnum &, QString &);
-
- virtual void write(const QByteArray &data);
- virtual void write(const QByteArray &data, qint64);
- void close();
- virtual qint64 bytesAvailable();
- virtual QIODevice *connection() const = 0;
- void initializeDataStream();
- QDataStream& stream() { return m_dataStream; }
-
-Q_SIGNALS:
- void disconnected();
- void readyRead();
-
-protected:
- virtual void doClose() = 0;
-
-private:
- bool m_isClosing;
- quint32 m_curReadSize;
- QDataStream m_dataStream;
-};
-
-class Q_REMOTEOBJECTS_EXPORT QConnectionAbstractServer : public QObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(QConnectionAbstractServer)
-
-public:
- explicit QConnectionAbstractServer(QObject *parent = nullptr);
- virtual ~QConnectionAbstractServer();
-
- virtual bool hasPendingConnections() const = 0;
- ServerIoDevice* nextPendingConnection();
- virtual QUrl address() const = 0;
- virtual bool listen(const QUrl &address) = 0;
- virtual QAbstractSocket::SocketError serverError() const = 0;
- virtual void close() = 0;
-
-protected:
- virtual ServerIoDevice* configureNewConnection() = 0;
-
-Q_SIGNALS:
- void newConnection();
-};
-
-class Q_REMOTEOBJECTS_EXPORT ClientIoDevice : public QObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(ClientIoDevice)
-
-public:
- explicit ClientIoDevice(QObject *parent = nullptr);
- virtual ~ClientIoDevice();
-
- bool read(QtRemoteObjects::QRemoteObjectPacketTypeEnum &, QString &);
-
- virtual void write(const QByteArray &data);
- virtual void write(const QByteArray &data, qint64);
- void close();
- virtual void connectToServer() = 0;
- virtual qint64 bytesAvailable();
-
- QUrl url() const;
- void addSource(const QString &);
- void removeSource(const QString &);
- QSet<QString> remoteObjects() const;
-
- virtual bool isOpen() = 0;
- virtual QIODevice *connection() = 0;
- inline QDataStream& stream() { return m_dataStream; }
-
-Q_SIGNALS:
- void disconnected();
- void readyRead();
- void shouldReconnect(ClientIoDevice*);
-protected:
- virtual void doClose() = 0;
- inline bool isClosing() { return m_isClosing; }
- QDataStream m_dataStream;
-
-private:
- bool m_isClosing;
- QUrl m_url;
-
-private:
- friend class QtROClientFactory;
-
- quint32 m_curReadSize;
- QSet<QString> m_remoteObjects;
-};
-
-class QtROServerFactory
-{
-public:
- Q_REMOTEOBJECTS_EXPORT static QtROServerFactory *instance();
-
- QConnectionAbstractServer *create(const QUrl &url, QObject *parent = nullptr)
- {
- auto creatorFunc = m_creatorFuncs.value(url.scheme());
- return creatorFunc ? (*creatorFunc)(parent) : nullptr;
- }
-
- template<typename T>
- void registerType(const QString &id)
- {
- m_creatorFuncs[id] = [](QObject *parent) -> QConnectionAbstractServer * {
- return new T(parent);
- };
- }
-
-private:
- friend class QtROFactoryLoader;
- QtROServerFactory();
-
- using CreatorFunc = QConnectionAbstractServer * (*)(QObject *);
- QHash<QString, CreatorFunc> m_creatorFuncs;
-};
-
-class QtROClientFactory
-{
-public:
- Q_REMOTEOBJECTS_EXPORT static QtROClientFactory *instance();
-
- /// creates an object from a string
- ClientIoDevice *create(const QUrl &url, QObject *parent = nullptr)
- {
- auto creatorFunc = m_creatorFuncs.value(url.scheme());
- if (!creatorFunc)
- return nullptr;
-
- ClientIoDevice *res = (*creatorFunc)(parent);
- if (res)
- res->m_url = url;
- return res;
- }
-
- template<typename T>
- void registerType(const QString &id)
- {
- m_creatorFuncs[id] = [](QObject *parent) -> ClientIoDevice * {
- return new T(parent);
- };
- }
-
-private:
- friend class QtROFactoryLoader;
- QtROClientFactory();
-
- using CreatorFunc = ClientIoDevice * (*)(QObject *);
- QHash<QString, CreatorFunc> m_creatorFuncs;
-};
-
-template <typename T>
-inline void qRegisterRemoteObjectsClient(const QString &id)
-{
- QtROClientFactory::instance()->registerType<T>(id);
-}
-
-template <typename T>
-inline void qRegisterRemoteObjectsServer(const QString &id)
-{
- QtROServerFactory::instance()->registerType<T>(id);
-}
-
-QT_END_NAMESPACE
-
-#endif // QCONNECTIONFACTORIES_H
diff --git a/src/remoteobjects/qconnectionfactories_p.h b/src/remoteobjects/qconnectionfactories_p.h
index 305c567..a211727 100644
--- a/src/remoteobjects/qconnectionfactories_p.h
+++ b/src/remoteobjects/qconnectionfactories_p.h
@@ -51,14 +51,197 @@
// We mean it.
//
+#include <QAbstractSocket>
#include <QDataStream>
+#include <QtRemoteObjects/qtremoteobjectglobal.h>
+
QT_BEGIN_NAMESPACE
namespace QtRemoteObjects {
-const int dataStreamVersion = QDataStream::Qt_5_1;
+static const int dataStreamVersion = QDataStream::Qt_5_6;
+static const QLatin1String protocolVersion("QtRO 1.0");
+
+}
+
+//The Qt servers create QIODevice derived classes from handleConnection.
+//The problem is that they behave differently, so this class adds some
+//consistency.
+class Q_REMOTEOBJECTS_EXPORT ServerIoDevice : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ServerIoDevice)
+
+public:
+ explicit ServerIoDevice(QObject *parent = nullptr);
+ ~ServerIoDevice() override;
+
+ bool read(QtRemoteObjects::QRemoteObjectPacketTypeEnum &, QString &);
+
+ virtual void write(const QByteArray &data);
+ virtual void write(const QByteArray &data, qint64);
+ void close();
+ virtual qint64 bytesAvailable();
+ virtual QIODevice *connection() const = 0;
+ void initializeDataStream();
+ QDataStream& stream() { return m_dataStream; }
+
+Q_SIGNALS:
+ void disconnected();
+ void readyRead();
+
+protected:
+ virtual void doClose() = 0;
+
+private:
+ bool m_isClosing;
+ quint32 m_curReadSize;
+ QDataStream m_dataStream;
+};
+
+class Q_REMOTEOBJECTS_EXPORT QConnectionAbstractServer : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QConnectionAbstractServer)
+
+public:
+ explicit QConnectionAbstractServer(QObject *parent = nullptr);
+ ~QConnectionAbstractServer() override;
+
+ virtual bool hasPendingConnections() const = 0;
+ ServerIoDevice* nextPendingConnection();
+ virtual QUrl address() const = 0;
+ virtual bool listen(const QUrl &address) = 0;
+ virtual QAbstractSocket::SocketError serverError() const = 0;
+ virtual void close() = 0;
+
+protected:
+ virtual ServerIoDevice* configureNewConnection() = 0;
+
+Q_SIGNALS:
+ void newConnection();
+};
+
+class Q_REMOTEOBJECTS_EXPORT ClientIoDevice : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ClientIoDevice)
+
+public:
+ explicit ClientIoDevice(QObject *parent = nullptr);
+ ~ClientIoDevice() override;
+
+ bool read(QtRemoteObjects::QRemoteObjectPacketTypeEnum &, QString &);
+
+ virtual void write(const QByteArray &data);
+ virtual void write(const QByteArray &data, qint64);
+ void close();
+ void disconnectFromServer();
+ virtual void connectToServer() = 0;
+ virtual qint64 bytesAvailable() const;
+
+ QUrl url() const;
+ void addSource(const QString &);
+ void removeSource(const QString &);
+ QSet<QString> remoteObjects() const;
+
+ virtual bool isOpen() const = 0;
+ virtual QIODevice *connection() const = 0;
+ inline QDataStream& stream() { return m_dataStream; }
+
+Q_SIGNALS:
+ void disconnected();
+ void readyRead();
+ void shouldReconnect(ClientIoDevice*);
+protected:
+ virtual void doClose() = 0;
+ virtual void doDisconnectFromServer() = 0;
+ inline bool isClosing() const { return m_isClosing; }
+ QDataStream m_dataStream;
+
+private:
+ bool m_isClosing;
+ QUrl m_url;
+
+private:
+ friend class QtROClientFactory;
+
+ quint32 m_curReadSize;
+ QSet<QString> m_remoteObjects;
+};
+
+class QtROServerFactory
+{
+public:
+ Q_REMOTEOBJECTS_EXPORT static QtROServerFactory *instance();
+
+ QConnectionAbstractServer *create(const QUrl &url, QObject *parent = nullptr)
+ {
+ auto creatorFunc = m_creatorFuncs.value(url.scheme());
+ return creatorFunc ? (*creatorFunc)(parent) : nullptr;
+ }
+
+ template<typename T>
+ void registerType(const QString &id)
+ {
+ m_creatorFuncs[id] = [](QObject *parent) -> QConnectionAbstractServer * {
+ return new T(parent);
+ };
+ }
+
+private:
+ friend class QtROFactoryLoader;
+ QtROServerFactory();
+
+ using CreatorFunc = QConnectionAbstractServer * (*)(QObject *);
+ QHash<QString, CreatorFunc> m_creatorFuncs;
+};
+
+class QtROClientFactory
+{
+public:
+ Q_REMOTEOBJECTS_EXPORT static QtROClientFactory *instance();
+
+ /// creates an object from a string
+ ClientIoDevice *create(const QUrl &url, QObject *parent = nullptr)
+ {
+ auto creatorFunc = m_creatorFuncs.value(url.scheme());
+ if (!creatorFunc)
+ return nullptr;
+
+ ClientIoDevice *res = (*creatorFunc)(parent);
+ if (res)
+ res->m_url = url;
+ return res;
+ }
+
+ template<typename T>
+ void registerType(const QString &id)
+ {
+ m_creatorFuncs[id] = [](QObject *parent) -> ClientIoDevice * {
+ return new T(parent);
+ };
+ }
+
+private:
+ friend class QtROFactoryLoader;
+ QtROClientFactory();
+
+ using CreatorFunc = ClientIoDevice * (*)(QObject *);
+ QHash<QString, CreatorFunc> m_creatorFuncs;
+};
+
+template <typename T>
+inline void qRegisterRemoteObjectsClient(const QString &id)
+{
+ QtROClientFactory::instance()->registerType<T>(id);
+}
+template <typename T>
+inline void qRegisterRemoteObjectsServer(const QString &id)
+{
+ QtROServerFactory::instance()->registerType<T>(id);
}
QT_END_NAMESPACE
diff --git a/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp b/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp
index 7f6cb49..409f72d 100644
--- a/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp
+++ b/src/remoteobjects/qremoteobjectabstractitemmodeladapter.cpp
@@ -92,6 +92,7 @@ void QAbstractItemModelSourceAdapter::registerTypes()
qRegisterMetaTypeStreamOperators<ModelIndex>();
qRegisterMetaTypeStreamOperators<IndexList>();
qRegisterMetaTypeStreamOperators<DataEntries>();
+ qRegisterMetaTypeStreamOperators<MetaAndDataEntries>();
qRegisterMetaTypeStreamOperators<Qt::Orientation>();
qRegisterMetaTypeStreamOperators<QVector<Qt::Orientation> >();
qRegisterMetaType<QItemSelectionModel::SelectionFlags>();
@@ -134,7 +135,7 @@ DataEntries QAbstractItemModelSourceAdapter::replicaRowRequest(IndexList start,
Q_ASSERT(!start.isEmpty());
if (roles.isEmpty())
- roles << Qt::DisplayRole << Qt::BackgroundRole; //FIX
+ roles << m_availableRoles;
IndexList parentList = start;
Q_ASSERT(!parentList.isEmpty());
@@ -169,6 +170,17 @@ DataEntries QAbstractItemModelSourceAdapter::replicaRowRequest(IndexList start,
return entries;
}
+MetaAndDataEntries QAbstractItemModelSourceAdapter::replicaCacheRequest(size_t size, const QVector<int> &roles)
+{
+ MetaAndDataEntries res;
+ res.roles = roles.isEmpty() ? m_availableRoles : roles;
+ res.data = fetchTree(QModelIndex{}, size, roles);
+ const int rowCount = m_model->rowCount(QModelIndex{});
+ const int columnCount = m_model->columnCount(QModelIndex{});
+ res.size = QSize{columnCount, rowCount};
+ return res;
+}
+
QVariantList QAbstractItemModelSourceAdapter::replicaHeaderRequest(QVector<Qt::Orientation> orientations, QVector<int> sections, QVector<int> roles)
{
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "orientations=" << orientations << "sections=" << sections << "roles=" << roles;
@@ -232,3 +244,29 @@ void QAbstractItemModelSourceAdapter::sourceCurrentChanged(const QModelIndex & c
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "current=" << currentIndex << "previous=" << previousIndex;
emit currentChanged(currentIndex, previousIndex);
}
+
+QVector<IndexValuePair> QAbstractItemModelSourceAdapter::fetchTree(const QModelIndex &parent, size_t &size, const QVector<int> &roles)
+{
+ QVector<IndexValuePair> entries;
+ const int rowCount = m_model->rowCount(parent);
+ const int columnCount = m_model->columnCount(parent);
+ if (!columnCount || !rowCount)
+ return entries;
+ entries.reserve(std::min(size_t(rowCount * columnCount), size));
+ for (int row = 0; row < rowCount && size > 0; ++row)
+ for (int column = 0; column < columnCount && size > 0; ++column) {
+ const auto index = m_model->index(row, column, parent);
+ const IndexList currentList = toModelIndexList(index, m_model);
+ const QVariantList data = collectData(index, m_model, roles);
+ const bool hasChildren = m_model->hasChildren(index);
+ const Qt::ItemFlags flags = m_model->flags(index);
+ int rc = m_model->rowCount(index);
+ int cc = m_model->columnCount(index);
+ IndexValuePair rowData(currentList, data, hasChildren, flags, QSize{cc, rc});
+ --size;
+ if (hasChildren)
+ rowData.children = fetchTree(index, size, roles);
+ entries.push_back(rowData);
+ }
+ return entries;
+}
diff --git a/src/remoteobjects/qremoteobjectabstractitemmodeladapter_p.h b/src/remoteobjects/qremoteobjectabstractitemmodeladapter_p.h
index 9e7f7f0..fddf9b6 100644
--- a/src/remoteobjects/qremoteobjectabstractitemmodeladapter_p.h
+++ b/src/remoteobjects/qremoteobjectabstractitemmodeladapter_p.h
@@ -89,6 +89,7 @@ public Q_SLOTS:
QVariantList replicaHeaderRequest(QVector<Qt::Orientation> orientations, QVector<int> sections, QVector<int> roles);
void replicaSetCurrentIndex(IndexList index, QItemSelectionModel::SelectionFlags command);
void replicaSetData(const IndexList &index, const QVariant &value, int role);
+ MetaAndDataEntries replicaCacheRequest(size_t size, const QVector<int> &roles);
void sourceDataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector<int> & roles = QVector<int> ()) const;
void sourceRowsInserted(const QModelIndex & parent, int start, int end);
@@ -108,6 +109,8 @@ Q_SIGNALS:
private:
QAbstractItemModelSourceAdapter();
+ QVector<IndexValuePair> fetchTree(const QModelIndex &parent, size_t &size, const QVector<int> &roles);
+
QAbstractItemModel *m_model;
QItemSelectionModel *m_selectionModel;
QVector<int> m_availableRoles;
@@ -118,63 +121,77 @@ struct QAbstractItemAdapterSourceAPI : public SourceApiMap
{
QAbstractItemAdapterSourceAPI(const QString &name)
: SourceApiMap()
- , signalArgTypes{}
- , methodArgTypes{}
+ , m_signalArgTypes {}
+ , m_methodArgTypes {}
, m_name(name)
{
- _properties[0] = 2;
- _properties[1] = qtro_prop_index<AdapterType>(&AdapterType::availableRoles, static_cast<QVector<int> (QObject::*)()>(0),"availableRoles");
- _properties[2] = qtro_prop_index<AdapterType>(&AdapterType::roleNames, static_cast<QIntHash (QObject::*)()>(0),"roleNames");
- _signals[0] = 9;
- _signals[1] = qtro_signal_index<AdapterType>(&AdapterType::availableRolesChanged, static_cast<void (QObject::*)()>(0),signalArgCount+0,&signalArgTypes[0]);
- _signals[2] = qtro_signal_index<AdapterType>(&AdapterType::dataChanged, static_cast<void (QObject::*)(IndexList,IndexList,QVector<int>)>(0),signalArgCount+1,&signalArgTypes[1]);
- _signals[3] = qtro_signal_index<AdapterType>(&AdapterType::rowsInserted, static_cast<void (QObject::*)(IndexList,int,int)>(0),signalArgCount+2,&signalArgTypes[2]);
- _signals[4] = qtro_signal_index<AdapterType>(&AdapterType::rowsRemoved, static_cast<void (QObject::*)(IndexList,int,int)>(0),signalArgCount+3,&signalArgTypes[3]);
- _signals[5] = qtro_signal_index<AdapterType>(&AdapterType::rowsMoved, static_cast<void (QObject::*)(IndexList,int,int,IndexList,int)>(0),signalArgCount+4,&signalArgTypes[4]);
- _signals[6] = qtro_signal_index<AdapterType>(&AdapterType::currentChanged, static_cast<void (QObject::*)(IndexList,IndexList)>(0),signalArgCount+5,&signalArgTypes[5]);
- _signals[7] = qtro_signal_index<ObjectType>(&ObjectType::modelReset, static_cast<void (QObject::*)()>(0),signalArgCount+6,&signalArgTypes[6]);
- _signals[8] = qtro_signal_index<ObjectType>(&ObjectType::headerDataChanged, static_cast<void (QObject::*)(Qt::Orientation,int,int)>(0),signalArgCount+7,&signalArgTypes[7]);
- _signals[9] = qtro_signal_index<AdapterType>(&AdapterType::columnsInserted, static_cast<void (QObject::*)(IndexList,int,int)>(0),signalArgCount+8,&signalArgTypes[8]);
- _methods[0] = 5;
- _methods[1] = qtro_method_index<AdapterType>(&AdapterType::replicaSizeRequest, static_cast<void (QObject::*)(IndexList)>(0),"replicaSizeRequest(IndexList)",methodArgCount+0,&methodArgTypes[0]);
- _methods[2] = qtro_method_index<AdapterType>(&AdapterType::replicaRowRequest, static_cast<void (QObject::*)(IndexList,IndexList,QVector<int>)>(0),"replicaRowRequest(IndexList,IndexList,QVector<int>)",methodArgCount+1,&methodArgTypes[1]);
- _methods[3] = qtro_method_index<AdapterType>(&AdapterType::replicaHeaderRequest, static_cast<void (QObject::*)(QVector<Qt::Orientation>,QVector<int>,QVector<int>)>(0),"replicaHeaderRequest(QVector<Qt::Orientation>,QVector<int>,QVector<int>)",methodArgCount+2,&methodArgTypes[2]);
- _methods[4] = qtro_method_index<AdapterType>(&AdapterType::replicaSetCurrentIndex, static_cast<void (QObject::*)(IndexList,QItemSelectionModel::SelectionFlags)>(0),"replicaSetCurrentIndex(IndexList,QItemSelectionModel::SelectionFlags)",methodArgCount+3,&methodArgTypes[3]);
- _methods[5] = qtro_method_index<AdapterType>(&AdapterType::replicaSetData, static_cast<void (QObject::*)(IndexList,QVariant,int)>(0),"replicaSetData(IndexList,QVariant,int)",methodArgCount+4,&methodArgTypes[4]);
+ m_properties[0] = 2;
+ m_properties[1] = QtPrivate::qtro_property_index<AdapterType>(&AdapterType::availableRoles, static_cast<QVector<int> (QObject::*)()>(0),"availableRoles");
+ m_properties[2] = QtPrivate::qtro_property_index<AdapterType>(&AdapterType::roleNames, static_cast<QIntHash (QObject::*)()>(0),"roleNames");
+ m_signals[0] = 9;
+ m_signals[1] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::availableRolesChanged, static_cast<void (QObject::*)()>(0),m_signalArgCount+0,&m_signalArgTypes[0]);
+ m_signals[2] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::dataChanged, static_cast<void (QObject::*)(IndexList,IndexList,QVector<int>)>(0),m_signalArgCount+1,&m_signalArgTypes[1]);
+ m_signals[3] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::rowsInserted, static_cast<void (QObject::*)(IndexList,int,int)>(0),m_signalArgCount+2,&m_signalArgTypes[2]);
+ m_signals[4] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::rowsRemoved, static_cast<void (QObject::*)(IndexList,int,int)>(0),m_signalArgCount+3,&m_signalArgTypes[3]);
+ m_signals[5] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::rowsMoved, static_cast<void (QObject::*)(IndexList,int,int,IndexList,int)>(0),m_signalArgCount+4,&m_signalArgTypes[4]);
+ m_signals[6] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::currentChanged, static_cast<void (QObject::*)(IndexList,IndexList)>(0),m_signalArgCount+5,&m_signalArgTypes[5]);
+ m_signals[7] = QtPrivate::qtro_signal_index<ObjectType>(&ObjectType::modelReset, static_cast<void (QObject::*)()>(0),m_signalArgCount+6,&m_signalArgTypes[6]);
+ m_signals[8] = QtPrivate::qtro_signal_index<ObjectType>(&ObjectType::headerDataChanged, static_cast<void (QObject::*)(Qt::Orientation,int,int)>(0),m_signalArgCount+7,&m_signalArgTypes[7]);
+ m_signals[9] = QtPrivate::qtro_signal_index<AdapterType>(&AdapterType::columnsInserted, static_cast<void (QObject::*)(IndexList,int,int)>(0),m_signalArgCount+8,&m_signalArgTypes[8]);
+ m_methods[0] = 6;
+ m_methods[1] = QtPrivate::qtro_method_index<AdapterType>(&AdapterType::replicaSizeRequest, static_cast<void (QObject::*)(IndexList)>(0),"replicaSizeRequest(IndexList)",m_methodArgCount+0,&m_methodArgTypes[0]);
+ m_methods[2] = QtPrivate::qtro_method_index<AdapterType>(&AdapterType::replicaRowRequest, static_cast<void (QObject::*)(IndexList,IndexList,QVector<int>)>(0),"replicaRowRequest(IndexList,IndexList,QVector<int>)",m_methodArgCount+1,&m_methodArgTypes[1]);
+ m_methods[3] = QtPrivate::qtro_method_index<AdapterType>(&AdapterType::replicaHeaderRequest, static_cast<void (QObject::*)(QVector<Qt::Orientation>,QVector<int>,QVector<int>)>(0),"replicaHeaderRequest(QVector<Qt::Orientation>,QVector<int>,QVector<int>)",m_methodArgCount+2,&m_methodArgTypes[2]);
+ m_methods[4] = QtPrivate::qtro_method_index<AdapterType>(&AdapterType::replicaSetCurrentIndex, static_cast<void (QObject::*)(IndexList,QItemSelectionModel::SelectionFlags)>(0),"replicaSetCurrentIndex(IndexList,QItemSelectionModel::SelectionFlags)",m_methodArgCount+3,&m_methodArgTypes[3]);
+ m_methods[5] = QtPrivate::qtro_method_index<AdapterType>(&AdapterType::replicaSetData, static_cast<void (QObject::*)(IndexList,QVariant,int)>(0),"replicaSetData(IndexList,QVariant,int)",m_methodArgCount+4,&m_methodArgTypes[4]);
+ m_methods[6] = QtPrivate::qtro_method_index<AdapterType>(&AdapterType::replicaCacheRequest, static_cast<void (QObject::*)(size_t,QVector<int>)>(0),"replicaCacheRequest(size_t,QVector<int>)",m_methodArgCount+5,&m_methodArgTypes[5]);
}
QString name() const override { return m_name; }
QString typeName() const override { return QStringLiteral("QAbstractItemModelAdapter"); }
- int propertyCount() const override { return _properties[0]; }
- int signalCount() const override { return _signals[0]; }
- int methodCount() const override { return _methods[0]; }
+ int enumCount() const override { return 0; }
+ int propertyCount() const override { return m_properties[0]; }
+ int signalCount() const override { return m_signals[0]; }
+ int methodCount() const override { return m_methods[0]; }
+ int sourceEnumIndex(int /*index*/) const override
+ {
+ return -1;
+ }
int sourcePropertyIndex(int index) const override
{
- if (index < 0 || index >= _properties[0])
+ if (index < 0 || index >= m_properties[0])
return -1;
- return _properties[index+1];
+ return m_properties[index+1];
}
int sourceSignalIndex(int index) const override
{
- if (index < 0 || index >= _signals[0])
+ if (index < 0 || index >= m_signals[0])
return -1;
- return _signals[index+1];
+ return m_signals[index+1];
}
int sourceMethodIndex(int index) const override
{
- if (index < 0 || index >= _methods[0])
+ if (index < 0 || index >= m_methods[0])
return -1;
- return _methods[index+1];
+ return m_methods[index+1];
+ }
+ int signalParameterCount(int index) const override { return m_signalArgCount[index]; }
+ int signalParameterType(int sigIndex, int paramIndex) const override { return m_signalArgTypes[sigIndex][paramIndex]; }
+ int methodParameterCount(int index) const override { return m_methodArgCount[index]; }
+ int methodParameterType(int methodIndex, int paramIndex) const override { return m_methodArgTypes[methodIndex][paramIndex]; }
+ QList<QByteArray> signalParameterNames(int index) const override
+ {
+ QList<QByteArray> res;
+ int count = signalParameterCount(index);
+ while (count--)
+ res << QByteArray{};
+ return res;
}
- int signalParameterCount(int index) const override { return signalArgCount[index]; }
- int signalParameterType(int sigIndex, int paramIndex) const override { return signalArgTypes[sigIndex][paramIndex]; }
- int methodParameterCount(int index) const override { return methodArgCount[index]; }
- int methodParameterType(int methodIndex, int paramIndex) const override { return methodArgTypes[methodIndex][paramIndex]; }
int propertyIndexFromSignal(int index) const override
{
switch (index) {
- case 0: return _properties[1];
- case 1: return _properties[2];
+ case 0: return m_properties[1];
+ case 1: return m_properties[2];
}
return -1;
}
@@ -209,6 +226,7 @@ struct QAbstractItemAdapterSourceAPI : public SourceApiMap
case 2: return QByteArrayLiteral("replicaHeaderRequest(QVector<Qt::Orientation>,QVector<int>,QVector<int>)");
case 3: return QByteArrayLiteral("replicaSetCurrentIndex(IndexList,QItemSelectionModel::SelectionFlags)");
case 4: return QByteArrayLiteral("replicaSetData(IndexList,QVariant,int)");
+ case 5: return QByteArrayLiteral("replicaCacheRequest(size_t,QVector<int>)");
}
return QByteArrayLiteral("");
}
@@ -223,9 +241,20 @@ struct QAbstractItemAdapterSourceAPI : public SourceApiMap
case 1: return QByteArrayLiteral("DataEntries");
case 2: return QByteArrayLiteral("QVariantList");
case 3: return QByteArrayLiteral("");
+ case 5: return QByteArrayLiteral("MetaAndDataEntries");
}
return QByteArrayLiteral("");
}
+
+ QList<QByteArray> methodParameterNames(int index) const override
+ {
+ QList<QByteArray> res;
+ int count = methodParameterCount(index);
+ while (count--)
+ res << QByteArray{};
+ return res;
+ }
+
QByteArray objectSignature() const override { return QByteArray{}; }
bool isAdapterSignal(int index) const override
{
@@ -249,6 +278,7 @@ struct QAbstractItemAdapterSourceAPI : public SourceApiMap
case 2:
case 3:
case 4:
+ case 5:
return true;
}
return false;
@@ -263,13 +293,13 @@ struct QAbstractItemAdapterSourceAPI : public SourceApiMap
return false;
}
- int _properties[3];
- int _signals[10];
- int _methods[6];
- int signalArgCount[9];
- const int* signalArgTypes[9];
- int methodArgCount[5];
- const int* methodArgTypes[5];
+ int m_properties[3];
+ int m_signals[10];
+ int m_methods[7];
+ int m_signalArgCount[9];
+ const int* m_signalArgTypes[9];
+ int m_methodArgCount[6];
+ const int* m_methodArgTypes[6];
QString m_name;
};
diff --git a/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp b/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp
index 06e131a..6a4e4e9 100644
--- a/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp
+++ b/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp
@@ -47,16 +47,13 @@
#include <QPoint>
QT_BEGIN_NAMESPACE
-enum {
- DefaultRootCacheSize = 1000
-};
inline QDebug operator<<(QDebug stream, const RequestedData &data)
{
return stream.nospace() << "RequestedData[start=" << data.start << ", end=" << data.end << ", roles=" << data.roles << "]";
}
-CacheData::CacheData(QAbstractItemModelReplicaPrivate *model, CacheData *parentItem)
+CacheData::CacheData(QAbstractItemModelReplicaImplementation *model, CacheData *parentItem)
: replicaModel(model)
, parent(parentItem)
, hasChildren(false)
@@ -72,42 +69,40 @@ CacheData::~CacheData() {
replicaModel->m_activeParents.erase(this);
}
-QAbstractItemModelReplicaPrivate::QAbstractItemModelReplicaPrivate()
+QAbstractItemModelReplicaImplementation::QAbstractItemModelReplicaImplementation()
: QRemoteObjectReplica()
, m_selectionModel(0)
, m_rootItem(this)
, m_lastRequested(-1)
{
- m_rootItem.children.setCacheSize(DefaultRootCacheSize);
- QAbstractItemModelReplicaPrivate::registerMetatypes();
+ QAbstractItemModelReplicaImplementation::registerMetatypes();
initializeModelConnections();
- connect(this, &QAbstractItemModelReplicaPrivate::availableRolesChanged, this, [this]{
+ connect(this, &QAbstractItemModelReplicaImplementation::availableRolesChanged, this, [this]{
m_availableRoles.clear();
});
}
-QAbstractItemModelReplicaPrivate::QAbstractItemModelReplicaPrivate(QRemoteObjectNode *node, const QString &name)
+QAbstractItemModelReplicaImplementation::QAbstractItemModelReplicaImplementation(QRemoteObjectNode *node, const QString &name)
: QRemoteObjectReplica(ConstructWithNode)
, m_selectionModel(0)
, m_rootItem(this)
, m_lastRequested(-1)
{
- m_rootItem.children.setCacheSize(DefaultRootCacheSize);
- QAbstractItemModelReplicaPrivate::registerMetatypes();
+ QAbstractItemModelReplicaImplementation::registerMetatypes();
initializeModelConnections();
initializeNode(node, name);
- connect(this, &QAbstractItemModelReplicaPrivate::availableRolesChanged, this, [this]{
+ connect(this, &QAbstractItemModelReplicaImplementation::availableRolesChanged, this, [this]{
m_availableRoles.clear();
});
}
-QAbstractItemModelReplicaPrivate::~QAbstractItemModelReplicaPrivate()
+QAbstractItemModelReplicaImplementation::~QAbstractItemModelReplicaImplementation()
{
m_rootItem.clear();
qDeleteAll(m_pendingRequests);
}
-void QAbstractItemModelReplicaPrivate::initialize()
+void QAbstractItemModelReplicaImplementation::initialize()
{
QVariantList properties;
properties << QVariant::fromValue(QVector<int>());
@@ -115,7 +110,7 @@ void QAbstractItemModelReplicaPrivate::initialize()
setProperties(properties);
}
-void QAbstractItemModelReplicaPrivate::registerMetatypes()
+void QAbstractItemModelReplicaImplementation::registerMetatypes()
{
static bool alreadyRegistered = false;
if (!alreadyRegistered) {
@@ -125,25 +120,27 @@ void QAbstractItemModelReplicaPrivate::registerMetatypes()
qRegisterMetaTypeStreamOperators<ModelIndex>();
qRegisterMetaTypeStreamOperators<IndexList>();
qRegisterMetaTypeStreamOperators<DataEntries>();
+ qRegisterMetaTypeStreamOperators<MetaAndDataEntries>();
qRegisterMetaTypeStreamOperators<Qt::Orientation>();
qRegisterMetaTypeStreamOperators<QVector<Qt::Orientation> >();
qRegisterMetaTypeStreamOperators<QItemSelectionModel::SelectionFlags>();
qRegisterMetaType<QItemSelectionModel::SelectionFlags>();
+ qRegisterMetaType<QSize>();
qRegisterMetaType<QIntHash>();
qRegisterMetaTypeStreamOperators<QIntHash>();
}
}
-void QAbstractItemModelReplicaPrivate::initializeModelConnections()
+void QAbstractItemModelReplicaImplementation::initializeModelConnections()
{
- connect(this, &QAbstractItemModelReplicaPrivate::dataChanged, this, &QAbstractItemModelReplicaPrivate::onDataChanged);
- connect(this, &QAbstractItemModelReplicaPrivate::rowsInserted, this, &QAbstractItemModelReplicaPrivate::onRowsInserted);
- connect(this, &QAbstractItemModelReplicaPrivate::columnsInserted, this, &QAbstractItemModelReplicaPrivate::onColumnsInserted);
- connect(this, &QAbstractItemModelReplicaPrivate::rowsRemoved, this, &QAbstractItemModelReplicaPrivate::onRowsRemoved);
- connect(this, &QAbstractItemModelReplicaPrivate::rowsMoved, this, &QAbstractItemModelReplicaPrivate::onRowsMoved);
- connect(this, &QAbstractItemModelReplicaPrivate::currentChanged, this, &QAbstractItemModelReplicaPrivate::onCurrentChanged);
- connect(this, &QAbstractItemModelReplicaPrivate::modelReset, this, &QAbstractItemModelReplicaPrivate::onModelReset);
- connect(this, &QAbstractItemModelReplicaPrivate::headerDataChanged, this, &QAbstractItemModelReplicaPrivate::onHeaderDataChanged);
+ connect(this, &QAbstractItemModelReplicaImplementation::dataChanged, this, &QAbstractItemModelReplicaImplementation::onDataChanged);
+ connect(this, &QAbstractItemModelReplicaImplementation::rowsInserted, this, &QAbstractItemModelReplicaImplementation::onRowsInserted);
+ connect(this, &QAbstractItemModelReplicaImplementation::columnsInserted, this, &QAbstractItemModelReplicaImplementation::onColumnsInserted);
+ connect(this, &QAbstractItemModelReplicaImplementation::rowsRemoved, this, &QAbstractItemModelReplicaImplementation::onRowsRemoved);
+ connect(this, &QAbstractItemModelReplicaImplementation::rowsMoved, this, &QAbstractItemModelReplicaImplementation::onRowsMoved);
+ connect(this, &QAbstractItemModelReplicaImplementation::currentChanged, this, &QAbstractItemModelReplicaImplementation::onCurrentChanged);
+ connect(this, &QAbstractItemModelReplicaImplementation::modelReset, this, &QAbstractItemModelReplicaImplementation::onModelReset);
+ connect(this, &QAbstractItemModelReplicaImplementation::headerDataChanged, this, &QAbstractItemModelReplicaImplementation::onHeaderDataChanged);
}
inline void removeIndexFromRow(const QModelIndex &index, const QVector<int> &roles, CachedRowEntry *entry)
@@ -161,7 +158,7 @@ inline void removeIndexFromRow(const QModelIndex &index, const QVector<int> &rol
}
}
-void QAbstractItemModelReplicaPrivate::onReplicaCurrentChanged(const QModelIndex &current, const QModelIndex &previous)
+void QAbstractItemModelReplicaImplementation::onReplicaCurrentChanged(const QModelIndex &current, const QModelIndex &previous)
{
Q_UNUSED(previous)
IndexList currentIndex = toModelIndexList(current, q);
@@ -169,15 +166,15 @@ void QAbstractItemModelReplicaPrivate::onReplicaCurrentChanged(const QModelIndex
replicaSetCurrentIndex(currentIndex, QItemSelectionModel::Clear|QItemSelectionModel::Select|QItemSelectionModel::Current);
}
-void QAbstractItemModelReplicaPrivate::setModel(QAbstractItemModelReplica *model)
+void QAbstractItemModelReplicaImplementation::setModel(QAbstractItemModelReplica *model)
{
q = model;
setParent(model);
m_selectionModel.reset(new QItemSelectionModel(model));
- connect(m_selectionModel.data(), &QItemSelectionModel::currentChanged, this, &QAbstractItemModelReplicaPrivate::onReplicaCurrentChanged);
+ connect(m_selectionModel.data(), &QItemSelectionModel::currentChanged, this, &QAbstractItemModelReplicaImplementation::onReplicaCurrentChanged);
}
-bool QAbstractItemModelReplicaPrivate::clearCache(const IndexList &start, const IndexList &end, const QVector<int> &roles = QVector<int>())
+bool QAbstractItemModelReplicaImplementation::clearCache(const IndexList &start, const IndexList &end, const QVector<int> &roles = QVector<int>())
{
Q_ASSERT(start.size() == end.size());
@@ -211,7 +208,7 @@ bool QAbstractItemModelReplicaPrivate::clearCache(const IndexList &start, const
return true;
}
-void QAbstractItemModelReplicaPrivate::onDataChanged(const IndexList &start, const IndexList &end, const QVector<int> &roles)
+void QAbstractItemModelReplicaImplementation::onDataChanged(const IndexList &start, const IndexList &end, const QVector<int> &roles)
{
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "start=" << start << "end=" << end << "roles=" << roles;
@@ -258,7 +255,7 @@ void QAbstractItemModelReplicaPrivate::onDataChanged(const IndexList &start, con
}
}
-void QAbstractItemModelReplicaPrivate::onRowsInserted(const IndexList &parent, int start, int end)
+void QAbstractItemModelReplicaImplementation::onRowsInserted(const IndexList &parent, int start, int end)
{
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "start=" << start << "end=" << end << "parent=" << parent;
@@ -277,7 +274,7 @@ void QAbstractItemModelReplicaPrivate::onRowsInserted(const IndexList &parent, i
}
}
-void QAbstractItemModelReplicaPrivate::onColumnsInserted(const IndexList &parent, int start, int end)
+void QAbstractItemModelReplicaImplementation::onColumnsInserted(const IndexList &parent, int start, int end)
{
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "start=" << start << "end=" << end << "parent=" << parent;
@@ -304,7 +301,7 @@ void QAbstractItemModelReplicaPrivate::onColumnsInserted(const IndexList &parent
}
-void QAbstractItemModelReplicaPrivate::onRowsRemoved(const IndexList &parent, int start, int end)
+void QAbstractItemModelReplicaImplementation::onRowsRemoved(const IndexList &parent, int start, int end)
{
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "start=" << start << "end=" << end << "parent=" << parent;
@@ -320,7 +317,7 @@ void QAbstractItemModelReplicaPrivate::onRowsRemoved(const IndexList &parent, in
q->endRemoveRows();
}
-void QAbstractItemModelReplicaPrivate::onRowsMoved(IndexList srcParent, int srcRow, int count, IndexList destParent, int destRow)
+void QAbstractItemModelReplicaImplementation::onRowsMoved(IndexList srcParent, int srcRow, int count, IndexList destParent, int destRow)
{
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO;
@@ -341,7 +338,7 @@ void QAbstractItemModelReplicaPrivate::onRowsMoved(IndexList srcParent, int srcR
q->endMoveRows();
}
-void QAbstractItemModelReplicaPrivate::onCurrentChanged(IndexList current, IndexList previous)
+void QAbstractItemModelReplicaImplementation::onCurrentChanged(IndexList current, IndexList previous)
{
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "current=" << current << "previous=" << previous;
Q_UNUSED(previous);
@@ -356,18 +353,24 @@ void QAbstractItemModelReplicaPrivate::onCurrentChanged(IndexList current, Index
m_selectionModel->setCurrentIndex(currentIndex, QItemSelectionModel::Clear|QItemSelectionModel::Select|QItemSelectionModel::Current);
}
-void QAbstractItemModelReplicaPrivate::handleInitDone(QRemoteObjectPendingCallWatcher *watcher)
+void QAbstractItemModelReplicaImplementation::handleInitDone(QRemoteObjectPendingCallWatcher *watcher)
{
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO;
handleModelResetDone(watcher);
-
emit q->initialized();
}
-void QAbstractItemModelReplicaPrivate::handleModelResetDone(QRemoteObjectPendingCallWatcher *watcher)
+void QAbstractItemModelReplicaImplementation::handleModelResetDone(QRemoteObjectPendingCallWatcher *watcher)
{
- const QSize size = watcher->returnValue().toSize();
+ QSize size;
+ if (m_initialAction == QtRemoteObjects::FetchRootSize)
+ size = watcher->returnValue().toSize();
+ else {
+ Q_ASSERT(watcher->returnValue().canConvert<MetaAndDataEntries>());
+ size = watcher->returnValue().value<MetaAndDataEntries>().size;
+ }
+
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO << "size=" << size;
q->beginResetModel();
@@ -380,12 +383,17 @@ void QAbstractItemModelReplicaPrivate::handleModelResetDone(QRemoteObjectPending
m_rootItem.columnCount = size.width();
m_headerData[0].resize(size.width());
m_headerData[1].resize(size.height());
+ if (m_initialAction == QtRemoteObjects::PrefetchData) {
+ auto entries = watcher->returnValue().value<MetaAndDataEntries>();
+ for (int i = 0; i < entries.data.size(); ++i)
+ fillCache(entries.data[i], entries.roles);
+ }
q->endResetModel();
m_pendingRequests.removeAll(watcher);
delete watcher;
}
-void QAbstractItemModelReplicaPrivate::handleSizeDone(QRemoteObjectPendingCallWatcher *watcher)
+void QAbstractItemModelReplicaImplementation::handleSizeDone(QRemoteObjectPendingCallWatcher *watcher)
{
SizeWatcher *sizeWatcher = static_cast<SizeWatcher*>(watcher);
const QSize size = sizeWatcher->returnValue().toSize();
@@ -419,21 +427,26 @@ void QAbstractItemModelReplicaPrivate::handleSizeDone(QRemoteObjectPendingCallWa
delete watcher;
}
-void QAbstractItemModelReplicaPrivate::init()
+void QAbstractItemModelReplicaImplementation::init()
{
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO;
- SizeWatcher *watcher = doModelReset();
- m_pendingRequests.push_back(watcher);
- connect(watcher, &SizeWatcher::finished, this, &QAbstractItemModelReplicaPrivate::handleInitDone);
+ QRemoteObjectPendingCallWatcher *watcher = doModelReset();
+ connect(watcher, &QRemoteObjectPendingCallWatcher::finished, this, &QAbstractItemModelReplicaImplementation::handleInitDone);
}
-SizeWatcher* QAbstractItemModelReplicaPrivate::doModelReset()
+QRemoteObjectPendingCallWatcher* QAbstractItemModelReplicaImplementation::doModelReset()
{
qDeleteAll(m_pendingRequests);
m_pendingRequests.clear();
IndexList parentList;
- QRemoteObjectPendingReply<QSize> reply = replicaSizeRequest(parentList);
- SizeWatcher *watcher = new SizeWatcher(parentList, reply);
+ QRemoteObjectPendingCallWatcher *watcher;
+ if (m_initialAction == QtRemoteObjects::FetchRootSize) {
+ auto call = replicaSizeRequest(parentList);
+ watcher = new SizeWatcher(parentList, call);
+ } else {
+ auto call = replicaCacheRequest(m_rootItem.children.cacheSize, m_initialFetchRolesHint);
+ watcher = new QRemoteObjectPendingCallWatcher(call);
+ }
m_pendingRequests.push_back(watcher);
return watcher;
}
@@ -494,7 +507,18 @@ int collectEntriesForRow(DataEntries* filteredEntries, int row, const DataEntrie
return size;
}
-void QAbstractItemModelReplicaPrivate::requestedData(QRemoteObjectPendingCallWatcher *qobject)
+void QAbstractItemModelReplicaImplementation::fillCache(const IndexValuePair &pair, const QVector<int> &roles)
+{
+ if (auto item = createCacheData(pair.index)) {
+ fillRow(item, pair, q, roles);
+ item->rowCount = pair.size.height();
+ item->columnCount = pair.size.width();
+ }
+ for (const auto &it : pair.children)
+ fillCache(it, roles);
+}
+
+void QAbstractItemModelReplicaImplementation::requestedData(QRemoteObjectPendingCallWatcher *qobject)
{
RowWatcher *watcher = static_cast<RowWatcher *>(qobject);
Q_ASSERT(watcher);
@@ -537,7 +561,7 @@ void QAbstractItemModelReplicaPrivate::requestedData(QRemoteObjectPendingCallWat
delete watcher;
}
-void QAbstractItemModelReplicaPrivate::fetchPendingData()
+void QAbstractItemModelReplicaImplementation::fetchPendingData()
{
if (m_requestedData.isEmpty())
return;
@@ -616,19 +640,19 @@ void QAbstractItemModelReplicaPrivate::fetchPendingData()
RowWatcher *watcher = new RowWatcher(it->start, it->end, it->roles, reply);
rows += 1 + it->end.first().row - it->start.first().row;
m_pendingRequests.push_back(watcher);
- connect(watcher, &RowWatcher::finished, this, &QAbstractItemModelReplicaPrivate::requestedData);
+ connect(watcher, &RowWatcher::finished, this, &QAbstractItemModelReplicaImplementation::requestedData);
}
m_requestedData.clear();
}
-void QAbstractItemModelReplicaPrivate::onModelReset()
+void QAbstractItemModelReplicaImplementation::onModelReset()
{
qCDebug(QT_REMOTEOBJECT_MODELS) << Q_FUNC_INFO;
- SizeWatcher *watcher = doModelReset();
- connect(watcher, &SizeWatcher::finished, this, &QAbstractItemModelReplicaPrivate::handleModelResetDone);
+ QRemoteObjectPendingCallWatcher *watcher = doModelReset();
+ connect(watcher, &QRemoteObjectPendingCallWatcher::finished, this, &QAbstractItemModelReplicaImplementation::handleModelResetDone);
}
-void QAbstractItemModelReplicaPrivate::onHeaderDataChanged(Qt::Orientation orientation, int first, int last)
+void QAbstractItemModelReplicaImplementation::onHeaderDataChanged(Qt::Orientation orientation, int first, int last)
{
// TODO clean cache
const int index = orientation == Qt::Horizontal ? 0 : 1;
@@ -638,7 +662,7 @@ void QAbstractItemModelReplicaPrivate::onHeaderDataChanged(Qt::Orientation orien
emit q->headerDataChanged(orientation, first, last);
}
-void QAbstractItemModelReplicaPrivate::fetchPendingHeaderData()
+void QAbstractItemModelReplicaImplementation::fetchPendingHeaderData()
{
QVector<int> roles;
QVector<int> sections;
@@ -650,7 +674,7 @@ void QAbstractItemModelReplicaPrivate::fetchPendingHeaderData()
}
QRemoteObjectPendingReply<QVariantList> reply = replicaHeaderRequest(orientations, sections, roles);
HeaderWatcher *watcher = new HeaderWatcher(orientations, sections, roles, reply);
- connect(watcher, &HeaderWatcher::finished, this, &QAbstractItemModelReplicaPrivate::requestedHeaderData);
+ connect(watcher, &HeaderWatcher::finished, this, &QAbstractItemModelReplicaImplementation::requestedHeaderData);
m_requestedHeaderData.clear();
m_pendingRequests.push_back(watcher);
}
@@ -679,7 +703,7 @@ static inline QVector<QPair<int, int> > listRanges(const QVector<int> &list)
return result;
}
-void QAbstractItemModelReplicaPrivate::requestedHeaderData(QRemoteObjectPendingCallWatcher *qobject)
+void QAbstractItemModelReplicaImplementation::requestedHeaderData(QRemoteObjectPendingCallWatcher *qobject)
{
HeaderWatcher *watcher = static_cast<HeaderWatcher *>(qobject);
Q_ASSERT(watcher);
@@ -712,13 +736,15 @@ void QAbstractItemModelReplicaPrivate::requestedHeaderData(QRemoteObjectPendingC
delete watcher;
}
-QAbstractItemModelReplica::QAbstractItemModelReplica(QAbstractItemModelReplicaPrivate *rep)
+QAbstractItemModelReplica::QAbstractItemModelReplica(QAbstractItemModelReplicaImplementation *rep, QtRemoteObjects::InitialAction action, const QVector<int> &rolesHint)
: QAbstractItemModel()
, d(rep)
{
- rep->setModel(this);
+ d->m_initialAction = action;
+ d->m_initialFetchRolesHint = rolesHint;
- connect(rep, &QAbstractItemModelReplicaPrivate::initialized, d.data(), &QAbstractItemModelReplicaPrivate::init);
+ rep->setModel(this);
+ connect(rep, &QAbstractItemModelReplicaImplementation::initialized, d.data(), &QAbstractItemModelReplicaImplementation::init);
}
QAbstractItemModelReplica::~QAbstractItemModelReplica()
@@ -869,7 +895,7 @@ int QAbstractItemModelReplica::rowCount(const QModelIndex &parent) const
IndexList parentList = toModelIndexList(parent, this);
QRemoteObjectPendingReply<QSize> reply = d->replicaSizeRequest(parentList);
SizeWatcher *watcher = new SizeWatcher(parentList, reply);
- connect(watcher, &SizeWatcher::finished, d.data(), &QAbstractItemModelReplicaPrivate::handleSizeDone);
+ connect(watcher, &SizeWatcher::finished, d.data(), &QAbstractItemModelReplicaImplementation::handleSizeDone);
} else if (parent.column() > 0) {
return 0;
}
diff --git a/src/remoteobjects/qremoteobjectabstractitemmodelreplica.h b/src/remoteobjects/qremoteobjectabstractitemmodelreplica.h
index 5920b15..caf6c60 100644
--- a/src/remoteobjects/qremoteobjectabstractitemmodelreplica.h
+++ b/src/remoteobjects/qremoteobjectabstractitemmodelreplica.h
@@ -47,13 +47,13 @@
QT_BEGIN_NAMESPACE
-class QAbstractItemModelReplicaPrivate;
+class QAbstractItemModelReplicaImplementation;
class Q_REMOTEOBJECTS_EXPORT QAbstractItemModelReplica : public QAbstractItemModel
{
Q_OBJECT
public:
- ~QAbstractItemModelReplica();
+ ~QAbstractItemModelReplica() override;
QItemSelectionModel* selectionModel() const;
@@ -79,9 +79,9 @@ Q_SIGNALS:
void initialized();
private:
- explicit QAbstractItemModelReplica(QAbstractItemModelReplicaPrivate *rep);
- QScopedPointer<QAbstractItemModelReplicaPrivate> d;
- friend class QAbstractItemModelReplicaPrivate;
+ explicit QAbstractItemModelReplica(QAbstractItemModelReplicaImplementation *rep, QtRemoteObjects::InitialAction action, const QVector<int> &rolesHint);
+ QScopedPointer<QAbstractItemModelReplicaImplementation> d;
+ friend class QAbstractItemModelReplicaImplementation;
friend class QRemoteObjectNode;
};
diff --git a/src/remoteobjects/qremoteobjectabstractitemmodelreplica_p.h b/src/remoteobjects/qremoteobjectabstractitemmodelreplica_p.h
index 0c8ea9d..c765813 100644
--- a/src/remoteobjects/qremoteobjectabstractitemmodelreplica_p.h
+++ b/src/remoteobjects/qremoteobjectabstractitemmodelreplica_p.h
@@ -62,7 +62,7 @@
QT_BEGIN_NAMESPACE
namespace {
- const int DefaultNodesCacheSize = 50;
+ const int DefaultNodesCacheSize = 1000;
}
struct CacheEntry
@@ -104,7 +104,7 @@ struct LRUCache
Q_ASSERT(cachedItems.size() == cachedItemsMap.size());
auto it = cachedItems.rbegin();
- while (cachedItemsMap.size() >= cacheSize) {
+ while (cachedItemsMap.size() > cacheSize) {
// Do not trash elements with children
// Workaround QTreeView bugs which caches the children indexes for very long time
while (it->second->hasChildren && it != cachedItems.rend())
@@ -219,10 +219,10 @@ struct LRUCache
}
};
-class QAbstractItemModelReplicaPrivate;
+class QAbstractItemModelReplicaImplementation;
struct CacheData
{
- QAbstractItemModelReplicaPrivate *replicaModel;
+ QAbstractItemModelReplicaImplementation *replicaModel;
CacheData *parent;
CachedRowEntry cachedRowEntry;
@@ -231,7 +231,7 @@ struct CacheData
int columnCount;
int rowCount;
- explicit CacheData(QAbstractItemModelReplicaPrivate *model, CacheData *parentItem = nullptr);
+ explicit CacheData(QAbstractItemModelReplicaImplementation *model, CacheData *parentItem = nullptr);
~CacheData();
@@ -320,7 +320,7 @@ public:
QVector<int> sections, roles;
};
-class QAbstractItemModelReplicaPrivate : public QRemoteObjectReplica
+class QAbstractItemModelReplicaImplementation : public QRemoteObjectReplica
{
Q_OBJECT
//TODO Use an input name for the model on the Replica side
@@ -328,10 +328,10 @@ class QAbstractItemModelReplicaPrivate : public QRemoteObjectReplica
Q_PROPERTY(QVector<int> availableRoles READ availableRoles NOTIFY availableRolesChanged)
Q_PROPERTY(QIntHash roleNames READ roleNames)
public:
- QAbstractItemModelReplicaPrivate();
- QAbstractItemModelReplicaPrivate(QRemoteObjectNode *node, const QString &name);
- ~QAbstractItemModelReplicaPrivate();
- void initialize();
+ QAbstractItemModelReplicaImplementation();
+ QAbstractItemModelReplicaImplementation(QRemoteObjectNode *node, const QString &name);
+ ~QAbstractItemModelReplicaImplementation() override;
+ void initialize() override;
static void registerMetatypes();
inline const QVector<int> &availableRoles() const
@@ -364,39 +364,46 @@ Q_SIGNALS:
public Q_SLOTS:
QRemoteObjectPendingReply<QSize> replicaSizeRequest(IndexList parentList)
{
- static int __repc_index = QAbstractItemModelReplicaPrivate::staticMetaObject.indexOfSlot("replicaSizeRequest(IndexList)");
+ static int __repc_index = QAbstractItemModelReplicaImplementation::staticMetaObject.indexOfSlot("replicaSizeRequest(IndexList)");
QVariantList __repc_args;
__repc_args << QVariant::fromValue(parentList);
return QRemoteObjectPendingReply<QSize>(sendWithReply(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args));
}
QRemoteObjectPendingReply<DataEntries> replicaRowRequest(IndexList start, IndexList end, QVector<int> roles)
{
- static int __repc_index = QAbstractItemModelReplicaPrivate::staticMetaObject.indexOfSlot("replicaRowRequest(IndexList,IndexList,QVector<int>)");
+ static int __repc_index = QAbstractItemModelReplicaImplementation::staticMetaObject.indexOfSlot("replicaRowRequest(IndexList,IndexList,QVector<int>)");
QVariantList __repc_args;
__repc_args << QVariant::fromValue(start) << QVariant::fromValue(end) << QVariant::fromValue(roles);
return QRemoteObjectPendingReply<DataEntries>(sendWithReply(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args));
}
QRemoteObjectPendingReply<QVariantList> replicaHeaderRequest(QVector<Qt::Orientation> orientations, QVector<int> sections, QVector<int> roles)
{
- static int __repc_index = QAbstractItemModelReplicaPrivate::staticMetaObject.indexOfSlot("replicaHeaderRequest(QVector<Qt::Orientation>,QVector<int>,QVector<int>)");
+ static int __repc_index = QAbstractItemModelReplicaImplementation::staticMetaObject.indexOfSlot("replicaHeaderRequest(QVector<Qt::Orientation>,QVector<int>,QVector<int>)");
QVariantList __repc_args;
__repc_args << QVariant::fromValue(orientations) << QVariant::fromValue(sections) << QVariant::fromValue(roles);
return QRemoteObjectPendingReply<QVariantList>(sendWithReply(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args));
}
void replicaSetCurrentIndex(IndexList index, QItemSelectionModel::SelectionFlags command)
{
- static int __repc_index = QAbstractItemModelReplicaPrivate::staticMetaObject.indexOfSlot("replicaSetCurrentIndex(IndexList,QItemSelectionModel::SelectionFlags)");
+ static int __repc_index = QAbstractItemModelReplicaImplementation::staticMetaObject.indexOfSlot("replicaSetCurrentIndex(IndexList,QItemSelectionModel::SelectionFlags)");
QVariantList __repc_args;
__repc_args << QVariant::fromValue(index) << QVariant::fromValue(command);
send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);
}
void replicaSetData(IndexList index, const QVariant &value, int role)
{
- static int __repc_index = QAbstractItemModelReplicaPrivate::staticMetaObject.indexOfSlot("replicaSetData(IndexList,QVariant,int)");
+ static int __repc_index = QAbstractItemModelReplicaImplementation::staticMetaObject.indexOfSlot("replicaSetData(IndexList,QVariant,int)");
QVariantList __repc_args;
__repc_args << QVariant::fromValue(index) << QVariant::fromValue(value) << QVariant::fromValue(role);
send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);
}
+ QRemoteObjectPendingReply<MetaAndDataEntries> replicaCacheRequest(size_t size, QVector<int> roles)
+ {
+ static int __repc_index = QAbstractItemModelReplicaImplementation::staticMetaObject.indexOfSlot("replicaCacheRequest(size_t,QVector<int>)");
+ QVariantList __repc_args;
+ __repc_args << QVariant::fromValue(size) << QVariant::fromValue(roles);
+ return QRemoteObjectPendingReply<MetaAndDataEntries>(sendWithReply(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args));
+ }
void onHeaderDataChanged(Qt::Orientation orientation, int first, int last);
void onDataChanged(const IndexList &start, const IndexList &end, const QVector<int> &roles);
void onRowsInserted(const IndexList &parent, int start, int end);
@@ -414,6 +421,7 @@ public Q_SLOTS:
void handleModelResetDone(QRemoteObjectPendingCallWatcher *watcher);
void handleSizeDone(QRemoteObjectPendingCallWatcher *watcher);
void onReplicaCurrentChanged(const QModelIndex &current, const QModelIndex &previous);
+ void fillCache(const IndexValuePair &pair,const QVector<int> &roles);
public:
QScopedPointer<QItemSelectionModel> m_selectionModel;
@@ -449,7 +457,7 @@ public:
return cacheEntry(toQModelIndex(index, q));
}
- SizeWatcher* doModelReset();
+ QRemoteObjectPendingCallWatcher *doModelReset();
void initializeModelConnections();
int m_lastRequested;
@@ -459,6 +467,8 @@ public:
QAbstractItemModelReplica *q;
mutable QVector<int> m_availableRoles;
std::unordered_set<CacheData*> m_activeParents;
+ QtRemoteObjects::InitialAction m_initialAction;
+ QVector<int> m_initialFetchRolesHint;
};
QT_END_NAMESPACE
diff --git a/src/remoteobjects/qremoteobjectabstractitemmodeltypes.h b/src/remoteobjects/qremoteobjectabstractitemmodeltypes.h
index d1adfb9..797024b 100644
--- a/src/remoteobjects/qremoteobjectabstractitemmodeltypes.h
+++ b/src/remoteobjects/qremoteobjectabstractitemmodeltypes.h
@@ -47,6 +47,7 @@
#include <QVariant>
#include <QModelIndex>
#include <QItemSelectionModel>
+#include <QSize>
#include <QDebug>
#include <qnamespace.h>
#include <QtRemoteObjects/qtremoteobjectglobal.h>
@@ -71,11 +72,13 @@ typedef QList<ModelIndex> IndexList;
struct IndexValuePair
{
- explicit IndexValuePair(const IndexList index_ = IndexList(), const QVariantList &data_ = QVariantList(), bool hasChildren_ = false, const Qt::ItemFlags &flags_ = Qt::ItemFlags())
+ explicit IndexValuePair(const IndexList index_ = IndexList(), const QVariantList &data_ = QVariantList(),
+ bool hasChildren_ = false, const Qt::ItemFlags &flags_ = Qt::ItemFlags(), const QSize &size_ = {})
: index(index_)
, data(data_)
, flags(flags_)
, hasChildren(hasChildren_)
+ , size(size_)
{}
inline bool operator==(const IndexValuePair &other) const { return index == other.index && data == other.data && hasChildren == other.hasChildren && flags == other.flags; }
@@ -85,6 +88,8 @@ struct IndexValuePair
QVariantList data;
Qt::ItemFlags flags;
bool hasChildren;
+ QVector<IndexValuePair> children;
+ QSize size;
};
struct DataEntries
@@ -95,6 +100,12 @@ struct DataEntries
QVector<IndexValuePair> data;
};
+struct MetaAndDataEntries : DataEntries
+{
+ QVector<int> roles;
+ QSize size;
+};
+
inline QDebug operator<<(QDebug stream, const ModelIndex &index)
{
return stream.nospace() << "ModelIndex[row=" << index.row << ", column=" << index.column << "]";
@@ -156,15 +167,25 @@ inline QDataStream& operator>>(QDataStream &stream, DataEntries &entries)
return stream >> entries.data;
}
+inline QDataStream& operator<<(QDataStream &stream, const MetaAndDataEntries &entries)
+{
+ return stream << entries.data << entries.roles << entries.size;
+}
+
+inline QDataStream& operator>>(QDataStream &stream, MetaAndDataEntries &entries)
+{
+ return stream >> entries.data >> entries.roles >> entries.size;
+}
+
inline QDataStream& operator<<(QDataStream &stream, const IndexValuePair &pair)
{
- return stream << pair.index << pair.data << pair.hasChildren << static_cast<int>(pair.flags);
+ return stream << pair.index << pair.data << pair.hasChildren << static_cast<int>(pair.flags) << pair.children << pair.size;
}
inline QDataStream& operator>>(QDataStream &stream, IndexValuePair &pair)
{
int flags;
- QDataStream &ret = stream >> pair.index >> pair.data >> pair.hasChildren >> flags;
+ QDataStream &ret = stream >> pair.index >> pair.data >> pair.hasChildren >> flags >> pair.children >> pair.size;
pair.flags = static_cast<Qt::ItemFlags>(flags);
return ret;
}
@@ -223,6 +244,7 @@ QT_END_NAMESPACE
Q_DECLARE_METATYPE(ModelIndex)
Q_DECLARE_METATYPE(IndexList)
Q_DECLARE_METATYPE(DataEntries)
+Q_DECLARE_METATYPE(MetaAndDataEntries)
Q_DECLARE_METATYPE(IndexValuePair)
Q_DECLARE_METATYPE(Qt::Orientation)
Q_DECLARE_METATYPE(QItemSelectionModel::SelectionFlags)
diff --git a/src/remoteobjects/qremoteobjectdynamicreplica.cpp b/src/remoteobjects/qremoteobjectdynamicreplica.cpp
index 77bb780..a25893e 100644
--- a/src/remoteobjects/qremoteobjectdynamicreplica.cpp
+++ b/src/remoteobjects/qremoteobjectdynamicreplica.cpp
@@ -84,9 +84,9 @@ QRemoteObjectDynamicReplica::~QRemoteObjectDynamicReplica()
*/
const QMetaObject* QRemoteObjectDynamicReplica::metaObject() const
{
- QSharedPointer<QRemoteObjectReplicaPrivate> d = qSharedPointerCast<QRemoteObjectReplicaPrivate>(d_ptr);
+ auto impl = qSharedPointerCast<QRemoteObjectReplicaImplementation>(d_impl);
- return d->m_metaObject ? d->m_metaObject : QRemoteObjectReplica::metaObject();
+ return impl->m_metaObject ? impl->m_metaObject : QRemoteObjectReplica::metaObject();
}
/*!
@@ -97,8 +97,6 @@ const QMetaObject* QRemoteObjectDynamicReplica::metaObject() const
*/
void *QRemoteObjectDynamicReplica::qt_metacast(const char *name)
{
- QSharedPointer<QRemoteObjectReplicaPrivate> d = qSharedPointerCast<QRemoteObjectReplicaPrivate>(d_ptr);
-
if (!name)
return 0;
@@ -106,7 +104,8 @@ void *QRemoteObjectDynamicReplica::qt_metacast(const char *name)
return static_cast<void*>(const_cast<QRemoteObjectDynamicReplica*>(this));
// not entirely sure that one is needed... TODO: check
- if (QString::fromLatin1(name) == d->m_objectName)
+ auto impl = qSharedPointerCast<QRemoteObjectReplicaImplementation>(d_impl);
+ if (QString::fromLatin1(name) == impl->m_objectName)
return static_cast<void*>(const_cast<QRemoteObjectDynamicReplica*>(this));
return QObject::qt_metacast(name);
@@ -122,11 +121,11 @@ int QRemoteObjectDynamicReplica::qt_metacall(QMetaObject::Call call, int id, voi
{
static const bool debugArgs = qEnvironmentVariableIsSet("QT_REMOTEOBJECT_DEBUG_ARGUMENTS");
- QSharedPointer<QRemoteObjectReplicaPrivate> d = qSharedPointerCast<QRemoteObjectReplicaPrivate>(d_ptr);
+ auto impl = qSharedPointerCast<QRemoteObjectReplicaImplementation>(d_impl);
int saved_id = id;
id = QRemoteObjectReplica::qt_metacall(call, id, argv);
- if (id < 0 || d->m_metaObject == nullptr)
+ if (id < 0 || impl->m_metaObject == nullptr)
return id;
if (call == QMetaObject::ReadProperty || call == QMetaObject::WriteProperty) {
@@ -152,20 +151,23 @@ int QRemoteObjectDynamicReplica::qt_metacall(QMetaObject::Call call, int id, voi
id = -1;
} else if (call == QMetaObject::InvokeMetaMethod) {
- if (id < d->m_numSignals) {
+ if (id < impl->m_numSignals) {
// signal relay from Source world to Replica
- QMetaObject::activate(this, d->m_metaObject, id, argv);
+ QMetaObject::activate(this, impl->m_metaObject, id, argv);
} else {
// method relay from Replica to Source
- const QMetaMethod mm = d->m_metaObject->method(saved_id);
+ const QMetaMethod mm = impl->m_metaObject->method(saved_id);
const QList<QByteArray> types = mm.parameterTypes();
const int typeSize = types.size();
QVariantList args;
args.reserve(typeSize);
for (int i = 0; i < typeSize; ++i) {
- args.push_back(QVariant(QMetaType::type(types[i].constData()), argv[i + 1]));
+ if (impl->m_metaObject->indexOfEnumerator(types[i].constData()) != -1)
+ args.push_back(QVariant(QMetaType::Int, argv[i + 1]));
+ else
+ args.push_back(QVariant(QMetaType::type(types[i].constData()), argv[i + 1]));
}
if (debugArgs) {
diff --git a/src/remoteobjects/qremoteobjectdynamicreplica.h b/src/remoteobjects/qremoteobjectdynamicreplica.h
index 74a1a28..f30d0d0 100644
--- a/src/remoteobjects/qremoteobjectdynamicreplica.h
+++ b/src/remoteobjects/qremoteobjectdynamicreplica.h
@@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE
class Q_REMOTEOBJECTS_EXPORT QRemoteObjectDynamicReplica : public QRemoteObjectReplica
{
public:
- ~QRemoteObjectDynamicReplica();
+ ~QRemoteObjectDynamicReplica() override;
const QMetaObject *metaObject() const override;
void *qt_metacast(const char *name) override;
diff --git a/src/remoteobjects/qremoteobjectnode.cpp b/src/remoteobjects/qremoteobjectnode.cpp
index 93752ee..05a2015 100644
--- a/src/remoteobjects/qremoteobjectnode.cpp
+++ b/src/remoteobjects/qremoteobjectnode.cpp
@@ -78,13 +78,10 @@ QRemoteObjectNodePrivate::QRemoteObjectNodePrivate()
, retryInterval(250)
, lastError(QRemoteObjectNode::NoError)
, persistedStore(nullptr)
- , persistedStoreOwnership(QRemoteObjectNode::DoNotPassOwnership)
{ }
QRemoteObjectNodePrivate::~QRemoteObjectNodePrivate()
{
- if (persistedStore && persistedStoreOwnership == QRemoteObjectNode::PassOwnershipToNode)
- delete persistedStore;
}
QRemoteObjectSourceLocations QRemoteObjectNodePrivate::remoteObjectAddresses() const
@@ -121,6 +118,33 @@ void QRemoteObjectNode::timerEvent(QTimerEvent*)
}
/*!
+ \property QRemoteObjectNode::heartbeatInterval
+ \brief Heartbeat interval in ms.
+
+ The heartbeat (only helpful for socket connections) will periodically send a
+ message to connected nodes to detect whether the connection was disrupted.
+ Qt Remote Objects will try to reconnect automatically if it detects a dropped
+ connection, this function can help with that detection since the client will
+ only detect the server is unavailable when it tries to send data.
+
+ Setting to 0 (the default) will disable the heartbeat.
+*/
+int QRemoteObjectNode::heartbeatInterval() const
+{
+ Q_D(const QRemoteObjectNode);
+ return d->m_heartbeatInterval;
+}
+
+void QRemoteObjectNode::setHeartbeatInterval(int interval)
+{
+ Q_D(QRemoteObjectNode);
+ if (d->m_heartbeatInterval == interval)
+ return;
+ d->m_heartbeatInterval = interval;
+ emit heartbeatIntervalChanged(interval);
+}
+
+/*!
\internal The replica needs to have a default constructor to be able
to create a replica from QML. In order for it to be properly
constructed, there needs to be a way to associate the replica with a
@@ -131,10 +155,10 @@ void QRemoteObjectNode::initializeReplica(QRemoteObjectReplica *instance, const
{
Q_D(QRemoteObjectNode);
if (instance->inherits("QRemoteObjectDynamicReplica")) {
- d->setReplicaPrivate(nullptr, instance, name);
+ d->setReplicaImplementation(nullptr, instance, name);
} else {
const QMetaObject *meta = instance->metaObject();
- d->setReplicaPrivate(meta, instance, name.isEmpty() ? ::name(meta) : name);
+ d->setReplicaImplementation(meta, instance, name.isEmpty() ? ::name(meta) : name);
}
}
@@ -145,23 +169,23 @@ void QRemoteObjectNodePrivate::setLastError(QRemoteObjectNode::ErrorCode errorCo
emit q->error(lastError);
}
-void QRemoteObjectNodePrivate::setReplicaPrivate(const QMetaObject *meta, QRemoteObjectReplica *instance, const QString &name)
+void QRemoteObjectNodePrivate::setReplicaImplementation(const QMetaObject *meta, QRemoteObjectReplica *instance, const QString &name)
{
- qROPrivDebug() << "Starting setReplicaPrivate for" << name;
+ qROPrivDebug() << "Starting setReplicaImplementation for" << name;
isInitialized.storeRelease(1);
openConnectionIfNeeded(name);
QMutexLocker locker(&mutex);
if (hasInstance(name)) {
- qCDebug(QT_REMOTEOBJECT)<<"setReplicaPrivate - using existing instance";
- QSharedPointer<QRemoteObjectReplicaPrivate> rep = qSharedPointerCast<QRemoteObjectReplicaPrivate>(replicas.value(name).toStrongRef());
+ qCDebug(QT_REMOTEOBJECT)<<"setReplicaImplementation - using existing instance";
+ QSharedPointer<QRemoteObjectReplicaImplementation> rep = qSharedPointerCast<QRemoteObjectReplicaImplementation>(replicas.value(name).toStrongRef());
Q_ASSERT(rep);
- instance->d_ptr = rep;
+ instance->d_impl = rep;
rep->configurePrivate(instance);
} else {
- instance->d_ptr.reset(handleNewAcquire(meta, instance, name));
+ instance->d_impl.reset(handleNewAcquire(meta, instance, name));
instance->initialize();
- replicas.insert(name, instance->d_ptr.toWeakRef());
- qROPrivDebug() << "setReplicaPrivate - Created new instance" << name<<remoteObjectAddresses();
+ replicas.insert(name, instance->d_impl.toWeakRef());
+ qROPrivDebug() << "setReplicaImplementation - Created new instance" << name<<remoteObjectAddresses();
}
}
@@ -176,18 +200,17 @@ const QRemoteObjectRegistry *QRemoteObjectNode::registry() const
}
/*!
- \class QRemoteObjectPersistedStore
+ \class QRemoteObjectAbstractPersistedStore
\inmodule QtRemoteObjects
- \brief The QRemoteObjectPersistedStore virtual class provides the methods
- for setting PROP values of a replica to value they had the last time the
- replica was used.
+ \brief A class which provides the methods for setting PROP values of a
+ replica to value they had the last time the replica was used.
This can be used to provide a "reasonable" value to be displayed until the
connection to the source is established and current values are available.
This class must be overridden to provide an implementation for saving (\l
- QRemoteObjectPersistedStore::saveProperties) and restoring (\l
- QRemoteObjectPersistedStore::restoreProperties) PROP values. The derived
+ QRemoteObjectAbstractPersistedStore::saveProperties) and restoring (\l
+ QRemoteObjectAbstractPersistedStore::restoreProperties) PROP values. The derived
type can then be set for a node, and any replica acquired from that node
will then automatically store PERSISTED properties when the replica
destructor is called, and retrieve the values when the replica is
@@ -195,54 +218,77 @@ const QRemoteObjectRegistry *QRemoteObjectNode::registry() const
*/
/*!
- \fn virtual void QRemoteObjectPersistedStore::saveProperties(const QString &repName, const QByteArray &repSig, const QVariantList &values)
+ Constructs a QRemoteObjectAbstractPersistedStore with the given \a parent.
+ The default value of \a parent is \c nullptr.
+*/
+QRemoteObjectAbstractPersistedStore::QRemoteObjectAbstractPersistedStore(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QRemoteObjectAbstractPersistedStore::~QRemoteObjectAbstractPersistedStore()
+{
+}
+
+/*!
+ \fn virtual void QRemoteObjectAbstractPersistedStore::saveProperties(const QString &repName, const QByteArray &repSig, const QVariantList &values)
This method will be provided the replica class's \a repName, \a repSig and the list of
\a values that PERSISTED properties have when the replica destructor was
called. It is the responsibility of the inheriting class to store the
information in a manner consistent for \l
- QRemoteObjectPersistedStore::restoreProperties to retrieve.
+ QRemoteObjectAbstractPersistedStore::restoreProperties to retrieve.
- \sa QRemoteObjectPersistedStore::restoreProperties
+ \sa QRemoteObjectAbstractPersistedStore::restoreProperties
*/
/*!
- \fn virtual QVariantList QRemoteObjectPersistedStore::restoreProperties(const QString &repName, const QByteArray &repSig)
+ \fn virtual QVariantList QRemoteObjectAbstractPersistedStore::restoreProperties(const QString &repName, const QByteArray &repSig)
This method will be provided the replica class's \a repName and \a repSig when the
replica is being initialized. It is the responsibility of the inheriting
class to get the last values persisted by \l
- QRemoteObjectPersistedStore::saveProperties and return them. An empty
+ QRemoteObjectAbstractPersistedStore::saveProperties and return them. An empty
QVariantList should be returned if no values are available.
- \sa QRemoteObjectPersistedStore::saveProperties
+ \sa QRemoteObjectAbstractPersistedStore::saveProperties
*/
-/*!
- \enum QRemoteObjectNode::StorageOwnership
- Used to tell a node whether it should take ownership of a passed pointer or not:
-
- \value DoNotPassOwnership The ownership of the object is not passed.
- \value PassOwnershipToNode The ownership of the object is passed, and the node destructor will call delete.
-*/
+QRemoteObjectAbstractPersistedStore *QRemoteObjectNode::persistedStore() const
+{
+ Q_D(const QRemoteObjectNode);
+ return d->persistedStore;
+}
/*!
- Provides a \l QRemoteObjectPersistedStore \a store for the node, allowing
- replica \l PROP members with the PERSISTED trait of \l PROP to save their
- current value when the replica is deleted and restore a stored value the
- next time the replica is started. Requires a \l QRemoteObjectPersistedStore
- class implementation to control where and how persistence is handled. Use
- the \l QRemoteObjectNode::StorageOwnership enum passed by \a ownership to
- determine whether the Node will delete the provided pointer or not.
-
- \sa QRemoteObjectPersistedStore, QRemoteObjectNode::StorageOwnership
+ \since 5.11
+ \property QRemoteObjectNode::persistedStore
+ \brief Allows setting a \l QRemoteObjectAbstractPersistedStore instance for the node
+
+ Allows replica \l PROP members with the PERSISTED trait to save their current value when the
+ replica is deleted and restore a stored value the next time the replica is started.
+
+ Requires a \l QRemoteObjectAbstractPersistedStore class implementation to control where and how
+ persistence is handled.
*/
-void QRemoteObjectNode::setPersistedStore(QRemoteObjectPersistedStore *store, StorageOwnership ownership)
+void QRemoteObjectNode::setPersistedStore(QRemoteObjectAbstractPersistedStore *persistedStore)
{
Q_D(QRemoteObjectNode);
- d->persistedStore = store;
- d->persistedStoreOwnership = ownership;
+ d->persistedStore = persistedStore;
+}
+
+QRemoteObjectAbstractPersistedStore::QRemoteObjectAbstractPersistedStore(QRemoteObjectAbstractPersistedStorePrivate &dptr, QObject *parent)
+ : QObject(dptr, parent)
+{
+}
+
+QRemoteObjectAbstractPersistedStorePrivate::QRemoteObjectAbstractPersistedStorePrivate()
+{
+}
+
+QRemoteObjectAbstractPersistedStorePrivate::~QRemoteObjectAbstractPersistedStorePrivate()
+{
}
void QRemoteObjectNodePrivate::connectReplica(QObject *object, QRemoteObjectReplica *instance)
@@ -307,10 +353,13 @@ bool QRemoteObjectNodePrivate::initConnection(const QUrl &address)
qROPrivDebug() << "Opening connection to" << address.toString();
qROPrivDebug() << "Replica Connection isValid" << connection->isOpen();
- QObject::connect(connection, SIGNAL(shouldReconnect(ClientIoDevice*)), q, SLOT(onShouldReconnect(ClientIoDevice*)));
+ QObject::connect(connection, &ClientIoDevice::shouldReconnect, q, [this, connection]() {
+ onShouldReconnect(connection);
+ });
+ QObject::connect(connection, &ClientIoDevice::readyRead, q, [this, connection]() {
+ onClientRead(connection);
+ });
connection->connectToServer();
- QObject::connect(connection, SIGNAL(readyRead()), &clientRead, SLOT(map()));
- clientRead.setMapping(connection, connection);
return true;
}
@@ -319,7 +368,7 @@ bool QRemoteObjectNodePrivate::hasInstance(const QString &name)
if (!replicas.contains(name))
return false;
- QSharedPointer<QReplicaPrivateInterface> rep = replicas.value(name).toStrongRef();
+ QSharedPointer<QReplicaImplementationInterface> rep = replicas.value(name).toStrongRef();
if (!rep) { //already deleted
replicas.remove(name);
return false;
@@ -335,12 +384,12 @@ void QRemoteObjectNodePrivate::onRemoteObjectSourceAdded(const QRemoteObjectSour
QRemoteObjectSourceLocations locs = registry->sourceLocations();
locs[entry.first] = entry.second;
//TODO Is there a way to extend QRemoteObjectSourceLocations in place?
- registry->d_ptr->setProperty(0, QVariant::fromValue(locs));
+ registry->d_impl->setProperty(0, QVariant::fromValue(locs));
qROPrivDebug() << "onRemoteObjectSourceAdded, now locations =" << locs;
}
if (replicas.contains(entry.first)) //We have a replica waiting on this remoteObject
{
- QSharedPointer<QReplicaPrivateInterface> rep = replicas.value(entry.first).toStrongRef();
+ QSharedPointer<QReplicaImplementationInterface> rep = replicas.value(entry.first).toStrongRef();
if (!rep) { //replica has been deleted, remove from list
replicas.remove(entry.first);
return;
@@ -357,7 +406,7 @@ void QRemoteObjectNodePrivate::onRemoteObjectSourceRemoved(const QRemoteObjectSo
if (!entry.first.isEmpty()) {
QRemoteObjectSourceLocations locs = registry->sourceLocations();
locs.remove(entry.first);
- registry->d_ptr->setProperty(0, QVariant::fromValue(locs));
+ registry->d_impl->setProperty(0, QVariant::fromValue(locs));
}
}
@@ -370,7 +419,7 @@ void QRemoteObjectNodePrivate::onRegistryInitialized()
i.next();
if (replicas.contains(i.key())) //We have a replica waiting on this remoteObject
{
- QSharedPointer<QReplicaPrivateInterface> rep = replicas.value(i.key()).toStrongRef();
+ QSharedPointer<QReplicaImplementationInterface> rep = replicas.value(i.key()).toStrongRef();
if (rep && !requestedUrls.contains(i.value().hostUrl))
initConnection(i.value().hostUrl);
else if (!rep) //replica has been deleted, remove from list
@@ -389,7 +438,7 @@ void QRemoteObjectNodePrivate::onShouldReconnect(ClientIoDevice *ioDevice)
connectedSources.remove(remoteObject);
ioDevice->removeSource(remoteObject);
if (replicas.contains(remoteObject)) { //We have a replica waiting on this remoteObject
- QSharedPointer<QConnectedReplicaPrivate> rep = qSharedPointerCast<QConnectedReplicaPrivate>(replicas.value(remoteObject).toStrongRef());
+ QSharedPointer<QConnectedReplicaImplementation> rep = qSharedPointerCast<QConnectedReplicaImplementation>(replicas.value(remoteObject).toStrongRef());
if (rep && !rep->connectionToSource.isNull()) {
rep->setDisconnected();
} else if (!rep) {
@@ -413,16 +462,13 @@ void QRemoteObjectNodePrivate::onShouldReconnect(ClientIoDevice *ioDevice)
//This version of handleNewAcquire creates a QConnectedReplica. If this is a
//host node, the QRemoteObjectHostBasePrivate overload is called instead.
-QReplicaPrivateInterface *QRemoteObjectNodePrivate::handleNewAcquire(const QMetaObject *meta, QRemoteObjectReplica *instance, const QString &name)
+QReplicaImplementationInterface *QRemoteObjectNodePrivate::handleNewAcquire(const QMetaObject *meta, QRemoteObjectReplica *instance, const QString &name)
{
Q_Q(QRemoteObjectNode);
- QConnectedReplicaPrivate *rp = new QConnectedReplicaPrivate(name, meta, q);
+ QConnectedReplicaImplementation *rp = new QConnectedReplicaImplementation(name, meta, q);
rp->configurePrivate(instance);
if (connectedSources.contains(name)) { //Either we have a peer connections, or existing connection via registry
- if (checkSignatures(rp->m_objectSignature, connectedSources[name].objectSignature))
- rp->setConnection(connectedSources[name].device);
- else
- rp->setState(QRemoteObjectReplica::SignatureMismatch);
+ handleReplicaConnection(connectedSources[name].objectSignature, rp, connectedSources[name].device);
} else {
//No existing connection, but we know we can connect via registry
const auto &sourceLocations = remoteObjectAddresses();
@@ -435,14 +481,60 @@ QReplicaPrivateInterface *QRemoteObjectNodePrivate::handleNewAcquire(const QMeta
return rp;
}
+void QRemoteObjectNodePrivate::handleReplicaConnection(const QString &name)
+{
+ QSharedPointer<QConnectedReplicaImplementation> rep = qSharedPointerCast<QConnectedReplicaImplementation>(replicas.value(name).toStrongRef());
+ if (!rep) { //replica has been deleted, remove from list
+ replicas.remove(name);
+ return;
+ }
+ if (rep->connectionToSource.isNull()) {
+ const auto sourceInfo = connectedSources.value(name);
+ handleReplicaConnection(sourceInfo.objectSignature, rep.data(), sourceInfo.device);
+ }
+}
+
+void QRemoteObjectNodePrivate::handleReplicaConnection(const QByteArray &sourceSignature, QConnectedReplicaImplementation *rep, ClientIoDevice *connection)
+{
+ if (!checkSignatures(rep->m_objectSignature, sourceSignature)) {
+ rep->setState(QRemoteObjectReplica::SignatureMismatch);
+ return;
+ }
+ if (!rep->m_metaObject) {
+ rep->setConnection(connection);
+ return;
+ }
+ for (int i = rep->m_metaObject->propertyOffset(); i < rep->m_metaObject->propertyCount(); ++i) {
+ const QMetaProperty property = rep->m_metaObject->property(i);
+ if (!QMetaType::typeFlags(property.userType()).testFlag(QMetaType::PointerToQObject))
+ continue;
+
+ const auto type = property.typeName();
+ const size_t len = strlen(type);
+ if (len > 8 && strncmp(&type[len-8], "Replica*", 8) == 0) {
+ auto propertyMeta = QMetaType::metaObjectForType(property.userType());
+ QString name;
+ if (propertyMeta->inherits(&QAbstractItemModel::staticMetaObject))
+ name = QStringLiteral("Model::%1").arg(QString::fromLatin1(property.name()));
+ else
+ name = QStringLiteral("Class::%1").arg(QString::fromLatin1(property.name()));
+ if (replicas.contains(name))
+ handleReplicaConnection(name);
+ else
+ qROPrivWarning() << "Child type" << name << "not available. Objects:" << replicas.keys();
+ }
+ }
+ rep->setConnection(connection);
+}
+
//Host Nodes can use the more efficient InProcess Replica if we (this Node) hold the Source for the
//requested Replica. If not, fall back to the Connected Replica case.
-QReplicaPrivateInterface *QRemoteObjectHostBasePrivate::handleNewAcquire(const QMetaObject *meta, QRemoteObjectReplica *instance, const QString &name)
+QReplicaImplementationInterface *QRemoteObjectHostBasePrivate::handleNewAcquire(const QMetaObject *meta, QRemoteObjectReplica *instance, const QString &name)
{
QMap<QString, QRemoteObjectSource*>::const_iterator mapIt;
if (remoteObjectIo && map_contains(remoteObjectIo->m_remoteObjects, name, mapIt)) {
Q_Q(QRemoteObjectHostBase);
- QInProcessReplicaPrivate *rp = new QInProcessReplicaPrivate(name, meta, q);
+ QInProcessReplicaImplementation *rp = new QInProcessReplicaImplementation(name, meta, q);
rp->configurePrivate(instance);
connectReplica(mapIt.value()->m_object, instance);
rp->connectionToSource = mapIt.value();
@@ -459,44 +551,62 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj)
Q_ASSERT(connection);
do {
-
if (!connection->read(packetType, rxName))
return;
+ if (packetType != Handshake && !m_handshakeReceived) {
+ qROPrivWarning() << "Expected Handshake, got " << packetType;
+ setLastError(QRemoteObjectNode::ProtocolMismatch);
+ connection->close();
+ break;
+ }
+
switch (packetType) {
+ case Pong:
+ {
+ QSharedPointer<QRemoteObjectReplicaImplementation> rep = qSharedPointerCast<QRemoteObjectReplicaImplementation>(replicas.value(rxName).toStrongRef());
+ if (rep)
+ rep->notifyAboutReply(0, {});
+ else //replica has been deleted, remove from list
+ replicas.remove(rxName);
+ break;
+ }
+ case Handshake:
+ if (rxName != QtRemoteObjects::protocolVersion) {
+ qROPrivWarning() << "Protocol Mismatch, closing connection. Got" << rxObjects << "expected" << QtRemoteObjects::protocolVersion;
+ setLastError(QRemoteObjectNode::ProtocolMismatch);
+ connection->close();
+ } else {
+ m_handshakeReceived = true;
+ }
+ break;
case ObjectList:
{
deserializeObjectListPacket(connection->stream(), rxObjects);
qROPrivDebug() << "newObjects:" << rxObjects;
+ // We need to make sure all of the source objects are in connectedSources before we add connections,
+ // otherwise nested QObjects could fail (we want to acquire children before parents, and the object
+ // list is unordered)
Q_FOREACH (const auto &remoteObject, rxObjects) {
qROPrivDebug() << " connectedSources.contains(" << remoteObject << ")" << connectedSources.contains(remoteObject.name) << replicas.contains(remoteObject.name);
if (!connectedSources.contains(remoteObject.name)) {
connectedSources[remoteObject.name] = SourceInfo{connection, remoteObject.typeName, remoteObject.signature};
connection->addSource(remoteObject.name);
- if (replicas.contains(remoteObject.name)) { //We have a replica waiting on this remoteObject
- QSharedPointer<QConnectedReplicaPrivate> rep = qSharedPointerCast<QConnectedReplicaPrivate>(replicas.value(remoteObject.name).toStrongRef());
- if (!rep || checkSignatures(remoteObject.signature, rep->m_objectSignature)) {
- if (rep && rep->connectionToSource.isNull()) {
- qROPrivDebug() << "Test" << remoteObject<<replicas.keys();
- qROPrivDebug() << rep;
- rep->setConnection(connection);
- } else if (!rep) { //replica has been deleted, remove from list
- replicas.remove(remoteObject.name);
- }
- } else {
- if (rep)
- rep->setState(QRemoteObjectReplica::SignatureMismatch);
- }
- continue;
- }
+ // Make sure we handle Registry first if it is available
+ if (remoteObject.name == QStringLiteral("Registry") && replicas.contains(remoteObject.name))
+ handleReplicaConnection(remoteObject.name);
}
}
+ Q_FOREACH (const auto &remoteObject, rxObjects) {
+ if (replicas.contains(remoteObject.name)) //We have a replica waiting on this remoteObject
+ handleReplicaConnection(remoteObject.name);
+ }
break;
}
case InitPacket:
{
qROPrivDebug() << "InitObject-->" << rxName << this;
- QSharedPointer<QConnectedReplicaPrivate> rep = qSharedPointerCast<QConnectedReplicaPrivate>(replicas.value(rxName).toStrongRef());
+ QSharedPointer<QConnectedReplicaImplementation> rep = qSharedPointerCast<QConnectedReplicaImplementation>(replicas.value(rxName).toStrongRef());
//Use m_rxArgs (a QVariantList to hold the properties QVariantList)
deserializeInitPacket(connection->stream(), rxArgs);
if (rep)
@@ -515,7 +625,7 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj)
builder.setSuperClass(&QRemoteObjectReplica::staticMetaObject);
builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
deserializeInitDynamicPacket(connection->stream(), builder, rxArgs);
- QSharedPointer<QConnectedReplicaPrivate> rep = qSharedPointerCast<QConnectedReplicaPrivate>(replicas.value(rxName).toStrongRef());
+ QSharedPointer<QConnectedReplicaImplementation> rep = qSharedPointerCast<QConnectedReplicaImplementation>(replicas.value(rxName).toStrongRef());
if (rep)
{
rep->initializeMetaObject(builder, rxArgs);
@@ -530,7 +640,7 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj)
connectedSources.remove(rxName);
connection->removeSource(rxName);
if (replicas.contains(rxName)) { //We have a replica waiting on this remoteObject
- QSharedPointer<QConnectedReplicaPrivate> rep = qSharedPointerCast<QConnectedReplicaPrivate>(replicas.value(rxName).toStrongRef());
+ QSharedPointer<QConnectedReplicaImplementation> rep = qSharedPointerCast<QConnectedReplicaImplementation>(replicas.value(rxName).toStrongRef());
if (rep && !rep->connectionToSource.isNull()) {
rep->connectionToSource.clear();
rep->setState(QRemoteObjectReplica::Suspect);
@@ -544,7 +654,7 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj)
{
int propertyIndex;
deserializePropertyChangePacket(connection->stream(), propertyIndex, rxValue);
- QSharedPointer<QRemoteObjectReplicaPrivate> rep = qSharedPointerCast<QRemoteObjectReplicaPrivate>(replicas.value(rxName).toStrongRef());
+ QSharedPointer<QRemoteObjectReplicaImplementation> rep = qSharedPointerCast<QRemoteObjectReplicaImplementation>(replicas.value(rxName).toStrongRef());
if (rep) {
const QMetaProperty property = rep->m_metaObject->property(propertyIndex + rep->m_metaObject->propertyOffset());
rep->setProperty(propertyIndex, deserializedProperty(rxValue, property));
@@ -557,7 +667,7 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj)
{
int call, index, serialId, propertyIndex;
deserializeInvokePacket(connection->stream(), call, index, rxArgs, serialId, propertyIndex);
- QSharedPointer<QRemoteObjectReplicaPrivate> rep = qSharedPointerCast<QRemoteObjectReplicaPrivate>(replicas.value(rxName).toStrongRef());
+ QSharedPointer<QRemoteObjectReplicaImplementation> rep = qSharedPointerCast<QRemoteObjectReplicaImplementation>(replicas.value(rxName).toStrongRef());
if (rep) {
static QVariant null(QMetaType::QObjectStar, (void*)0);
QVariant paramValue;
@@ -584,7 +694,7 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj)
{
int ackedSerialId;
deserializeInvokeReplyPacket(connection->stream(), ackedSerialId, rxValue);
- QSharedPointer<QRemoteObjectReplicaPrivate> rep = qSharedPointerCast<QRemoteObjectReplicaPrivate>(replicas.value(rxName).toStrongRef());
+ QSharedPointer<QRemoteObjectReplicaImplementation> rep = qSharedPointerCast<QRemoteObjectReplicaImplementation>(replicas.value(rxName).toStrongRef());
if (rep) {
qROPrivDebug() << "Received InvokeReplyPacket ack'ing serial id:" << ackedSerialId;
rep->notifyAboutReply(ackedSerialId, rxValue);
@@ -595,6 +705,7 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj)
}
case AddObject:
case Invalid:
+ case Ping:
qROPrivWarning() << "Unexpected packet received";
}
} while (connection->bytesAvailable()); // have bytes left over, so do another iteration
@@ -706,6 +817,7 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj)
\value SourceNotRegistered The given QRemoteObjectSource is not registered on this node.
\value MissingObjectName The given QObject does not have objectName() set.
\value HostUrlInvalid The given url has an invalid or unrecognized scheme.
+ \value ProtocolMismatch The client and the server have different protocol versions.
*/
/*!
@@ -720,12 +832,10 @@ void QRemoteObjectNodePrivate::onClientRead(QObject *obj)
void QRemoteObjectNodePrivate::initialize()
{
- Q_Q(QRemoteObjectNode);
qRegisterMetaType<QRemoteObjectNode *>();
qRegisterMetaType<QRemoteObjectNode::ErrorCode>();
qRegisterMetaType<QAbstractSocket::SocketError>(); //For queued qnx error()
qRegisterMetaTypeStreamOperators<QVector<int> >();
- QObject::connect(&clientRead, SIGNAL(mapped(QObject*)), q, SLOT(onClientRead(QObject*)));
}
bool QRemoteObjectNodePrivate::checkSignatures(const QByteArray &a, const QByteArray &b)
@@ -1065,10 +1175,18 @@ void QRemoteObjectNodePrivate::setRegistry(QRemoteObjectRegistry *reg)
registry = reg;
reg->setParent(q);
//Make sure when we get the registry initialized, we update our replicas
- QObject::connect(reg, SIGNAL(initialized()), q, SLOT(onRegistryInitialized()));
+ QObject::connect(reg, &QRemoteObjectRegistry::initialized, q, [this]() {
+ onRegistryInitialized();
+ });
//Make sure we handle new RemoteObjectSources on Registry...
- QObject::connect(reg, SIGNAL(remoteObjectAdded(QRemoteObjectSourceLocation)), q, SLOT(onRemoteObjectSourceAdded(QRemoteObjectSourceLocation)));
- QObject::connect(reg, SIGNAL(remoteObjectRemoved(QRemoteObjectSourceLocation)), q, SLOT(onRemoteObjectSourceRemoved(QRemoteObjectSourceLocation)));
+ QObject::connect(reg, &QRemoteObjectRegistry::remoteObjectAdded,
+ q, [this](const QRemoteObjectSourceLocation &location) {
+ onRemoteObjectSourceAdded(location);
+ });
+ QObject::connect(reg, &QRemoteObjectRegistry::remoteObjectRemoved,
+ q, [this](const QRemoteObjectSourceLocation &location) {
+ onRemoteObjectSourceRemoved(location);
+ });
}
/*!
@@ -1234,7 +1352,7 @@ bool QRemoteObjectHostBase::enableRemoting(QObject *object, const QString &name)
}
}
}
- return d->remoteObjectIo->enableRemoting(object, meta, _name, typeName);
+ return d->remoteObjectIo->enableRemoting(object, meta, _name, typeName, this);
}
/*!
@@ -1307,8 +1425,7 @@ bool QRemoteObjectHostBase::enableRemoting(QAbstractItemModel *model, const QStr
bool QRemoteObjectHostBase::enableRemoting(QObject *object, const SourceApiMap *api, QObject *adapter)
{
Q_D(QRemoteObjectHostBase);
- api->modelSetup(this);
- return d->remoteObjectIo->enableRemoting(object, api, adapter);
+ return d->remoteObjectIo->enableRemoting(object, api, this, adapter);
}
/*!
@@ -1344,10 +1461,10 @@ bool QRemoteObjectHostBase::disableRemoting(QObject *remoteObject)
the Model on the network. The returned \c model will be empty until it is
initialized with the \l Source.
*/
-QAbstractItemModelReplica *QRemoteObjectNode::acquireModel(const QString &name)
+QAbstractItemModelReplica *QRemoteObjectNode::acquireModel(const QString &name, QtRemoteObjects::InitialAction action, const QVector<int> &rolesHint)
{
- QAbstractItemModelReplicaPrivate *rep = acquire<QAbstractItemModelReplicaPrivate>(name);
- return new QAbstractItemModelReplica(rep);
+ QAbstractItemModelReplicaImplementation *rep = acquire<QAbstractItemModelReplicaImplementation>(name);
+ return new QAbstractItemModelReplica(rep, action, rolesHint);
}
QRemoteObjectHostBasePrivate::QRemoteObjectHostBasePrivate()
diff --git a/src/remoteobjects/qremoteobjectnode.h b/src/remoteobjects/qremoteobjectnode.h
index f8ca6b4..0987621 100644
--- a/src/remoteobjects/qremoteobjectnode.h
+++ b/src/remoteobjects/qremoteobjectnode.h
@@ -53,24 +53,34 @@ class SourceApiMap;
class QAbstractItemModel;
class QAbstractItemModelReplica;
class QItemSelectionModel;
+class QRemoteObjectAbstractPersistedStorePrivate;
class QRemoteObjectNodePrivate;
class QRemoteObjectHostBasePrivate;
class QRemoteObjectHostPrivate;
class QRemoteObjectRegistryHostPrivate;
-class ClientIoDevice;
-class Q_REMOTEOBJECTS_EXPORT QRemoteObjectPersistedStore
+class Q_REMOTEOBJECTS_EXPORT QRemoteObjectAbstractPersistedStore : public QObject
{
+ Q_OBJECT
+
public:
- virtual ~QRemoteObjectPersistedStore() {}
+ QRemoteObjectAbstractPersistedStore (QObject *parent = nullptr);
+ virtual ~QRemoteObjectAbstractPersistedStore();
+
virtual void saveProperties(const QString &repName, const QByteArray &repSig, const QVariantList &values) = 0;
virtual QVariantList restoreProperties(const QString &repName, const QByteArray &repSig) = 0;
+
+protected:
+ QRemoteObjectAbstractPersistedStore(QRemoteObjectAbstractPersistedStorePrivate &, QObject *parent);
+ Q_DECLARE_PRIVATE(QRemoteObjectAbstractPersistedStore)
};
class Q_REMOTEOBJECTS_EXPORT QRemoteObjectNode : public QObject
{
Q_OBJECT
Q_PROPERTY(QUrl registryUrl READ registryUrl WRITE setRegistryUrl)
+ Q_PROPERTY(QRemoteObjectAbstractPersistedStore* persistedStore READ persistedStore WRITE setPersistedStore)
+ Q_PROPERTY(int heartbeatInterval READ heartbeatInterval WRITE setHeartbeatInterval NOTIFY heartbeatIntervalChanged)
public:
enum ErrorCode{
@@ -83,17 +93,14 @@ public:
OperationNotValidOnClientNode,
SourceNotRegistered,
MissingObjectName,
- HostUrlInvalid
+ HostUrlInvalid,
+ ProtocolMismatch
};
Q_ENUM(ErrorCode)
- enum StorageOwnership {
- DoNotPassOwnership,
- PassOwnershipToNode
- };
QRemoteObjectNode(QObject *parent = nullptr);
QRemoteObjectNode(const QUrl &registryAddress, QObject *parent = nullptr);
- virtual ~QRemoteObjectNode();
+ ~QRemoteObjectNode() override;
Q_INVOKABLE bool connectToNode(const QUrl &address);
virtual void setName(const QString &name);
@@ -117,36 +124,38 @@ public:
QStringList instances(const QString &typeName) const;
QRemoteObjectDynamicReplica *acquireDynamic(const QString &name);
- QAbstractItemModelReplica *acquireModel(const QString &name);
+ QAbstractItemModelReplica *acquireModel(const QString &name, QtRemoteObjects::InitialAction action = QtRemoteObjects::FetchRootSize, const QVector<int> &rolesHint = {});
QUrl registryUrl() const;
virtual bool setRegistryUrl(const QUrl &registryAddress);
bool waitForRegistry(int timeout = 30000);
const QRemoteObjectRegistry *registry() const;
- void setPersistedStore(QRemoteObjectPersistedStore *store, StorageOwnership ownership=DoNotPassOwnership);
+
+ QRemoteObjectAbstractPersistedStore *persistedStore() const;
+ void setPersistedStore(QRemoteObjectAbstractPersistedStore *persistedStore);
ErrorCode lastError() const;
- void timerEvent(QTimerEvent*);
+ int heartbeatInterval() const;
+ void setHeartbeatInterval(int interval);
Q_SIGNALS:
void remoteObjectAdded(const QRemoteObjectSourceLocation &);
void remoteObjectRemoved(const QRemoteObjectSourceLocation &);
void error(QRemoteObjectNode::ErrorCode errorCode);
+ void heartbeatIntervalChanged(int heartbeatInterval);
protected:
QRemoteObjectNode(QRemoteObjectNodePrivate &, QObject *parent);
+ void timerEvent(QTimerEvent*) override;
+
private:
void initializeReplica(QRemoteObjectReplica *instance, const QString &name = QString());
void persistProperties(const QString &repName, const QByteArray &repSig, const QVariantList &props);
QVariantList retrieveProperties(const QString &repName, const QByteArray &repSig);
+
Q_DECLARE_PRIVATE(QRemoteObjectNode)
- Q_PRIVATE_SLOT(d_func(), void onClientRead(QObject *obj))
- Q_PRIVATE_SLOT(d_func(), void onRemoteObjectSourceAdded(const QRemoteObjectSourceLocation &entry))
- Q_PRIVATE_SLOT(d_func(), void onRemoteObjectSourceRemoved(const QRemoteObjectSourceLocation &entry))
- Q_PRIVATE_SLOT(d_func(), void onRegistryInitialized())
- Q_PRIVATE_SLOT(d_func(), void onShouldReconnect(ClientIoDevice *ioDevice))
friend class QRemoteObjectReplica;
};
@@ -183,7 +192,7 @@ public:
QRemoteObjectHost(QObject *parent = nullptr);
QRemoteObjectHost(const QUrl &address, const QUrl &registryAddress = QUrl(), QObject *parent = nullptr);
QRemoteObjectHost(const QUrl &address, QObject *parent);
- virtual ~QRemoteObjectHost();
+ ~QRemoteObjectHost() override;
QUrl hostUrl() const override;
bool setHostUrl(const QUrl &hostAddress) override;
@@ -199,7 +208,7 @@ class Q_REMOTEOBJECTS_EXPORT QRemoteObjectRegistryHost : public QRemoteObjectHos
Q_OBJECT
public:
QRemoteObjectRegistryHost(const QUrl &registryAddress = QUrl(), QObject *parent = nullptr);
- virtual ~QRemoteObjectRegistryHost();
+ ~QRemoteObjectRegistryHost() override;
bool setRegistryUrl(const QUrl &registryUrl) override;
protected:
diff --git a/src/remoteobjects/qremoteobjectnode_p.h b/src/remoteobjects/qremoteobjectnode_p.h
index 8a948f6..839dbb3 100644
--- a/src/remoteobjects/qremoteobjectnode_p.h
+++ b/src/remoteobjects/qremoteobjectnode_p.h
@@ -72,16 +72,26 @@ QT_BEGIN_NAMESPACE
class QRemoteObjectRegistry;
class QRegistrySource;
+class QConnectedReplicaImplementation;
+
+class QRemoteObjectAbstractPersistedStorePrivate : public QObjectPrivate
+{
+public:
+ QRemoteObjectAbstractPersistedStorePrivate();
+ virtual ~QRemoteObjectAbstractPersistedStorePrivate();
+
+ Q_DECLARE_PUBLIC(QRemoteObjectAbstractPersistedStore)
+};
class QRemoteObjectNodePrivate : public QObjectPrivate
{
public:
QRemoteObjectNodePrivate();
- virtual ~QRemoteObjectNodePrivate();
+ ~QRemoteObjectNodePrivate() override;
virtual QRemoteObjectSourceLocations remoteObjectAddresses() const;
- void setReplicaPrivate(const QMetaObject *, QRemoteObjectReplica *, const QString &);
+ void setReplicaImplementation(const QMetaObject *, QRemoteObjectReplica *, const QString &);
void setLastError(QRemoteObjectNode::ErrorCode errorCode);
@@ -98,7 +108,9 @@ public:
void onRegistryInitialized();
void onShouldReconnect(ClientIoDevice *ioDevice);
- virtual QReplicaPrivateInterface *handleNewAcquire(const QMetaObject *meta, QRemoteObjectReplica *instance, const QString &name);
+ virtual QReplicaImplementationInterface *handleNewAcquire(const QMetaObject *meta, QRemoteObjectReplica *instance, const QString &name);
+ void handleReplicaConnection(const QString &name);
+ void handleReplicaConnection(const QByteArray &sourceSignature, QConnectedReplicaImplementation *rep, ClientIoDevice *connection);
void initialize();
private:
bool checkSignatures(const QByteArray &a, const QByteArray &b);
@@ -114,11 +126,10 @@ public:
QAtomicInt isInitialized;
QMutex mutex;
QUrl registryAddress;
- QHash<QString, QWeakPointer<QReplicaPrivateInterface> > replicas;
+ QHash<QString, QWeakPointer<QReplicaImplementationInterface> > replicas;
QMap<QString, SourceInfo> connectedSources;
QSet<ClientIoDevice*> pendingReconnect;
QSet<QUrl> requestedUrls;
- QSignalMapper clientRead;
QRemoteObjectRegistry *registry;
int retryInterval;
QBasicTimer reconnectTimer;
@@ -127,8 +138,9 @@ public:
QRemoteObjectPackets::ObjectInfoList rxObjects;
QVariantList rxArgs;
QVariant rxValue;
- QRemoteObjectPersistedStore *persistedStore;
- QRemoteObjectNode::StorageOwnership persistedStoreOwnership;
+ QRemoteObjectAbstractPersistedStore *persistedStore;
+ bool m_handshakeReceived = false;
+ int m_heartbeatInterval = 0;
Q_DECLARE_PUBLIC(QRemoteObjectNode)
};
@@ -136,8 +148,8 @@ class QRemoteObjectHostBasePrivate : public QRemoteObjectNodePrivate
{
public:
QRemoteObjectHostBasePrivate();
- virtual ~QRemoteObjectHostBasePrivate() {}
- QReplicaPrivateInterface *handleNewAcquire(const QMetaObject *meta, QRemoteObjectReplica *instance, const QString &name) override;
+ ~QRemoteObjectHostBasePrivate() override {}
+ QReplicaImplementationInterface *handleNewAcquire(const QMetaObject *meta, QRemoteObjectReplica *instance, const QString &name) override;
public:
QRemoteObjectSourceIo *remoteObjectIo;
@@ -148,7 +160,7 @@ class QRemoteObjectHostPrivate : public QRemoteObjectHostBasePrivate
{
public:
QRemoteObjectHostPrivate();
- virtual ~QRemoteObjectHostPrivate() {}
+ ~QRemoteObjectHostPrivate() override {}
Q_DECLARE_PUBLIC(QRemoteObjectHost);
};
@@ -156,7 +168,7 @@ class QRemoteObjectRegistryHostPrivate : public QRemoteObjectHostBasePrivate
{
public:
QRemoteObjectRegistryHostPrivate();
- virtual ~QRemoteObjectRegistryHostPrivate() {}
+ ~QRemoteObjectRegistryHostPrivate() override {}
QRemoteObjectSourceLocations remoteObjectAddresses() const override;
QRegistrySource *registrySource;
Q_DECLARE_PUBLIC(QRemoteObjectRegistryHost);
diff --git a/src/remoteobjects/qremoteobjectpacket.cpp b/src/remoteobjects/qremoteobjectpacket.cpp
index c504171..b21eb88 100644
--- a/src/remoteobjects/qremoteobjectpacket.cpp
+++ b/src/remoteobjects/qremoteobjectpacket.cpp
@@ -71,6 +71,13 @@ QVariant deserializedProperty(const QVariant &in, const QMetaProperty &property)
}
}
+void serializeHandshakePacket(DataStreamPacket &ds)
+{
+ ds.setId(Handshake);
+ ds << QString(protocolVersion);
+ ds.finishPacket();
+}
+
void serializeInitPacket(DataStreamPacket &ds, const QRemoteObjectSource *object)
{
const SourceApiMap *api = object->m_api;
@@ -143,11 +150,25 @@ void serializeInitDynamicPacket(DataStreamPacket &ds, const QRemoteObjectSource
ds << api->name();
//Now copy the property data
+ const int numEnums = api->enumCount();
+ const auto metaObject = object->m_object->metaObject();
+ ds << quint32(numEnums); //Number of Enums
+ for (int i = 0; i < numEnums; ++i) {
+ auto enumerator = metaObject->enumerator(api->sourceEnumIndex(i));
+ Q_ASSERT(enumerator.isValid());
+ ds << enumerator.name();
+ ds << enumerator.isFlag();
+ ds << enumerator.scope();
+ const int keyCount = enumerator.keyCount();
+ ds << keyCount;
+ for (int k = 0; k < keyCount; ++k) {
+ ds << enumerator.key(k);
+ ds << enumerator.value(k);
+ }
+ }
+
const int numSignals = api->signalCount();
ds << quint32(numSignals); //Number of signals
- const int numMethods = api->methodCount();
- ds << quint32(numMethods); //Number of methods
-
for (int i = 0; i < numSignals; ++i) {
const int index = api->sourceSignalIndex(i);
if (index < 0) {
@@ -156,8 +177,11 @@ void serializeInitDynamicPacket(DataStreamPacket &ds, const QRemoteObjectSource
return;
}
ds << api->signalSignature(i);
+ ds << api->signalParameterNames(i);
}
+ const int numMethods = api->methodCount();
+ ds << quint32(numMethods); //Number of methods
for (int i = 0; i < numMethods; ++i) {
const int index = api->sourceMethodIndex(i);
if (index < 0) {
@@ -167,11 +191,11 @@ void serializeInitDynamicPacket(DataStreamPacket &ds, const QRemoteObjectSource
}
ds << api->methodSignature(i);
ds << api->typeName(i);
+ ds << api->methodParameterNames(i);
}
const int numProperties = api->propertyCount();
ds << quint32(numProperties); //Number of properties
-
for (int i = 0; i < numProperties; ++i) {
const int index = api->sourcePropertyIndex(i);
if (index < 0) {
@@ -195,33 +219,64 @@ void serializeInitDynamicPacket(DataStreamPacket &ds, const QRemoteObjectSource
void deserializeInitDynamicPacket(QDataStream &in, QMetaObjectBuilder &builder, QVariantList &values)
{
+ quint32 numEnums = 0;
quint32 numSignals = 0;
quint32 numMethods = 0;
quint32 numProperties = 0;
- in >> numSignals;
- in >> numMethods;
+ in >> numEnums;
+ for (quint32 i = 0; i < numEnums; ++i) {
+ QByteArray name;
+ in >> name;
+ auto enumBuilder = builder.addEnumerator(name);
+ bool isFlag;
+ in >> isFlag;
+ enumBuilder.setIsFlag(isFlag);
+
+ QByteArray scopeName;
+ in >> scopeName; // scope
+ // TODO uncomment this line after https://bugreports.qt.io/browse/QTBUG-64081 is implemented
+ //enumBuilder.setScope(scopeName);
+
+ int keyCount;
+ in >> keyCount;
+ for (int k = 0; k < keyCount; ++k) {
+ QByteArray key;
+ int value;
+ in >> key;
+ in >> value;
+ enumBuilder.addKey(key, value);
+ }
+ }
int curIndex = 0;
+ in >> numSignals;
for (quint32 i = 0; i < numSignals; ++i) {
QByteArray signature;
+ QList<QByteArray> paramNames;
in >> signature;
+ in >> paramNames;
++curIndex;
- builder.addSignal(signature);
+ auto mmb = builder.addSignal(signature);
+ mmb.setParameterNames(paramNames);
}
+ in >> numMethods;
for (quint32 i = 0; i < numMethods; ++i) {
QByteArray signature, returnType;
-
+ QList<QByteArray> paramNames;
in >> signature;
in >> returnType;
+ in >> paramNames;
++curIndex;
const bool isVoid = returnType.isEmpty() || returnType == QByteArrayLiteral("void");
+ QMetaMethodBuilder mmb;
if (isVoid)
- builder.addMethod(signature);
+ mmb = builder.addMethod(signature);
else
- builder.addMethod(signature, QByteArrayLiteral("QRemoteObjectPendingCall"));
+ mmb = builder.addMethod(signature, QByteArrayLiteral("QRemoteObjectPendingCall"));
+ mmb.setParameterNames(paramNames);
}
in >> numProperties;
@@ -345,6 +400,20 @@ void deserializeObjectListPacket(QDataStream &in, ObjectInfoList &objects)
in >> objects;
}
+void serializePingPacket(DataStreamPacket &ds, const QString &name)
+{
+ ds.setId(Ping);
+ ds << name;
+ ds.finishPacket();
+}
+
+void serializePongPacket(DataStreamPacket &ds, const QString &name)
+{
+ ds.setId(Pong);
+ ds << name;
+ ds.finishPacket();
+}
+
} // namespace QRemoteObjectPackets
QT_END_NAMESPACE
diff --git a/src/remoteobjects/qremoteobjectpacket_p.h b/src/remoteobjects/qremoteobjectpacket_p.h
index 5b81df9..51353cd 100644
--- a/src/remoteobjects/qremoteobjectpacket_p.h
+++ b/src/remoteobjects/qremoteobjectpacket_p.h
@@ -138,6 +138,7 @@ private:
QVariant serializedProperty(const QMetaProperty &property, const QObject *object);
QVariant deserializedProperty(const QVariant &in, const QMetaProperty &property);
+void serializeHandshakePacket(DataStreamPacket &ds);
void serializeInitPacket(DataStreamPacket&, const QRemoteObjectSource*);
void deserializeInitPacket(QDataStream&, QVariantList&);
@@ -160,6 +161,11 @@ void deserializeInvokeReplyPacket(QDataStream& in, int &ackedSerialId, QVariant
void serializePropertyChangePacket(DataStreamPacket&, const QString &name, int index, const QVariant &value);
void deserializePropertyChangePacket(QDataStream& in, int &index, QVariant &value);
+// Heartbeat packets
+void serializePingPacket(DataStreamPacket &ds, const QString &name);
+void serializePongPacket(DataStreamPacket &ds, const QString &name);
+
+
} // namespace QRemoteObjectPackets
QT_END_NAMESPACE
diff --git a/src/remoteobjects/qremoteobjectpendingcall.cpp b/src/remoteobjects/qremoteobjectpendingcall.cpp
index 5813346..94decf0 100644
--- a/src/remoteobjects/qremoteobjectpendingcall.cpp
+++ b/src/remoteobjects/qremoteobjectpendingcall.cpp
@@ -48,7 +48,7 @@
QT_BEGIN_NAMESPACE
-QRemoteObjectPendingCallData::QRemoteObjectPendingCallData(int serialId, QRemoteObjectReplicaPrivate *replica)
+QRemoteObjectPendingCallData::QRemoteObjectPendingCallData(int serialId, QRemoteObjectReplicaImplementation *replica)
: replica(replica)
, serialId(serialId)
, error(QRemoteObjectPendingCall::InvalidMessage)
@@ -62,7 +62,9 @@ QRemoteObjectPendingCallData::~QRemoteObjectPendingCallData()
void QRemoteObjectPendingCallWatcherHelper::add(QRemoteObjectPendingCallWatcher *watcher)
{
- connect(this, SIGNAL(finished()), watcher, SLOT(_q_finished()), Qt::QueuedConnection);
+ connect(this, &QRemoteObjectPendingCallWatcherHelper::finished, watcher, [watcher]() {
+ emit watcher->finished(watcher);
+ }, Qt::QueuedConnection);
}
void QRemoteObjectPendingCallWatcherHelper::emitSignals()
@@ -148,17 +150,9 @@ QRemoteObjectPendingCall QRemoteObjectPendingCall::fromCompletedCall(const QVari
class QRemoteObjectPendingCallWatcherPrivate: public QObjectPrivate
{
public:
- void _q_finished();
-
Q_DECLARE_PUBLIC(QRemoteObjectPendingCallWatcher)
};
-inline void QRemoteObjectPendingCallWatcherPrivate::_q_finished()
-{
- Q_Q(QRemoteObjectPendingCallWatcher);
- emit q->finished(q);
-}
-
QRemoteObjectPendingCallWatcher::QRemoteObjectPendingCallWatcher(const QRemoteObjectPendingCall &call, QObject *parent)
: QObject(*new QRemoteObjectPendingCallWatcherPrivate, parent)
, QRemoteObjectPendingCall(call)
diff --git a/src/remoteobjects/qremoteobjectpendingcall.h b/src/remoteobjects/qremoteobjectpendingcall.h
index 06c5a67..41a18a7 100644
--- a/src/remoteobjects/qremoteobjectpendingcall.h
+++ b/src/remoteobjects/qremoteobjectpendingcall.h
@@ -79,7 +79,7 @@ protected:
QExplicitlySharedDataPointer<QRemoteObjectPendingCallData> d;
private:
- friend class QConnectedReplicaPrivate;
+ friend class QConnectedReplicaImplementation;
};
QT_END_NAMESPACE
@@ -92,7 +92,7 @@ class Q_REMOTEOBJECTS_EXPORT QRemoteObjectPendingCallWatcher: public QObject, pu
public:
QRemoteObjectPendingCallWatcher(const QRemoteObjectPendingCall &call, QObject *parent = nullptr);
- ~QRemoteObjectPendingCallWatcher();
+ ~QRemoteObjectPendingCallWatcher() override;
bool isFinished() const;
@@ -103,7 +103,6 @@ Q_SIGNALS:
private:
Q_DECLARE_PRIVATE(QRemoteObjectPendingCallWatcher)
- Q_PRIVATE_SLOT(d_func(), void _q_finished())
};
template<typename T>
diff --git a/src/remoteobjects/qremoteobjectpendingcall_p.h b/src/remoteobjects/qremoteobjectpendingcall_p.h
index a92234f..9a19d9b 100644
--- a/src/remoteobjects/qremoteobjectpendingcall_p.h
+++ b/src/remoteobjects/qremoteobjectpendingcall_p.h
@@ -58,17 +58,17 @@
QT_BEGIN_NAMESPACE
class QRemoteObjectPendingCallWatcherHelper;
-class QRemoteObjectReplicaPrivate;
+class QRemoteObjectReplicaImplementation;
class QRemoteObjectPendingCallData : public QSharedData
{
public:
typedef QExplicitlySharedDataPointer<QRemoteObjectPendingCallData> Ptr;
- explicit QRemoteObjectPendingCallData(int serialId = -1, QRemoteObjectReplicaPrivate *replica = nullptr);
+ explicit QRemoteObjectPendingCallData(int serialId = -1, QRemoteObjectReplicaImplementation *replica = nullptr);
~QRemoteObjectPendingCallData();
- QRemoteObjectReplicaPrivate *replica;
+ QRemoteObjectReplicaImplementation *replica;
int serialId;
QVariant returnValue;
diff --git a/src/remoteobjects/qremoteobjectregistry.cpp b/src/remoteobjects/qremoteobjectregistry.cpp
index f226f57..8be15ec 100644
--- a/src/remoteobjects/qremoteobjectregistry.cpp
+++ b/src/remoteobjects/qremoteobjectregistry.cpp
@@ -40,12 +40,19 @@
#include "qremoteobjectregistry.h"
#include "qremoteobjectreplica_p.h"
+#include <private/qobject_p.h>
#include <QSet>
#include <QDataStream>
-
QT_BEGIN_NAMESPACE
+class QRemoteObjectRegistryPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QRemoteObjectRegistry)
+
+ QRemoteObjectSourceLocations hostedSources;
+};
+
/*!
\class QRemoteObjectRegistry
\inmodule QtRemoteObjects
@@ -56,13 +63,14 @@ QT_BEGIN_NAMESPACE
available on the network, and simplifies the process of connecting to other
\l {QRemoteObjectNode} {node}s.
*/
-QRemoteObjectRegistry::QRemoteObjectRegistry() : QRemoteObjectReplica()
+QRemoteObjectRegistry::QRemoteObjectRegistry(QObject *parent)
+ : QRemoteObjectReplica(*new QRemoteObjectRegistryPrivate, parent)
{
connect(this, &QRemoteObjectRegistry::stateChanged, this, &QRemoteObjectRegistry::pushToRegistryIfNeeded);
}
-QRemoteObjectRegistry::QRemoteObjectRegistry(QRemoteObjectNode *node, const QString &name)
- : QRemoteObjectReplica(ConstructWithNode)
+QRemoteObjectRegistry::QRemoteObjectRegistry(QRemoteObjectNode *node, const QString &name, QObject *parent)
+ : QRemoteObjectReplica(*new QRemoteObjectRegistryPrivate, parent)
{
connect(this, &QRemoteObjectRegistry::stateChanged, this, &QRemoteObjectRegistry::pushToRegistryIfNeeded);
initializeNode(node, name);
@@ -138,12 +146,13 @@ QRemoteObjectSourceLocations QRemoteObjectRegistry::sourceLocations() const
*/
void QRemoteObjectRegistry::addSource(const QRemoteObjectSourceLocation &entry)
{
- if (hostedSources.contains(entry.first)) {
+ Q_D(QRemoteObjectRegistry);
+ if (d->hostedSources.contains(entry.first)) {
qCWarning(QT_REMOTEOBJECT) << "Node warning: ignoring source" << entry.first
<< "as this node already has a source by that name.";
return;
}
- hostedSources.insert(entry.first, entry.second);
+ d->hostedSources.insert(entry.first, entry.second);
if (state() != QRemoteObjectReplica::State::Valid)
return;
@@ -166,9 +175,11 @@ void QRemoteObjectRegistry::addSource(const QRemoteObjectSourceLocation &entry)
*/
void QRemoteObjectRegistry::removeSource(const QRemoteObjectSourceLocation &entry)
{
- if (!hostedSources.contains(entry.first))
+ Q_D(QRemoteObjectRegistry);
+ if (!d->hostedSources.contains(entry.first))
return;
- hostedSources.remove(entry.first);
+
+ d->hostedSources.remove(entry.first);
if (state() != QRemoteObjectReplica::State::Valid)
return;
@@ -189,23 +200,26 @@ void QRemoteObjectRegistry::removeSource(const QRemoteObjectSourceLocation &entr
*/
void QRemoteObjectRegistry::pushToRegistryIfNeeded()
{
+ Q_D(QRemoteObjectRegistry);
if (state() != QRemoteObjectReplica::State::Valid)
return;
- const QSet<QString> myLocs = QSet<QString>::fromList(hostedSources.keys());
+
+ const QSet<QString> myLocs = QSet<QString>::fromList(d->hostedSources.keys());
if (myLocs.empty())
return;
+
const QSet<QString> registryLocs = QSet<QString>::fromList(sourceLocations().keys());
foreach (const QString &loc, myLocs & registryLocs) {
qCWarning(QT_REMOTEOBJECT) << "Node warning: Ignoring Source" << loc << "as another source ("
<< sourceLocations().value(loc) << ") has already registered that name.";
- hostedSources.remove(loc);
+ d->hostedSources.remove(loc);
return;
}
//Sources that need to be pushed to the registry...
foreach (const QString &loc, myLocs - registryLocs) {
static int index = QRemoteObjectRegistry::staticMetaObject.indexOfMethod("addSource(QRemoteObjectSourceLocation)");
QVariantList args;
- args << QVariant::fromValue(QRemoteObjectSourceLocation(loc, hostedSources[loc]));
+ args << QVariant::fromValue(QRemoteObjectSourceLocation(loc, d->hostedSources[loc]));
send(QMetaObject::InvokeMetaMethod, index, args);
}
}
diff --git a/src/remoteobjects/qremoteobjectregistry.h b/src/remoteobjects/qremoteobjectregistry.h
index cac2542..94ef60e 100644
--- a/src/remoteobjects/qremoteobjectregistry.h
+++ b/src/remoteobjects/qremoteobjectregistry.h
@@ -44,6 +44,8 @@
QT_BEGIN_NAMESPACE
+class QRemoteObjectRegistryPrivate;
+
class Q_REMOTEOBJECTS_EXPORT QRemoteObjectRegistry : public QRemoteObjectReplica
{
Q_OBJECT
@@ -52,7 +54,7 @@ class Q_REMOTEOBJECTS_EXPORT QRemoteObjectRegistry : public QRemoteObjectReplica
Q_PROPERTY(QRemoteObjectSourceLocations sourceLocations READ sourceLocations)
public:
- ~QRemoteObjectRegistry();
+ ~QRemoteObjectRegistry() override;
static void registerMetatypes();
QRemoteObjectSourceLocations sourceLocations() const;
@@ -68,9 +70,11 @@ protected Q_SLOTS:
private:
void initialize() override;
- explicit QRemoteObjectRegistry();
- explicit QRemoteObjectRegistry(QRemoteObjectNode *node, const QString &name);
- QRemoteObjectSourceLocations hostedSources;
+
+ explicit QRemoteObjectRegistry(QObject *parent = nullptr);
+ explicit QRemoteObjectRegistry(QRemoteObjectNode *node, const QString &name, QObject *parent = nullptr);
+
+ Q_DECLARE_PRIVATE(QRemoteObjectRegistry)
friend class QT_PREPEND_NAMESPACE(QRemoteObjectNode);
};
diff --git a/src/remoteobjects/qremoteobjectregistrysource_p.h b/src/remoteobjects/qremoteobjectregistrysource_p.h
index 1571439..fcf4355 100644
--- a/src/remoteobjects/qremoteobjectregistrysource_p.h
+++ b/src/remoteobjects/qremoteobjectregistrysource_p.h
@@ -64,7 +64,7 @@ class QRegistrySource : public QObject
public:
explicit QRegistrySource(QObject *parent = nullptr);
- ~QRegistrySource();
+ ~QRegistrySource() override;
QRemoteObjectSourceLocations sourceLocations() const;
diff --git a/src/remoteobjects/qremoteobjectreplica.cpp b/src/remoteobjects/qremoteobjectreplica.cpp
index bf6ea37..bb1b9a8 100644
--- a/src/remoteobjects/qremoteobjectreplica.cpp
+++ b/src/remoteobjects/qremoteobjectreplica.cpp
@@ -44,7 +44,7 @@
#include "qremoteobjectdynamicreplica.h"
#include "qremoteobjectpacket_p.h"
#include "qremoteobjectpendingcall_p.h"
-#include "qconnectionfactories.h"
+#include "qconnectionfactories_p.h"
#include "qremoteobjectsource_p.h"
#include "private/qmetaobjectbuilder_p.h"
@@ -53,7 +53,6 @@
#include <QElapsedTimer>
#include <QVariant>
#include <QThread>
-#include <QTimer>
#include <limits>
@@ -69,7 +68,7 @@ Q_STATIC_ASSERT_X(&QRemoteObjectReplica::staticMetaObject == &QRemoteObjectDynam
// used. It was changed to avoid a Coverity complaint. We use the above static assert to detect if this changes
// in the future. See FIX #1, #2, #3 in this file.
-QRemoteObjectReplicaPrivate::QRemoteObjectReplicaPrivate(const QString &name, const QMetaObject *meta, QRemoteObjectNode *_node)
+QRemoteObjectReplicaImplementation::QRemoteObjectReplicaImplementation(const QString &name, const QMetaObject *meta, QRemoteObjectNode *_node)
: QObject(nullptr), m_objectName(name), m_metaObject(meta), m_numSignals(0), m_methodOffset(0)
// Uncomment the following two lines if QRemoteObjectDynamicReplica gets a unique staticMetaObject (FIX #1, #2)
//, m_signalOffset(meta ? QRemoteObjectReplica::staticMetaObject.methodCount() : QRemoteObjectDynamicReplica::staticMetaObject.methodCount())
@@ -77,23 +76,47 @@ QRemoteObjectReplicaPrivate::QRemoteObjectReplicaPrivate(const QString &name, co
, m_signalOffset(QRemoteObjectReplica::staticMetaObject.methodCount())
, m_propertyOffset(QRemoteObjectReplica::staticMetaObject.propertyCount())
, m_node(_node)
- , m_objectSignature(qtro_classinfo_signature(m_metaObject))
+ , m_objectSignature(QtPrivate::qtro_classinfo_signature(m_metaObject))
, m_state(meta ? QRemoteObjectReplica::Default : QRemoteObjectReplica::Uninitialized)
{
}
-QRemoteObjectReplicaPrivate::~QRemoteObjectReplicaPrivate()
+QRemoteObjectReplicaImplementation::~QRemoteObjectReplicaImplementation()
{
if (m_metaObject && qstrcmp(m_metaObject->className(), "QRemoteObjectDynamicReplica") == 0)
free(const_cast<QMetaObject*>(m_metaObject));
}
-QConnectedReplicaPrivate::QConnectedReplicaPrivate(const QString &name, const QMetaObject *meta, QRemoteObjectNode *node)
- : QRemoteObjectReplicaPrivate(name, meta, node), connectionToSource(nullptr), m_curSerialId(0)
-{
+QConnectedReplicaImplementation::QConnectedReplicaImplementation(const QString &name, const QMetaObject *meta, QRemoteObjectNode *node)
+ : QRemoteObjectReplicaImplementation(name, meta, node), connectionToSource(nullptr)
+{
+ m_heartbeatTimer.setTimerType(Qt::CoarseTimer);
+ m_heartbeatTimer.setSingleShot(true);
+ m_heartbeatTimer.setInterval(node->heartbeatInterval());
+
+ connect(node, &QRemoteObjectNode::heartbeatIntervalChanged, this, [this](int interval) {
+ m_heartbeatTimer.stop();
+ m_heartbeatTimer.setInterval(interval);
+ if (interval)
+ m_heartbeatTimer.start();
+ });
+ connect(&m_heartbeatTimer, &QTimer::timeout, this, [this] {
+ if (m_pendingCalls.contains(0)) {
+ // The source didn't respond in time, disconnect the connection
+ if (connectionToSource)
+ connectionToSource->disconnectFromServer();
+ } else {
+ serializePingPacket(m_packet, m_objectName);
+ if (sendCommandWithReply(0).d->serialId == -1) {
+ m_heartbeatTimer.stop();
+ if (connectionToSource)
+ connectionToSource->disconnectFromServer();
+ }
+ }
+ });
}
-QConnectedReplicaPrivate::~QConnectedReplicaPrivate()
+QConnectedReplicaImplementation::~QConnectedReplicaImplementation()
{
if (!connectionToSource.isNull()) {
qCDebug(QT_REMOTEOBJECT) << "Replica deleted: sending RemoveObject to RemoteObjectSource" << m_objectName;
@@ -102,12 +125,12 @@ QConnectedReplicaPrivate::~QConnectedReplicaPrivate()
}
}
-bool QRemoteObjectReplicaPrivate::needsDynamicInitialization() const
+bool QRemoteObjectReplicaImplementation::needsDynamicInitialization() const
{
return m_metaObject == nullptr;
}
-void QRemoteObjectReplicaPrivate::setState(QRemoteObjectReplica::State state)
+void QRemoteObjectReplicaImplementation::setState(QRemoteObjectReplica::State state)
{
if (m_state != QRemoteObjectReplica::Suspect && m_state >= state)
return;
@@ -117,7 +140,7 @@ void QRemoteObjectReplicaPrivate::setState(QRemoteObjectReplica::State state)
// We should emit initialized before emitting any changed signals in case connections are made in a
// Slot responding to initialized/validChanged.
- if (oldState < QRemoteObjectReplica::Valid && m_state == QRemoteObjectReplica::Valid) {
+ if (m_state == QRemoteObjectReplica::Valid) {
// we're initialized now, emit signal
emitInitialized();
}
@@ -128,7 +151,7 @@ void QRemoteObjectReplicaPrivate::setState(QRemoteObjectReplica::State state)
QMetaObject::activate(this, metaObject(), stateChangedIndex, args);
}
-bool QConnectedReplicaPrivate::sendCommand()
+bool QConnectedReplicaImplementation::sendCommand()
{
if (connectionToSource.isNull() || !connectionToSource->isOpen()) {
if (connectionToSource.isNull())
@@ -137,10 +160,12 @@ bool QConnectedReplicaPrivate::sendCommand()
}
connectionToSource->write(m_packet.array, m_packet.size);
+ if (m_heartbeatTimer.interval())
+ m_heartbeatTimer.start();
return true;
}
-void QConnectedReplicaPrivate::initialize(const QVariantList &values)
+void QConnectedReplicaImplementation::initialize(const QVariantList &values)
{
qCDebug(QT_REMOTEOBJECT) << "initialize()" << m_propertyStorage.size();
const int nParam = values.size();
@@ -157,7 +182,7 @@ void QConnectedReplicaPrivate::initialize(const QVariantList &values)
qCDebug(QT_REMOTEOBJECT) << "SETPROPERTY" << i << m_metaObject->property(i+offset).name() << values.at(i).typeName() << values.at(i).toString();
}
- Q_ASSERT(m_state < QRemoteObjectReplica::Valid);
+ Q_ASSERT(m_state < QRemoteObjectReplica::Valid || m_state == QRemoteObjectReplica::Suspect);
setState(QRemoteObjectReplica::Valid);
void *args[] = {nullptr, nullptr};
@@ -173,9 +198,11 @@ void QConnectedReplicaPrivate::initialize(const QVariantList &values)
}
qCDebug(QT_REMOTEOBJECT) << "isSet = true for" << m_objectName;
+ if (node()->heartbeatInterval())
+ m_heartbeatTimer.start();
}
-void QRemoteObjectReplicaPrivate::emitInitialized()
+void QRemoteObjectReplicaImplementation::emitInitialized()
{
const static int initializedIndex = QRemoteObjectReplica::staticMetaObject.indexOfMethod("initialized()");
Q_ASSERT(initializedIndex != -1);
@@ -207,7 +234,7 @@ QVariantList QRemoteObjectReplica::retrieveProperties(const QString &repName, co
return node()->retrieveProperties(repName, repSig);
}
-void QRemoteObjectReplicaPrivate::initializeMetaObject(const QMetaObjectBuilder &builder, const QVariantList &values)
+void QRemoteObjectReplicaImplementation::initializeMetaObject(const QMetaObjectBuilder &builder, const QVariantList &values)
{
Q_ASSERT(!m_metaObject);
@@ -216,9 +243,9 @@ void QRemoteObjectReplicaPrivate::initializeMetaObject(const QMetaObjectBuilder
setProperties(values);
}
-void QConnectedReplicaPrivate::initializeMetaObject(const QMetaObjectBuilder &builder, const QVariantList &values)
+void QConnectedReplicaImplementation::initializeMetaObject(const QMetaObjectBuilder &builder, const QVariantList &values)
{
- QRemoteObjectReplicaPrivate::initializeMetaObject(builder, values);
+ QRemoteObjectReplicaImplementation::initializeMetaObject(builder, values);
foreach (QRemoteObjectReplica *obj, m_parentsNeedingConnect)
configurePrivate(obj);
m_parentsNeedingConnect.clear();
@@ -239,12 +266,12 @@ void QConnectedReplicaPrivate::initializeMetaObject(const QMetaObjectBuilder &bu
qCDebug(QT_REMOTEOBJECT) << "isSet = true for" << m_objectName;
}
-bool QConnectedReplicaPrivate::isInitialized() const
+bool QConnectedReplicaImplementation::isInitialized() const
{
return m_state > QRemoteObjectReplica::Default && m_state != QRemoteObjectReplica::SignatureMismatch;
}
-bool QConnectedReplicaPrivate::waitForSource(int timeout)
+bool QConnectedReplicaImplementation::waitForSource(int timeout)
{
switch (state()) {
case QRemoteObjectReplica::State::Valid:
@@ -273,7 +300,7 @@ bool QConnectedReplicaPrivate::waitForSource(int timeout)
return state() == QRemoteObjectReplica::State::Valid;
}
-void QConnectedReplicaPrivate::_q_send(QMetaObject::Call call, int index, const QVariantList &args)
+void QConnectedReplicaImplementation::_q_send(QMetaObject::Call call, int index, const QVariantList &args)
{
static const bool debugArgs = qEnvironmentVariableIsSet("QT_REMOTEOBJECT_DEBUG_ARGUMENTS");
@@ -302,17 +329,17 @@ void QConnectedReplicaPrivate::_q_send(QMetaObject::Call call, int index, const
}
}
-QRemoteObjectPendingCall QConnectedReplicaPrivate::_q_sendWithReply(QMetaObject::Call call, int index, const QVariantList &args)
+QRemoteObjectPendingCall QConnectedReplicaImplementation::_q_sendWithReply(QMetaObject::Call call, int index, const QVariantList &args)
{
Q_ASSERT(call == QMetaObject::InvokeMetaMethod);
qCDebug(QT_REMOTEOBJECT) << "Send" << call << this->m_metaObject->method(index).name() << index << args << connectionToSource;
- int serialId = (m_curSerialId == std::numeric_limits<int>::max() ? 0 : m_curSerialId++);
+ int serialId = (m_curSerialId == std::numeric_limits<int>::max() ? 1 : m_curSerialId++);
serializeInvokePacket(m_packet, m_objectName, call, index - m_methodOffset, args, serialId);
return sendCommandWithReply(serialId);
}
-QRemoteObjectPendingCall QConnectedReplicaPrivate::sendCommandWithReply(int serialId)
+QRemoteObjectPendingCall QConnectedReplicaImplementation::sendCommandWithReply(int serialId)
{
bool success = sendCommand();
if (!success) {
@@ -326,9 +353,15 @@ QRemoteObjectPendingCall QConnectedReplicaPrivate::sendCommandWithReply(int seri
return pendingCall;
}
-void QConnectedReplicaPrivate::notifyAboutReply(int ackedSerialId, const QVariant &value)
+void QConnectedReplicaImplementation::notifyAboutReply(int ackedSerialId, const QVariant &value)
{
QRemoteObjectPendingCall call = m_pendingCalls.take(ackedSerialId);
+ if (ackedSerialId == 0) {
+ m_heartbeatTimer.stop();
+ if (m_heartbeatTimer.interval())
+ m_heartbeatTimer.start();
+ return;
+ }
QMutexLocker mutex(&call.d->mutex);
@@ -341,7 +374,7 @@ void QConnectedReplicaPrivate::notifyAboutReply(int ackedSerialId, const QVarian
call.d->watcherHelper->emitSignals();
}
-bool QConnectedReplicaPrivate::waitForFinished(const QRemoteObjectPendingCall& call, int timeout)
+bool QConnectedReplicaImplementation::waitForFinished(const QRemoteObjectPendingCall& call, int timeout)
{
if (!call.d->watcherHelper)
call.d->watcherHelper.reset(new QRemoteObjectPendingCallWatcherHelper);
@@ -360,25 +393,25 @@ bool QConnectedReplicaPrivate::waitForFinished(const QRemoteObjectPendingCall& c
return call.d->error != QRemoteObjectPendingCall::InvalidMessage;
}
-const QVariant QConnectedReplicaPrivate::getProperty(int i) const
+const QVariant QConnectedReplicaImplementation::getProperty(int i) const
{
Q_ASSERT_X(i >= 0 && i < m_propertyStorage.size(), __FUNCTION__, qPrintable(QString(QLatin1String("0 <= %1 < %2")).arg(i).arg(m_propertyStorage.size())));
return m_propertyStorage[i];
}
-void QConnectedReplicaPrivate::setProperties(const QVariantList &properties)
+void QConnectedReplicaImplementation::setProperties(const QVariantList &properties)
{
Q_ASSERT(m_propertyStorage.isEmpty());
m_propertyStorage.reserve(properties.length());
m_propertyStorage = properties;
}
-void QConnectedReplicaPrivate::setProperty(int i, const QVariant &prop)
+void QConnectedReplicaImplementation::setProperty(int i, const QVariant &prop)
{
m_propertyStorage[i] = prop;
}
-void QConnectedReplicaPrivate::setConnection(ClientIoDevice *conn)
+void QConnectedReplicaImplementation::setConnection(ClientIoDevice *conn)
{
if (connectionToSource.isNull()) {
connectionToSource = conn;
@@ -387,19 +420,19 @@ void QConnectedReplicaPrivate::setConnection(ClientIoDevice *conn)
requestRemoteObjectSource();
}
-void QConnectedReplicaPrivate::setDisconnected()
+void QConnectedReplicaImplementation::setDisconnected()
{
connectionToSource.clear();
setState(QRemoteObjectReplica::State::Suspect);
}
-void QConnectedReplicaPrivate::requestRemoteObjectSource()
+void QConnectedReplicaImplementation::requestRemoteObjectSource()
{
serializeAddObjectPacket(m_packet, m_objectName, needsDynamicInitialization());
sendCommand();
}
-void QRemoteObjectReplicaPrivate::configurePrivate(QRemoteObjectReplica *rep)
+void QRemoteObjectReplicaImplementation::configurePrivate(QRemoteObjectReplica *rep)
{
qCDebug(QT_REMOTEOBJECT) << "configurePrivate starting for" << this->m_objectName;
//We need to connect the Replicant only signals too
@@ -418,8 +451,20 @@ void QRemoteObjectReplicaPrivate::configurePrivate(QRemoteObjectReplica *rep)
}
if (m_methodOffset == 0) //We haven't initialized the offsets yet
{
- for (int i = m_signalOffset; i < m_metaObject->methodCount(); ++i) {
- const QMetaMethod mm = m_metaObject->method(i);
+ const int index = m_metaObject->indexOfClassInfo(QCLASSINFO_REMOTEOBJECT_TYPE);
+ const QMetaObject *metaObject = m_metaObject;
+ if (index != -1) { //We have an object created from repc or at least with QCLASSINFO defined
+ while (true) {
+ Q_ASSERT(metaObject->superClass()); //This recurses to QObject, which doesn't have QCLASSINFO_REMOTEOBJECT_TYPE
+ if (index != metaObject->superClass()->indexOfClassInfo(QCLASSINFO_REMOTEOBJECT_TYPE)) //At the point we don't find the same QCLASSINFO_REMOTEOBJECT_TYPE,
+ //we have the metaobject we should work from
+ break;
+ metaObject = metaObject->superClass();
+ }
+ }
+
+ for (int i = m_signalOffset; i < metaObject->methodCount(); ++i) {
+ const QMetaMethod mm = metaObject->method(i);
if (mm.methodType() == QMetaMethod::Signal) {
++m_numSignals;
const bool res = QMetaObject::connect(this, i, rep, i, Qt::DirectConnection, 0);
@@ -436,22 +481,22 @@ void QRemoteObjectReplicaPrivate::configurePrivate(QRemoteObjectReplica *rep)
Q_UNUSED(res);
}
if (isInitialized()) {
- qCDebug(QT_REMOTEOBJECT) << QStringLiteral("ReplicaPrivate initialized, emitting signal on replica");
+ qCDebug(QT_REMOTEOBJECT) << QStringLiteral("ReplicaImplementation initialized, emitting signal on replica");
emit rep->initialized(); //Emit from new replica only
}
if (state() != QRemoteObjectReplica::Valid) {
- qCDebug(QT_REMOTEOBJECT) << QStringLiteral("ReplicaPrivate not currently valid, emitting signal on replica");
+ qCDebug(QT_REMOTEOBJECT) << QStringLiteral("ReplicaImplementation not currently valid, emitting signal on replica");
emit rep->stateChanged(state(), m_metaObject ? QRemoteObjectReplica::Default : QRemoteObjectReplica::Uninitialized);
}
- qCDebug(QT_REMOTEOBJECT) << QStringLiteral("configurePrivate finished, added replica to existing ReplicaPrivate");
+ qCDebug(QT_REMOTEOBJECT) << QStringLiteral("configurePrivate finished, added replica to existing ReplicaImplementation");
}
}
-void QConnectedReplicaPrivate::configurePrivate(QRemoteObjectReplica *rep)
+void QConnectedReplicaImplementation::configurePrivate(QRemoteObjectReplica *rep)
{
if (m_metaObject)
- QRemoteObjectReplicaPrivate::configurePrivate(rep);
+ QRemoteObjectReplicaImplementation::configurePrivate(rep);
else
m_parentsNeedingConnect.append(rep);
}
@@ -528,11 +573,17 @@ void QConnectedReplicaPrivate::configurePrivate(QRemoteObjectReplica *rep)
*/
QRemoteObjectReplica::QRemoteObjectReplica(ConstructorType t)
: QObject(nullptr)
- , d_ptr(t == DefaultConstructor ? new QStubReplicaPrivate : 0)
+ , d_impl(t == DefaultConstructor ? new QStubReplicaImplementation : 0)
{
qRegisterMetaType<State>("State");
}
+QRemoteObjectReplica::QRemoteObjectReplica(QObjectPrivate &dptr, QObject *parent)
+ : QObject(dptr, parent)
+ , d_impl(new QStubReplicaImplementation)
+{
+}
+
/*!
\internal
*/
@@ -547,7 +598,7 @@ void QRemoteObjectReplica::send(QMetaObject::Call call, int index, const QVarian
{
Q_ASSERT(index != -1);
- d_ptr->_q_send(call, index, args);
+ d_impl->_q_send(call, index, args);
}
/*!
@@ -555,7 +606,7 @@ void QRemoteObjectReplica::send(QMetaObject::Call call, int index, const QVarian
*/
QRemoteObjectPendingCall QRemoteObjectReplica::sendWithReply(QMetaObject::Call call, int index, const QVariantList &args)
{
- return d_ptr->_q_sendWithReply(call, index, args);
+ return d_impl->_q_sendWithReply(call, index, args);
}
/*!
@@ -563,7 +614,7 @@ QRemoteObjectPendingCall QRemoteObjectReplica::sendWithReply(QMetaObject::Call c
*/
const QVariant QRemoteObjectReplica::propAsVariant(int i) const
{
- return d_ptr->getProperty(i);
+ return d_impl->getProperty(i);
}
/*!
@@ -579,7 +630,7 @@ void QRemoteObjectReplica::initializeNode(QRemoteObjectNode *node, const QString
*/
void QRemoteObjectReplica::setProperties(const QVariantList &properties)
{
- d_ptr->setProperties(properties);
+ d_impl->setProperties(properties);
}
/*!
@@ -589,7 +640,7 @@ void QRemoteObjectReplica::setProperties(const QVariantList &properties)
*/
bool QRemoteObjectReplica::isInitialized() const
{
- return d_ptr->isInitialized();
+ return d_impl->isInitialized();
}
/*!
@@ -599,12 +650,12 @@ bool QRemoteObjectReplica::isInitialized() const
*/
QRemoteObjectReplica::State QRemoteObjectReplica::state() const
{
- return d_ptr->state();
+ return d_impl->state();
}
QRemoteObjectNode *QRemoteObjectReplica::node() const
{
- return d_ptr->node();
+ return d_impl->node();
}
void QRemoteObjectReplica::setNode(QRemoteObjectNode *_node)
@@ -614,7 +665,7 @@ void QRemoteObjectReplica::setNode(QRemoteObjectNode *_node)
qCWarning(QT_REMOTEOBJECT) << "Ignoring call to setNode as the node has already been set";
return;
}
- d_ptr.clear();
+ d_impl.clear();
_node->initializeReplica(this);
}
@@ -644,19 +695,19 @@ bool QRemoteObjectReplica::isReplicaValid() const
*/
bool QRemoteObjectReplica::waitForSource(int timeout)
{
- return d_ptr->waitForSource(timeout);
+ return d_impl->waitForSource(timeout);
}
-QInProcessReplicaPrivate::QInProcessReplicaPrivate(const QString &name, const QMetaObject *meta, QRemoteObjectNode * node)
- : QRemoteObjectReplicaPrivate(name, meta, node)
+QInProcessReplicaImplementation::QInProcessReplicaImplementation(const QString &name, const QMetaObject *meta, QRemoteObjectNode * node)
+ : QRemoteObjectReplicaImplementation(name, meta, node)
{
}
-QInProcessReplicaPrivate::~QInProcessReplicaPrivate()
+QInProcessReplicaImplementation::~QInProcessReplicaImplementation()
{
}
-const QVariant QInProcessReplicaPrivate::getProperty(int i) const
+const QVariant QInProcessReplicaImplementation::getProperty(int i) const
{
Q_ASSERT(connectionToSource);
Q_ASSERT(connectionToSource->m_object);
@@ -665,12 +716,12 @@ const QVariant QInProcessReplicaPrivate::getProperty(int i) const
return connectionToSource->m_object->metaObject()->property(index).read(connectionToSource->m_object);
}
-void QInProcessReplicaPrivate::setProperties(const QVariantList &)
+void QInProcessReplicaImplementation::setProperties(const QVariantList &)
{
//TODO some verification here maybe?
}
-void QInProcessReplicaPrivate::setProperty(int i, const QVariant &property)
+void QInProcessReplicaImplementation::setProperty(int i, const QVariant &property)
{
Q_ASSERT(connectionToSource);
Q_ASSERT(connectionToSource->m_object);
@@ -679,7 +730,7 @@ void QInProcessReplicaPrivate::setProperty(int i, const QVariant &property)
connectionToSource->m_object->metaObject()->property(index).write(connectionToSource->m_object, property);
}
-void QInProcessReplicaPrivate::_q_send(QMetaObject::Call call, int index, const QVariantList &args)
+void QInProcessReplicaImplementation::_q_send(QMetaObject::Call call, int index, const QVariantList &args)
{
Q_ASSERT(call == QMetaObject::InvokeMetaMethod || call == QMetaObject::WriteProperty);
@@ -699,7 +750,7 @@ void QInProcessReplicaPrivate::_q_send(QMetaObject::Call call, int index, const
}
}
-QRemoteObjectPendingCall QInProcessReplicaPrivate::_q_sendWithReply(QMetaObject::Call call, int index, const QVariantList &args)
+QRemoteObjectPendingCall QInProcessReplicaImplementation::_q_sendWithReply(QMetaObject::Call call, int index, const QVariantList &args)
{
Q_ASSERT(call == QMetaObject::InvokeMetaMethod);
@@ -719,29 +770,29 @@ QRemoteObjectPendingCall QInProcessReplicaPrivate::_q_sendWithReply(QMetaObject:
return QRemoteObjectPendingCall::fromCompletedCall(returnValue);
}
-QStubReplicaPrivate::QStubReplicaPrivate() {}
+QStubReplicaImplementation::QStubReplicaImplementation() {}
-QStubReplicaPrivate::~QStubReplicaPrivate() {}
+QStubReplicaImplementation::~QStubReplicaImplementation() {}
-const QVariant QStubReplicaPrivate::getProperty(int i) const
+const QVariant QStubReplicaImplementation::getProperty(int i) const
{
Q_ASSERT_X(i >= 0 && i < m_propertyStorage.size(), __FUNCTION__, qPrintable(QString(QLatin1String("0 <= %1 < %2")).arg(i).arg(m_propertyStorage.size())));
return m_propertyStorage[i];
}
-void QStubReplicaPrivate::setProperties(const QVariantList &properties)
+void QStubReplicaImplementation::setProperties(const QVariantList &properties)
{
Q_ASSERT(m_propertyStorage.isEmpty());
m_propertyStorage.reserve(properties.length());
m_propertyStorage = properties;
}
-void QStubReplicaPrivate::setProperty(int i, const QVariant &prop)
+void QStubReplicaImplementation::setProperty(int i, const QVariant &prop)
{
m_propertyStorage[i] = prop;
}
-void QStubReplicaPrivate::_q_send(QMetaObject::Call call, int index, const QVariantList &args)
+void QStubReplicaImplementation::_q_send(QMetaObject::Call call, int index, const QVariantList &args)
{
Q_UNUSED(call);
Q_UNUSED(index);
@@ -749,7 +800,7 @@ void QStubReplicaPrivate::_q_send(QMetaObject::Call call, int index, const QVari
qWarning("Tried calling a slot or setting a property on a replica that hasn't been initialized with a node");
}
-QRemoteObjectPendingCall QStubReplicaPrivate::_q_sendWithReply(QMetaObject::Call call, int index, const QVariantList &args)
+QRemoteObjectPendingCall QStubReplicaImplementation::_q_sendWithReply(QMetaObject::Call call, int index, const QVariantList &args)
{
Q_UNUSED(call);
Q_UNUSED(index);
diff --git a/src/remoteobjects/qremoteobjectreplica.h b/src/remoteobjects/qremoteobjectreplica.h
index f2d5481..a6b7d56 100644
--- a/src/remoteobjects/qremoteobjectreplica.h
+++ b/src/remoteobjects/qremoteobjectreplica.h
@@ -46,9 +46,10 @@
QT_BEGIN_NAMESPACE
+class QObjectPrivate;
class QRemoteObjectPendingCall;
-class QRemoteObjectReplicaPrivate;
-class QReplicaPrivateInterface;
+class QRemoteObjectReplicaImplementation;
+class QReplicaImplementationInterface;
class QRemoteObjectNode;
class Q_REMOTEOBJECTS_EXPORT QRemoteObjectReplica : public QObject
@@ -67,14 +68,14 @@ public:
Q_ENUM(State)
public:
- virtual ~QRemoteObjectReplica();
+ ~QRemoteObjectReplica() override;
bool isReplicaValid() const;
bool waitForSource(int timeout = 30000);
bool isInitialized() const;
State state() const;
QRemoteObjectNode *node() const;
- void setNode(QRemoteObjectNode *node);
+ virtual void setNode(QRemoteObjectNode *node);
Q_SIGNALS:
void initialized();
@@ -83,6 +84,7 @@ Q_SIGNALS:
protected:
enum ConstructorType {DefaultConstructor, ConstructWithNode};
explicit QRemoteObjectReplica(ConstructorType t = DefaultConstructor);
+ QRemoteObjectReplica(QObjectPrivate &dptr, QObject *parent);
virtual void initialize();
void send(QMetaObject::Call call, int index, const QVariantList &args);
@@ -94,7 +96,7 @@ protected:
void persistProperties(const QString &repName, const QByteArray &repSig, const QVariantList &props) const;
QVariantList retrieveProperties(const QString &repName, const QByteArray &repSig) const;
void initializeNode(QRemoteObjectNode *node, const QString &name = QString());
- QSharedPointer<QReplicaPrivateInterface> d_ptr;
+ QSharedPointer<QReplicaImplementationInterface> d_impl;
private:
friend class QRemoteObjectNodePrivate;
};
diff --git a/src/remoteobjects/qremoteobjectreplica_p.h b/src/remoteobjects/qremoteobjectreplica_p.h
index 7c2f517..61ad51f 100644
--- a/src/remoteobjects/qremoteobjectreplica_p.h
+++ b/src/remoteobjects/qremoteobjectreplica_p.h
@@ -61,6 +61,7 @@
#include <QVector>
#include <QDataStream>
#include <qcompilerdetection.h>
+#include <QTimer>
QT_BEGIN_NAMESPACE
@@ -75,10 +76,10 @@ class QInvokeReplyPacket;
class QRemoteObjectPacket;
}
-class QReplicaPrivateInterface
+class QReplicaImplementationInterface
{
public:
- virtual ~QReplicaPrivateInterface() {}
+ virtual ~QReplicaImplementationInterface() {}
virtual const QVariant getProperty(int i) const = 0;
virtual void setProperties(const QVariantList &) = 0;
virtual void setProperty(int i, const QVariant &) = 0;
@@ -91,11 +92,11 @@ public:
virtual QRemoteObjectPendingCall _q_sendWithReply(QMetaObject::Call call, int index, const QVariantList &args) = 0;
};
-class QStubReplicaPrivate : public QReplicaPrivateInterface
+class QStubReplicaImplementation : public QReplicaImplementationInterface
{
public:
- explicit QStubReplicaPrivate();
- virtual ~QStubReplicaPrivate();
+ explicit QStubReplicaImplementation();
+ ~QStubReplicaImplementation() override;
const QVariant getProperty(int i) const override;
void setProperties(const QVariantList &) override;
@@ -110,30 +111,30 @@ public:
QVariantList m_propertyStorage;
};
-class QRemoteObjectReplicaPrivate : public QObject, public QReplicaPrivateInterface
+class QRemoteObjectReplicaImplementation : public QObject, public QReplicaImplementationInterface
{
public:
- explicit QRemoteObjectReplicaPrivate(const QString &name, const QMetaObject *, QRemoteObjectNode *);
- virtual ~QRemoteObjectReplicaPrivate();
+ explicit QRemoteObjectReplicaImplementation(const QString &name, const QMetaObject *, QRemoteObjectNode *);
+ ~QRemoteObjectReplicaImplementation() override;
bool needsDynamicInitialization() const;
- virtual const QVariant getProperty(int i) const override = 0;
- virtual void setProperties(const QVariantList &) override = 0;
- virtual void setProperty(int i, const QVariant &) override = 0;
+ const QVariant getProperty(int i) const override = 0;
+ void setProperties(const QVariantList &) override = 0;
+ void setProperty(int i, const QVariant &) override = 0;
virtual bool isShortCircuit() const = 0;
- virtual bool isInitialized() const override { return true; }
+ bool isInitialized() const override { return true; }
QRemoteObjectReplica::State state() const override { return QRemoteObjectReplica::State(m_state.load()); }
void setState(QRemoteObjectReplica::State state);
- virtual bool waitForSource(int) override { return true; }
+ bool waitForSource(int) override { return true; }
virtual bool waitForFinished(const QRemoteObjectPendingCall &, int) { return true; }
virtual void notifyAboutReply(int, const QVariant &) {}
virtual void configurePrivate(QRemoteObjectReplica *);
void emitInitialized();
QRemoteObjectNode *node() const override { return m_node; }
- virtual void _q_send(QMetaObject::Call call, int index, const QVariantList &args) override = 0;
- virtual QRemoteObjectPendingCall _q_sendWithReply(QMetaObject::Call call, int index, const QVariantList &args) override = 0;
+ void _q_send(QMetaObject::Call call, int index, const QVariantList &args) override = 0;
+ QRemoteObjectPendingCall _q_sendWithReply(QMetaObject::Call call, int index, const QVariantList &args) override = 0;
//Dynamic replica functions
virtual void initializeMetaObject(const QMetaObjectBuilder &builder, const QVariantList &values);
@@ -151,11 +152,11 @@ public:
QAtomicInt m_state;
};
-class QConnectedReplicaPrivate : public QRemoteObjectReplicaPrivate
+class QConnectedReplicaImplementation : public QRemoteObjectReplicaImplementation
{
public:
- explicit QConnectedReplicaPrivate(const QString &name, const QMetaObject *, QRemoteObjectNode *);
- virtual ~QConnectedReplicaPrivate();
+ explicit QConnectedReplicaImplementation(const QString &name, const QMetaObject *, QRemoteObjectNode *);
+ ~QConnectedReplicaImplementation() override;
const QVariant getProperty(int i) const override;
void setProperties(const QVariantList &) override;
void setProperty(int i, const QVariant &) override;
@@ -181,16 +182,17 @@ public:
QPointer<ClientIoDevice> connectionToSource;
// pending call data
- int m_curSerialId;
+ int m_curSerialId = 1; // 0 is reserved for heartbeat signals
QHash<int, QRemoteObjectPendingCall> m_pendingCalls;
QRemoteObjectPackets::DataStreamPacket m_packet;
+ QTimer m_heartbeatTimer;
};
-class QInProcessReplicaPrivate : public QRemoteObjectReplicaPrivate
+class QInProcessReplicaImplementation : public QRemoteObjectReplicaImplementation
{
public:
- explicit QInProcessReplicaPrivate(const QString &name, const QMetaObject *, QRemoteObjectNode *);
- virtual ~QInProcessReplicaPrivate();
+ explicit QInProcessReplicaImplementation(const QString &name, const QMetaObject *, QRemoteObjectNode *);
+ ~QInProcessReplicaImplementation() override;
const QVariant getProperty(int i) const override;
void setProperties(const QVariantList &) override;
diff --git a/src/remoteobjects/qremoteobjectsettingsstore.cpp b/src/remoteobjects/qremoteobjectsettingsstore.cpp
new file mode 100644
index 0000000..fdc747e
--- /dev/null
+++ b/src/remoteobjects/qremoteobjectsettingsstore.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qremoteobjectsettingsstore.h"
+
+#include "qremoteobjectnode_p.h"
+
+#include <QtCore/private/qobject_p.h>
+#include <QSettings>
+
+QT_BEGIN_NAMESPACE
+
+class QRemoteObjectSettingsStorePrivate : public QRemoteObjectAbstractPersistedStorePrivate
+{
+public:
+ QRemoteObjectSettingsStorePrivate();
+ virtual ~QRemoteObjectSettingsStorePrivate();
+
+ QSettings settings;
+ Q_DECLARE_PUBLIC(QRemoteObjectSettingsStore)
+};
+
+QRemoteObjectSettingsStorePrivate::QRemoteObjectSettingsStorePrivate()
+{
+}
+
+QRemoteObjectSettingsStorePrivate::~QRemoteObjectSettingsStorePrivate()
+{
+}
+
+QRemoteObjectSettingsStore::QRemoteObjectSettingsStore(QObject *parent)
+ : QRemoteObjectAbstractPersistedStore(*new QRemoteObjectSettingsStorePrivate, parent)
+{
+}
+
+QRemoteObjectSettingsStore::~QRemoteObjectSettingsStore()
+{
+}
+
+QVariantList QRemoteObjectSettingsStore::restoreProperties(const QString &repName, const QByteArray &repSig)
+{
+ Q_D(QRemoteObjectSettingsStore);
+ d->settings.beginGroup(repName + QLatin1Char('/') + QString::fromLatin1(repSig));
+ const QVariantList values = d->settings.value(QStringLiteral("values")).toList();
+ d->settings.endGroup();
+ return values;
+}
+
+void QRemoteObjectSettingsStore::saveProperties(const QString &repName, const QByteArray &repSig, const QVariantList &values)
+{
+ Q_D(QRemoteObjectSettingsStore);
+ d->settings.beginGroup(repName + QLatin1Char('/') + QString::fromLatin1(repSig));
+ d->settings.setValue(QStringLiteral("values"), values);
+ d->settings.endGroup();
+ d->settings.sync();
+}
+
+QT_END_NAMESPACE
diff --git a/src/remoteobjects/qremoteobjectsettingsstore.h b/src/remoteobjects/qremoteobjectsettingsstore.h
new file mode 100644
index 0000000..841b41a
--- /dev/null
+++ b/src/remoteobjects/qremoteobjectsettingsstore.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QREMOTEOBJECTSETTINGSSTORE_H
+#define QREMOTEOBJECTSETTINGSSTORE_H
+
+#include "qremoteobjectnode.h"
+
+QT_BEGIN_NAMESPACE
+
+class QRemoteObjectSettingsStorePrivate;
+
+class Q_REMOTEOBJECTS_EXPORT QRemoteObjectSettingsStore : public QRemoteObjectAbstractPersistedStore
+{
+ Q_OBJECT
+
+public:
+ QRemoteObjectSettingsStore(QObject *parent = nullptr);
+ ~QRemoteObjectSettingsStore() override;
+
+ void saveProperties(const QString &repName, const QByteArray &repSig, const QVariantList &values) override;
+ QVariantList restoreProperties(const QString &repName, const QByteArray &repSig) override;
+
+private:
+ Q_DECLARE_PRIVATE(QRemoteObjectSettingsStore)
+};
+
+QT_END_NAMESPACE
+
+#endif // QREMOTEOBJECTSETTINGSSTORE_H
diff --git a/src/remoteobjects/qremoteobjectsource.cpp b/src/remoteobjects/qremoteobjectsource.cpp
index 50f9593..d28c59e 100644
--- a/src/remoteobjects/qremoteobjectsource.cpp
+++ b/src/remoteobjects/qremoteobjectsource.cpp
@@ -39,12 +39,14 @@
#include "qremoteobjectsource.h"
#include "qremoteobjectsource_p.h"
+#include "qremoteobjectnode.h"
-#include "qconnectionfactories.h"
+#include "qconnectionfactories_p.h"
#include "qremoteobjectsourceio_p.h"
#include <QMetaProperty>
#include <QVarLengthArray>
+#include <QAbstractItemModel>
#include <algorithm>
#include <iterator>
@@ -58,7 +60,7 @@ const int QRemoteObjectSource::qobjectMethodOffset = QObject::staticMetaObject.m
static const QByteArray s_classinfoRemoteobjectSignature(QCLASSINFO_REMOTEOBJECT_SIGNATURE);
-QByteArray qtro_classinfo_signature(const QMetaObject *metaObject)
+QByteArray QtPrivate::qtro_classinfo_signature(const QMetaObject *metaObject)
{
if (!metaObject)
return QByteArray{};
@@ -241,17 +243,42 @@ int QRemoteObjectSource::qt_metacall(QMetaObject::Call call, int methodId, void
return -1;
}
-DynamicApiMap::DynamicApiMap(const QMetaObject *metaObject, const QString &name, const QString &typeName)
+DynamicApiMap::DynamicApiMap(QObject *object, const QMetaObject *metaObject, const QString &name, const QString &typeName)
: m_name(name),
m_typeName(typeName),
m_metaObject(metaObject),
m_cachedMetamethodIndex(-1)
{
+ m_enumOffset = metaObject->enumeratorOffset();
+ m_enumCount = metaObject->enumeratorCount() - m_enumOffset;
+
const int propCount = metaObject->propertyCount();
const int propOffset = metaObject->propertyOffset();
m_properties.reserve(propCount-propOffset);
int i = 0;
for (i = propOffset; i < propCount; ++i) {
+ const QMetaProperty property = metaObject->property(i);
+ if (QMetaType::typeFlags(property.userType()).testFlag(QMetaType::PointerToQObject)) {
+ auto propertyMeta = QMetaType::metaObjectForType(property.userType());
+ QObject *child = property.read(object).value<QObject *>();
+ if (propertyMeta->inherits(&QAbstractItemModel::staticMetaObject)) {
+ const QByteArray name = QByteArray::fromRawData(property.name(),
+ qstrlen(property.name()));
+ const QByteArray infoName = name.toUpper() + QByteArrayLiteral("_ROLES");
+ const int infoIndex = metaObject->indexOfClassInfo(infoName.constData());
+ QByteArray roleInfo;
+ if (infoIndex >= 0) {
+ auto ci = metaObject->classInfo(infoIndex);
+ roleInfo = QByteArray::fromRawData(ci.value(), qstrlen(ci.value()));
+ }
+ m_models << ModelInfo({qobject_cast<QAbstractItemModel *>(child),
+ QString::fromLatin1(property.name()),
+ roleInfo});
+ } else {
+ m_subclasses << SubclassInfo({child, QString::fromLatin1(property.name())});
+ }
+ continue;
+ }
m_properties << i;
const int notifyIndex = metaObject->property(i).notifySignalIndex();
if (notifyIndex != -1) {
@@ -275,7 +302,14 @@ DynamicApiMap::DynamicApiMap(const QMetaObject *metaObject, const QString &name,
m_methods << i;
}
- m_objectSignature = qtro_classinfo_signature(metaObject);
+ m_objectSignature = QtPrivate::qtro_classinfo_signature(metaObject);
+}
+
+QList<QByteArray> DynamicApiMap::signalParameterNames(int index) const
+{
+ const int objectIndex = m_signals.at(index);
+ checkCache(objectIndex);
+ return m_cachedMetamethod.parameterNames();
}
int DynamicApiMap::parameterCount(int objectIndex) const
@@ -310,4 +344,50 @@ const QByteArray DynamicApiMap::typeName(int index) const
return m_cachedMetamethod.typeName();
}
+QList<QByteArray> DynamicApiMap::methodParameterNames(int index) const
+{
+ const int objectIndex = m_methods.at(index);
+ checkCache(objectIndex);
+ return m_cachedMetamethod.parameterNames();
+}
+
+void SourceApiMap::qobjectSetup(QRemoteObjectHostBase *node) const
+{
+ if (m_models.isEmpty() && m_subclasses.isEmpty())
+ return;
+
+ QVector<int> roles;
+
+ qCDebug(QT_REMOTEOBJECT) << "In qobjectSetup, model count =" << m_models.count() << "subclass count =" << m_subclasses.count();
+ for (int i = 0; i < m_models.count(); ++i) {
+ const auto model = m_models.at(i);
+ if (!model.ptr)
+ continue; // Pointer not initialized
+ roles.clear();
+ const auto knownRoles = model.ptr->roleNames();
+ for (auto role : model.roles.split('|')) {
+ const int roleIndex = knownRoles.key(role, -1);
+ if (roleIndex == -1) {
+ qCWarning(QT_REMOTEOBJECT) << "Invalid role" << role << "for model" << model.ptr->metaObject()->className();
+ qCWarning(QT_REMOTEOBJECT) << " known roles:" << knownRoles;
+ } else
+ roles << roleIndex;
+ }
+ const auto reportedName = QString::fromLatin1("Model::%1").arg(model.name);
+ // TODO handle selection model
+ if (roles.isEmpty())
+ node->enableRemoting(model.ptr, reportedName, knownRoles.keys().toVector(), nullptr);
+ else
+ node->enableRemoting(model.ptr, reportedName, roles, nullptr);
+ }
+
+ for (int i = 0; i < m_subclasses.count(); ++i) {
+ const auto subclass = m_subclasses.at(i);
+ if (subclass.ptr) {
+ const auto reportedName = QString::fromLatin1("Class::%1").arg(subclass.name);
+ node->enableRemoting(subclass.ptr, reportedName);
+ }
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/remoteobjects/qremoteobjectsource.h b/src/remoteobjects/qremoteobjectsource.h
index 86bd42e..a5b738b 100644
--- a/src/remoteobjects/qremoteobjectsource.h
+++ b/src/remoteobjects/qremoteobjectsource.h
@@ -46,9 +46,11 @@
QT_BEGIN_NAMESPACE
+namespace QtPrivate {
+
//Based on compile time checks for static connect() from qobjectdefs_impl.h
template <class ObjectType, typename Func1, typename Func2>
-static inline int qtro_prop_index(Func1, Func2, const char *propName)
+static inline int qtro_property_index(Func1, Func2, const char *propName)
{
typedef QtPrivate::FunctionPointer<Func1> Type1;
typedef QtPrivate::FunctionPointer<Func2> Type2;
@@ -117,30 +119,52 @@ static inline int qtro_method_index(Func1, Func2, const char *methodName, int *c
QByteArray qtro_classinfo_signature(const QMetaObject *metaObject);
+}
+
class QRemoteObjectHostBase;
+class QAbstractItemModel;
+
+struct ModelInfo
+{
+ QAbstractItemModel *ptr;
+ QString name;
+ QByteArray roles;
+};
+
+struct SubclassInfo
+{
+ QObject *ptr;
+ QString name;
+};
+
class SourceApiMap
{
protected:
SourceApiMap() {}
+ QVector<ModelInfo> m_models;
+ QVector<SubclassInfo> m_subclasses;
public:
virtual ~SourceApiMap() {}
virtual QString name() const = 0;
virtual QString typeName() const = 0;
+ virtual int enumCount() const = 0;
virtual int propertyCount() const = 0;
virtual int signalCount() const = 0;
virtual int methodCount() const = 0;
- virtual int modelCount() const { return 0; }
+ virtual int sourceEnumIndex(int index) const = 0;
virtual int sourcePropertyIndex(int index) const = 0;
virtual int sourceSignalIndex(int index) const = 0;
virtual int sourceMethodIndex(int index) const = 0;
virtual int signalParameterCount(int index) const = 0;
virtual int signalParameterType(int sigIndex, int paramIndex) const = 0;
virtual const QByteArray signalSignature(int index) const = 0;
+ virtual QList<QByteArray> signalParameterNames(int index) const = 0;
virtual int methodParameterCount(int index) const = 0;
virtual int methodParameterType(int methodIndex, int paramIndex) const = 0;
virtual const QByteArray methodSignature(int index) const = 0;
virtual QMetaMethod::MethodType methodType(int index) const = 0;
virtual const QByteArray typeName(int index) const = 0;
+ virtual QList<QByteArray> methodParameterNames(int index) const = 0;
virtual int propertyIndexFromSignal(int index) const = 0;
virtual int propertyRawIndexFromSignal(int index) const = 0;
virtual QByteArray objectSignature() const = 0;
@@ -148,7 +172,7 @@ public:
virtual bool isAdapterSignal(int) const { return false; }
virtual bool isAdapterMethod(int) const { return false; }
virtual bool isAdapterProperty(int) const { return false; }
- virtual void modelSetup(QRemoteObjectHostBase *) const { }
+ void qobjectSetup(QRemoteObjectHostBase *node) const;
};
QT_END_NAMESPACE
diff --git a/src/remoteobjects/qremoteobjectsource_p.h b/src/remoteobjects/qremoteobjectsource_p.h
index 3713f54..2e6d83f 100644
--- a/src/remoteobjects/qremoteobjectsource_p.h
+++ b/src/remoteobjects/qremoteobjectsource_p.h
@@ -69,9 +69,9 @@ public:
explicit QRemoteObjectSource(QObject *object, const SourceApiMap *,
QObject *adapter, QRemoteObjectSourceIo *sourceIo);
- ~QRemoteObjectSource();
+ ~QRemoteObjectSource() override;
- int qt_metacall(QMetaObject::Call call, int methodId, void **a);
+ int qt_metacall(QMetaObject::Call call, int methodId, void **a) override;
QVector<ServerIoDevice*> listeners;
QObject *m_object, *m_adapter;
const SourceApiMap * const m_api;
@@ -93,13 +93,20 @@ public:
class DynamicApiMap : public SourceApiMap
{
public:
- DynamicApiMap(const QMetaObject *metaObject, const QString &name, const QString &typeName);
- ~DynamicApiMap() {}
+ DynamicApiMap(QObject *object, const QMetaObject *metaObject, const QString &name, const QString &typeName);
+ ~DynamicApiMap() override {}
QString name() const override { return m_name; }
QString typeName() const override { return m_typeName; }
+ int enumCount() const override { return m_enumCount; }
int propertyCount() const override { return m_properties.size(); }
int signalCount() const override { return m_signals.size(); }
int methodCount() const override { return m_methods.size(); }
+ int sourceEnumIndex(int index) const override
+ {
+ if (index < 0 || index >= enumCount())
+ return -1;
+ return m_enumOffset + index;
+ }
int sourcePropertyIndex(int index) const override
{
if (index < 0 || index >= propertyCount())
@@ -121,11 +128,15 @@ public:
int signalParameterCount(int index) const override { return parameterCount(m_signals.at(index)); }
int signalParameterType(int sigIndex, int paramIndex) const override { return parameterType(m_signals.at(sigIndex), paramIndex); }
const QByteArray signalSignature(int index) const override { return signature(m_signals.at(index)); }
+ QList<QByteArray> signalParameterNames(int index) const override;
+
int methodParameterCount(int index) const override { return parameterCount(m_methods.at(index)); }
int methodParameterType(int methodIndex, int paramIndex) const override { return parameterType(m_methods.at(methodIndex), paramIndex); }
const QByteArray methodSignature(int index) const override { return signature(m_methods.at(index)); }
QMetaMethod::MethodType methodType(int index) const override;
const QByteArray typeName(int index) const override;
+ QList<QByteArray> methodParameterNames(int index) const override;
+
int propertyIndexFromSignal(int index) const override
{
if (index >= 0 && index < m_propertyAssociatedWithSignal.size())
@@ -155,6 +166,8 @@ private:
QString m_name;
QString m_typeName;
+ int m_enumCount;
+ int m_enumOffset;
QVector<int> m_properties;
QVector<int> m_signals;
QVector<int> m_methods;
diff --git a/src/remoteobjects/qremoteobjectsourceio.cpp b/src/remoteobjects/qremoteobjectsourceio.cpp
index 17a6638..2c13f4a 100644
--- a/src/remoteobjects/qremoteobjectsourceio.cpp
+++ b/src/remoteobjects/qremoteobjectsourceio.cpp
@@ -66,8 +66,6 @@ QRemoteObjectSourceIo::QRemoteObjectSourceIo(const QUrl &address, QObject *paren
}
connect(m_server.data(), &QConnectionAbstractServer::newConnection, this, &QRemoteObjectSourceIo::handleConnection);
- connect(&m_serverDelete, static_cast<void (QSignalMapper::*)(QObject *)>(&QSignalMapper::mapped), this, &QRemoteObjectSourceIo::onServerDisconnect);
- connect(&m_serverRead, static_cast<void (QSignalMapper::*)(QObject *)>(&QSignalMapper::mapped), this, &QRemoteObjectSourceIo::onServerRead);
}
QRemoteObjectSourceIo::~QRemoteObjectSourceIo()
@@ -75,17 +73,18 @@ QRemoteObjectSourceIo::~QRemoteObjectSourceIo()
qDeleteAll(m_remoteObjects.values());
}
-bool QRemoteObjectSourceIo::enableRemoting(QObject *object, const QMetaObject *meta, const QString &name, const QString &typeName)
+bool QRemoteObjectSourceIo::enableRemoting(QObject *object, const QMetaObject *meta, const QString &name,
+ const QString &typeName, QRemoteObjectHostBase *node)
{
if (m_remoteObjects.contains(name)) {
qROWarning(this) << "Tried to register QRemoteObjectSource twice" << name;
return false;
}
- return enableRemoting(object, new DynamicApiMap(meta, name, typeName));
+ return enableRemoting(object, new DynamicApiMap(object, meta, name, typeName), node);
}
-bool QRemoteObjectSourceIo::enableRemoting(QObject *object, const SourceApiMap *api, QObject *adapter)
+bool QRemoteObjectSourceIo::enableRemoting(QObject *object, const SourceApiMap *api, QRemoteObjectHostBase *node, QObject *adapter)
{
const QString name = api->name();
if (!api->isDynamic() && m_remoteObjects.contains(name)) {
@@ -93,6 +92,8 @@ bool QRemoteObjectSourceIo::enableRemoting(QObject *object, const SourceApiMap *
return false;
}
+ api->qobjectSetup(node);
+
new QRemoteObjectSource(object, api, adapter, this);
QRemoteObjectPackets::serializeObjectListPacket(m_packet, {QRemoteObjectPackets::ObjectInfo{api->name(), api->typeName(), api->objectSignature()}});
foreach (ServerIoDevice *conn, m_connections)
@@ -164,6 +165,10 @@ void QRemoteObjectSourceIo::onServerRead(QObject *conn)
using namespace QRemoteObjectPackets;
switch (packetType) {
+ case Ping:
+ serializePongPacket(m_packet, m_rxName);
+ connection->write(m_packet.array, m_packet.size);
+ break;
case AddObject:
{
bool isDynamic;
@@ -250,10 +255,15 @@ void QRemoteObjectSourceIo::handleConnection()
ServerIoDevice *conn = m_server->nextPendingConnection();
m_connections.insert(conn);
- connect(conn, SIGNAL(disconnected()), &m_serverDelete, SLOT(map()));
- m_serverDelete.setMapping(conn, conn);
- connect(conn, SIGNAL(readyRead()), &m_serverRead, SLOT(map()));
- m_serverRead.setMapping(conn, conn);
+ connect(conn, &ServerIoDevice::disconnected, this, [this, conn]() {
+ onServerDisconnect(conn);
+ });
+ connect(conn, &ServerIoDevice::readyRead, this, [this, conn]() {
+ onServerRead(conn);
+ });
+
+ serializeHandshakePacket(m_packet);
+ conn->write(m_packet.array, m_packet.size);
QRemoteObjectPackets::ObjectInfoList infos;
foreach (auto remoteObject, m_remoteObjects) {
diff --git a/src/remoteobjects/qremoteobjectsourceio_p.h b/src/remoteobjects/qremoteobjectsourceio_p.h
index b3045cd..5cadfc1 100644
--- a/src/remoteobjects/qremoteobjectsourceio_p.h
+++ b/src/remoteobjects/qremoteobjectsourceio_p.h
@@ -51,28 +51,30 @@
// We mean it.
//
-#include "qconnectionfactories.h"
+#include "qconnectionfactories_p.h"
#include "qtremoteobjectglobal.h"
#include "qremoteobjectpacket_p.h"
#include <QIODevice>
#include <QScopedPointer>
-#include <QSignalMapper>
QT_BEGIN_NAMESPACE
class QRemoteObjectSource;
class SourceApiMap;
+class QRemoteObjectHostBase;
class QRemoteObjectSourceIo : public QObject
{
Q_OBJECT
public:
explicit QRemoteObjectSourceIo(const QUrl &address, QObject *parent = nullptr);
- ~QRemoteObjectSourceIo();
+ ~QRemoteObjectSourceIo() override;
- bool enableRemoting(QObject *object, const QMetaObject *meta, const QString &name, const QString &typeName);
- bool enableRemoting(QObject *object, const SourceApiMap *api, QObject *adapter = nullptr);
+ bool enableRemoting(QObject *object, const QMetaObject *meta, const QString &name,
+ const QString &typeName, QRemoteObjectHostBase *node);
+ bool enableRemoting(QObject *object, const SourceApiMap *api, QRemoteObjectHostBase *node,
+ QObject *adapter = nullptr);
bool disableRemoting(QObject *object);
QUrl serverAddress() const;
@@ -95,8 +97,6 @@ public:
QSet<ServerIoDevice*> m_connections;
QHash<QObject *, QRemoteObjectSource*> m_objectToSourceMap;
QMap<QString, QRemoteObjectSource*> m_remoteObjects;
- QSignalMapper m_serverDelete;
- QSignalMapper m_serverRead;
QHash<ServerIoDevice*, QUrl> m_registryMapping;
QScopedPointer<QConnectionAbstractServer> m_server;
QRemoteObjectPackets::DataStreamPacket m_packet;
diff --git a/src/remoteobjects/qtremoteobjectglobal.h b/src/remoteobjects/qtremoteobjectglobal.h
index b08f1f7..69ba108 100644
--- a/src/remoteobjects/qtremoteobjectglobal.h
+++ b/src/remoteobjects/qtremoteobjectglobal.h
@@ -130,6 +130,8 @@ Q_DECLARE_LOGGING_CATEGORY(QT_REMOTEOBJECT_IO)
namespace QtRemoteObjects {
+Q_NAMESPACE
+
Q_REMOTEOBJECTS_EXPORT void copyStoredProperties(const QMetaObject *mo, const void *src, void *dst);
Q_REMOTEOBJECTS_EXPORT void copyStoredProperties(const QMetaObject *mo, const void *src, QDataStream &dst);
Q_REMOTEOBJECTS_EXPORT void copyStoredProperties(const QMetaObject *mo, QDataStream &src, void *dst);
@@ -155,6 +157,7 @@ void copyStoredProperties(QDataStream &src, T *dst)
enum QRemoteObjectPacketTypeEnum
{
Invalid = 0,
+ Handshake,
InitPacket,
InitDynamicPacket,
AddObject,
@@ -162,8 +165,16 @@ enum QRemoteObjectPacketTypeEnum
InvokePacket,
InvokeReplyPacket,
PropertyChangePacket,
- ObjectList
+ ObjectList,
+ Ping,
+ Pong
+};
+
+enum InitialAction {
+ FetchRootSize,
+ PrefetchData
};
+Q_ENUM_NS(InitialAction)
}
diff --git a/src/remoteobjects/remoteobjects.pro b/src/remoteobjects/remoteobjects.pro
index 9fb658a..f170afc 100644
--- a/src/remoteobjects/remoteobjects.pro
+++ b/src/remoteobjects/remoteobjects.pro
@@ -5,11 +5,12 @@ QT += network core-private
QT -= gui
QMAKE_DOCS = $$PWD/doc/qtremoteobjects.qdocconf
-OTHER_FILES += $$PWD/doc/qtremoteobjects.qdocconf \
- $$PWD/doc/src/remoteobjects-cpp.qdoc \
- $$PWD/doc/src/remoteobjects-index.qdoc \
- $$PWD/doc/src/remoteobjects-overview.qdoc \
- $$PWD/doc/src/remoteobjects-repc.qdoc
+OTHER_FILES += \
+ $$PWD/doc/qtremoteobjects.qdocconf \
+ $$PWD/doc/src/remoteobjects-cpp.qdoc \
+ $$PWD/doc/src/remoteobjects-index.qdoc \
+ $$PWD/doc/src/remoteobjects-overview.qdoc \
+ $$PWD/doc/src/remoteobjects-repc.qdoc \
load(qt_module)
@@ -18,48 +19,49 @@ DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII QT_NO_CAST_FROM_BYTEARRAY Q
INCLUDEPATH *= .
PUBLIC_HEADERS += \
- $$PWD/qconnectionfactories.h \
+ $$PWD/qremoteobjectabstractitemmodelreplica.h \
+ $$PWD/qremoteobjectabstractitemmodeltypes.h \
$$PWD/qremoteobjectdynamicreplica.h \
- $$PWD/qremoteobjectsource.h \
- $$PWD/qremoteobjectreplica.h \
$$PWD/qremoteobjectnode.h \
$$PWD/qremoteobjectpendingcall.h \
- $$PWD/qtremoteobjectglobal.h \
$$PWD/qremoteobjectregistry.h \
- $$PWD/qremoteobjectabstractitemmodeltypes.h \
- $$PWD/qremoteobjectabstractitemmodelreplica.h
+ $$PWD/qremoteobjectreplica.h \
+ $$PWD/qremoteobjectsource.h \
+ $$PWD/qtremoteobjectglobal.h \
PRIVATE_HEADERS += \
$$PWD/qconnectionfactories_p.h \
$$PWD/qconnection_local_backend_p.h \
$$PWD/qconnection_tcpip_backend_p.h \
- $$PWD/qremoteobjectsourceio_p.h \
- $$PWD/qremoteobjectsource_p.h \
- $$PWD/qremoteobjectregistrysource_p.h \
+ $$PWD/qremoteobjectabstractitemmodeladapter_p.h \
+ $$PWD/qremoteobjectabstractitemmodelreplica_p.h \
$$PWD/qremoteobjectnode_p.h \
$$PWD/qremoteobjectpacket_p.h \
$$PWD/qremoteobjectpendingcall_p.h \
+ $$PWD/qremoteobjectregistrysource_p.h \
$$PWD/qremoteobjectreplica_p.h \
- $$PWD/qremoteobjectabstractitemmodelreplica_p.h \
- $$PWD/qremoteobjectabstractitemmodeladapter_p.h
+ $$PWD/qremoteobjectsettingsstore.h \
+ $$PWD/qremoteobjectsourceio_p.h \
+ $$PWD/qremoteobjectsource_p.h \
SOURCES += \
+ $$PWD/qconnectionfactories.cpp \
$$PWD/qconnection_local_backend.cpp \
$$PWD/qconnection_tcpip_backend.cpp \
- $$PWD/qconnectionfactories.cpp \
+ $$PWD/qremoteobjectabstractitemmodeladapter.cpp \
+ $$PWD/qremoteobjectabstractitemmodelreplica.cpp \
$$PWD/qremoteobjectdynamicreplica.cpp \
- $$PWD/qremoteobjectsource.cpp \
- $$PWD/qremoteobjectsourceio.cpp \
- $$PWD/qremoteobjectregistry.cpp \
- $$PWD/qremoteobjectregistrysource.cpp \
- $$PWD/qremoteobjectreplica.cpp \
$$PWD/qremoteobjectnode.cpp \
$$PWD/qremoteobjectpacket.cpp \
$$PWD/qremoteobjectpendingcall.cpp \
+ $$PWD/qremoteobjectregistry.cpp \
+ $$PWD/qremoteobjectregistrysource.cpp \
+ $$PWD/qremoteobjectreplica.cpp \
+ $$PWD/qremoteobjectsettingsstore.cpp \
+ $$PWD/qremoteobjectsource.cpp \
+ $$PWD/qremoteobjectsourceio.cpp \
$$PWD/qtremoteobjectglobal.cpp \
- $$PWD/qremoteobjectabstractitemmodelreplica.cpp \
- $$PWD/qremoteobjectabstractitemmodeladapter.cpp
qnx {
SOURCES += \
@@ -73,9 +75,9 @@ qnx {
PRIVATE_HEADERS +=\
qconnection_qnx_backend_p.h \
+ qconnection_qnx_global_p.h \
qconnection_qnx_qiodevices_p.h \
qconnection_qnx_server_p.h \
- qconnection_qnx_global_p.h \
contains(DEFINES , USE_HAM) {
LIBS += -lham
diff --git a/src/repparser/parser.g b/src/repparser/parser.g
index 07ace85..6736b67 100644
--- a/src/repparser/parser.g
+++ b/src/repparser/parser.g
@@ -52,6 +52,7 @@
%token signal "[signal][ \\t]*SIGNAL[ \\t]*\\([ \\t]*(?<name>\\S+)[ \\t]*\\((?<args>[^\\)]*)\\)[ \\t]*\\);?[ \\t]*"
%token slot "[slot][ \\t]*SLOT[ \\t]*\\((?<type>[^\\(]*)\\((?<args>[^\\)]*)\\)[ \\t]*\\);?[ \\t]*"
%token model "[model][ \\t]*MODEL[ \\t]+(?<name>[A-Za-z_][A-Za-z0-9_]+)\\((?<args>[^\\)]+)\\)[ \\t]*;?[ \\t]*"
+%token childrep "[childrep][ \\t]*CLASS[ \\t]+(?<name>[A-Za-z_][A-Za-z0-9_]+)\\((?<type>[^\\)]+)\\)[ \\t]*;?[ \\t]*"
%token start "[start]\\{[ \\t]*"
%token stop "[stop]\\};?[ \\t]*"
%token comma "[comma],"
@@ -184,6 +185,16 @@ struct ASTModel
};
Q_DECLARE_TYPEINFO(ASTModel, Q_MOVABLE_TYPE);
+struct ASTChildRep
+{
+ explicit ASTChildRep(const QString &name = QString(),
+ const QString &type = QString());
+
+ QString name;
+ QString type;
+};
+Q_DECLARE_TYPEINFO(ASTChildRep, Q_MOVABLE_TYPE);
+
/// A Class declaration
struct ASTClass
{
@@ -198,6 +209,7 @@ struct ASTClass
QVector<ASTEnum> enums;
bool hasPersisted;
QVector<ASTModel> models;
+ QVector<ASTChildRep> children;
};
Q_DECLARE_TYPEINFO(ASTClass, Q_MOVABLE_TYPE);
@@ -238,9 +250,9 @@ public:
explicit RepParser(QIODevice &outputDevice);
virtual ~RepParser() {}
- bool parse() Q_DECL_OVERRIDE { return QRegexParser<RepParser, $table>::parse(); }
+ bool parse() override { return QRegexParser<RepParser, $table>::parse(); }
- void reset() Q_DECL_OVERRIDE;
+ void reset() override;
int nextToken();
bool consumeRule(int ruleno);
@@ -380,6 +392,11 @@ ASTModel::ASTModel(const QString &name)
{
}
+ASTChildRep::ASTChildRep(const QString &name, const QString &type)
+ : name(name), type(type)
+{
+}
+
ASTClass::ASTClass(const QString &name)
: name(name), hasPersisted(false)
{
@@ -701,7 +718,7 @@ Class: ClassStart Start Stop;
./
ClassTypes: ClassType | ClassType ClassTypes;
-ClassType: DecoratedProp | DecoratedSignal | DecoratedSlot | DecoratedModel;
+ClassType: DecoratedProp | DecoratedSignal | DecoratedSlot | DecoratedModel | DecoratedClass;
ClassType: Enum;
/.
case $rule_number:
@@ -715,6 +732,7 @@ DecoratedSlot: Slot | Comments Slot | Slot Newlines | Comments Slot Newlines;
DecoratedSignal: Signal | Comments Signal | Signal Newlines | Comments Signal Newlines;
DecoratedProp: Prop | Comments Prop | Prop Newlines | Comments Prop Newlines;
DecoratedModel: Model | Comments Model | Model Newlines | Comments Model Newlines;
+DecoratedClass: ChildRep | Comments ChildRep | ChildRep Newlines | Comments ChildRep Newlines;
DecoratedEnumParam: EnumParam | Comments EnumParam | EnumParam Newlines | Comments EnumParam Newlines;
Start: start | Comments start | start Newlines | Comments start Newlines;
@@ -835,6 +853,19 @@ Model: model;
break;
./
+ChildRep: childrep;
+/.
+case $rule_number:
+{
+ ASTChildRep child;
+ child.name = captured().value(QLatin1String("name")).trimmed();
+ child.type = captured().value(QLatin1String("type")).trimmed();
+
+ m_astClass.children << child;
+}
+break;
+./
+
ClassStart: class Newlines;
/.
case $rule_number:
@@ -927,6 +958,16 @@ Type: Model;
break;
./
+Type: ChildRep;
+/.
+ case $rule_number:
+ {
+ setErrorString(QStringLiteral("CLASS: Can only be used in class scope"));
+ return false;
+ }
+ break;
+./
+
/.
} // switch
return true;
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 9f4646a..a1bc76a 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -7,11 +7,18 @@ sub_integration.subdir = integration
sub_integration.target = sub-integration
sub_integration.depends = sub-localsockettestserver
-SUBDIRS += benchmarks repc sub_integration modelview cmake pods repcodegenerator repparser \
- sub_localsockettestserver \
- modelreplica
+SUBDIRS += \
+ benchmarks \
+ cmake \
+ modelreplica \
+ modelview \
+ pods \
+ repc \
+ repcodegenerator \
+ repparser \
+ subclassreplica \
+ sub_integration \
+ sub_localsockettestserver
+qtHaveModule(qml): SUBDIRS += qml
qtConfig(process): SUBDIRS += integration_multiprocess
-
-# QTBUG-60268
-boot2qt: SUBDIRS -= sub_integration modelview
diff --git a/tests/auto/benchmarks/tst_benchmarkstest.cpp b/tests/auto/benchmarks/tst_benchmarkstest.cpp
index f1182da..9c6a1dd 100644
--- a/tests/auto/benchmarks/tst_benchmarkstest.cpp
+++ b/tests/auto/benchmarks/tst_benchmarkstest.cpp
@@ -285,7 +285,7 @@ void BenchmarksTest::benchModelLinearAccess()
loop.quit();
});
- auto beginBenchmark = [&model, &loop, &dataToWait] {
+ auto beginBenchmark = [&model, &dataToWait] {
for (int row = 0; row < 1000; ++row) {
if (row >= 950)
dataToWait.insert(row, QPair<QString, QString>());
@@ -357,7 +357,7 @@ void BenchmarksTest::benchModelRandomAccess()
loop.quit();
});
- auto beginBenchmark = [&model, &loop, &dataToWait] {
+ auto beginBenchmark = [&model, &dataToWait] {
for (int chunck = 0; chunck < 100; ++chunck) {
int row = chunck * 950;
for (int r = 0; r < 50; ++r) {
diff --git a/tests/auto/integration/engine.h b/tests/auto/integration/engine.h
index 9e5c976..7252f38 100644
--- a/tests/auto/integration/engine.h
+++ b/tests/auto/integration/engine.h
@@ -38,7 +38,7 @@ class Engine : public EngineSimpleSource
public:
Engine(QObject *parent = nullptr);
- virtual ~Engine();
+ ~Engine() override;
bool start() override;
void increaseRpm(int deltaRpm) override;
diff --git a/tests/auto/integration/integration.pro b/tests/auto/integration/integration.pro
index 601d9ad..d241f67 100644
--- a/tests/auto/integration/integration.pro
+++ b/tests/auto/integration/integration.pro
@@ -6,3 +6,6 @@ qnx: SUBDIRS += qnx
local.path = local
tcp.path = tcp
qnx.path = qnx
+
+# QTBUG-61552
+boot2qt: SUBDIRS -= local
diff --git a/tests/auto/integration/local/local.pro b/tests/auto/integration/local/local.pro
index fd1fd66..19f5a41 100644
--- a/tests/auto/integration/local/local.pro
+++ b/tests/auto/integration/local/local.pro
@@ -1,9 +1,6 @@
DEFINES += BACKEND=\\\"local\\\"
DEFINES += HOST_URL=\\\"local:replica_local_integration\\\"
DEFINES += REGISTRY_URL=\\\"local:registry_local_integration\\\"
-CONFIG += testcase
TARGET = tst_integration_local
-QT += testlib remoteobjects
-QT -= gui
include(../template.pri)
diff --git a/tests/auto/integration/qnx/qnx.pro b/tests/auto/integration/qnx/qnx.pro
index d5109ed..c44ed8a 100644
--- a/tests/auto/integration/qnx/qnx.pro
+++ b/tests/auto/integration/qnx/qnx.pro
@@ -1,9 +1,6 @@
DEFINES += BACKEND=\\\"qnx\\\"
DEFINES += HOST_URL=\\\"qnx:replica\\\"
DEFINES += REGISTRY_URL=\\\"qnx:registry\\\"
-CONFIG += testcase
TARGET = tst_integration_qnx
-QT += testlib remoteobjects
-QT -= gui
include(../template.pri)
diff --git a/tests/auto/integration/speedometer.h b/tests/auto/integration/speedometer.h
index a488cc8..7514e12 100644
--- a/tests/auto/integration/speedometer.h
+++ b/tests/auto/integration/speedometer.h
@@ -36,7 +36,7 @@ class Speedometer : public SpeedometerSimpleSource
Q_OBJECT
public:
Speedometer(QObject *parent = nullptr);
- virtual ~Speedometer();
+ ~Speedometer() override;
private:
int speed;
diff --git a/tests/auto/integration/tcp/tcp.pro b/tests/auto/integration/tcp/tcp.pro
index 1d0e003..3ebb6f9 100644
--- a/tests/auto/integration/tcp/tcp.pro
+++ b/tests/auto/integration/tcp/tcp.pro
@@ -1,9 +1,6 @@
DEFINES += BACKEND=\\\"tcp\\\"
DEFINES += HOST_URL=\\\"tcp://127.0.0.1:65511\\\"
DEFINES += REGISTRY_URL=\\\"tcp://127.0.0.1:65512\\\"
-CONFIG += testcase
TARGET = tst_integration_tcp
-QT += testlib remoteobjects
-QT -= gui
include(../template.pri)
diff --git a/tests/auto/integration/template.pri b/tests/auto/integration/template.pri
index 08c2d52..48f940e 100644
--- a/tests/auto/integration/template.pri
+++ b/tests/auto/integration/template.pri
@@ -19,4 +19,8 @@ SOURCES += $$PWD/engine.cpp \
$$PWD/speedometer.cpp \
$$PWD/tst_integration.cpp
+CONFIG += testcase
+QT += testlib remoteobjects
+QT -= gui
+
contains(QT_CONFIG, c++11): CONFIG += c++11
diff --git a/tests/auto/integration/tst_integration.cpp b/tests/auto/integration/tst_integration.cpp
index f5c7b99..2112bfd 100644
--- a/tests/auto/integration/tst_integration.cpp
+++ b/tests/auto/integration/tst_integration.cpp
@@ -26,12 +26,17 @@
**
****************************************************************************/
+#include "../../shared/testutils.h"
+
#include <QtTest/QtTest>
#include <QMetaType>
#include <QProcess>
#include <QFileInfo>
-#include <qremoteobjectreplica.h>
+
+#include <QRemoteObjectReplica>
#include <QRemoteObjectNode>
+#include <QRemoteObjectSettingsStore>
+
#include "engine.h"
#include "speedometer.h"
#include "rep_engine_replica.h"
@@ -66,14 +71,27 @@ Q_SIGNALS:
void send(const QByteArray &data);
};
-class TestDynamic : public QObject
+class TestDynamicBase : public QObject
+{
+ Q_OBJECT
+public:
+ TestDynamicBase(QObject *parent=nullptr) : QObject(parent) {}
+
+signals:
+ void otherValueChanged();
+};
+
+
+class TestDynamic : public TestDynamicBase
{
Q_OBJECT
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
+ Q_PROPERTY(int otherValue READ otherValue WRITE setOtherValue NOTIFY otherValueChanged)
public:
TestDynamic(QObject *parent=nullptr) :
- QObject(parent),
- m_value(0) {}
+ TestDynamicBase(parent),
+ m_value(0),
+ m_otherValue(0) {}
int value() const { return m_value; }
void setValue(int value)
@@ -85,17 +103,30 @@ public:
emit valueChanged();
}
+ int otherValue() const { return m_otherValue; }
+ void setOtherValue(int otherValue)
+ {
+ if (m_otherValue == otherValue)
+ return;
+
+ m_otherValue = otherValue;
+ emit otherValueChanged();
+ }
+
signals:
void valueChanged();
private:
int m_value;
+ int m_otherValue;
};
-class Persist : public QRemoteObjectPersistedStore
+class TestPersistedStore : public QRemoteObjectAbstractPersistedStore
{
+ Q_OBJECT
+
public:
- Persist() : type(EngineReplica::HYBRID) {}
+ TestPersistedStore() : type(EngineReplica::HYBRID) {}
void saveProperties(const QString &, const QByteArray &, const QVariantList &values) override
{
type = values.at(0).value<EngineReplica::EngineType>();
@@ -104,6 +135,7 @@ public:
{
return QVariantList() << QVariant::fromValue(type);
}
+private:
EngineReplica::EngineType type;
};
@@ -119,6 +151,10 @@ private slots:
{
QLoggingCategory::setFilterRules("qt.remoteobjects.warning=false");
+ // use different paths in QRemoteObjectSettingsStore
+ QCoreApplication::setOrganizationName(QLatin1String("QtProject"));
+ QStandardPaths::setTestModeEnabled(true);
+
qDebug() << "Running tst_Integration for backend:" << BACKEND;
}
@@ -150,7 +186,8 @@ private slots:
QRemoteObjectNode client;
client.connectToNode(hostUrl);
Q_SET_OBJECT_NAME(client);
- client.setPersistedStore(new Persist, QRemoteObjectNode::PassOwnershipToNode);
+ TestPersistedStore store;
+ client.setPersistedStore(&store);
const QScopedPointer<EngineReplica> engine_r(client.acquire<EngineReplica>());
QCOMPARE(engine_r->engineType(), EngineReplica::HYBRID);
@@ -158,7 +195,7 @@ private slots:
void persistTest()
{
- Persist persist;
+ QRemoteObjectSettingsStore store;
QRemoteObjectHost host(hostUrl);
SET_NODE_NAME(host);
@@ -169,7 +206,7 @@ private slots:
QRemoteObjectNode client;
client.connectToNode(hostUrl);
Q_SET_OBJECT_NAME(client);
- client.setPersistedStore(&persist);
+ client.setPersistedStore(&store);
QScopedPointer<EngineReplica> engine_r(client.acquire<EngineReplica>());
engine_r->waitForSource();
@@ -1026,6 +1063,22 @@ private slots:
replica->setProperty("value", 2);
QTRY_COMPARE(replica->property("value"), QVariant(2));
QCOMPARE(source.value(), 2);
+
+ // test parent NOTIFY
+ QSignalSpy otherSpy(replica.data(), SIGNAL(otherValueChanged()));
+
+ const int baseSignalIndex = metaObject->indexOfSignal("otherValueChanged()");
+ QVERIFY(baseSignalIndex != -1);
+
+ // replica gets source change
+ source.setOtherValue(1);
+ QTRY_COMPARE(otherSpy.count(), 1);
+ QCOMPARE(replica->property("otherValue"), QVariant(1));
+
+ // source gets replica change
+ replica->setProperty("otherValue", 2);
+ QTRY_COMPARE(replica->property("otherValue"), QVariant(2));
+ QCOMPARE(source.otherValue(), 2);
}
void dynamicReplicaTest()
@@ -1211,8 +1264,10 @@ private slots:
#ifdef Q_OS_LINUX
void localServerConnectionTest()
{
- QProcess testServer;
- const QString progName = QStringLiteral("../../localsockettestserver/localsockettestserver");
+ const auto progName = TestUtils::findExecutable("localsockettestserver", {
+ QCoreApplication::applicationDirPath() + "/../../localsockettestserver"
+ });
+
//create a fake socket as killing doesn't produce a necessarily unusable socket
QFile fake(QDir::temp().absoluteFilePath(QStringLiteral("crashMe")));
fake.remove();
@@ -1228,6 +1283,7 @@ private slots:
QScopedPointer<QRemoteObjectDynamicReplica> replica;
replica.reset(localSocketTestClient.acquireDynamic(objectname));
+ QProcess testServer;
testServer.start(progName);
QVERIFY(testServer.waitForStarted());
QVERIFY(localSocketTestClient.lastError() == QRemoteObjectNode::NoError);
@@ -1239,9 +1295,11 @@ private slots:
// Tests to take over an existing socket if its still valid
void localServerConnectionTest2()
{
- QProcess testServer;
- const QString progName = QStringLiteral("../../localsockettestserver/localsockettestserver");
+ const auto progName = TestUtils::findExecutable("localsockettestserver", {
+ QCoreApplication::applicationDirPath() + "/../../localsockettestserver"
+ });
+ QProcess testServer;
testServer.start(progName);
QVERIFY(testServer.waitForStarted());
QFileInfo info(QDir::temp().absoluteFilePath(QStringLiteral("crashMe")));
diff --git a/tests/auto/integration_multiprocess/MyInterface.rep b/tests/auto/integration_multiprocess/MyInterface.rep
index 7c66879..fc6a565 100644
--- a/tests/auto/integration_multiprocess/MyInterface.rep
+++ b/tests/auto/integration_multiprocess/MyInterface.rep
@@ -3,12 +3,15 @@
class MyInterface
{
ENUM Enum1 { First, Second, Third }
- PROP(Enum1 enum1 = First)
+ PROP(Enum1 enum1 = First READWRITE)
PROP(bool started = false)
SLOT(bool start())
SLOT(bool stop())
+ SLOT(bool quit())
+ SLOT(void testEnumParamsInSlots(Enum1 enumSlotParam, bool slotParam2, int))
SIGNAL(advance())
+ SIGNAL(testEnumParamsInSignals(Enum1 enumSignalParam, bool signalParam2, QString))
};
diff --git a/tests/auto/integration_multiprocess/client/main.cpp b/tests/auto/integration_multiprocess/client/main.cpp
index 4e2ed1d..d2041be 100644
--- a/tests/auto/integration_multiprocess/client/main.cpp
+++ b/tests/auto/integration_multiprocess/client/main.cpp
@@ -37,34 +37,131 @@ class tst_Client_Process : public QObject
Q_OBJECT
private Q_SLOTS:
- void testRun()
+ void initTestCase()
{
- QRemoteObjectNode repNode;
- repNode.connectToNode(QUrl(QStringLiteral("tcp://127.0.0.1:65213")));
+ m_repNode.connectToNode(QUrl(QStringLiteral("tcp://127.0.0.1:65213")));
+ m_rep.reset(m_repNode.acquire<MyInterfaceReplica>());
+ QVERIFY(m_rep->waitForSource());
+ }
- QSharedPointer<MyInterfaceReplica> rep(repNode.acquire<MyInterfaceReplica>());
- QVERIFY(rep->waitForSource());
+ void testRun()
+ {
- auto reply = rep->start();
+ auto reply = m_rep->start();
QVERIFY(reply.waitForFinished());
// BEGIN: Testing
- QSignalSpy advanceSpy(rep.data(), SIGNAL(advance()));
+ QSignalSpy advanceSpy(m_rep.data(), SIGNAL(advance()));
- QSignalSpy spy(rep.data(), SIGNAL(enum1Changed(MyInterfaceReplica::Enum1)));
+ QSignalSpy spy(m_rep.data(), SIGNAL(enum1Changed(MyInterfaceReplica::Enum1)));
QVERIFY(advanceSpy.wait());
QCOMPARE(spy.count(), 2);
// END: Testing
- reply = rep->stop();
+ reply = m_rep->stop();
QVERIFY(reply.waitForFinished());
+ }
+
+ void testEnumDetails()
+ {
+ QHash<QByteArray, int> kvs = {{"First", 0}, {"Second", 1}, {"Third", 2}};
+ QScopedPointer<QRemoteObjectDynamicReplica> rep(m_repNode.acquireDynamic("MyInterface"));
+ QVERIFY(rep->waitForSource());
+
+ auto mo = rep->metaObject();
+ int enumIdx = mo->indexOfEnumerator("Enum1");
+ QVERIFY(enumIdx != -1);
+ auto enumerator = mo->enumerator(enumIdx);
+ QCOMPARE(enumerator.name(), "Enum1");
+ QCOMPARE(enumerator.keyCount(), 3);
+ for (int i = 0; i < 3; ++i) {
+ auto key = enumerator.key(i);
+ auto val = enumerator.value(i);
+ auto it = kvs.find(key);
+ QVERIFY(it != kvs.end());
+ QCOMPARE(*it, val);
+ kvs.erase(it);
+ }
+
+ int propIdx = mo->indexOfProperty("enum1");
+ QVERIFY(propIdx != -1);
+ auto property = mo->property(propIdx);
+ property.write(rep.data(), 1);
+ QTRY_COMPARE(property.read(rep.data()).toInt(), 1);
+ }
+
+ void testMethodSignalParamDetails()
+ {
+ QScopedPointer<QRemoteObjectDynamicReplica> rep(m_repNode.acquireDynamic("MyInterface"));
+ QVERIFY(rep->waitForSource());
- qDebug() << "Done. Shutting down.";
+ auto mo = rep->metaObject();
+ int signalIdx = mo->indexOfSignal("testEnumParamsInSignals(MyInterfaceReplica::Enum1,bool,QString)");
+ QVERIFY(signalIdx != -1);
+ auto simm = mo->method(signalIdx);
+ {
+ QCOMPARE(simm.parameterCount(), 3);
+ auto paramNames = simm.parameterNames();
+ QCOMPARE(paramNames.size(), 3);
+ QCOMPARE(paramNames.at(0), QByteArrayLiteral("enumSignalParam"));
+ QCOMPARE(paramNames.at(1), QByteArrayLiteral("signalParam2"));
+ QCOMPARE(paramNames.at(2), QByteArrayLiteral("__repc_variable_1"));
+ QCOMPARE(simm.parameterType(0), QMetaType::type("MyInterfaceReplica::Enum1"));
+ QCOMPARE(simm.parameterType(1), int(QMetaType::Bool));
+ QCOMPARE(simm.parameterType(2), int(QMetaType::QString));
+ }
- // wait for delivery of events
- QTest::qWait(200);
+ int slotIdx = mo->indexOfSlot("testEnumParamsInSlots(Enum1,bool,int)");
+ QVERIFY(slotIdx != -1);
+ auto slmm = mo->method(slotIdx);
+ {
+ QCOMPARE(slmm .parameterCount(), 3);
+ auto paramNames = slmm .parameterNames();
+ QCOMPARE(paramNames.size(), 3);
+ QCOMPARE(paramNames.at(0), QByteArrayLiteral("enumSlotParam"));
+ QCOMPARE(paramNames.at(1), QByteArrayLiteral("slotParam2"));
+ QCOMPARE(paramNames.at(2), QByteArrayLiteral("__repc_variable_1"));
+ }
+
+ int enumVal = 0;
+ mo->invokeMethod(rep.data(), "testEnumParamsInSlots",
+ QGenericArgument("Enum1", &enumVal),
+ Q_ARG(bool, true), Q_ARG(int, 1234));
+
+ int enumIdx = mo->indexOfProperty("enum1");
+ QVERIFY(enumIdx != -1);
+ QTRY_COMPARE(mo->property(enumIdx).read(rep.data()).toInt(), 0);
+
+ int startedIdx = mo->indexOfProperty("started");
+ QVERIFY(startedIdx != -1);
+ QTRY_COMPARE(mo->property(startedIdx).read(rep.data()).toBool(), true);
}
+
+ void testMethodSignal()
+ {
+ QScopedPointer<MyInterfaceReplica> rep(new MyInterfaceReplica());
+ rep->setNode(&m_repNode);
+ QVERIFY(rep->waitForSource());
+
+ rep->testEnumParamsInSlots(MyInterfaceReplica::Second, false, 74);
+
+ connect(rep.data(), &MyInterfaceReplica::testEnumParamsInSignals,
+ [](MyInterfaceReplica::Enum1 enumSignalParam) { QCOMPARE(enumSignalParam, MyInterfaceReplica::Second); });
+
+ QTRY_COMPARE(rep->enum1(), MyInterfaceReplica::Second);
+ QTRY_COMPARE(rep->started(), false);
+ }
+
+ void cleanupTestCase()
+ {
+ auto reply = m_rep->quit();
+ QVERIFY(reply.waitForFinished());
+ }
+
+private:
+ QRemoteObjectNode m_repNode;
+ QScopedPointer<MyInterfaceReplica> m_rep;
};
QTEST_MAIN(tst_Client_Process)
diff --git a/tests/auto/integration_multiprocess/server/main.cpp b/tests/auto/integration_multiprocess/server/main.cpp
index 7a2ec9f..d76cc11 100644
--- a/tests/auto/integration_multiprocess/server/main.cpp
+++ b/tests/auto/integration_multiprocess/server/main.cpp
@@ -40,8 +40,11 @@ private Q_SLOTS:
{
QRemoteObjectHost srcNode(QUrl(QStringLiteral("tcp://127.0.0.1:65213")));
MyTestServer myTestServer;
-
- srcNode.enableRemoting(&myTestServer);
+ bool templated = qEnvironmentVariableIsSet("TEMPLATED_REMOTING");
+ if (templated)
+ srcNode.enableRemoting<MyInterfaceSourceAPI>(&myTestServer);
+ else
+ srcNode.enableRemoting(&myTestServer);
qDebug() << "Waiting for incoming connections";
@@ -69,10 +72,15 @@ private Q_SLOTS:
QVERIFY(waitForStartedSpy.wait());
QCOMPARE(waitForStartedSpy.value(0).value(0).toBool(), false);
- qDebug() << "Done. Shutting down.";
+ // wait for quit
+ bool quit = false;
+ connect(&myTestServer, &MyTestServer::quitApp, [&quit]{quit = true;});
+ QTRY_VERIFY_WITH_TIMEOUT(quit, 5000);
// wait for delivery of events
QTest::qWait(200);
+
+ qDebug() << "Done. Shutting down.";
}
};
diff --git a/tests/auto/integration_multiprocess/server/mytestserver.cpp b/tests/auto/integration_multiprocess/server/mytestserver.cpp
index 6f37c94..94983d1 100644
--- a/tests/auto/integration_multiprocess/server/mytestserver.cpp
+++ b/tests/auto/integration_multiprocess/server/mytestserver.cpp
@@ -53,3 +53,16 @@ bool MyTestServer::stop()
setStarted(false);
return true;
}
+
+bool MyTestServer::quit()
+{
+ emit quitApp();
+ return true;
+}
+
+void MyTestServer::testEnumParamsInSlots(Enum1 enumSlotParam, bool slotParam2, int number)
+{
+ setEnum1(enumSlotParam);
+ setStarted(slotParam2);
+ emit testEnumParamsInSignals(enum1(), started(), QString::number(number));
+}
diff --git a/tests/auto/integration_multiprocess/server/mytestserver.h b/tests/auto/integration_multiprocess/server/mytestserver.h
index 3c64f8a..cbdd1c0 100644
--- a/tests/auto/integration_multiprocess/server/mytestserver.h
+++ b/tests/auto/integration_multiprocess/server/mytestserver.h
@@ -42,11 +42,16 @@ class MyTestServer : public MyInterfaceSimpleSource
public:
MyTestServer(QObject *parent = nullptr);
- ~MyTestServer();
+ ~MyTestServer() override;
public Q_SLOTS:
bool start() override;
bool stop() override;
+ bool quit() override;
+ void testEnumParamsInSlots(Enum1 enumSlotParam, bool slotParam2, int __repc_variable_1) override;
+
+Q_SIGNALS:
+ void quitApp();
};
#endif // MYTESTSERVER_H
diff --git a/tests/auto/integration_multiprocess/tst/tst_integration_multiprocess.cpp b/tests/auto/integration_multiprocess/tst/tst_integration_multiprocess.cpp
index e9cc316..fe5d929 100644
--- a/tests/auto/integration_multiprocess/tst/tst_integration_multiprocess.cpp
+++ b/tests/auto/integration_multiprocess/tst/tst_integration_multiprocess.cpp
@@ -62,11 +62,25 @@ private slots:
QTest::qWait(200);
}
+ void testRun_data()
+ {
+ QTest::addColumn<bool>("templated");
+ QTest::newRow("non-templated enableRemoting") << false;
+ QTest::newRow("templated enableRemoting") << true;
+ }
+
void testRun()
{
+ QFETCH(bool, templated);
+
qDebug() << "Starting server process";
QProcess serverProc;
serverProc.setProcessChannelMode(QProcess::ForwardedChannels);
+ if (templated) {
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ env.insert("TEMPLATED_REMOTING", "true");
+ serverProc.setProcessEnvironment(env);
+ }
serverProc.start(findExecutable("server", {
QCoreApplication::applicationDirPath() + "/../server/"
}));
diff --git a/tests/auto/modelreplica/tst_modelreplicatest.cpp b/tests/auto/modelreplica/tst_modelreplicatest.cpp
index fc70652..cd4292f 100644
--- a/tests/auto/modelreplica/tst_modelreplicatest.cpp
+++ b/tests/auto/modelreplica/tst_modelreplicatest.cpp
@@ -38,25 +38,38 @@ public:
ModelreplicaTest();
private Q_SLOTS:
- void testCase1();
+ void basicFunctions();
+ void basicFunctions_data();
};
ModelreplicaTest::ModelreplicaTest()
{
}
-void ModelreplicaTest::testCase1()
+void ModelreplicaTest::basicFunctions_data()
{
+ QTest::addColumn<bool>("templated");
+ QTest::newRow("non-templated enableRemoting") << false;
+ QTest::newRow("templated enableRemoting") << true;
+}
+
+void ModelreplicaTest::basicFunctions()
+{
+ QFETCH(bool, templated);
+
QRemoteObjectRegistryHost host(QUrl("tcp://localhost:5555"));
QStringListModel *model = new QStringListModel();
model->setStringList(QStringList() << "Track1" << "Track2" << "Track3");
MediaSimpleSource source(model);
- host.enableRemoting<MediaSourceAPI>(&source);
+ if (templated)
+ host.enableRemoting<MediaSourceAPI>(&source);
+ else
+ host.enableRemoting(&source);
QRemoteObjectNode client(QUrl("tcp://localhost:5555"));
const QScopedPointer<MediaReplica> replica(client.acquire<MediaReplica>());
QSignalSpy tracksSpy(replica->tracks(), &QAbstractItemModelReplica::initialized);
- QVERIFY2(replica->waitForSource(100), "Failure");
+ QVERIFY(replica->waitForSource(100));
QVERIFY(tracksSpy.wait());
// Rep file only uses display role
QCOMPARE(QVector<int>{Qt::DisplayRole}, replica->tracks()->availableRoles());
diff --git a/tests/auto/modelview/modelview.pro b/tests/auto/modelview/modelview.pro
index b89b500..b21c191 100644
--- a/tests/auto/modelview/modelview.pro
+++ b/tests/auto/modelview/modelview.pro
@@ -8,3 +8,4 @@ HEADERS += $$PWD/modeltest.h
contains(QT_CONFIG, c++11): CONFIG += c++11
+boot2qt: DEFINES += SLOW_MODELTEST
diff --git a/tests/auto/modelview/tst_modelview.cpp b/tests/auto/modelview/tst_modelview.cpp
index 071d164..29b1728 100644
--- a/tests/auto/modelview/tst_modelview.cpp
+++ b/tests/auto/modelview/tst_modelview.cpp
@@ -36,8 +36,7 @@
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include <QEventLoop>
-
-#include <cstdlib>
+#include <QRandomGenerator>
namespace {
@@ -401,7 +400,7 @@ QList<QStandardItem*> addChild(int numChilds, int nestingLevel)
int getRandomNumber(int min, int max)
{
- int res = std::rand();
+ int res = QRandomGenerator::global()->generate() & INT_MAX;
const int diff = (max - min);
res = res % diff;
res += min;
@@ -619,6 +618,9 @@ private slots:
void testSelectionFromReplica();
void testSelectionFromSource();
+ void testChildSelection();
+
+ void testCacheData();
void cleanup();
};
@@ -636,7 +638,8 @@ void TestModelView::initTestCase()
static const int modelSize = 20;
- QVector<int> roles = QVector<int>() << Qt::DisplayRole << Qt::BackgroundRole;
+ // QStandardItem::flags are stored as data with Qt::UserRole - 1
+ QVector<int> roles = QVector<int>() << Qt::DisplayRole << Qt::BackgroundRole << (Qt::UserRole - 1);
QHash<int,QByteArray> roleNames;
roleNames[Qt::DisplayRole] = "text";
@@ -650,7 +653,6 @@ void TestModelView::initTestCase()
hHeaderList << QStringLiteral("First Column with spacing") << QStringLiteral("Second Column with spacing");
m_sourceModel.setHorizontalHeaderLabels(hHeaderList);
- std::srand(0);
for (int i = 0; i < modelSize; ++i) {
QStandardItem *firstItem = new QStandardItem(QStringLiteral("FancyTextNumber %1").arg(i));
QStandardItem *secondItem = new QStandardItem(QStringLiteral("FancyRow2TextNumber %1").arg(i));
@@ -1066,6 +1068,12 @@ void TestModelView::testServerInsertDataTree()
compareData(&testTreeModel, model.data());
}
+#ifdef SLOW_MODELTEST
+#define MODELTEST_WAIT_TIME 15000
+#else
+#define MODELTEST_WAIT_TIME
+#endif
+
void TestModelView::testModelTest()
{
QScopedPointer<QAbstractItemModelReplica> repModel( m_client.acquireModel(QStringLiteral("test")));
@@ -1073,7 +1081,7 @@ void TestModelView::testModelTest()
FetchData f(repModel.data());
f.addAll();
- QVERIFY(f.fetchAndWait());
+ QVERIFY(f.fetchAndWait(MODELTEST_WAIT_TIME));
Q_UNUSED(test);
}
@@ -1211,6 +1219,44 @@ void TestModelView::testSelectionFromSource()
QTRY_COMPARE(replicaSelectionModel->currentIndex().row(), 1);
}
+void TestModelView::testCacheData()
+{
+ QVector<int> roles = QVector<int>() << Qt::UserRole << Qt::UserRole + 1;
+ QScopedPointer<QAbstractItemModelReplica> model(m_client.acquireModel("testRoleNames", QtRemoteObjects::PrefetchData, roles));
+ model->setRootCacheSize(1000);
+
+ QEventLoop l;
+ connect(model.data(), SIGNAL(initialized()), &l, SLOT(quit()));
+ l.exec();
+
+ compareData(&m_listModel, model.data());
+}
+
+void TestModelView::testChildSelection()
+{
+ QVector<int> roles = {Qt::DisplayRole, Qt::BackgroundRole};
+ QStandardItemModel simpleModel;
+ QStandardItem *parentItem = simpleModel.invisibleRootItem();
+ for (int i = 0; i < 4; ++i) {
+ QStandardItem *item = new QStandardItem(QString("item %0").arg(i));
+ parentItem->appendRow(item);
+ parentItem = item;
+ }
+ QItemSelectionModel selectionModel(&simpleModel);
+ m_basicServer.enableRemoting(&simpleModel, "treeModelFromSource", roles, &selectionModel);
+
+ QScopedPointer<QAbstractItemModelReplica> model(m_client.acquireModel("treeModelFromSource", QtRemoteObjects::PrefetchData, roles));
+ QItemSelectionModel *replicaSelectionModel = model->selectionModel();
+
+ QTRY_COMPARE(simpleModel.rowCount(), model->rowCount());
+ QTRY_COMPARE(model->data(model->index(0, 0)), QVariant(QString("item 0")));
+
+ // select an item not yet "seen" by the replica
+ selectionModel.setCurrentIndex(simpleModel.index(0, 0, simpleModel.index(0,0)), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Current);
+ QTRY_COMPARE(replicaSelectionModel->currentIndex().row(), 0);
+ QVERIFY(replicaSelectionModel->currentIndex().parent().isValid());
+}
+
void TestModelView::cleanup()
{
// wait for delivery of RemoveObject events to the source
diff --git a/tests/auto/qml/integration/data/tst_integration.qml b/tests/auto/qml/integration/data/tst_integration.qml
new file mode 100644
index 0000000..0f8b115
--- /dev/null
+++ b/tests/auto/qml/integration/data/tst_integration.qml
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtTest 1.1
+import QtQml.RemoteObjects 1.0
+
+TestCase {
+ id: testCase
+
+ Node {
+ id: defaultNode
+ }
+
+ Node {
+ id: nodeWithPersistedStore
+
+ persistedStore: SettingsStore {}
+ }
+
+ name: "testIntegration"
+ function test_integration()
+ {
+ // test defaultNode
+ compare(defaultNode.registryUrl, "")
+ compare(defaultNode.persistedStore, null)
+
+ // test nodeWithPersistedStore
+ compare(nodeWithPersistedStore.registryUrl, "")
+ verify(nodeWithPersistedStore.persistedStore)
+ }
+}
diff --git a/tests/auto/qml/integration/integration.pro b/tests/auto/qml/integration/integration.pro
new file mode 100644
index 0000000..0ad77a0
--- /dev/null
+++ b/tests/auto/qml/integration/integration.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+TARGET = tst_integration
+CONFIG += qmltestcase
+
+SOURCES += \
+ $$PWD/tst_integration.cpp
+
+OTHER_FILES += \
+ $$PWD/data/*.qml
+
+TESTDATA += \
+ $$PWD/data/tst_*
diff --git a/tests/auto/qml/integration/tst_integration.cpp b/tests/auto/qml/integration/tst_integration.cpp
new file mode 100644
index 0000000..6709f1a
--- /dev/null
+++ b/tests/auto/qml/integration/tst_integration.cpp
@@ -0,0 +1,30 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtQuickTest/quicktest.h>
+QUICK_TEST_MAIN(tst_integration)
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
new file mode 100644
index 0000000..cfdeabc
--- /dev/null
+++ b/tests/auto/qml/qml.pro
@@ -0,0 +1,5 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ integration \
+ usertypes
diff --git a/tests/auto/qml/usertypes/data/complex.qml b/tests/auto/qml/usertypes/data/complex.qml
new file mode 100644
index 0000000..4d80717
--- /dev/null
+++ b/tests/auto/qml/usertypes/data/complex.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+import QtQml.RemoteObjects 1.0
+import usertypes 1.0
+
+ComplexTypeReplica {
+ node: Node {
+ registryUrl: "local:testModel"
+ }
+}
diff --git a/tests/auto/qml/usertypes/data/extraprop.qml b/tests/auto/qml/usertypes/data/extraprop.qml
new file mode 100644
index 0000000..c37721b
--- /dev/null
+++ b/tests/auto/qml/usertypes/data/extraprop.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.0
+import QtQml.RemoteObjects 1.0
+import usertypes 1.0
+
+SimpleClockReplica {
+ property string result: hour // test that the existence of this property doesn't cause issues
+
+ node: Node {
+ registryUrl: "local:test"
+ }
+ onStateChanged: if (state == SimpleClockReplica.Valid) pushHour(10)
+}
diff --git a/tests/auto/qml/usertypes/data/model.qml b/tests/auto/qml/usertypes/data/model.qml
new file mode 100644
index 0000000..4be7bc8
--- /dev/null
+++ b/tests/auto/qml/usertypes/data/model.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+import QtQml.RemoteObjects 1.0
+import usertypes 1.0
+
+TypeWithModelReplica {
+ node: Node {
+ registryUrl: "local:testModel"
+ }
+}
diff --git a/tests/auto/qml/usertypes/data/subObject.qml b/tests/auto/qml/usertypes/data/subObject.qml
new file mode 100644
index 0000000..90c6adb
--- /dev/null
+++ b/tests/auto/qml/usertypes/data/subObject.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.0
+import QtQml.RemoteObjects 1.0
+import usertypes 1.0
+
+Item {
+ property int result: replica.clock.hour
+
+ property Node sharedNode: Node {
+ registryUrl: "local:testSubObject"
+ }
+
+ property TypeWithSubObjectReplica replica: TypeWithSubObjectReplica {
+ node: sharedNode
+ onStateChanged: if (state == TypeWithSubObjectReplica.Valid) clock.pushHour(7)
+ }
+}
+
diff --git a/tests/auto/qml/usertypes/tst_usertypes.cpp b/tests/auto/qml/usertypes/tst_usertypes.cpp
new file mode 100644
index 0000000..405b84b
--- /dev/null
+++ b/tests/auto/qml/usertypes/tst_usertypes.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QString>
+#include <QtTest>
+#include <qqmlengine.h>
+#include <qqmlcomponent.h>
+#include "rep_usertypes_merged.h"
+
+class tst_usertypes : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_usertypes();
+
+private Q_SLOTS:
+ void extraPropertyInQml();
+ void modelInQml();
+ void subObjectInQml();
+ void complexInQml_data();
+ void complexInQml();
+};
+
+tst_usertypes::tst_usertypes()
+{
+ qmlRegisterType<ComplexTypeReplica>("usertypes", 1, 0, "ComplexTypeReplica");
+}
+
+void tst_usertypes::extraPropertyInQml()
+{
+ qmlRegisterType<SimpleClockReplica>("usertypes", 1, 0, "SimpleClockReplica");
+
+ QRemoteObjectRegistryHost host(QUrl("local:test"));
+ SimpleClockSimpleSource clock;
+ host.enableRemoting(&clock);
+
+ QQmlEngine e;
+ QQmlComponent c(&e, SRCDIR "data/extraprop.qml");
+ QObject *obj = c.create();
+ QVERIFY(obj);
+
+ QTRY_COMPARE_WITH_TIMEOUT(obj->property("result").value<int>(), 10, 300);
+}
+
+void tst_usertypes::modelInQml()
+{
+ qmlRegisterType<TypeWithModelReplica>("usertypes", 1, 0, "TypeWithModelReplica");
+
+ QRemoteObjectRegistryHost host(QUrl("local:testModel"));
+
+ QStringListModel *model = new QStringListModel();
+ model->setStringList(QStringList() << "Track1" << "Track2" << "Track3");
+ TypeWithModelSimpleSource source(model);
+ host.enableRemoting<TypeWithModelSourceAPI>(&source);
+
+ QQmlEngine e;
+ QQmlComponent c(&e, SRCDIR "data/model.qml");
+ QObject *obj = c.create();
+ QVERIFY(obj);
+
+ QTRY_VERIFY_WITH_TIMEOUT(obj->property("tracks").value<QAbstractItemModelReplica*>() != nullptr, 300);
+ auto tracks = obj->property("tracks").value<QAbstractItemModelReplica*>();
+ QTRY_VERIFY_WITH_TIMEOUT(tracks->isInitialized(), 300);
+
+ TypeWithModelReplica *rep = qobject_cast<TypeWithModelReplica *>(obj);
+ QVERIFY(rep->isInitialized());
+}
+
+void tst_usertypes::subObjectInQml()
+{
+ qmlRegisterType<TypeWithSubObjectReplica>("usertypes", 1, 0, "TypeWithSubObjectReplica");
+
+ QRemoteObjectRegistryHost host(QUrl("local:testSubObject"));
+
+ SimpleClockSimpleSource clock;
+ TypeWithSubObjectSimpleSource source(&clock);
+ host.enableRemoting(&source);
+
+ QQmlEngine e;
+ QQmlComponent c(&e, SRCDIR "data/subObject.qml");
+ QObject *obj = c.create();
+ QVERIFY(obj);
+
+ TypeWithSubObjectReplica *replica = obj->property("replica").value<TypeWithSubObjectReplica*>();
+ QVERIFY(replica);
+
+ QTRY_VERIFY_WITH_TIMEOUT(replica->property("clock").value<SimpleClockReplica*>() != nullptr, 300);
+ QTRY_COMPARE_WITH_TIMEOUT(obj->property("result").toInt(), 7, 300);
+}
+
+void tst_usertypes::complexInQml_data()
+{
+ QTest::addColumn<bool>("templated");
+ QTest::addColumn<bool>("nullobject");
+ QTest::newRow("non-templated pointer") << false << false;
+ QTest::newRow("templated pointer") << true << false;
+ QTest::newRow("non-templated nullptr") << false << true;
+ QTest::newRow("templated nullptr") << true << true;
+}
+
+void tst_usertypes::complexInQml()
+{
+ QFETCH(bool, templated);
+ QFETCH(bool, nullobject);
+
+ QRemoteObjectRegistryHost host(QUrl("local:testModel"));
+
+ QStringListModel *model = new QStringListModel();
+ model->setStringList(QStringList() << "Track1" << "Track2" << "Track3");
+ QScopedPointer<SimpleClockSimpleSource> clock;
+ if (!nullobject)
+ clock.reset(new SimpleClockSimpleSource());
+ ComplexTypeSimpleSource source(model, clock.data());
+ if (templated)
+ host.enableRemoting<ComplexTypeSourceAPI>(&source);
+ else
+ host.enableRemoting(&source);
+
+ QQmlEngine e;
+ QQmlComponent c(&e, SRCDIR "data/complex.qml");
+ QObject *obj = c.create();
+ QVERIFY(obj);
+
+ QTRY_VERIFY_WITH_TIMEOUT(obj->property("tracks").value<QAbstractItemModelReplica*>() != nullptr, 300);
+ auto tracks = obj->property("tracks").value<QAbstractItemModelReplica*>();
+ QTRY_VERIFY_WITH_TIMEOUT(tracks->isInitialized(), 300);
+ ComplexTypeReplica *rep = qobject_cast<ComplexTypeReplica *>(obj);
+ QVERIFY(rep->waitForSource(300));
+ QCOMPARE(rep->property("before").value<int>(), 0);
+ QCOMPARE(rep->property("after").value<int>(), 42);
+ if (nullobject) {
+ QCOMPARE(rep->clock(), nullptr);
+ QCOMPARE(source.clock(), nullptr);
+ } else {
+ QCOMPARE(source.clock()->hour(), 6);
+ QCOMPARE(rep->clock()->hour(), source.clock()->hour());
+ }
+}
+
+QTEST_MAIN(tst_usertypes)
+
+#include "tst_usertypes.moc"
diff --git a/tests/auto/qml/usertypes/usertypes.pro b/tests/auto/qml/usertypes/usertypes.pro
new file mode 100644
index 0000000..9c771a6
--- /dev/null
+++ b/tests/auto/qml/usertypes/usertypes.pro
@@ -0,0 +1,14 @@
+QT += testlib remoteobjects qml
+QT -= gui
+
+REPC_MERGED += usertypes.rep
+#REPC_SOURCE += usertypes.rep
+
+TARGET = tst_usertypes
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+SOURCES += tst_usertypes.cpp
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/auto/qml/usertypes/usertypes.rep b/tests/auto/qml/usertypes/usertypes.rep
new file mode 100644
index 0000000..dff361d
--- /dev/null
+++ b/tests/auto/qml/usertypes/usertypes.rep
@@ -0,0 +1,25 @@
+#include <QtCore>
+
+class SimpleClock
+{
+ PROP(int hour=6);
+ PROP(int minute=30);
+};
+
+class TypeWithModel
+{
+ MODEL tracks(display);
+};
+
+class TypeWithSubObject
+{
+ CLASS clock(SimpleClock);
+};
+
+class ComplexType
+{
+ PROP(int before = 0)
+ MODEL tracks(display)
+ CLASS clock(SimpleClock)
+ PROP(int after = 42)
+}
diff --git a/tests/auto/repc/signature/signatureTests/tst_signature.cpp b/tests/auto/repc/signature/signatureTests/tst_signature.cpp
index def0b82..371b0ec 100644
--- a/tests/auto/repc/signature/signatureTests/tst_signature.cpp
+++ b/tests/auto/repc/signature/signatureTests/tst_signature.cpp
@@ -26,25 +26,13 @@
**
****************************************************************************/
+#include "../../../../shared/testutils.h"
+
#include <QtTest/QtTest>
#include <QMetaType>
#include <QProcess>
#include <QStandardPaths>
-namespace {
-
-QString findExecutable(const QString &executableName, const QStringList &paths)
-{
- const auto path = QStandardPaths::findExecutable(executableName, paths);
- if (!path.isEmpty()) {
- return path;
- }
-
- qWarning() << "Could not find executable:" << executableName << "in any of" << paths;
- return QString();
-}
-
-}
typedef QLatin1String _;
class tst_Signature: public QObject
{
@@ -67,7 +55,7 @@ private slots:
qDebug() << "Starting signatureServer process";
QProcess serverProc;
serverProc.setProcessChannelMode(QProcess::ForwardedChannels);
- serverProc.start(findExecutable("signatureServer", {
+ serverProc.start(TestUtils::findExecutable("signatureServer", {
QCoreApplication::applicationDirPath() + "/../signatureServer/"
}));
QVERIFY(serverProc.waitForStarted());
@@ -97,7 +85,7 @@ private slots:
qDebug() << "Starting" << test << "process";
QProcess testProc;
testProc.setProcessChannelMode(QProcess::ForwardedChannels);
- testProc.start(findExecutable(test, {
+ testProc.start(TestUtils::findExecutable(test, {
QCoreApplication::applicationDirPath() + _("/../") + test + _("/")
}));
QVERIFY(testProc.waitForStarted());
diff --git a/tests/auto/repc/signature/state/main.cpp b/tests/auto/repc/signature/state/main.cpp
index 7a9fc28..8cba5f7 100644
--- a/tests/auto/repc/signature/state/main.cpp
+++ b/tests/auto/repc/signature/state/main.cpp
@@ -32,7 +32,7 @@
#include <QtRemoteObjects/qremoteobjectnode.h>
#include <QtTest/QtTest>
-class tst_Mismatch_Process : public QObject
+class tst_State_Process : public QObject
{
Q_OBJECT
@@ -66,6 +66,6 @@ private Q_SLOTS:
}
};
-QTEST_MAIN(tst_Mismatch_Process)
+QTEST_MAIN(tst_State_Process)
#include "main.moc"
diff --git a/tests/auto/repcodegenerator/classwithreadonlypropertytest.rep b/tests/auto/repcodegenerator/classwithreadonlypropertytest.rep
new file mode 100644
index 0000000..c713c23
--- /dev/null
+++ b/tests/auto/repcodegenerator/classwithreadonlypropertytest.rep
@@ -0,0 +1,4 @@
+class MyReadOnlyPropClass
+{
+ PROP(bool myProp READONLY)
+}
diff --git a/tests/auto/repcodegenerator/repcodegenerator.pro b/tests/auto/repcodegenerator/repcodegenerator.pro
index 9edb91d..79f8655 100644
--- a/tests/auto/repcodegenerator/repcodegenerator.pro
+++ b/tests/auto/repcodegenerator/repcodegenerator.pro
@@ -8,6 +8,7 @@ SOURCES += tst_repcodegenerator.cpp
REP_FILES += \
classwithsignalonlytest.rep \
preprocessortest.rep \
+ classwithreadonlypropertytest.rep
# Make sure we test both source + replica generated code
REPC_MERGED = $$REP_FILES
diff --git a/tests/auto/repparser/tst_parser.cpp b/tests/auto/repparser/tst_parser.cpp
index 03712e0..58162ce 100644
--- a/tests/auto/repparser/tst_parser.cpp
+++ b/tests/auto/repparser/tst_parser.cpp
@@ -53,6 +53,8 @@ private Q_SLOTS:
void testEnums();
void testModels_data();
void testModels();
+ void testClasses_data();
+ void testClasses();
void testInvalid_data();
void testInvalid();
};
@@ -393,6 +395,46 @@ void tst_Parser::testModels()
}
}
+void tst_Parser::testClasses_data()
+{
+ QTest::addColumn<QString>("classDeclaration");
+ QTest::addColumn<QString>("expectedType");
+ QTest::addColumn<QString>("expectedName");
+ QTest::newRow("basicclass") << "CLASS sub(subObject)" << "subObject" << "sub";
+}
+
+void tst_Parser::testClasses()
+{
+ QFETCH(QString, classDeclaration);
+ QFETCH(QString, expectedType);
+ QFETCH(QString, expectedName);
+
+ QTemporaryFile file;
+ file.open();
+ QTextStream stream(&file);
+ stream << "class subObject" << endl;
+ stream << "{" << endl;
+ stream << " PROP(int value)" << endl;
+ stream << "};" << endl;
+ stream << "class parentObject" << endl;
+ stream << "{" << endl;
+ stream << classDeclaration << endl;
+ stream << "};" << endl;
+ file.seek(0);
+
+ RepParser parser(file);
+ QVERIFY(parser.parse());
+
+ const AST ast = parser.ast();
+ QCOMPARE(ast.classes.count(), 2);
+
+ const ASTClass astSub = ast.classes.value(0);
+ const ASTClass astObj = ast.classes.value(1);
+ const ASTChildRep child = astObj.children.first();
+ QCOMPARE(child.name, expectedName);
+ QCOMPARE(child.type, expectedType);
+}
+
void tst_Parser::testInvalid_data()
{
QTest::addColumn<QString>("content");
@@ -413,6 +455,7 @@ void tst_Parser::testInvalid_data()
QTest::newRow("slot_outsideclass") << "SLOT(void foo())" << ".?SLOT: Can only be used in class scope";
QTest::newRow("slot_noargs") << "class Foo\n{\nSLOT()\n}" << ".?Unknown token encountered";
QTest::newRow("model_outsideclass") << "MODEL foo" << ".?Unknown token encountered";
+ QTest::newRow("class_outsideclass") << "CLASS foo" << ".?Unknown token encountered";
QTest::newRow("preprecessor_line_inclass") << "class Foo\n{\n#define foo\n}" << ".?Unknown token encountered";
}
diff --git a/tests/auto/subclassreplica/class.rep b/tests/auto/subclassreplica/class.rep
new file mode 100644
index 0000000..8fd27d6
--- /dev/null
+++ b/tests/auto/subclassreplica/class.rep
@@ -0,0 +1,9 @@
+class SubClass
+{
+ PROP(int value)
+}
+class ParentClass
+{
+ CLASS sub1(SubClass)
+ CLASS sub2(SubClass)
+}
diff --git a/tests/auto/subclassreplica/subclassreplica.pro b/tests/auto/subclassreplica/subclassreplica.pro
new file mode 100644
index 0000000..354ec33
--- /dev/null
+++ b/tests/auto/subclassreplica/subclassreplica.pro
@@ -0,0 +1,15 @@
+QT += testlib remoteobjects
+
+QT -= gui
+
+REPC_MERGED += class.rep
+
+TARGET = tst_subclassreplicatest
+CONFIG += console
+CONFIG -= app_bundle
+
+TEMPLATE = app
+
+
+SOURCES += tst_subclassreplicatest.cpp
+DEFINES += SRCDIR=\\\"$$PWD/\\\"
diff --git a/tests/auto/subclassreplica/tst_subclassreplicatest.cpp b/tests/auto/subclassreplica/tst_subclassreplicatest.cpp
new file mode 100644
index 0000000..f328fd8
--- /dev/null
+++ b/tests/auto/subclassreplica/tst_subclassreplicatest.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QString>
+#include <QtTest>
+#include "rep_class_merged.h"
+
+class SubClassReplicaTest : public QObject
+{
+ Q_OBJECT
+
+public:
+ SubClassReplicaTest();
+
+private Q_SLOTS:
+ void basicFunctions();
+ void basicFunctions_data();
+};
+
+SubClassReplicaTest::SubClassReplicaTest()
+{
+}
+
+void SubClassReplicaTest::basicFunctions_data()
+{
+ QTest::addColumn<bool>("templated");
+ QTest::addColumn<bool>("nullobject");
+ QTest::newRow("non-templated pointer") << false << false;
+ QTest::newRow("templated pointer") << true << false;
+ QTest::newRow("non-templated nullptr") << false << true;
+ QTest::newRow("templated nullptr") << true << true;
+}
+
+void SubClassReplicaTest::basicFunctions()
+{
+ QFETCH(bool, templated);
+ QFETCH(bool, nullobject);
+
+ QRemoteObjectRegistryHost host(QUrl("local:test"));
+ SubClassSimpleSource subclass1, subclass2;
+ QScopedPointer<ParentClassSimpleSource> parent;
+ if (nullobject)
+ parent.reset(new ParentClassSimpleSource(&subclass1, nullptr));
+ else
+ parent.reset(new ParentClassSimpleSource(&subclass1, &subclass2));
+ if (templated)
+ host.enableRemoting<ParentClassSourceAPI>(parent.data());
+ else
+ host.enableRemoting(parent.data());
+
+ QRemoteObjectNode client(QUrl("local:test"));
+ const QScopedPointer<ParentClassReplica> replica(client.acquire<ParentClassReplica>());
+ QVERIFY(replica->waitForSource(1000));
+
+ auto sub1 = replica->sub1();
+ QSignalSpy spy(sub1, &SubClassReplica::valueChanged);
+ subclass1.setValue(10);
+ QVERIFY(spy.wait());
+ QCOMPARE(subclass1.value(), sub1->value());
+ if (nullobject) {
+ QCOMPARE(replica->sub2(), nullptr);
+ QCOMPARE(parent->sub2(), nullptr);
+ } else
+ QCOMPARE(subclass2.value(), replica->sub2()->value());
+}
+
+QTEST_MAIN(SubClassReplicaTest)
+
+#include "tst_subclassreplicatest.moc"
diff --git a/tests/shared/testutils.h b/tests/shared/testutils.h
new file mode 100644
index 0000000..54b3a4a
--- /dev/null
+++ b/tests/shared/testutils.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Ford Motor Company
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtRemoteObjects module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TESTUTILS_H
+#define TESTUTILS_H
+
+#include <QDebug>
+#include <QString>
+#include <QStandardPaths>
+
+namespace TestUtils {
+
+QString findExecutable(const QString &executableName, const QStringList &paths)
+{
+ const auto path = QStandardPaths::findExecutable(executableName, paths);
+ if (!path.isEmpty()) {
+ return path;
+ }
+
+ qWarning() << "Could not find executable:" << executableName << "in any of" << paths;
+ return QString();
+}
+
+}
+
+#endif // TESTUTILS_H
diff --git a/tools/repc/repc.pro b/tools/repc/repc.pro
index 204bd16..76c3a7f 100644
--- a/tools/repc/repc.pro
+++ b/tools/repc/repc.pro
@@ -23,4 +23,5 @@ HEADERS += \
cppcodegenerator.h \
utils.h
+QMAKE_TARGET_DESCRIPTION = "Qt Remote Objects Compiler"
load(qt_tool)
diff --git a/tools/repc/repcodegenerator.cpp b/tools/repc/repcodegenerator.cpp
index c34c284..3ef6ab9 100644
--- a/tools/repc/repcodegenerator.cpp
+++ b/tools/repc/repcodegenerator.cpp
@@ -83,6 +83,21 @@ static QString fullyQualifiedTypeName(const ASTClass& classContext, const QStrin
return typeName;
}
+// for enums we need to transform signal/slot arguments to include the class scope
+static QVector<ASTFunction> transformEnumParams(const ASTClass& classContext, const QVector<ASTFunction> &methodList, const QString &typeName) {
+ QVector<ASTFunction> localList = methodList;
+ for (ASTFunction &astFunction : localList) {
+ for (ASTDeclaration &astParam : astFunction.params) {
+ for (const ASTEnum &astEnum : classContext.enums) {
+ if (astEnum.name == astParam.type) {
+ astParam.type = typeName + QStringLiteral("::") + astParam.type;
+ }
+ }
+ }
+ }
+ return localList;
+}
+
/*
Returns \c true if the type is a built-in type.
*/
@@ -287,8 +302,8 @@ QString RepCodeGenerator::formatConstructors(const POD &pod)
QString defaultInitializerString = initializerString;
QString argString;
Q_FOREACH (const PODAttribute &a, pod.attributes) {
- initializerString += QString::fromLatin1("_%1(%1), ").arg(a.name);
- defaultInitializerString += QString::fromLatin1("_%1(), ").arg(a.name);
+ initializerString += QString::fromLatin1("m_%1(%1), ").arg(a.name);
+ defaultInitializerString += QString::fromLatin1("m_%1(), ").arg(a.name);
argString += QString::fromLatin1("%1 %2, ").arg(a.type, a.name);
}
argString.chop(2);
@@ -304,7 +319,7 @@ QString RepCodeGenerator::formatPropertyGettersAndSetters(const POD &pod)
{
// MSVC doesn't like adjacent string literal concatenation within QStringLiteral, so keep it in one line:
QString templateString
- = QStringLiteral(" %1 %2() const { return _%2; }\n void set%3(%1 %2) { if (%2 != _%2) { _%2 = %2; } }\n");
+ = QStringLiteral(" %1 %2() const { return m_%2; }\n void set%3(%1 %2) { if (%2 != m_%2) { m_%2 = %2; } }\n");
return formatTemplateStringArgTypeNameCapitalizedName(2, 8, qMove(templateString), pod);
}
@@ -312,7 +327,7 @@ QString RepCodeGenerator::formatDataMembers(const POD &pod)
{
QString out;
const QString prefix = QStringLiteral(" ");
- const QString infix = QStringLiteral(" _");
+ const QString infix = QStringLiteral(" m_");
const QString suffix = QStringLiteral(";\n");
const int expectedOutSize
= accumulatedSizeOfNames(pod.attributes)
@@ -344,6 +359,20 @@ QString RepCodeGenerator::formatMarshallingOperators(const POD &pod)
;
}
+void RepCodeGenerator::generateSimpleSetter(QTextStream &out, const ASTProperty &property, bool generateOverride)
+{
+ out << " virtual void set" << cap(property.name) << "(" << property.type << " " << property.name << ")";
+ if (generateOverride)
+ out << " override";
+ out << endl;
+ out << " {" << endl;
+ out << " if (" << property.name << " != m_" << property.name << ") {" << endl;
+ out << " m_" << property.name << " = " << property.name << ";" << endl;
+ out << " Q_EMIT " << property.name << "Changed(m_" << property.name << ");" << endl;
+ out << " }" << endl;
+ out << " }" << endl;
+}
+
void RepCodeGenerator::generatePOD(QTextStream &out, const POD &pod)
{
QByteArray podData = pod.name.toLatin1();
@@ -552,42 +581,62 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
const QString className = (astClass.name + (mode == REPLICA ? QStringLiteral("Replica") : mode == SOURCE ? QStringLiteral("Source") : QStringLiteral("SimpleSource")));
if (mode == REPLICA)
out << "class " << className << " : public QRemoteObjectReplica" << endl;
+ else if (mode == SIMPLE_SOURCE)
+ out << "class " << className << " : public " << astClass.name << "Source" << endl;
else
out << "class " << className << " : public QObject" << endl;
out << "{" << endl;
out << " Q_OBJECT" << endl;
- out << " Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_TYPE, \"" << astClass.name << "\")" << endl;
- out << " Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_SIGNATURE, \"" << QLatin1String(classSignature(astClass)) << "\")" << endl;
+ if (mode != SIMPLE_SOURCE) {
+ out << " Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_TYPE, \"" << astClass.name << "\")" << endl;
+ out << " Q_CLASSINFO(QCLASSINFO_REMOTEOBJECT_SIGNATURE, \"" << QLatin1String(classSignature(astClass)) << "\")" << endl;
+ for (int i = 0; i < astClass.models.count(); i++) {
+ const auto model = astClass.models.at(i);
+ if (!model.roles.isEmpty()) {
+ QStringList list;
+ for (auto role : model.roles)
+ list << role.name;
+ out << QString::fromLatin1(" Q_CLASSINFO(\"%1_ROLES\", \"%2\")").arg(model.name.toUpper(), list.join(QChar::fromLatin1('|'))) << endl;
+ }
+ }
- //First output properties
- Q_FOREACH (const ASTProperty &property, astClass.properties) {
- out << " Q_PROPERTY(" << property.type << " " << property.name << " READ " << property.name;
- if (property.modifier == ASTProperty::Constant)
- out << " CONSTANT";
- else if (property.modifier == ASTProperty::ReadOnly)
- out << " NOTIFY " << property.name << "Changed";
- else if (property.modifier == ASTProperty::ReadWrite)
- out << " WRITE set" << cap(property.name) << " NOTIFY " << property.name << "Changed";
- else if (property.modifier == ASTProperty::ReadPush) {
- if (mode == REPLICA) // The setter slot isn't known to the PROP
+
+ //First output properties
+ Q_FOREACH (const ASTProperty &property, astClass.properties) {
+ out << " Q_PROPERTY(" << property.type << " " << property.name << " READ " << property.name;
+ if (property.modifier == ASTProperty::Constant)
+ out << " CONSTANT";
+ else if (property.modifier == ASTProperty::ReadOnly)
out << " NOTIFY " << property.name << "Changed";
- else // The Source can use the setter, since non-asynchronous
+ else if (property.modifier == ASTProperty::ReadWrite)
out << " WRITE set" << cap(property.name) << " NOTIFY " << property.name << "Changed";
+ else if (property.modifier == ASTProperty::ReadPush) {
+ if (mode == REPLICA) // The setter slot isn't known to the PROP
+ out << " NOTIFY " << property.name << "Changed";
+ else // The Source can use the setter, since non-asynchronous
+ out << " WRITE set" << cap(property.name) << " NOTIFY " << property.name << "Changed";
+ }
+ out << ")" << endl;
+ }
+ for (auto model : astClass.models) {
+ if (mode == REPLICA)
+ out << QString::fromLatin1(" Q_PROPERTY(QAbstractItemModelReplica *%1 READ %1 NOTIFY %1Changed)").arg(model.name) << endl;
+ else
+ out << QString::fromLatin1(" Q_PROPERTY(QAbstractItemModel *%1 READ %1 CONSTANT)").arg(model.name) << endl;
+ }
+ for (auto child : astClass.children) {
+ if (mode == REPLICA)
+ out << QString::fromLatin1(" Q_PROPERTY(%1Replica *%2 READ %2 NOTIFY %2Changed)").arg(child.type, child.name) << endl;
+ else
+ out << QString::fromLatin1(" Q_PROPERTY(%1Source *%2 READ %2 CONSTANT)").arg(child.type, child.name) << endl;
}
- out << ")" << endl;
- }
- for (auto model : astClass.models) {
- if (mode == REPLICA)
- out << QString::fromLatin1(" Q_PROPERTY(QAbstractItemModelReplica *%1 READ %1 CONSTANT)").arg(model.name) << endl;
- else
- out << QString::fromLatin1(" Q_PROPERTY(QAbstractItemModel *%1 READ %1 CONSTANT)").arg(model.name) << endl;
- }
- if (!astClass.enums.isEmpty()) {
- out << "" << endl;
- out << "public:" << endl;
- generateDeclarationsForEnums(out, astClass.enums);
+ if (!astClass.enums.isEmpty()) {
+ out << "" << endl;
+ out << "public:" << endl;
+ generateDeclarationsForEnums(out, astClass.enums);
+ }
}
out << "" << endl;
@@ -607,14 +656,47 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
out << " }" << endl;
+ if (!astClass.models.isEmpty() || !astClass.children.isEmpty())
+ {
+ out << " void setNode(QRemoteObjectNode *node) override" << endl;
+ out << " {" << endl;
+ for (auto model : astClass.models) {
+ out << QString::fromLatin1(" m_%1.reset(node->acquireModel(\"Model::%1\"));")
+ .arg(model.name) << endl;
+ out << " emit " << model.name << "Changed();" << endl;
+ }
+ for (auto child : astClass.children) {
+ out << QString::fromLatin1(" m_%1.reset(node->acquire<%2Replica>(\"Class::%1\"));")
+ .arg(child.name, child.type) << endl;
+ out << " emit " << child.name << "Changed();" << endl;
+ }
+ if (!astClass.children.isEmpty()) {
+ out << " // This relies on finalize being called before any other slots connected to initialized to ensure" << endl;
+ out << " // any child replicas that don't have sources are null instead of the replica defaults." << endl;
+ out << " connect(this, &" << className << "::initialized, [this]() { finalize(); });" << endl;
+ }
+ out << " QRemoteObjectReplica::setNode(node);" << endl;
+ out << " }" << endl;
+ }
out << "" << endl;
out << "private:" << endl;
out << " " << className << "(QRemoteObjectNode *node, const QString &name = QString())" << endl;
out << " : QRemoteObjectReplica(ConstructWithNode)" << endl;
for (auto model : astClass.models)
- out << QString::fromLatin1(" , m_%1(node->acquireModel(\"%2::%1\"))")
- .arg(model.name, astClass.name) << endl;
- out << " { initializeNode(node, name); }" << endl;
+ out << QString::fromLatin1(" , m_%1(node->acquireModel(\"Model::%1\"))")
+ .arg(model.name) << endl;
+ for (auto child : astClass.children)
+ out << QString::fromLatin1(" , m_%1(node->acquire<%2Replica>(\"Class::%1\"))")
+ .arg(child.name, child.type) << endl;
+ if (astClass.children.count()) {
+ out << " {" << endl;
+ out << " // This relies on finalize being called before any other slots connected to initialized to ensure" << endl;
+ out << " // any child replicas that don't have sources are null instead of the replica defaults." << endl;
+ out << " connect(this, &" << className << "::initialized, [this]() { finalize(); });" << endl;
+ out << " initializeNode(node, name);" << endl;
+ out << " }" << endl;
+ } else
+ out << " { initializeNode(node, name); }" << endl;
out << "" << endl;
@@ -641,31 +723,44 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
out << " setProperties(properties);" << endl;
out << " }" << endl;
} else {
- if (astClass.models.isEmpty() || mode == SOURCE)
- out << " explicit " << className << "(QObject *parent = nullptr) : QObject(parent)" << endl;
- else {
- const QString modelParameterString = QStringLiteral("model%1");
- QStringList parametersForModels;
- for (int i = 0; i < astClass.models.count(); i++)
- parametersForModels << modelParameterString.arg(i+1);
- out << " explicit " << className << "(QAbstractItemModel *"
- << parametersForModels.join(QString::fromLatin1(", QAbstractItemModel *"))
- << ", QObject *parent = nullptr) : QObject(parent)" << endl;
+ if ( (astClass.models.isEmpty() && astClass.children.isEmpty()) || mode == SOURCE) {
+ if (mode == SOURCE)
+ out << " explicit " << className << "(QObject *parent = nullptr) : QObject(parent)" << endl;
+ else
+ out << " explicit " << className << "(QObject *parent = nullptr) : " << astClass.name << "Source(parent)" << endl;
+ } else {
+ int childIndex = 0;
+ if (astClass.models.count())
+ out << " explicit " << className << "(QAbstractItemModel *model0";
+ else {
+ out << " explicit " << className << "(" << astClass.children.at(0).type << "Source *sub0";
+ childIndex = 1;
+ }
+ for (int i = 1; i < astClass.models.count(); i++)
+ out << QString::fromLatin1(", QAbstractItemModel *model%1").arg(QString::number(i));
+ for (int i = childIndex; i < astClass.children.count(); i++)
+ out << QString::fromLatin1(", %1Source *sub%2").arg(astClass.children.at(childIndex).type, QString::number(i));
+ out << ", QObject *parent = nullptr) : " << astClass.name << "Source(parent)" << endl;
for (int i = 0; i < astClass.models.count(); i++)
{
- out << " , m_" << astClass.models[i].name
- << "(" << parametersForModels.at(i) << ")" << endl;
+ out << " , m_" << astClass.models[i].name
+ << QString::fromLatin1("(model%1)").arg(QString::number(i)) << endl;
+ }
+ for (int i = 0; i < astClass.children.count(); i++)
+ {
+ out << " , m_" << astClass.children[i].name
+ << QString::fromLatin1("(sub%1)").arg(QString::number(i)) << endl;
}
}
if (mode == SIMPLE_SOURCE) {
Q_FOREACH (const ASTProperty &property, astClass.properties) {
- out << " , _" << property.name << "(" << property.defaultValue << ")" << endl;
+ out << " , m_" << property.name << "(" << property.defaultValue << ")" << endl;
}
}
out << " {" << endl;
- if (!metaTypeRegistrationCode.isEmpty())
+ if (mode != SIMPLE_SOURCE && !metaTypeRegistrationCode.isEmpty())
out << metaTypeRegistrationCode << endl;
out << " }" << endl;
}
@@ -688,7 +783,8 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
}
out << "" << endl;
- generateConversionFunctionsForEnums(out, astClass.enums);
+ if (mode != SIMPLE_SOURCE)
+ generateConversionFunctionsForEnums(out, astClass.enums);
//Next output getter/setter
if (mode == REPLICA) {
@@ -725,18 +821,12 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
}
} else {
Q_FOREACH (const ASTProperty &property, astClass.properties) {
- out << " virtual " << property.type << " " << property.name << "() const { return _" << property.name << "; }" << endl;
+ out << " virtual " << property.type << " " << property.name << "() const override { return m_" << property.name << "; }" << endl;
}
Q_FOREACH (const ASTProperty &property, astClass.properties) {
if (property.modifier == ASTProperty::ReadWrite ||
property.modifier == ASTProperty::ReadPush) {
- out << " virtual void set" << cap(property.name) << "(" << property.type << " " << property.name << ")" << endl;
- out << " {" << endl;
- out << " if (" << property.name << " != _" << property.name << ") { " << endl;
- out << " _" << property.name << " = " << property.name << ";" << endl;
- out << " Q_EMIT " << property.name << "Changed(_" << property.name << ");" << endl;
- out << " }" << endl;
- out << " }" << endl;
+ generateSimpleSetter(out, property);
}
}
}
@@ -747,7 +837,7 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
if (mode == REPLICA)
out << " QAbstractItemModelReplica *" << model.name << "()" << endl;
else
- out << " QAbstractItemModel *" << model.name << "()" << endl;
+ out << " QAbstractItemModel *" << model.name << "() override" << endl;
out << " {" << endl;
out << " return m_" << model.name << ".data();" << endl;
out << " }" << endl;
@@ -757,105 +847,171 @@ void RepCodeGenerator::generateClass(Mode mode, QTextStream &out, const ASTClass
}
}
- //Next output property signals
- if (!astClass.properties.isEmpty() || !astClass.signalsList.isEmpty()) {
- out << "" << endl;
- out << "Q_SIGNALS:" << endl;
- Q_FOREACH (const ASTProperty &property, astClass.properties) {
- if (property.modifier != ASTProperty::Constant)
- out << " void " << property.name << "Changed(" << fullyQualifiedTypeName(astClass, className, property.type) << ");" << endl;
+ if (!astClass.children.isEmpty()) {
+ Q_FOREACH (const ASTChildRep &child, astClass.children) {
+ if (mode != SOURCE) {
+ if (mode == REPLICA) {
+ out << " " << child.type << "Replica *" << child.name << "()" << endl;
+ out << " {" << endl;
+ out << " return m_" << child.name << ".data();" << endl;
+ out << " }" << endl;
+ } else {
+ out << " " << child.type << "Source *" << child.name << "() override" << endl;
+ out << " {" << endl;
+ out << " return m_" << child.name << ";" << endl;
+ out << " }" << endl;
+ }
+ } else {
+ out << " virtual " << child.type << "Source *" << child.name << "() = 0;" << endl;
+ }
}
-
- Q_FOREACH (const ASTFunction &signal, astClass.signalsList)
- out << " void " << signal.name << "(" << signal.paramsAsString() << ");" << endl;
- }
- bool hasWriteSlots = false;
- Q_FOREACH (const ASTProperty &property, astClass.properties) {
- if (property.modifier == ASTProperty::ReadPush)
- hasWriteSlots = true;
}
- if (hasWriteSlots || !astClass.slotsList.isEmpty()) {
- out << "" << endl;
- out << "public Q_SLOTS:" << endl;
+
+ if (mode != SIMPLE_SOURCE) {
+ //Next output property signals
+ if (!astClass.properties.isEmpty() || !astClass.signalsList.isEmpty()) {
+ out << "" << endl;
+ out << "Q_SIGNALS:" << endl;
+ Q_FOREACH (const ASTProperty &property, astClass.properties) {
+ if (property.modifier != ASTProperty::Constant)
+ out << " void " << property.name << "Changed(" << fullyQualifiedTypeName(astClass, className, property.type) << " " << property.name << ");" << endl;
+ }
+
+ QVector<ASTFunction> signalsList = transformEnumParams(astClass, astClass.signalsList, className);
+ Q_FOREACH (const ASTFunction &signal, signalsList)
+ out << " void " << signal.name << "(" << signal.paramsAsString() << ");" << endl;
+ for (auto model : astClass.models)
+ out << " void " << model.name << "Changed();" << endl;
+ for (auto child : astClass.children)
+ out << " void " << child.name << "Changed();" << endl;
+ } else if (!astClass.models.isEmpty() || !astClass.children.isEmpty()) {
+ out << "" << endl;
+ out << "Q_SIGNALS:" << endl;
+ for (auto model : astClass.models)
+ out << " void " << model.name << "Changed();" << endl;
+ for (auto child : astClass.children)
+ out << " void " << child.name << "Changed();" << endl;
+ }
+ bool hasWriteSlots = false;
Q_FOREACH (const ASTProperty &property, astClass.properties) {
if (property.modifier == ASTProperty::ReadPush) {
+ hasWriteSlots = true;
+ break;
+ }
+ }
+ if (hasWriteSlots || !astClass.slotsList.isEmpty()) {
+ out << "" << endl;
+ out << "public Q_SLOTS:" << endl;
+ Q_FOREACH (const ASTProperty &property, astClass.properties) {
+ if (property.modifier == ASTProperty::ReadPush) {
+ if (mode != REPLICA) {
+ out << " virtual void push" << cap(property.name) << "(" << property.type << " " << property.name << ")" << endl;
+ out << " {" << endl;
+ out << " set" << cap(property.name) << "(" << property.name << ");" << endl;
+ out << " }" << endl;
+ } else {
+ out << " void push" << cap(property.name) << "(" << property.type << " " << property.name << ")" << endl;
+ out << " {" << endl;
+ out << " static int __repc_index = " << className << "::staticMetaObject.indexOfSlot(\"push" << cap(property.name) << "(" << property.type << ")\");" << endl;
+ out << " QVariantList __repc_args;" << endl;
+ out << " __repc_args << QVariant::fromValue(" << property.name << ");" << endl;
+ out << " send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);" << endl;
+ out << " }" << endl;
+ }
+ }
+ }
+ Q_FOREACH (const ASTFunction &slot, astClass.slotsList) {
if (mode != REPLICA) {
- out << " virtual void push" << cap(property.name) << "(" << property.type << " " << property.name << ")" << endl;
- out << " {" << endl;
- out << " set" << cap(property.name) << "(" << property.name << ");" << endl;
- out << " }" << endl;
+ out << " virtual " << slot.returnType << " " << slot.name << "(" << slot.paramsAsString() << ") = 0;" << endl;
} else {
- out << " void push" << cap(property.name) << "(" << property.type << " " << property.name << ")" << endl;
+ // TODO: Discuss whether it is a good idea to special-case for void here,
+ const bool isVoid = slot.returnType == QStringLiteral("void");
+
+ if (isVoid)
+ out << " void " << slot.name << "(" << slot.paramsAsString() << ")" << endl;
+ else
+ out << " QRemoteObjectPendingReply<" << slot.returnType << "> " << slot.name << "(" << slot.paramsAsString()<< ")" << endl;
out << " {" << endl;
- out << " static int __repc_index = " << className << "::staticMetaObject.indexOfSlot(\"push" << cap(property.name) << "(" << property.type << ")\");" << endl;
+ out << " static int __repc_index = " << className << "::staticMetaObject.indexOfSlot(\"" << slot.name << "(" << slot.paramsAsString(ASTFunction::Normalized) << ")\");" << endl;
out << " QVariantList __repc_args;" << endl;
- out << " __repc_args << QVariant::fromValue(" << property.name << ");" << endl;
- out << " send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);" << endl;
+ if (!slot.paramNames().isEmpty()) {
+ out << " __repc_args" << endl;
+ Q_FOREACH (const QString &name, slot.paramNames())
+ out << " << " << "QVariant::fromValue(" << name << ")" << endl;
+ out << " ;" << endl;
+ }
+ if (isVoid)
+ out << " send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);" << endl;
+ else
+ out << " return QRemoteObjectPendingReply<" << slot.returnType << ">(sendWithReply(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args));" << endl;
out << " }" << endl;
}
}
}
- Q_FOREACH (const ASTFunction &slot, astClass.slotsList) {
- if (mode != REPLICA) {
- out << " virtual " << slot.returnType << " " << slot.name << "(" << slot.paramsAsString() << ") = 0;" << endl;
- } else {
- // TODO: Discuss whether it is a good idea to special-case for void here,
- const bool isVoid = slot.returnType == QStringLiteral("void");
-
- if (isVoid)
- out << " void " << slot.name << "(" << slot.paramsAsString() << ")" << endl;
- else
- out << " QRemoteObjectPendingReply<" << slot.returnType << "> " << slot.name << "(" << slot.paramsAsString()<< ")" << endl;
- out << " {" << endl;
- out << " static int __repc_index = " << className << "::staticMetaObject.indexOfSlot(\"" << slot.name << "(" << slot.paramsAsString(ASTFunction::Normalized) << ")\");" << endl;
- out << " QVariantList __repc_args;" << endl;
- if (!slot.paramNames().isEmpty()) {
- out << " __repc_args" << endl;
- Q_FOREACH (const QString &name, slot.paramNames())
- out << " << " << "QVariant::fromValue(" << name << ")" << endl;
- out << " ;" << endl;
+ } else {
+ if (!astClass.properties.isEmpty()) {
+ bool addProtected = true;
+ Q_FOREACH (const ASTProperty &property, astClass.properties) {
+ if (property.modifier == ASTProperty::ReadOnly) {
+ if (addProtected) {
+ out << "" << endl;
+ out << "protected:" << endl;
+ addProtected = false;
+ }
+ generateSimpleSetter(out, property, false);
}
- if (isVoid)
- out << " send(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args);" << endl;
- else
- out << " return QRemoteObjectPendingReply<" << slot.returnType << ">(sendWithReply(QMetaObject::InvokeMetaMethod, __repc_index, __repc_args));" << endl;
- out << " }" << endl;
}
}
}
- if (mode == SIMPLE_SOURCE)
- {
- //Next output data members
+ out << "" << endl;
+ out << "private:" << endl;
+
+ //Next output data members
+ if (mode == SIMPLE_SOURCE) {
+ Q_FOREACH (const ASTModel &model, astClass.models)
+ out << " QScopedPointer<QAbstractItemModel> m_" << model.name << ";" << endl;
+ Q_FOREACH (const ASTChildRep &child, astClass.children)
+ out << " " << child.type << "Source *m_" << child.name << ";" << endl;
+
if (!astClass.properties.isEmpty()) {
- out << "" << endl;
- out << "private:" << endl;
Q_FOREACH (const ASTProperty &property, astClass.properties) {
- out << " " << property.type << " " << "_" << property.name << ";" << endl;
+ out << " " << property.type << " " << "m_" << property.name << ";" << endl;
}
}
- Q_FOREACH (const ASTModel &model, astClass.models)
- out << " QScopedPointer<QAbstractItemModel> m_" << model.name << ";" << endl;
- }
-
- out << "" << endl;
- out << "private:" << endl;
- if (mode == REPLICA) {
+ } else if (mode == REPLICA) {
+ if (astClass.children.count()) {
+ out << " void finalize()" << endl;
+ out << " {" << endl;
+ Q_FOREACH (const ASTChildRep &child, astClass.children) {
+ out << " if (!m_" << child.name << "->isInitialized()) {" << endl;
+ out << " m_" << child.name << ".reset(nullptr);" << endl;
+ out << " emit " << child.name << "Changed();" << endl;
+ out << " }" << endl;
+ }
+ out << " }" << endl << endl;
+ }
Q_FOREACH (const ASTModel &model, astClass.models)
out << " QScopedPointer<QAbstractItemModelReplica> m_" << model.name << ";" << endl;
+ Q_FOREACH (const ASTChildRep &child, astClass.children)
+ out << " QScopedPointer<" << child.type << "Replica> m_" << child.name << ";" << endl;
}
- out << " friend class QT_PREPEND_NAMESPACE(QRemoteObjectNode);" << endl;
+
+ if (mode != SIMPLE_SOURCE)
+ out << " friend class QT_PREPEND_NAMESPACE(QRemoteObjectNode);" << endl;
out << "};" << endl;
out << "" << endl;
- out << "#if (QT_VERSION < QT_VERSION_CHECK(5, 5, 0))" << endl;
- Q_FOREACH (const ASTEnum &en, astClass.enums)
- out << " Q_DECLARE_METATYPE(" << className << "::" << en.name << ")" << endl;
- out << "#endif" << endl;
- out << "" << endl;
+ if (mode != SIMPLE_SOURCE) {
+ out << "#if (QT_VERSION < QT_VERSION_CHECK(5, 5, 0))" << endl;
+ Q_FOREACH (const ASTEnum &en, astClass.enums)
+ out << " Q_DECLARE_METATYPE(" << className << "::" << en.name << ")" << endl;
+ out << "#endif" << endl;
+ out << "" << endl;
- generateStreamOperatorsForEnums(out, astClass.enums, className);
+ generateStreamOperatorsForEnums(out, astClass.enums, className);
+ }
out << "" << endl;
}
@@ -873,40 +1029,50 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
out << QString::fromLatin1(" %1(ObjectType *object)").arg(className) << endl;
out << QStringLiteral(" : SourceApiMap()") << endl;
out << QStringLiteral(" {") << endl;
- if (astClass.models.isEmpty())
+ if (astClass.models.isEmpty() && astClass.children.isEmpty())
out << QStringLiteral(" Q_UNUSED(object);") << endl;
+
+ const int enumCount = astClass.enums.count();
+ out << QString::fromLatin1(" m_enums[0] = %1;").arg(enumCount) << endl;
+ for (int i = 0; i < enumCount; ++i) {
+ const auto enumerator = astClass.enums.at(i);
+ out << QString::fromLatin1(" m_enums[%1] = ObjectType::staticMetaObject.indexOfEnumerator(\"%2\");")
+ .arg(i+1).arg(enumerator.name) << endl;
+ }
const int propCount = astClass.properties.count();
- out << QString::fromLatin1(" _properties[0] = %1;").arg(propCount) << endl;
+ out << QString::fromLatin1(" m_properties[0] = %1;").arg(propCount) << endl;
QStringList changeSignals;
QList<int> propertyChangeIndex;
for (int i = 0; i < propCount; ++i) {
const ASTProperty &prop = astClass.properties.at(i);
const QString propTypeName = fullyQualifiedTypeName(astClass, QStringLiteral("typename ObjectType"), prop.type);
- out << QString::fromLatin1(" _properties[%1] = qtro_prop_index<ObjectType>(&ObjectType::%2, "
+ out << QString::fromLatin1(" m_properties[%1] = QtPrivate::qtro_property_index<ObjectType>(&ObjectType::%2, "
"static_cast<%3 (QObject::*)()>(0),\"%2\");")
.arg(QString::number(i+1), prop.name, propTypeName) << endl;
if (prop.modifier == prop.ReadWrite) //Make sure we have a setter function
- out << QStringLiteral(" qtro_method_test<ObjectType>(&ObjectType::set%1, static_cast<void (QObject::*)(%2)>(0));")
+ out << QStringLiteral(" QtPrivate::qtro_method_test<ObjectType>(&ObjectType::set%1, static_cast<void (QObject::*)(%2)>(0));")
.arg(cap(prop.name), propTypeName) << endl;
if (prop.modifier != prop.Constant) { //Make sure we have an onChange signal
- out << QStringLiteral(" qtro_method_test<ObjectType>(&ObjectType::%1Changed, static_cast<void (QObject::*)()>(0));")
+ out << QStringLiteral(" QtPrivate::qtro_method_test<ObjectType>(&ObjectType::%1Changed, static_cast<void (QObject::*)()>(0));")
.arg(prop.name) << endl;
changeSignals << QString::fromLatin1("%1Changed").arg(prop.name);
- propertyChangeIndex << i + 1; //_properties[0] is the count, so index is one higher
+ propertyChangeIndex << i + 1; //m_properties[0] is the count, so index is one higher
}
}
const int signalCount = astClass.signalsList.count();
const int changedCount = changeSignals.size();
- out << QString::fromLatin1(" _signals[0] = %1;").arg(signalCount+changeSignals.size()) << endl;
+ out << QString::fromLatin1(" m_signals[0] = %1;").arg(signalCount+changeSignals.size()) << endl;
for (int i = 0; i < changedCount; ++i)
- out << QString::fromLatin1(" _signals[%1] = qtro_signal_index<ObjectType>(&ObjectType::%2, "
- "static_cast<void (QObject::*)()>(0),signalArgCount+%4,&signalArgTypes[%4]);")
+ out << QString::fromLatin1(" m_signals[%1] = QtPrivate::qtro_signal_index<ObjectType>(&ObjectType::%2, "
+ "static_cast<void (QObject::*)()>(0),m_signalArgCount+%4,&m_signalArgTypes[%4]);")
.arg(i+1).arg(changeSignals.at(i)).arg(i) << endl;
+
+ QVector<ASTFunction> signalsList = transformEnumParams(astClass, astClass.signalsList, QStringLiteral("typename ObjectType"));
for (int i = 0; i < signalCount; ++i) {
- const ASTFunction &sig = astClass.signalsList.at(i);
- out << QString::fromLatin1(" _signals[%1] = qtro_signal_index<ObjectType>(&ObjectType::%2, "
- "static_cast<void (QObject::*)(%3)>(0),signalArgCount+%4,&signalArgTypes[%4]);")
- .arg(QString::number(changedCount+i+1), sig.name, sig.paramsAsString(ASTFunction::Normalized), QString::number(i)) << endl;
+ const ASTFunction &sig = signalsList.at(i);
+ out << QString::fromLatin1(" m_signals[%1] = QtPrivate::qtro_signal_index<ObjectType>(&ObjectType::%2, "
+ "static_cast<void (QObject::*)(%3)>(0),m_signalArgCount+%4,&m_signalArgTypes[%4]);")
+ .arg(QString::number(changedCount+i+1), sig.name, sig.paramsAsString(ASTFunction::Normalized), QString::number(changedCount+i)) << endl;
}
const int slotCount = astClass.slotsList.count();
QVector<ASTProperty> pushProps;
@@ -916,65 +1082,86 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
}
const int pushCount = pushProps.count();
const int methodCount = slotCount + pushCount;
- out << QString::fromLatin1(" _methods[0] = %1;").arg(methodCount) << endl;
+ out << QString::fromLatin1(" m_methods[0] = %1;").arg(methodCount) << endl;
for (int i = 0; i < pushCount; ++i) {
const ASTProperty &prop = pushProps.at(i);
const QString propTypeName = fullyQualifiedTypeName(astClass, QStringLiteral("typename ObjectType"), prop.type);
- out << QString::fromLatin1(" _methods[%1] = qtro_method_index<ObjectType>(&ObjectType::push%2, "
- "static_cast<void (QObject::*)(%3)>(0),\"push%2(%3)\",methodArgCount+%4,&methodArgTypes[%4]);")
+ out << QString::fromLatin1(" m_methods[%1] = QtPrivate::qtro_method_index<ObjectType>(&ObjectType::push%2, "
+ "static_cast<void (QObject::*)(%3)>(0),\"push%2(%3)\",m_methodArgCount+%4,&m_methodArgTypes[%4]);")
.arg(QString::number(i+1), cap(prop.name), propTypeName, QString::number(i)) << endl;
}
+
+ QVector<ASTFunction> slotsList = transformEnumParams(astClass, astClass.slotsList, QStringLiteral("typename ObjectType"));
for (int i = 0; i < slotCount; ++i) {
- const ASTFunction &slot = astClass.slotsList.at(i);
- out << QString::fromLatin1(" _methods[%1] = qtro_method_index<ObjectType>(&ObjectType::%2, "
- "static_cast<void (QObject::*)(%3)>(0),\"%2(%3)\",methodArgCount+%4,&methodArgTypes[%4]);")
- .arg(QString::number(i+pushCount+1), slot.name, slot.paramsAsString(ASTFunction::Normalized), QString::number(i+pushCount)) << endl;
+ const ASTFunction &slot = slotsList.at(i);
+ const QString params = slot.paramsAsString(ASTFunction::Normalized);
+ out << QString::fromLatin1(" m_methods[%1] = QtPrivate::qtro_method_index<ObjectType>(&ObjectType::%2, "
+ "static_cast<void (QObject::*)(%3)>(0),\"%2(%4)\",m_methodArgCount+%5,&m_methodArgTypes[%5]);")
+ .arg(QString::number(i+pushCount+1), slot.name, params,
+ QString(params).remove(QStringLiteral("typename ObjectType::")), // we don't want this in the string signature
+ QString::number(i+pushCount)) << endl;
}
const int modelCount = astClass.models.count();
- out << QString::fromLatin1(" _modelCount = %1;").arg(modelCount) << endl;
for (int i = 0; i < modelCount; ++i) {
const ASTModel &model = astClass.models.at(i);
- out << QString::fromLatin1(" _models[%1] = object->%2();").arg(QString::number(i), model.name) << endl;
+ out << QString::fromLatin1(" m_models << ModelInfo({object->%1(),").arg(model.name) << endl;
+ out << QString::fromLatin1(" QStringLiteral(\"%1\"),").arg(model.name) << endl;
+ QStringList list;
+ if (!model.roles.isEmpty()) {
+ for (auto role : model.roles)
+ list << role.name;
+ }
+ out << QString::fromLatin1(" QByteArrayLiteral(\"%1\")});").arg(list.join(QChar::fromLatin1('|'))) << endl;
+ }
+ const int subclassCount = astClass.children.count();
+ for (int i = 0; i < subclassCount; ++i) {
+ const ASTChildRep &child = astClass.children.at(i);
+ out << QString::fromLatin1(" m_subclasses << SubclassInfo({object->%1(), QStringLiteral(\"%1\")});").arg(child.name) << endl;
}
-
out << QStringLiteral(" }") << endl;
out << QStringLiteral("") << endl;
out << QString::fromLatin1(" QString name() const override { return QStringLiteral(\"%1\"); }").arg(astClass.name) << endl;
out << QString::fromLatin1(" QString typeName() const override { return QStringLiteral(\"%1\"); }").arg(astClass.name) << endl;
- out << QStringLiteral(" int propertyCount() const override { return _properties[0]; }") << endl;
- out << QStringLiteral(" int signalCount() const override { return _signals[0]; }") << endl;
- out << QStringLiteral(" int methodCount() const override { return _methods[0]; }") << endl;
- out << QStringLiteral(" int modelCount() const override { return _modelCount; }") << endl;
+ out << QStringLiteral(" int enumCount() const override { return m_enums[0]; }") << endl;
+ out << QStringLiteral(" int propertyCount() const override { return m_properties[0]; }") << endl;
+ out << QStringLiteral(" int signalCount() const override { return m_signals[0]; }") << endl;
+ out << QStringLiteral(" int methodCount() const override { return m_methods[0]; }") << endl;
+ out << QStringLiteral(" int sourceEnumIndex(int index) const override") << endl;
+ out << QStringLiteral(" {") << endl;
+ out << QStringLiteral(" if (index < 0 || index >= m_enums[0])") << endl;
+ out << QStringLiteral(" return -1;") << endl;
+ out << QStringLiteral(" return m_enums[index+1];") << endl;
+ out << QStringLiteral(" }") << endl;
out << QStringLiteral(" int sourcePropertyIndex(int index) const override") << endl;
out << QStringLiteral(" {") << endl;
- out << QStringLiteral(" if (index < 0 || index >= _properties[0])") << endl;
+ out << QStringLiteral(" if (index < 0 || index >= m_properties[0])") << endl;
out << QStringLiteral(" return -1;") << endl;
- out << QStringLiteral(" return _properties[index+1];") << endl;
+ out << QStringLiteral(" return m_properties[index+1];") << endl;
out << QStringLiteral(" }") << endl;
out << QStringLiteral(" int sourceSignalIndex(int index) const override") << endl;
out << QStringLiteral(" {") << endl;
- out << QStringLiteral(" if (index < 0 || index >= _signals[0])") << endl;
+ out << QStringLiteral(" if (index < 0 || index >= m_signals[0])") << endl;
out << QStringLiteral(" return -1;") << endl;
- out << QStringLiteral(" return _signals[index+1];") << endl;
+ out << QStringLiteral(" return m_signals[index+1];") << endl;
out << QStringLiteral(" }") << endl;
out << QStringLiteral(" int sourceMethodIndex(int index) const override") << endl;
out << QStringLiteral(" {") << endl;
- out << QStringLiteral(" if (index < 0 || index >= _methods[0])") << endl;
+ out << QStringLiteral(" if (index < 0 || index >= m_methods[0])") << endl;
out << QStringLiteral(" return -1;") << endl;
- out << QStringLiteral(" return _methods[index+1];") << endl;
+ out << QStringLiteral(" return m_methods[index+1];") << endl;
out << QStringLiteral(" }") << endl;
if (signalCount+changedCount > 0) {
out << QStringLiteral(" int signalParameterCount(int index) const override") << endl;
out << QStringLiteral(" {") << endl;
- out << QStringLiteral(" if (index < 0 || index >= _signals[0])") << endl;
+ out << QStringLiteral(" if (index < 0 || index >= m_signals[0])") << endl;
out << QStringLiteral(" return -1;") << endl;
- out << QStringLiteral(" return signalArgCount[index];") << endl;
+ out << QStringLiteral(" return m_signalArgCount[index];") << endl;
out << QStringLiteral(" }") << endl;
out << QStringLiteral(" int signalParameterType(int sigIndex, int paramIndex) const override") << endl;
out << QStringLiteral(" {") << endl;
- out << QStringLiteral(" if (sigIndex < 0 || sigIndex >= _signals[0] || paramIndex < 0 || paramIndex >= signalArgCount[sigIndex])") << endl;
+ out << QStringLiteral(" if (sigIndex < 0 || sigIndex >= m_signals[0] || paramIndex < 0 || paramIndex >= m_signalArgCount[sigIndex])") << endl;
out << QStringLiteral(" return -1;") << endl;
- out << QStringLiteral(" return signalArgTypes[sigIndex][paramIndex];") << endl;
+ out << QStringLiteral(" return m_signalArgTypes[sigIndex][paramIndex];") << endl;
out << QStringLiteral(" }") << endl;
} else {
out << QStringLiteral(" int signalParameterCount(int index) const override { Q_UNUSED(index); return -1; }") << endl;
@@ -984,15 +1171,15 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
if (methodCount > 0) {
out << QStringLiteral(" int methodParameterCount(int index) const override") << endl;
out << QStringLiteral(" {") << endl;
- out << QStringLiteral(" if (index < 0 || index >= _methods[0])") << endl;
+ out << QStringLiteral(" if (index < 0 || index >= m_methods[0])") << endl;
out << QStringLiteral(" return -1;") << endl;
- out << QStringLiteral(" return methodArgCount[index];") << endl;
+ out << QStringLiteral(" return m_methodArgCount[index];") << endl;
out << QStringLiteral(" }") << endl;
out << QStringLiteral(" int methodParameterType(int methodIndex, int paramIndex) const override") << endl;
out << QStringLiteral(" {") << endl;
- out << QStringLiteral(" if (methodIndex < 0 || methodIndex >= _methods[0] || paramIndex < 0 || paramIndex >= methodArgCount[methodIndex])") << endl;
+ out << QStringLiteral(" if (methodIndex < 0 || methodIndex >= m_methods[0] || paramIndex < 0 || paramIndex >= m_methodArgCount[methodIndex])") << endl;
out << QStringLiteral(" return -1;") << endl;
- out << QStringLiteral(" return methodArgTypes[methodIndex][paramIndex];") << endl;
+ out << QStringLiteral(" return m_methodArgTypes[methodIndex][paramIndex];") << endl;
out << QStringLiteral(" }") << endl;
} else {
out << QStringLiteral(" int methodParameterCount(int index) const override { Q_UNUSED(index); return -1; }") << endl;
@@ -1005,7 +1192,7 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
if (!propertyChangeIndex.isEmpty()) {
out << QStringLiteral(" switch (index) {") << endl;
for (int i = 0; i < propertyChangeIndex.size(); ++i)
- out << QString::fromLatin1(" case %1: return _properties[%2];").arg(i).arg(propertyChangeIndex.at(i)) << endl;
+ out << QString::fromLatin1(" case %1: return m_properties[%2];").arg(i).arg(propertyChangeIndex.at(i)) << endl;
out << QStringLiteral(" }") << endl;
} else
out << QStringLiteral(" Q_UNUSED(index);") << endl;
@@ -1017,7 +1204,7 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
if (!propertyChangeIndex.isEmpty()) {
out << QStringLiteral(" switch (index) {") << endl;
for (int i = 0; i < propertyChangeIndex.size(); ++i)
- out << QString::fromLatin1(" case %1: return %2;").arg(i).arg(propertyChangeIndex.at(i)) << endl;
+ out << QString::fromLatin1(" case %1: return %2;").arg(i).arg(propertyChangeIndex.at(i)-1) << endl;
out << QStringLiteral(" }") << endl;
} else
out << QStringLiteral(" Q_UNUSED(index);") << endl;
@@ -1043,6 +1230,14 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
out << QStringLiteral(" return QByteArrayLiteral(\"\");") << endl;
out << QStringLiteral(" }") << endl;
+ //signalParameterNames method
+ out << QStringLiteral(" QList<QByteArray> signalParameterNames(int index) const override") << endl;
+ out << QStringLiteral(" {") << endl;
+ out << QStringLiteral(" if (index < 0 || index >= m_signals[0])") << endl;
+ out << QStringLiteral(" return QList<QByteArray>();") << endl;
+ out << QStringLiteral(" return ObjectType::staticMetaObject.method(m_signals[index + 1]).parameterNames();") << endl;
+ out << QStringLiteral(" }") << endl;
+
//methodSignature method
out << QStringLiteral(" const QByteArray methodSignature(int index) const override") << endl;
out << QStringLiteral(" {") << endl;
@@ -1072,6 +1267,14 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
out << QStringLiteral(" return QMetaMethod::Slot;") << endl;
out << QStringLiteral(" }") << endl;
+ //methodParameterNames method
+ out << QStringLiteral(" QList<QByteArray> methodParameterNames(int index) const override") << endl;
+ out << QStringLiteral(" {") << endl;
+ out << QStringLiteral(" if (index < 0 || index >= m_methods[0])") << endl;
+ out << QStringLiteral(" return QList<QByteArray>();") << endl;
+ out << QStringLiteral(" return ObjectType::staticMetaObject.method(m_methods[index + 1]).parameterNames();") << endl;
+ out << QStringLiteral(" }") << endl;
+
//typeName method
out << QStringLiteral(" const QByteArray typeName(int index) const override") << endl;
out << QStringLiteral(" {") << endl;
@@ -1100,44 +1303,17 @@ void RepCodeGenerator::generateSourceAPI(QTextStream &out, const ASTClass &astCl
<< QStringLiteral("\"}; }") << endl;
out << QStringLiteral("") << endl;
- out << QString::fromLatin1(" int _properties[%1];").arg(propCount+1) << endl;
- out << QString::fromLatin1(" int _signals[%1];").arg(signalCount+changedCount+1) << endl;
- out << QString::fromLatin1(" int _methods[%1];").arg(methodCount+1) << endl;
+ out << QString::fromLatin1(" int m_enums[%1];").arg(enumCount + 1) << endl;
+ out << QString::fromLatin1(" int m_properties[%1];").arg(propCount+1) << endl;
+ out << QString::fromLatin1(" int m_signals[%1];").arg(signalCount+changedCount+1) << endl;
+ out << QString::fromLatin1(" int m_methods[%1];").arg(methodCount+1) << endl;
if (signalCount+changedCount > 0) {
- out << QString::fromLatin1(" int signalArgCount[%1];").arg(signalCount+changedCount) << endl;
- out << QString::fromLatin1(" const int* signalArgTypes[%1];").arg(signalCount+changedCount) << endl;
+ out << QString::fromLatin1(" int m_signalArgCount[%1];").arg(signalCount+changedCount) << endl;
+ out << QString::fromLatin1(" const int* m_signalArgTypes[%1];").arg(signalCount+changedCount) << endl;
}
if (methodCount > 0) {
- out << QString::fromLatin1(" int methodArgCount[%1];").arg(methodCount) << endl;
- out << QString::fromLatin1(" const int* methodArgTypes[%1];").arg(methodCount) << endl;
- }
- out << QString::fromLatin1(" int _modelCount;") << endl;
- if (modelCount > 0)
- {
- out << QString::fromLatin1(" QAbstractItemModel *_models[%1];").arg(modelCount) << endl;
- out << " void modelSetup(QRemoteObjectHostBase *node) const override" << endl;
- out << " {" << endl;
- out << " QVector<int> roles;" << endl;
- out << " int roleIndex;" << endl;
- out << " QHash<int, QByteArray> knownRoles;" << endl;
- for (int i = 0; i < astClass.models.count(); i++)
- {
- out << endl;
- const ASTModel model = astClass.models.at(i);
- out << " // Handle model #" << i+1 << " " << model.name << endl;
- out << " roles.clear();" << endl;
- out << " knownRoles = _models[" << i << "]->roleNames();" << endl;
- for (auto role : model.roles)
- {
- out << " roleIndex = knownRoles.key(\"" << role.name << "\", -1);" << endl;
- out << " if (roleIndex == -1)" << endl;
- out << " qWarning() << " << QString::fromLatin1("\"Invalid role %1 for model %2\";").arg(role.name, model.name) << endl;
- out << " else" << endl;
- out << " roles << roleIndex;" << endl;
- }
- out << " node->enableRemoting(" << QString::fromLatin1("_models[%1], \"%2::%3\", roles, nullptr);").arg(QString::number(i), astClass.name, model.name) << endl;
- }
- out << " }" << endl;
+ out << QString::fromLatin1(" int m_methodArgCount[%1];").arg(methodCount) << endl;
+ out << QString::fromLatin1(" const int* m_methodArgTypes[%1];").arg(methodCount) << endl;
}
out << QStringLiteral("};") << endl;
}
diff --git a/tools/repc/repcodegenerator.h b/tools/repc/repcodegenerator.h
index 18421e8..18af23c 100644
--- a/tools/repc/repcodegenerator.h
+++ b/tools/repc/repcodegenerator.h
@@ -38,6 +38,7 @@ struct AST;
struct ASTClass;
struct POD;
struct ASTEnum;
+struct ASTProperty;
class QIODevice;
class QStringList;
@@ -65,6 +66,7 @@ private:
QString generateMetaTypeRegistrationForEnums(const QVector<QString> &enums);
void generateStreamOperatorsForEnums(QTextStream &out, const QVector<QString> &enums);
+ void generateSimpleSetter(QTextStream &out, const ASTProperty &property, bool generateOverride = true);
void generatePOD(QTextStream &out, const POD &pod);
void generateENUMs(QTextStream &out, const QVector<ASTEnum> &enums, const QString &className);
void generateDeclarationsForEnums(QTextStream &out, const QVector<ASTEnum> &enums, bool generateQENUM=true);