diff options
| -rw-r--r-- | src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp | 10 | ||||
| -rw-r--r-- | src/remoteobjects/qremoteobjectnode.cpp | 27 | ||||
| -rw-r--r-- | src/remoteobjects/qremoteobjectnode.h | 2 | ||||
| -rw-r--r-- | src/repparser/parser.g | 11 | ||||
| -rw-r--r-- | tests/auto/proxy/tst_proxy.cpp | 79 | ||||
| -rw-r--r-- | tests/auto/repparser/tst_parser.cpp | 11 |
6 files changed, 133 insertions, 7 deletions
diff --git a/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp b/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp index 0b84975..27851c8 100644 --- a/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp +++ b/src/remoteobjects/qremoteobjectabstractitemmodelreplica.cpp @@ -383,6 +383,16 @@ void QAbstractItemModelReplicaImplementation::handleModelResetDone(QRemoteObject m_rootItem.columnCount = size.width(); m_headerData[0].resize(size.width()); m_headerData[1].resize(size.height()); + { + QVector<CacheEntry> &headerEntries = m_headerData[0]; + for (int i = 0; i < size.width(); ++i ) + headerEntries[i].data.clear(); + } + { + QVector<CacheEntry> &headerEntries = m_headerData[1]; + for (int i = 0; i < size.height(); ++i ) + headerEntries[i].data.clear(); + } if (m_initialAction == QtRemoteObjects::PrefetchData) { auto entries = watcher->returnValue().value<MetaAndDataEntries>(); for (int i = 0; i < entries.data.size(); ++i) diff --git a/src/remoteobjects/qremoteobjectnode.cpp b/src/remoteobjects/qremoteobjectnode.cpp index c2fba06..3b87605 100644 --- a/src/remoteobjects/qremoteobjectnode.cpp +++ b/src/remoteobjects/qremoteobjectnode.cpp @@ -437,9 +437,10 @@ bool QRemoteObjectHostBase::proxy(const QUrl ®istryUrl, const QUrl &hostUrl, // myInternalHost is a node only visible on the device... QRemoteObjectHost myInternalHost("local:MyHost"); - // Regular host node, listening on port 12123, so visible to other - // devices - QRemoteObjectHost proxyNode("tcp://localhost:12123"); + // RegistryHost node, listening on port 12123, so visible to other + // devices. The node must be a RegistryHost, so the Sources on + // the "outside" network can be forwarded to the inner network. + QRemoteObjectRegistryHost proxyNode("tcp://localhost:12123"); // Enable proxying objects from nodes on the local machine's internal // QtRO bus. Note the hostUrl parameter is now needed. @@ -2414,7 +2415,11 @@ ProxyInfo::~ProxyInfo() { bool ProxyInfo::setReverseProxy(QRemoteObjectHostBase::RemoteObjectNameFilter filter) { - const auto registry = proxyNode->registry(); + if (qobject_cast<QRemoteObjectRegistryHost *>(parentNode) == nullptr) { + qWarning() << "Setting up reverseProxy() can only be done on a Registry node."; + return false; + } + const auto registry = parentNode->registry(); this->reverseFilter = filter; connect(registry, &QRemoteObjectRegistry::remoteObjectAdded, this, @@ -2439,12 +2444,17 @@ bool ProxyInfo::setReverseProxy(QRemoteObjectHostBase::RemoteObjectNameFilter fi void ProxyInfo::proxyObject(const QRemoteObjectSourceLocation &entry, ProxyDirection direction) { const QString name = entry.first; - Q_ASSERT(!proxiedReplicas.contains(name)); const QString typeName = entry.second.typeName; if (direction == ProxyDirection::Forward) { + // If we are using the reverse proxy, this can be called when reverse proxy objects are added + // Don't try to proxy those back. We can detect this because the hosting node will be our proxyNode. + auto host = qobject_cast<QRemoteObjectHost *>(proxyNode); + if (host && entry.second.hostUrl == host->hostUrl()) + return; if (!proxyFilter(name, typeName)) return; + Q_ASSERT(!proxiedReplicas.contains(name)); qCDebug(QT_REMOTEOBJECT) << "Starting proxy for" << name << "from" << entry.second.hostUrl; @@ -2460,8 +2470,15 @@ void ProxyInfo::proxyObject(const QRemoteObjectSourceLocation &entry, ProxyDirec [rep, name, this]() { this->parentNode->enableRemoting(rep, name); }); } } else { + // If we are using the reverse proxy, this can be called when proxy objects are added + // Don't try to proxy those back. We can detect this because the hosting node will be the parentNode. + // Since we know the parentNode has to be a RegistryNode for reverse proxy to work, we compare against + // the registryUrl(). + if (entry.second.hostUrl == parentNode->registryUrl()) + return; if (!reverseFilter(name, typeName)) return; + Q_ASSERT(!proxiedReplicas.contains(name)); qCDebug(QT_REMOTEOBJECT) << "Starting reverse proxy for" << name << "from" << entry.second.hostUrl; diff --git a/src/remoteobjects/qremoteobjectnode.h b/src/remoteobjects/qremoteobjectnode.h index d69b369..ae63d61 100644 --- a/src/remoteobjects/qremoteobjectnode.h +++ b/src/remoteobjects/qremoteobjectnode.h @@ -189,6 +189,8 @@ public: typedef std::function<bool(const QString &, const QString &)> RemoteObjectNameFilter; bool proxy(const QUrl ®istryUrl, const QUrl &hostUrl={}, RemoteObjectNameFilter filter=[](const QString &, const QString &) {return true; }); + // ### Qt 6: Fix -> This should only be part of the QRemoteObjectRegistryHost type, since the + // reverse aspect requires the registry. bool reverseProxy(RemoteObjectNameFilter filter=[](const QString &, const QString &) {return true; }); protected: diff --git a/src/repparser/parser.g b/src/repparser/parser.g index 2930de3..6208c37 100644 --- a/src/repparser/parser.g +++ b/src/repparser/parser.g @@ -512,12 +512,19 @@ bool RepParser::parseProperty(ASTClass &astClass, const QString &propertyDeclara propertyName = input.left(equalSignIndex).trimmed(); input = input.mid(equalSignIndex + 1).trimmed(); + const int lastQuoteIndex = input.lastIndexOf(QLatin1Char('"')); + if (lastQuoteIndex != -1) { + propertyDefaultValue = input.left(lastQuoteIndex + 1); + input = input.mid(lastQuoteIndex + 1); + } const int whitespaceIndex = input.indexOf(whitespace); if (whitespaceIndex == -1) { // no flag given - propertyDefaultValue = input; + if (propertyDefaultValue.isEmpty()) + propertyDefaultValue = input; propertyModifier = ASTProperty::ReadPush; } else { // flag given - propertyDefaultValue = input.left(whitespaceIndex).trimmed(); + if (propertyDefaultValue.isEmpty()) + propertyDefaultValue = input.left(whitespaceIndex).trimmed(); const QString flag = input.mid(whitespaceIndex + 1).trimmed(); if (!parseModifierFlag(flag, propertyModifier, persisted)) diff --git a/tests/auto/proxy/tst_proxy.cpp b/tests/auto/proxy/tst_proxy.cpp index 79e1adf..aa914bc 100644 --- a/tests/auto/proxy/tst_proxy.cpp +++ b/tests/auto/proxy/tst_proxy.cpp @@ -36,7 +36,10 @@ const QUrl localHostUrl = QUrl(QLatin1String("local:testHost")); const QUrl tcpHostUrl = QUrl(QLatin1String("tcp://127.0.0.1:9989")); +const QUrl proxyNodeUrl = QUrl(QLatin1String("tcp://127.0.0.1:12123")); +const QUrl remoteNodeUrl = QUrl(QLatin1String("tcp://127.0.0.1:23234")); const QUrl registryUrl = QUrl(QLatin1String("local:testRegistry")); +const QUrl proxyHostUrl = QUrl(QLatin1String("local:fromProxy")); #define SET_NODE_NAME(obj) (obj).setName(QLatin1String(#obj)) @@ -52,6 +55,8 @@ private Q_SLOTS: void testProxy_data(); void testProxy(); + void testForwardProxy(); + void testReverseProxy(); // The following should fail to compile, verifying the SourceAPI templates work // for subclasses /* @@ -349,6 +354,80 @@ void ProxyTest::testProxy() replica.reset(); } +void ProxyTest::testForwardProxy() +{ + // Setup Local Registry + QRemoteObjectRegistryHost registry(registryUrl); + SET_NODE_NAME(registry); + + // Setup Local Host + QRemoteObjectHost host(localHostUrl, registryUrl); + SET_NODE_NAME(host); + + // Setup Proxy + QRemoteObjectRegistryHost proxyNode(proxyNodeUrl); + SET_NODE_NAME(proxyNode); + proxyNode.proxy(registryUrl, proxyHostUrl); + // Include the reverseProxy to make sure we don't try to send back + // proxied objects. + proxyNode.reverseProxy(); + + // Setup Source + EngineSimpleSource engine; + engine.setRpm(1234); + + // Setup Remote Node + QRemoteObjectHost remoteNode(remoteNodeUrl); + SET_NODE_NAME(remoteNode); + remoteNode.connectToNode(proxyNodeUrl); + + // Add source + host.enableRemoting(&engine); + + // Setup Replica + const QScopedPointer<EngineReplica> replica(remoteNode.acquire<EngineReplica>()); + QVERIFY(replica->waitForSource(1000)); + + // Compare Replica to Source + QCOMPARE(replica->rpm(), engine.rpm()); +} + +void ProxyTest::testReverseProxy() +{ + // Setup Local Registry + QRemoteObjectRegistryHost registry(registryUrl); + SET_NODE_NAME(registry); + + // Setup Local Host + QRemoteObjectHost host(localHostUrl, registryUrl); + SET_NODE_NAME(host); + + // Setup Proxy + // QRemoteObjectRegistryHost proxyNode(proxyNodeUrl); + QRemoteObjectRegistryHost proxyNode(proxyNodeUrl); + SET_NODE_NAME(proxyNode); + proxyNode.proxy(registryUrl, proxyHostUrl); + proxyNode.reverseProxy(); + + // Setup Source + EngineSimpleSource engine; + engine.setRpm(1234); + + // Setup Remote Node + QRemoteObjectHost remoteNode(remoteNodeUrl, proxyNodeUrl); + SET_NODE_NAME(remoteNode); + + // Add source + remoteNode.enableRemoting(&engine); + + // Setup Replica + const QScopedPointer<EngineReplica> replica(host.acquire<EngineReplica>()); + QVERIFY(replica->waitForSource(1000)); + + //Compare Replica to Source + QCOMPARE(replica->rpm(), engine.rpm()); +} + void ProxyTest::testTopLevelModel() { QRemoteObjectRegistryHost registry(registryUrl); diff --git a/tests/auto/repparser/tst_parser.cpp b/tests/auto/repparser/tst_parser.cpp index b749a15..a212059 100644 --- a/tests/auto/repparser/tst_parser.cpp +++ b/tests/auto/repparser/tst_parser.cpp @@ -128,6 +128,17 @@ void tst_Parser::testProperties_data() QTest::newRow("non-int default value") << "PROP(double foo=1.1 CONSTANT)" << "double" << "foo" << "1.1" << ASTProperty::Constant << false; QTest::newRow("tab") << "PROP(double\tfoo)" << "double" << "foo" << "" << ASTProperty::ReadPush << false; QTest::newRow("two tabs") << "PROP(double\t\tfoo)" << "double" << "foo" << "" << ASTProperty::ReadPush << false; + QTest::newRow("stringWithValue") << "PROP(QString foo=\"Hello World\")" << "QString" << "foo" + << QString("\"Hello World\"") << ASTProperty::ReadPush << false; + QTest::newRow("stringWithValueWhitespaces") << "PROP(QString foo = \"Hello World\")" + << "QString" << "foo" << QString("\"Hello World\"") + << ASTProperty::ReadPush << false; + QTest::newRow("readonlyStringWithValueWhitespaces") << "PROP(QString foo = \"Hello World\" READONLY )" + << "QString" << "foo" << "\"Hello World\"" + << ASTProperty::ReadOnly << false; + QTest::newRow("readonlyStringWithValue") << "PROP(QString foo=\"Hello World\" READONLY)" + << "QString" << "foo" << "\"Hello World\"" + << ASTProperty::ReadOnly << false; } void tst_Parser::testProperties() |
