implemented support for setting interface sub properties

see #107
Dieser Commit ist enthalten in:
Reinder Feenstra 2024-04-11 00:03:06 +02:00
Ursprung 4770643636
Commit 5746fb88aa
8 geänderte Dateien mit 299 neuen und 56 gelöschten Zeilen

Datei anzeigen

@ -240,7 +240,7 @@
"type": "serial",
"baudrate": 115200,
"flow_control": "hardware",
"settings.command_station": "%loconet_command_station%"
"loconet.command_station": "%loconet_command_station%"
}
}
}
@ -310,7 +310,7 @@
"type": "serial",
"baudrate": 115200,
"flow_control": "none",
"settings.command_station": "digikeijs_dr5000"
"loconet.command_station": "digikeijs_dr5000"
}
}
}
@ -325,7 +325,7 @@
"type": "serial",
"baudrate": 115200,
"flow_control": "none",
"settings.command_station": "digikeijs_dr5000"
"xpressnet.command_station": "digikeijs_dr5000"
}
}
}
@ -345,7 +345,7 @@
"class_id": "interface.loconet",
"properties": {
"type": "tcp_binary",
"settings.command_station": "digikeijs_dr5000"
"loconet.command_station": "digikeijs_dr5000"
}
}
}
@ -358,7 +358,7 @@
"class_id": "interface.loconet",
"properties": {
"type": "lbserver",
"settings.command_station": "digikeijs_dr5000"
"loconet.command_station": "digikeijs_dr5000"
}
}
}
@ -371,7 +371,7 @@
"class_id": "interface.xpressnet",
"properties": {
"type": "network",
"settings.command_station": "digikeijs_dr5000"
"xpressnet.command_station": "digikeijs_dr5000"
}
}
}
@ -402,7 +402,7 @@
"type": "serial",
"baudrate": 19200,
"flowcontrol": "hardware",
"settings.command_station": "%loconet_command_station%"
"loconet.command_station": "%loconet_command_station%"
}
},
"set_variables": {
@ -420,7 +420,7 @@
"type": "serial",
"baudrate": 115200,
"flowcontrol": "none",
"settings.command_station": "%loconet_command_station%"
"loconet.command_station": "%loconet_command_station%"
}
},
"set_variables": {
@ -445,7 +445,7 @@
"type": "serial",
"baudrate": 9600,
"flowcontrol": "hardware",
"settings.command_station": "%xpressnet_command_station%"
"xpressnet.command_station": "%xpressnet_command_station%"
}
},
"set_variables": {
@ -463,7 +463,7 @@
"type": "serial",
"baudrate": 19200,
"flowcontrol": "hardware",
"settings.command_station": "%xpressnet_command_station%"
"xpressnet.command_station": "%xpressnet_command_station%"
}
},
"set_variables": {

Datei anzeigen

@ -93,6 +93,38 @@ class AbstractProperty : public BaseProperty
virtual void setValueInt64(int64_t value) { Q_ASSERT(value != value); }
virtual void setValueDouble(double value) { Q_ASSERT(value != value); }
virtual void setValueString(const QString& value) { Q_ASSERT(value != value); }
void setValueVariant(const QVariant& value)
{
switch(value.type())
{
case QVariant::Bool:
setValueBool(value.toBool());
break;
case QVariant::Int:
setValueInt(value.toInt());
break;
case QVariant::UInt:
case QVariant::LongLong:
case QVariant::ULongLong:
setValueInt64(value.toLongLong());
break;
case QVariant::Double:
setValueDouble(value.toDouble());
break;
case QVariant::String:
setValueString(value.toString());
break;
default: /*[[unlikely]]*/
assert(false);
break;
}
}
};
#endif

Datei anzeigen

@ -21,10 +21,12 @@
*/
#include "createinterface.hpp"
#include "setobjectproperties.hpp"
#include "../connection.hpp"
#include "../error.hpp"
#include "../method.hpp"
#include "../object.hpp"
#include "../property.hpp"
#include "../objectproperty.hpp"
CreateInterface::CreateInterface(ObjectPtr world, QString classId, Properties properties)
@ -66,45 +68,33 @@ CreateInterface::CreateInterface(ObjectPtr world, QString classId, Properties pr
}
else if(interface)
{
for(const auto& it : m_properties)
m_interface = interface;
if(m_properties.empty())
{
// a bit hacky but easier for now #FIXME
auto event = Message::newEvent(Message::Command::ObjectSetProperty);
event->write(interface->handle());
event->write(it.first);
switch(it.second.type())
{
case QVariant::Bool:
event->write(ValueType::Boolean);
event->write(it.second.toBool());
break;
case QVariant::Int:
case QVariant::UInt:
case QVariant::LongLong:
case QVariant::ULongLong:
event->write(ValueType::Integer);
event->write(it.second.toLongLong());
break;
case QVariant::Double:
event->write(ValueType::Float);
event->write(it.second.toDouble());
break;
case QVariant::String:
event->write(ValueType::String);
event->write(it.second.toString().toUtf8());
break;
default: /*[[unlikely]]*/
assert(false);
continue;
}
interface->connection()->send(event);
m_promise.reportFinished(&m_interface);
}
else
{
m_setObjectProperties = std::make_shared<SetObjectProperties>(m_interface, m_properties);
if(m_setObjectProperties->future().isFinished())
{
m_promise.reportFinished(&m_interface);
}
else
{
m_setObjectPropertiesFutureWatcher = std::make_unique<QFutureWatcher<ObjectPtr>>();
m_setObjectPropertiesFutureWatcher->setFuture(m_setObjectProperties->future());
QObject::connect(m_setObjectPropertiesFutureWatcher.get(), &QFutureWatcher<ObjectPtr>::finished,
[this]()
{
if(!m_canceled)
{
m_promise.reportFinished(&m_interface);
}
});
}
}
m_promise.reportFinished(&interface);
}
else
{
@ -127,6 +117,10 @@ CreateInterface::~CreateInterface()
{
cancel();
}
if(m_requestId != Connection::invalidRequestId)
{
m_world->connection()->cancelRequest(m_requestId);
}
}
void CreateInterface::cancel()

Datei anzeigen

@ -24,25 +24,26 @@
#define TRAINTASTIC_CLIENT_NETWORK_CREATE_CREATEINTERFACE_HPP
#include <memory>
#include <vector>
#include <utility>
#include <QString>
#include <QFuture>
#include <QFutureInterface>
#include <QFutureWatcher>
#include "properties.hpp"
#include "../objectptr.hpp"
class SetObjectProperties;
class CreateInterface : public std::enable_shared_from_this<CreateInterface>
{
public:
using Properties = std::vector<std::pair<std::string, QVariant>>;
private:
QFutureInterface<ObjectPtr> m_promise;
ObjectPtr m_world;
ObjectPtr m_interfaceList;
ObjectPtr m_interface;
QString m_classId;
Properties m_properties;
int m_requestId;
std::shared_ptr<SetObjectProperties> m_setObjectProperties;
std::unique_ptr<QFutureWatcher<ObjectPtr>> m_setObjectPropertiesFutureWatcher;
bool m_canceled = false;
public:

Datei anzeigen

@ -0,0 +1,33 @@
/**
* client/src/network/create/properties.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2024 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_CLIENT_NETWORK_CREATE_PROPERTIES_HPP
#define TRAINTASTIC_CLIENT_NETWORK_CREATE_PROPERTIES_HPP
#include <vector>
#include <utility>
#include <QString>
#include <QVariant>
using Properties = std::vector<std::pair<QString, QVariant>>;
#endif

Datei anzeigen

@ -0,0 +1,120 @@
/**
* client/src/network/create/setobjectproperties.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2024 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "setobjectproperties.hpp"
#include "../connection.hpp"
#include "../error.hpp"
#include "../object.hpp"
#include "../abstractproperty.hpp"
#include "../objectproperty.hpp"
SetObjectProperties::SetObjectProperties(ObjectPtr object, Properties properties)
: m_object{std::move(object)}
, m_properties{std::move(properties)}
, m_requestId{Connection::invalidRequestId}
{
setProperties();
}
SetObjectProperties::SetObjectProperties(ObjectProperty& objectProperty, Properties properties)
: m_objectProperty{&objectProperty}
, m_properties{std::move(properties)}
{
m_requestId = m_objectProperty->getObject(
[this](const ObjectPtr& object, std::optional<const Error> /*error*/)
{
m_requestId = Connection::invalidRequestId;
if(!m_canceled)
{
m_object = object;
setProperties();
}
});
}
SetObjectProperties::~SetObjectProperties()
{
if(!m_promise.isFinished() && !m_canceled)
{
cancel();
}
if(m_requestId != Connection::invalidRequestId)
{
m_objectProperty->object().connection()->cancelRequest(m_requestId);
}
}
void SetObjectProperties::cancel()
{
m_canceled = true;
if(!m_promise.isFinished())
{
m_promise.reportCanceled();
}
}
void SetObjectProperties::setProperties()
{
assert(m_object);
std::map<ObjectProperty*, Properties> subObjects;
for(const auto& it : m_properties)
{
if(int pos = it.first.indexOf(QChar('.')); pos >= 0) // property of sub object
{
qDebug() << it.first << it.first.left(pos);
auto* objectProperty = m_object->getObjectProperty(it.first.left(pos));
if(objectProperty)
{
subObjects[objectProperty].emplace_back(it.first.mid(pos + 1), it.second);
}
}
else if(auto* property = m_object->getProperty(it.first))
{
qDebug() << it.first << it.second;
property->setValueVariant(it.second);
}
}
if(subObjects.empty()) // we're done
{
m_promise.reportFinished(&m_object);
}
else
{
for(const auto& it : subObjects)
{
m_setObjectProperties.emplace_back(std::make_shared<SetObjectProperties>(*it.first, it.second));
m_setObjectPropertiesFutureWatcher.emplace_back(std::make_unique<QFutureWatcher<ObjectPtr>>());
m_setObjectPropertiesFutureWatcher.back()->setFuture(m_setObjectProperties.back()->future());
QObject::connect(m_setObjectPropertiesFutureWatcher.back().get(), &QFutureWatcher<ObjectPtr>::finished,
[this]()
{
if(!m_canceled && ++m_setObjectPropertiesFinishedCount == m_setObjectProperties.size())
{
m_promise.reportFinished(&m_object);
}
});
}
}
}

Datei anzeigen

@ -0,0 +1,63 @@
/**
* client/src/network/create/setbjectproperties.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2024 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_CLIENT_NETWORK_CREATE_SETOBJECTPROPERTIES_HPP
#define TRAINTASTIC_CLIENT_NETWORK_CREATE_SETOBJECTPROPERTIES_HPP
#include <memory>
#include <QFuture>
#include <QFutureInterface>
#include <QFutureWatcher>
#include "properties.hpp"
#include "../objectptr.hpp"
class ObjectProperty;
class SetObjectProperties : public std::enable_shared_from_this<SetObjectProperties>
{
private:
QFutureInterface<ObjectPtr> m_promise;
ObjectPtr m_object;
ObjectProperty* m_objectProperty = nullptr;
Properties m_properties;
int m_requestId;
std::vector<std::shared_ptr<SetObjectProperties>> m_setObjectProperties;
std::vector<std::unique_ptr<QFutureWatcher<ObjectPtr>>> m_setObjectPropertiesFutureWatcher;
size_t m_setObjectPropertiesFinishedCount = 0;
bool m_canceled = false;
void setProperties();
public:
SetObjectProperties(ObjectPtr object, Properties properties);
SetObjectProperties(ObjectProperty& objectProperty, Properties properties);
~SetObjectProperties();
void cancel();
QFuture<ObjectPtr> future()
{
return m_promise.future();
}
};
#endif

Datei anzeigen

@ -53,15 +53,15 @@ static void setTitleAndText(JSONWizard& wizard, TextPage* page, const QJsonObjec
page->setText(wizard.translateAndReplaceVariables(object["text"].toString()));
}
static CreateInterface::Properties toProperties(const QJsonObject& object)
static Properties toProperties(const QJsonObject& object)
{
CreateInterface::Properties properties;
Properties properties;
for(const auto& key : object.keys())
{
auto value = object[key];
if(value.isBool() || value.isDouble() || value.isString())
{
properties.emplace_back(key.toStdString(), value.toVariant());
properties.emplace_back(key, value.toVariant());
}
else
{