From 35f1cfc2631315c50d4f47741e8cde5fac497a28 Mon Sep 17 00:00:00 2001 From: Reinder Feenstra Date: Wed, 2 Sep 2020 22:59:07 +0200 Subject: [PATCH] Implemented ClassList attribute --- client/src/widget/objectlistwidget.cpp | 82 ++++--------------- server/src/core/attributes.hpp | 6 ++ server/src/core/to.hpp | 4 + .../commandstation/commandstationlist.cpp | 1 + .../commandstation/commandstations.cpp | 21 ----- .../commandstation/commandstations.hpp | 19 ++++- .../hardware/controller/controllerlist.cpp | 25 +++--- .../hardware/controller/controllerlist.hpp | 2 +- .../src/hardware/controller/controllers.cpp | 9 -- .../src/hardware/controller/controllers.hpp | 7 +- server/src/utils/makearray.hpp | 36 ++++++++ server/src/vehicle/rail/railvehiclelist.cpp | 1 + server/src/vehicle/rail/railvehicles.cpp | 11 --- server/src/vehicle/rail/railvehicles.hpp | 9 +- shared/src/traintastic/enum/attributename.hpp | 1 + 15 files changed, 112 insertions(+), 122 deletions(-) create mode 100644 server/src/utils/makearray.hpp diff --git a/client/src/widget/objectlistwidget.cpp b/client/src/widget/objectlistwidget.cpp index a0ce6426..a5064fbe 100644 --- a/client/src/widget/objectlistwidget.cpp +++ b/client/src/widget/objectlistwidget.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "tablewidget.hpp" #include "../network/connection.hpp" #include "../network/object.hpp" @@ -116,83 +117,34 @@ ObjectListWidget::ObjectListWidget(const ObjectPtr& object, QWidget* parent) : m_buttonAdd->setPopupMode(QToolButton::InstantPopup); QMenu* menu = new QMenu(m_buttonAdd); - menu->addAction("li10x"); - menu->addAction("z21"); - menu->addAction("loconet_serial", - [this, method]() - { - if(m_requestIdAdd != Connection::invalidRequestId) - m_object->connection()->cancelRequest(m_requestIdAdd); - m_requestIdAdd = method->call("hardware.command_station.loconet_serial", - [this](const ObjectPtr& object, Message::ErrorCode /*ec*/) - { - m_requestIdAdd = Connection::invalidRequestId; - if(object) - { - MainWindow::instance->showObject(object); - } - // TODO: show error - }); - }); - menu->addAction("locomotive", - [this, method]() - { - if(m_requestIdAdd != Connection::invalidRequestId) - m_object->connection()->cancelRequest(m_requestIdAdd); + QStringList classList = method->getAttribute(AttributeName::ClassList, QVariant()).toStringList(); + for(const QString& classId : classList) + { + QAction* action = menu->addAction(Locale::tr("class_id:" + classId)); + action->setData(classId); + connect(action, &QAction::triggered, this, + [this, method, action]() + { + if(m_requestIdAdd != Connection::invalidRequestId) + m_object->connection()->cancelRequest(m_requestIdAdd); - m_requestIdAdd = method->call("vehicle.rail.locomotive", - [this](const ObjectPtr& object, Message::ErrorCode /*ec*/) - { - m_requestIdAdd = Connection::invalidRequestId; - if(object) - { - MainWindow::instance->showObject(object); - } - // TODO: show error - }); - }); - menu->addAction("locomotive", - [this, method]() - { - if(m_requestIdAdd != Connection::invalidRequestId) - m_object->connection()->cancelRequest(m_requestIdAdd); - - m_requestIdAdd = method->call("vehicle.rail.freight_car", - [this](const ObjectPtr& object, Message::ErrorCode /*ec*/) - { - m_requestIdAdd = Connection::invalidRequestId; - if(object) - { - MainWindow::instance->showObject(object); - } - // TODO: show error - }); - }); - - m_buttonAdd->setMenu(menu); - - m_toolbar->addWidget(m_buttonAdd); - - - /* - m_requestIdAdd = method->call("hardware.command_station.li10x", - [this](const ObjectPtr& object, Message::ErrorCode /*ec*//*) + m_requestIdAdd = method->call(action->data().toString(), + [this](const ObjectPtr& object, Message::ErrorCode /*ec*/) { m_requestIdAdd = Connection::invalidRequestId; - if(object) { MainWindow::instance->showObject(object); } - // TODO: show error - - }); + }); + } - */ + m_buttonAdd->setMenu(menu); + m_toolbar->addWidget(m_buttonAdd); m_buttonAdd->setEnabled(method->getAttributeBool(AttributeName::Enabled, true)); connect(method, &Method::attributeChanged, diff --git a/server/src/core/attributes.hpp b/server/src/core/attributes.hpp index 605b7fc2..c0c294fa 100644 --- a/server/src/core/attributes.hpp +++ b/server/src/core/attributes.hpp @@ -32,6 +32,12 @@ struct Attributes item.addAttribute(AttributeName::Category, value); } + template + static inline void addClassList(InterfaceItem& item, const std::array& classList) + { + item.addAttribute(AttributeName::ClassList, classList); + } + static inline void addEnabled(InterfaceItem& item, bool value) { item.addAttribute(AttributeName::Enabled, value); diff --git a/server/src/core/to.hpp b/server/src/core/to.hpp index e9303ef1..ea75bcde 100644 --- a/server/src/core/to.hpp +++ b/server/src/core/to.hpp @@ -99,6 +99,10 @@ To to(const From& value) { return std::to_string(value); } + else if constexpr(std::is_same_v && std::is_same_v) + { + return std::string(value); + } else if constexpr(std::is_same_v) { if constexpr(std::is_enum_v) diff --git a/server/src/hardware/commandstation/commandstationlist.cpp b/server/src/hardware/commandstation/commandstationlist.cpp index d77396a3..1d47f96f 100644 --- a/server/src/hardware/commandstation/commandstationlist.cpp +++ b/server/src/hardware/commandstation/commandstationlist.cpp @@ -49,6 +49,7 @@ CommandStationList::CommandStationList(Object& _parent, const std::string& paren const bool editable = world && contains(world->state.value(), WorldState::Edit); Attributes::addEnabled(add, editable); + Attributes::addClassList(add, CommandStations::classList); m_interfaceItems.add(add); Attributes::addEnabled(remove, editable); diff --git a/server/src/hardware/commandstation/commandstations.cpp b/server/src/hardware/commandstation/commandstations.cpp index 80e0ba79..effeb3a2 100644 --- a/server/src/hardware/commandstation/commandstations.cpp +++ b/server/src/hardware/commandstation/commandstations.cpp @@ -21,27 +21,6 @@ */ #include "commandstations.hpp" -#include "loconetserial.hpp" -#ifndef DISABLE_USB_XPRESSNET_INTERFACE - #include "usbxpressnetinterface.hpp" -#endif -#include "xpressnetserial.hpp" -#include "rocoz21.hpp" -#include "virtualcommandstation.hpp" - -const std::vector& CommandStations::classList() -{ - static std::vector list({ - LocoNetSerial::classId, -#ifndef DISABLE_USB_XPRESSNET_INTERFACE - USBXpressNetInterface::classId, -#endif - XpressNetSerial::classId, - RocoZ21::classId, - VirtualCommandStation::classId, - }); - return list; -} std::shared_ptr CommandStations::create(const std::weak_ptr& world, std::string_view classId, std::string_view id) { diff --git a/server/src/hardware/commandstation/commandstations.hpp b/server/src/hardware/commandstation/commandstations.hpp index 72ef6e63..cfc84de8 100644 --- a/server/src/hardware/commandstation/commandstations.hpp +++ b/server/src/hardware/commandstation/commandstations.hpp @@ -24,12 +24,29 @@ #define TRAINTASTIC_SERVER_HARDWARE_COMMANDSTATION_COMMANDSTATIONS_HPP #include "commandstation.hpp" +#include "../../utils/makearray.hpp" + +#include "loconetserial.hpp" +#ifndef DISABLE_USB_XPRESSNET_INTERFACE + #include "usbxpressnetinterface.hpp" +#endif +#include "xpressnetserial.hpp" +#include "rocoz21.hpp" +#include "virtualcommandstation.hpp" struct CommandStations { static constexpr std::string_view classIdPrefix = "command_station."; - static const std::vector& classList(); + static constexpr auto classList = makeArray( + LocoNetSerial::classId, +#ifndef DISABLE_USB_XPRESSNET_INTERFACE + USBXpressNetInterface::classId, +#endif + XpressNetSerial::classId, + RocoZ21::classId, + VirtualCommandStation::classId + ); static std::shared_ptr create(const std::weak_ptr& world, std::string_view classId, std::string_view id); }; diff --git a/server/src/hardware/controller/controllerlist.cpp b/server/src/hardware/controller/controllerlist.cpp index 94f84593..86df2fe6 100644 --- a/server/src/hardware/controller/controllerlist.cpp +++ b/server/src/hardware/controller/controllerlist.cpp @@ -30,23 +30,24 @@ ControllerList::ControllerList(Object& _parent, const std::string& parentPropertyName) : ObjectList(_parent, parentPropertyName), add{*this, "add", - [this]() - { - auto world = getWorld(&this->parent()); - if(!world) - return std::shared_ptr(); - auto controller = Controllers::create(world, "controller.wlanmaus", world->getUniqueId("controller")); - if(auto* cs = dynamic_cast(&this->parent())) - controller->commandStation = cs->shared_ptr(); - //else if(world->commandStations->length() == 1) - // decoder->commandStation = cs->shared_ptr(); - return controller; - }} + [this](std::string_view classId) + { + auto world = getWorld(&this->parent()); + if(!world) + return std::shared_ptr(); + auto controller = Controllers::create(world, classId, world->getUniqueId("controller")); + if(auto* cs = dynamic_cast(&this->parent())) + controller->commandStation = cs->shared_ptr(); + //else if(world->commandStations->length() == 1) + // decoder->commandStation = cs->shared_ptr(); + return controller; + }} { auto world = getWorld(&_parent); const bool editable = world && contains(world->state.value(), WorldState::Edit); Attributes::addEnabled(add, editable); + Attributes::addClassList(add, Controllers::classList); m_interfaceItems.add(add); } diff --git a/server/src/hardware/controller/controllerlist.hpp b/server/src/hardware/controller/controllerlist.hpp index 40250255..68019ccb 100644 --- a/server/src/hardware/controller/controllerlist.hpp +++ b/server/src/hardware/controller/controllerlist.hpp @@ -37,7 +37,7 @@ class ControllerList : public ObjectList public: CLASS_ID("controller_list") - Method()> add; + Method(std::string_view)> add; ControllerList(Object& _parent, const std::string& parentPropertyName); diff --git a/server/src/hardware/controller/controllers.cpp b/server/src/hardware/controller/controllers.cpp index 977a58fe..5ac8d724 100644 --- a/server/src/hardware/controller/controllers.cpp +++ b/server/src/hardware/controller/controllers.cpp @@ -21,15 +21,6 @@ */ #include "controllers.hpp" -#include "wlanmaus.hpp" - -const std::vector& Controllers::classList() -{ - static std::vector list({ - WLANmaus::classId, - }); - return list; -} std::shared_ptr Controllers::create(const std::weak_ptr& world, std::string_view classId, std::string_view id) { diff --git a/server/src/hardware/controller/controllers.hpp b/server/src/hardware/controller/controllers.hpp index b82bb41e..c0487e14 100644 --- a/server/src/hardware/controller/controllers.hpp +++ b/server/src/hardware/controller/controllers.hpp @@ -24,12 +24,17 @@ #define TRAINTASTIC_SERVER_HARDWARE_CONTROLLER_CONTROLLERS_HPP #include "controller.hpp" +#include "../../utils/makearray.hpp" + +#include "wlanmaus.hpp" struct Controllers { static constexpr std::string_view classIdPrefix = "controller."; - static const std::vector& classList(); + static constexpr auto classList = makeArray( + WLANmaus::classId + ); static std::shared_ptr create(const std::weak_ptr& world, std::string_view classId, std::string_view id); }; diff --git a/server/src/utils/makearray.hpp b/server/src/utils/makearray.hpp new file mode 100644 index 00000000..a70dc9df --- /dev/null +++ b/server/src/utils/makearray.hpp @@ -0,0 +1,36 @@ +/** + * server/src/utils/makearray.hpp + * + * This file is part of the traintastic source code. + * + * Copyright (C) 2019-2020 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_SERVER_UTILS_MAKEARRAY_HPP +#define TRAINTASTIC_SERVER_UTILS_MAKEARRAY_HPP + +#include +#include +#include + +template +constexpr std::array, 1 + sizeof...(Ts)> makeArray(T&& t, Ts&&... ts) noexcept(noexcept(std::is_nothrow_constructible, 1 + sizeof... (Ts)>, T&&, Ts&&...>::value)) +{ + return {{std::forward(t), std::forward(ts)...}}; +} + +#endif diff --git a/server/src/vehicle/rail/railvehiclelist.cpp b/server/src/vehicle/rail/railvehiclelist.cpp index 25dc707f..26913231 100644 --- a/server/src/vehicle/rail/railvehiclelist.cpp +++ b/server/src/vehicle/rail/railvehiclelist.cpp @@ -41,6 +41,7 @@ RailVehicleList::RailVehicleList(Object& _parent, const std::string& parentPrope const bool editable = world && contains(world->state.value(), WorldState::Edit); Attributes::addEnabled(add, editable); + Attributes::addClassList(add, RailVehicles::classList); m_interfaceItems.add(add); } diff --git a/server/src/vehicle/rail/railvehicles.cpp b/server/src/vehicle/rail/railvehicles.cpp index 8c3ccdef..d6f68d9a 100644 --- a/server/src/vehicle/rail/railvehicles.cpp +++ b/server/src/vehicle/rail/railvehicles.cpp @@ -21,17 +21,6 @@ */ #include "railvehicles.hpp" -#include "locomotive.hpp" -#include "freightcar.hpp" - -const std::vector& RailVehicles::classList() -{ - static std::vector list({ - Locomotive::classId, - FreightCar::classId, - }); - return list; -} std::shared_ptr RailVehicles::create(const std::weak_ptr& world, std::string_view classId, std::string_view id) { diff --git a/server/src/vehicle/rail/railvehicles.hpp b/server/src/vehicle/rail/railvehicles.hpp index 6e902f6b..fa0872ff 100644 --- a/server/src/vehicle/rail/railvehicles.hpp +++ b/server/src/vehicle/rail/railvehicles.hpp @@ -24,12 +24,19 @@ #define TRAINTASTIC_SERVER_VEHICLE_RAIL_RAILVEHICLES_HPP #include "railvehicle.hpp" +#include "../../utils/makearray.hpp" + +#include "locomotive.hpp" +#include "freightcar.hpp" struct RailVehicles { static constexpr std::string_view classIdPrefix = "vehicle.rail."; - static const std::vector& classList(); + static constexpr auto classList = makeArray( + Locomotive::classId, + FreightCar::classId + ); static std::shared_ptr create(const std::weak_ptr& world, std::string_view classId, std::string_view id); }; diff --git a/shared/src/traintastic/enum/attributename.hpp b/shared/src/traintastic/enum/attributename.hpp index c35b3616..8243393a 100644 --- a/shared/src/traintastic/enum/attributename.hpp +++ b/shared/src/traintastic/enum/attributename.hpp @@ -35,6 +35,7 @@ enum class AttributeName : uint16_t ObjectEditor = 5, Values = 6, SubObject = 7, + ClassList = 8, }; #endif