WIP: attribute support

Dieser Commit ist enthalten in:
reinder 2019-12-21 19:08:30 +01:00
Ursprung 33f4db0d4b
Commit af084bff45
51 geänderte Dateien mit 895 neuen und 153 gelöschten Zeilen

Datei anzeigen

@ -36,6 +36,7 @@
#include "network/object.hpp" #include "network/object.hpp"
#include "network/property.hpp" #include "network/property.hpp"
#include "subwindow/hardwarelistsubwindow.hpp" #include "subwindow/hardwarelistsubwindow.hpp"
#include "subwindow/objecteditsubwindow.hpp"
#include "subwindow/serversettingssubwindow.hpp" #include "subwindow/serversettingssubwindow.hpp"
#include "subwindow/serverconsolesubwindow.hpp" #include "subwindow/serverconsolesubwindow.hpp"
@ -47,6 +48,8 @@ MainWindow::MainWindow(QWidget* parent) :
QMainWindow(parent), QMainWindow(parent),
m_mdiArea{new QMdiArea()} m_mdiArea{new QMdiArea()}
{ {
instance = this;
setWindowTitle("Traintastic"); setWindowTitle("Traintastic");
QAction* actFullScreen; QAction* actFullScreen;
@ -207,6 +210,21 @@ void MainWindow::toggleFullScreen()
} }
} }
void MainWindow::showObjectEdit(const QString& id)
{
if(!m_mdiSubWindow.objectEdit.contains(id))
{
ObjectEditSubWindow* window = new ObjectEditSubWindow(id);
m_mdiArea->addSubWindow(window);
window->setAttribute(Qt::WA_DeleteOnClose);
connect(window, &QMdiSubWindow::destroyed, [this, id](QObject*){ m_mdiSubWindow.objectEdit.remove(id); });
window->show();
m_mdiSubWindow.objectEdit[id] = window;
}
else
m_mdiArea->setActiveSubWindow(m_mdiSubWindow.objectEdit[id]);
}
void MainWindow::showHardware() void MainWindow::showHardware()
{ {
if(!m_mdiSubWindow.hardwareList) if(!m_mdiSubWindow.hardwareList)

Datei anzeigen

@ -25,10 +25,12 @@
#define MAINWINDOW_HPP #define MAINWINDOW_HPP
#include <QMainWindow> #include <QMainWindow>
#include <QMap>
#include <enum/traintasticmode.hpp> #include <enum/traintasticmode.hpp>
class QMdiArea; class QMdiArea;
class QActionGroup; class QActionGroup;
class ObjectEditSubWindow;
class HardwareListSubWindow; class HardwareListSubWindow;
class ServerSettingsSubWindow; class ServerSettingsSubWindow;
class ServerConsoleSubWindow; class ServerConsoleSubWindow;
@ -41,6 +43,7 @@ class MainWindow : public QMainWindow
QMdiArea* m_mdiArea; QMdiArea* m_mdiArea;
struct struct
{ {
QMap<QString, ObjectEditSubWindow*> objectEdit;
HardwareListSubWindow* hardwareList = nullptr; HardwareListSubWindow* hardwareList = nullptr;
ServerSettingsSubWindow* serverSettings = nullptr; ServerSettingsSubWindow* serverSettings = nullptr;
ServerConsoleSubWindow* serverConsole = nullptr; ServerConsoleSubWindow* serverConsole = nullptr;
@ -73,6 +76,7 @@ class MainWindow : public QMainWindow
void exportWorld(); void exportWorld();
void toggleFullScreen(); void toggleFullScreen();
void showHardware(); void showHardware();
void showServerSettings(); void showServerSettings();
void showServerConsole(); void showServerConsole();
void showAbout(); void showAbout();
@ -80,11 +84,14 @@ class MainWindow : public QMainWindow
void updateModeActions(); void updateModeActions();
public: public:
inline static MainWindow* instance = nullptr;
MainWindow(QWidget *parent = nullptr); MainWindow(QWidget *parent = nullptr);
~MainWindow() override; ~MainWindow() override;
public slots: public slots:
void connectToServer(); void connectToServer();
void showObjectEdit(const QString& id);
}; };
#endif #endif

Datei anzeigen

@ -24,7 +24,7 @@
#define CLIENT_NETWORK_ABSTRACTPROPERTY_HPP #define CLIENT_NETWORK_ABSTRACTPROPERTY_HPP
#include "interfaceitem.hpp" #include "interfaceitem.hpp"
#include <enum/propertytype.hpp> #include <enum/valuetype.hpp>
class Object; class Object;
@ -33,16 +33,16 @@ class AbstractProperty : public InterfaceItem
Q_OBJECT Q_OBJECT
protected: protected:
const PropertyType m_type; const ValueType m_type;
public: public:
explicit AbstractProperty(Object& object, const QString& name, PropertyType type) : explicit AbstractProperty(Object& object, const QString& name, ValueType type) :
InterfaceItem(object, name), InterfaceItem(object, name),
m_type{type} m_type{type}
{ {
} }
PropertyType type() const { return m_type; } ValueType type() const { return m_type; }
virtual const QString& enumName() const = 0; virtual const QString& enumName() const = 0;

Datei anzeigen

@ -29,7 +29,7 @@
#include "property.hpp" #include "property.hpp"
#include "tablemodel.hpp" #include "tablemodel.hpp"
#include <enum/interfaceitemtype.hpp> #include <enum/interfaceitemtype.hpp>
#include <enum/propertytype.hpp> #include <enum/valuetype.hpp>
Client* Client::instance = nullptr; Client* Client::instance = nullptr;
@ -125,7 +125,7 @@ void Client::setPropertyBool(Property& property, bool value)
auto event = Message::newEvent(Message::Command::ObjectSetProperty); auto event = Message::newEvent(Message::Command::ObjectSetProperty);
event->write(static_cast<Object*>(property.parent())->m_handle); event->write(static_cast<Object*>(property.parent())->m_handle);
event->write(property.name().toLatin1()); event->write(property.name().toLatin1());
event->write(PropertyType::Boolean); event->write(ValueType::Boolean);
event->write(value); event->write(value);
send(event); send(event);
} }
@ -135,7 +135,7 @@ void Client::setPropertyInt64(Property& property, int64_t value)
auto event = Message::newEvent(Message::Command::ObjectSetProperty); auto event = Message::newEvent(Message::Command::ObjectSetProperty);
event->write(static_cast<Object*>(property.parent())->m_handle); event->write(static_cast<Object*>(property.parent())->m_handle);
event->write(property.name().toLatin1()); event->write(property.name().toLatin1());
event->write(PropertyType::Integer); event->write(ValueType::Integer);
event->write(value); event->write(value);
send(event); send(event);
} }
@ -145,7 +145,7 @@ void Client::setPropertyDouble(Property& property, double value)
auto event = Message::newEvent(Message::Command::ObjectSetProperty); auto event = Message::newEvent(Message::Command::ObjectSetProperty);
event->write(static_cast<Object*>(property.parent())->m_handle); event->write(static_cast<Object*>(property.parent())->m_handle);
event->write(property.name().toLatin1()); event->write(property.name().toLatin1());
event->write(PropertyType::Float); event->write(ValueType::Float);
event->write(value); event->write(value);
send(event); send(event);
} }
@ -155,7 +155,7 @@ void Client::setPropertyString(Property& property, const QString& value)
auto event = Message::newEvent(Message::Command::ObjectSetProperty); auto event = Message::newEvent(Message::Command::ObjectSetProperty);
event->write(static_cast<Object*>(property.parent())->m_handle); event->write(static_cast<Object*>(property.parent())->m_handle);
event->write(property.name().toLatin1()); event->write(property.name().toLatin1());
event->write(PropertyType::String); event->write(ValueType::String);
event->write(value.toUtf8()); event->write(value.toUtf8());
send(event); send(event);
} }
@ -229,52 +229,96 @@ ObjectPtr Client::readObject(const Message& message)
while(!message.endOfBlock()) while(!message.endOfBlock())
{ {
message.readBlock(); // item message.readBlock(); // item
InterfaceItem* item = nullptr;
const QString name = QString::fromLatin1(message.read<QByteArray>()); const QString name = QString::fromLatin1(message.read<QByteArray>());
const InterfaceItemType type = message.read<InterfaceItemType>(); const InterfaceItemType type = message.read<InterfaceItemType>();
switch(type) switch(type)
{ {
case InterfaceItemType::Property: case InterfaceItemType::Property:
{ {
const PropertyType propertyType = message.read<PropertyType>(); const ValueType type = message.read<ValueType>();
QVariant value; QVariant value;
switch(propertyType) switch(type)
{ {
case PropertyType::Boolean: case ValueType::Boolean:
value = message.read<bool>(); value = message.read<bool>();
break; break;
case PropertyType::Enum: case ValueType::Enum:
case PropertyType::Integer: case ValueType::Integer:
value = message.read<qint64>(); value = message.read<qint64>();
break; break;
case PropertyType::Float: case ValueType::Float:
value = message.read<double>(); value = message.read<double>();
break; break;
case PropertyType::String: case ValueType::String:
value = QString::fromUtf8(message.read<QByteArray>()); value = QString::fromUtf8(message.read<QByteArray>());
break; break;
case PropertyType::Object: case ValueType::Object:
// TODO // TODO
break; break;
case PropertyType::Invalid: case ValueType::Invalid:
break; break;
} }
// Q_ASSERT(value.isValid()); // Q_ASSERT(value.isValid());
if(Q_LIKELY(value.isValid())) if(Q_LIKELY(value.isValid()))
{ {
Property* p = new Property(*obj, name, propertyType, value); Property* p = new Property(*obj, name, type, value);
if(propertyType == PropertyType::Enum) if(type == ValueType::Enum)
p->m_enumName = QString::fromLatin1(message.read<QByteArray>()); p->m_enumName = QString::fromLatin1(message.read<QByteArray>());
obj->m_interfaceItems.add(*p); item = p;
} }
break; break;
} }
} }
if(Q_LIKELY(item))
{
message.readBlock(); // attributes
while(!message.endOfBlock())
{
message.readBlock(); // item
const AttributeName attributeName = message.read<AttributeName>();
QVariant value;
switch(message.read<ValueType>())
{
case ValueType::Boolean:
value = message.read<bool>();
break;
case ValueType::Enum:
case ValueType::Integer:
value = message.read<qint64>();
break;
case ValueType::Float:
value = message.read<double>();
break;
case ValueType::String:
value = QString::fromUtf8(message.read<QByteArray>());
break;
case ValueType::Object:
case ValueType::Invalid:
Q_ASSERT(false);
break;
}
if(Q_LIKELY(value.isValid()))
item->m_attributes[attributeName] = value;
message.readBlockEnd(); // end attribute
}
message.readBlockEnd(); // end attributes
obj->m_interfaceItems.add(*item);
}
message.readBlockEnd(); // end item message.readBlockEnd(); // end item
} }
message.readBlockEnd(); // end items message.readBlockEnd(); // end items
@ -329,9 +373,9 @@ void Client::processMessage(const std::shared_ptr<Message> message)
{ {
if(Property* property = object->getProperty(QString::fromLatin1(message->read<QByteArray>()))) if(Property* property = object->getProperty(QString::fromLatin1(message->read<QByteArray>())))
{ {
switch(message->read<PropertyType>()) switch(message->read<ValueType>())
{ {
case PropertyType::Boolean: case ValueType::Boolean:
{ {
const bool value = message->read<bool>(); const bool value = message->read<bool>();
property->m_value = value; property->m_value = value;
@ -339,8 +383,8 @@ void Client::processMessage(const std::shared_ptr<Message> message)
emit property->valueChangedBool(value); emit property->valueChangedBool(value);
break; break;
} }
case PropertyType::Integer: case ValueType::Integer:
case PropertyType::Enum: case ValueType::Enum:
{ {
const qlonglong value = message->read<qlonglong>(); const qlonglong value = message->read<qlonglong>();
property->m_value = value; property->m_value = value;
@ -350,7 +394,7 @@ void Client::processMessage(const std::shared_ptr<Message> message)
emit property->valueChangedInt(static_cast<int>(value)); emit property->valueChangedInt(static_cast<int>(value));
break; break;
} }
case PropertyType::Float: case ValueType::Float:
{ {
const double value = message->read<double>(); const double value = message->read<double>();
property->m_value = value; property->m_value = value;
@ -358,7 +402,7 @@ void Client::processMessage(const std::shared_ptr<Message> message)
emit property->valueChangedDouble(value); emit property->valueChangedDouble(value);
break; break;
} }
case PropertyType::String: case ValueType::String:
{ {
const QString value = QString::fromUtf8(message->read<QByteArray>()); const QString value = QString::fromUtf8(message->read<QByteArray>());
property->m_value = value; property->m_value = value;
@ -371,6 +415,42 @@ void Client::processMessage(const std::shared_ptr<Message> message)
} }
break; break;
case Message::Command::ObjectAttributeChanged:
if(Object* object = m_objects.value(message->read<Handle>(), nullptr))
{
if(Property* property = object->getProperty(QString::fromLatin1(message->read<QByteArray>())))
{
AttributeName attributeName = message->read<AttributeName>();
QVariant value;
switch(message->read<ValueType>())
{
case ValueType::Boolean:
value = message->read<bool>();
break;
case ValueType::Integer:
case ValueType::Enum:
value = message->read<qlonglong>();
break;
case ValueType::Float:
value = message->read<double>();
break;
case ValueType::String:
value = QString::fromUtf8(message->read<QByteArray>());
break;
}
if(Q_LIKELY(value.isValid()))
{
property->m_attributes[attributeName] = value;
emit property->attributeChanged(attributeName, value);
}
}
}
break;
case Message::Command::TableModelColumnHeadersChanged: case Message::Command::TableModelColumnHeadersChanged:
if(TableModel* model = m_tableModels.value(message->read<Handle>(), nullptr)) if(TableModel* model = m_tableModels.value(message->read<Handle>(), nullptr))
{ {

Datei anzeigen

@ -28,3 +28,18 @@ InterfaceItem::InterfaceItem(Object& object, const QString& name) :
m_name{name} m_name{name}
{ {
} }
QVariant InterfaceItem::getAttribute(AttributeName name, const QVariant& default_) const
{
return m_attributes.value(name, default_);
}
bool InterfaceItem::getAttributeBool(AttributeName name, bool default_) const
{
return m_attributes.value(name, default_).toBool();
}
qint64 InterfaceItem::getAttributeInt64(AttributeName name, qint64 default_) const
{
return m_attributes.value(name, default_).toLongLong();
}

Datei anzeigen

@ -24,6 +24,9 @@
#define CLIENT_NETWORK_INTERFACEITEM_HPP #define CLIENT_NETWORK_INTERFACEITEM_HPP
#include <QObject> #include <QObject>
#include <QMap>
#include <QVariant>
#include <enum/attributename.hpp>
class Object; class Object;
@ -31,14 +34,30 @@ class InterfaceItem : public QObject
{ {
Q_OBJECT Q_OBJECT
friend class Client;
protected: protected:
const QString m_name; const QString m_name;
QMap<AttributeName, QVariant> m_attributes;
public: public:
explicit InterfaceItem(Object& object, const QString& name); explicit InterfaceItem(Object& object, const QString& name);
const QString& name() const { return m_name; } const QString& name() const { return m_name; }
const QString& displayName() const { return m_name; } const QString& displayName() const { return m_name; }
QVariant getAttribute(AttributeName name, const QVariant& default_) const;
bool getAttributeBool(AttributeName name, bool default_) const;
qint64 getAttributeInt64(AttributeName name, qint64 default_) const;
template<typename T>
T getAttributeEnum(AttributeName name, T default_) const
{
return static_cast<T>(getAttributeInt64(name, static_cast<qint64>(default_)));
}
signals:
void attributeChanged(AttributeName name, const QVariant& value);
}; };
#endif #endif

Datei anzeigen

@ -23,7 +23,7 @@
#include "property.hpp" #include "property.hpp"
#include "client.hpp" #include "client.hpp"
Property::Property(Object& object, const QString& name, PropertyType type, const QVariant& value) : Property::Property(Object& object, const QString& name, ValueType type, const QVariant& value) :
AbstractProperty(object, name, type), AbstractProperty(object, name, type),
m_value{value} m_value{value}
{ {

Datei anzeigen

@ -40,7 +40,7 @@ class Property : public AbstractProperty
QString m_enumName; QString m_enumName;
public: public:
explicit Property(Object& object, const QString& name, PropertyType type, const QVariant& value); explicit Property(Object& object, const QString& name, ValueType type, const QVariant& value);
const QString& enumName() const final { Q_ASSERT(!m_enumName.isEmpty()); return m_enumName; } const QString& enumName() const final { Q_ASSERT(!m_enumName.isEmpty()); return m_enumName; }

Datei anzeigen

@ -32,7 +32,7 @@ HardwareListSubWindow::HardwareListSubWindow(QWidget* parent) :
QMdiSubWindow(parent) QMdiSubWindow(parent)
{ {
setWindowTitle(tr("Hardware")); setWindowTitle(tr("Hardware"));
//setWindowIcon(QIcon(":/dark/hardware.svg")); setWindowIcon(QIcon(":/dark/hardware.svg"));
setWidget(new HardwareWidget(this)); setWidget(new HardwareWidget(this));
QSettings settings; QSettings settings;

Datei anzeigen

@ -0,0 +1,9 @@
#include "objecteditsubwindow.hpp"
#include "../widget/objecteditwidget.hpp"
ObjectEditSubWindow::ObjectEditSubWindow(const QString& id, QWidget* parent) :
QMdiSubWindow(parent)
{
setWindowTitle(id);
setWidget(new ObjectEditWidget(id, this));
}

Datei anzeigen

@ -0,0 +1,12 @@
#ifndef OBJECTEDITSUBWINDOW_HPP
#define OBJECTEDITSUBWINDOW_HPP
#include <QMdiSubWindow>
class ObjectEditSubWindow : public QMdiSubWindow
{
public:
ObjectEditSubWindow(const QString& id, QWidget* parent = nullptr);
};
#endif

Datei anzeigen

@ -35,9 +35,25 @@
#include "../widget/propertylineedit.hpp" #include "../widget/propertylineedit.hpp"
#include "../widget/propertytextedit.hpp" #include "../widget/propertytextedit.hpp"
#include "../widget/propertydirectioncontrol.hpp" #include "../widget/propertydirectioncontrol.hpp"
#include <enum/category.hpp>
#include <enum/direction.hpp> #include <enum/direction.hpp>
QString toString(Category value)
{
switch(value)
{
case Category::General: return "General";
case Category::Info: return "Info";
case Category::Notes: return "Notes";
case Category::Status: return "Status";
}
return "?";
}
ObjectEditWidget::ObjectEditWidget(const QString& id, QWidget* parent) : ObjectEditWidget::ObjectEditWidget(const QString& id, QWidget* parent) :
QWidget(parent), QWidget(parent),
m_id{id} m_id{id}
@ -67,31 +83,34 @@ ObjectEditWidget::~ObjectEditWidget()
void ObjectEditWidget::buildForm() void ObjectEditWidget::buildForm()
{ {
QMap<QString, QWidget*> tabs; QMap<Category, QWidget*> tabs;
QList<Category> tabOrder;
for(const QString& name : m_object->interfaceItems().names()) for(const QString& name : m_object->interfaceItems().names())
if(Property* property = m_object->getProperty(name)) if(Property* property = m_object->getProperty(name))
{ {
Category category = property->getAttributeEnum<Category>(AttributeName::Category, Category::General);
QWidget* w = nullptr; QWidget* w = nullptr;
if(property->type() == PropertyType::Boolean) if(property->type() == ValueType::Boolean)
w = new PropertyCheckBox(*property); w = new PropertyCheckBox(*property);
else if(property->type() == PropertyType::Integer) else if(property->type() == ValueType::Integer)
w = new PropertySpinBox(*property); w = new PropertySpinBox(*property);
else if(property->type() == PropertyType::String) else if(property->type() == ValueType::String)
{ {
if(property->name() == "notes") if(category == Category::Notes && property->name() == "notes")
{ {
PropertyTextEdit* edit = new PropertyTextEdit(*property); PropertyTextEdit* edit = new PropertyTextEdit(*property);
edit->setPlaceholderText(property->displayName()); edit->setPlaceholderText(property->displayName());
Q_ASSERT(!tabs.contains("notes")); Q_ASSERT(!tabs.contains(category));
tabs.insert("notes", edit); tabs.insert(category, edit);
tabOrder.append(category);
continue; continue;
} }
else else
w = new PropertyLineEdit(*property); w = new PropertyLineEdit(*property);
} }
else if(property->type() == PropertyType::Enum) else if(property->type() == ValueType::Enum)
{ {
if(property->enumName() == EnumName<Direction>::value) if(property->enumName() == EnumName<Direction>::value)
{ {
@ -103,15 +122,15 @@ void ObjectEditWidget::buildForm()
} }
QWidget* tabWidget; QWidget* tabWidget;
QString tab = "general"; // TODO: get sttribute if(!tabs.contains(category))
if(!tabs.contains(tab))
{ {
tabWidget = new QWidget(); tabWidget = new QWidget();
tabWidget->setLayout(new QFormLayout()); tabWidget->setLayout(new QFormLayout());
tabs.insert(tab, tabWidget); tabs.insert(category, tabWidget);
tabOrder.append(category);
} }
else else
tabWidget = tabs[tab]; tabWidget = tabs[category];
static_cast<QFormLayout*>(tabWidget->layout())->addRow(property->displayName(), w); static_cast<QFormLayout*>(tabWidget->layout())->addRow(property->displayName(), w);
} }
@ -119,8 +138,8 @@ void ObjectEditWidget::buildForm()
if(tabs.count() > 1) if(tabs.count() > 1)
{ {
QTabWidget* tabWidget = new QTabWidget(); QTabWidget* tabWidget = new QTabWidget();
for(auto it = tabs.constBegin(); it != tabs.constEnd(); it++) for(Category category : tabOrder)
tabWidget->addTab(it.value(), it.key()); tabWidget->addTab(tabs.value(category), toString(category));
QVBoxLayout* l = new QVBoxLayout(); QVBoxLayout* l = new QVBoxLayout();
l->setMargin(0); l->setMargin(0);
l->addWidget(tabWidget); l->addWidget(tabWidget);

Datei anzeigen

@ -33,7 +33,7 @@
#include "../widget/alertwidget.hpp" #include "../widget/alertwidget.hpp"
#include "objecteditwidget.hpp" #include "../mainwindow.hpp"
ObjectListWidget::ObjectListWidget(const QString& id, QWidget* parent) : ObjectListWidget::ObjectListWidget(const QString& id, QWidget* parent) :
QWidget(parent), QWidget(parent),
@ -111,7 +111,7 @@ void ObjectListWidget::tableDoubleClicked(const QModelIndex& index)
{ {
const QString id = m_tableWidget->getRowObjectId(index.row()); const QString id = m_tableWidget->getRowObjectId(index.row());
if(!id.isEmpty()) if(!id.isEmpty())
(new ObjectEditWidget(id))->show(); MainWindow::instance->showObjectEdit(id);//emit rowDoubleClicked(id);
} }

Datei anzeigen

@ -53,6 +53,9 @@ class ObjectListWidget : public QWidget
public: public:
explicit ObjectListWidget(const QString& id, QWidget* parent = nullptr); explicit ObjectListWidget(const QString& id, QWidget* parent = nullptr);
~ObjectListWidget() override; ~ObjectListWidget() override;
//signals:
// void rowDoubleClicked(const QString& id);
}; };
#endif #endif

Datei anzeigen

@ -23,12 +23,62 @@
#include "propertycheckbox.hpp" #include "propertycheckbox.hpp"
#include "../network/property.hpp" #include "../network/property.hpp"
class InternalUpdateHolder
{
private:
bool& m_value;
public:
inline InternalUpdateHolder(bool& value) :
m_value{value}
{
Q_ASSERT(!m_value);
m_value = true;
}
inline ~InternalUpdateHolder()
{
Q_ASSERT(m_value);
m_value = false;
}
};
PropertyCheckBox::PropertyCheckBox(Property& property, QWidget* parent) : PropertyCheckBox::PropertyCheckBox(Property& property, QWidget* parent) :
QCheckBox(parent), QCheckBox(parent),
m_property{property} m_property{property},
m_internalUpdate{false}
{ {
Q_ASSERT(m_property.type() == PropertyType::Boolean); Q_ASSERT(m_property.type() == ValueType::Boolean);
setEnabled(m_property.getAttributeBool(AttributeName::Enabled, true));
setVisible(m_property.getAttributeBool(AttributeName::Visible, true));
setChecked(m_property.toBool()); setChecked(m_property.toBool());
connect(&m_property, &Property::valueChangedBool, this, &PropertyCheckBox::setChecked); connect(&m_property, &Property::valueChangedBool,
connect(this, &PropertyCheckBox::toggled, &m_property, &Property::setValueBool); [this](bool value)
{
InternalUpdateHolder hold(m_internalUpdate);
setChecked(value);
});
connect(&m_property, &Property::attributeChanged,
[this](AttributeName name, const QVariant& value)
{
switch(name)
{
case AttributeName::Enabled:
setEnabled(value.toBool());
break;
case AttributeName::Visible:
setVisible(value.toBool());
break;
default:
break;
}
});
connect(this, &PropertyCheckBox::toggled,
[this](bool value)
{
if(!m_internalUpdate)
m_property.setValueBool(value);
});
} }

Datei anzeigen

@ -31,6 +31,7 @@ class PropertyCheckBox : public QCheckBox
{ {
protected: protected:
Property& m_property; Property& m_property;
bool m_internalUpdate;
public: public:
PropertyCheckBox(Property& property, QWidget* parent = nullptr); PropertyCheckBox(Property& property, QWidget* parent = nullptr);

Datei anzeigen

@ -34,21 +34,36 @@ PropertyDirectionControl::PropertyDirectionControl(Property& property, QWidget*
{ {
Q_ASSERT(property.enumName() == EnumName<Direction>::value); Q_ASSERT(property.enumName() == EnumName<Direction>::value);
QHBoxLayout* l = new QHBoxLayout(); setEnabled(m_property.getAttributeBool(AttributeName::Enabled, true));
setVisible(m_property.getAttributeBool(AttributeName::Visible, true));
m_reverse->setArrowType(Qt::LeftArrow); m_reverse->setArrowType(Qt::LeftArrow);
//m_reverse->setCheckable(true);
m_forward->setArrowType(Qt::RightArrow); m_forward->setArrowType(Qt::RightArrow);
//m_forward->setCheckable(true);
QHBoxLayout* l = new QHBoxLayout();
l->addWidget(m_reverse); l->addWidget(m_reverse);
l->addWidget(m_forward); l->addWidget(m_forward);
setLayout(l); setLayout(l);
setValue(m_property.toInt64()); setValue(m_property.toInt64());
connect(&m_property, &Property::valueChangedInt64, this, &PropertyDirectionControl::setValue); connect(&m_property, &Property::valueChangedInt64, this, &PropertyDirectionControl::setValue);
connect(&m_property, &Property::attributeChanged,
[this](AttributeName name, const QVariant& value)
{
switch(name)
{
case AttributeName::Enabled:
setEnabled(value.toBool());
break;
case AttributeName::Visible:
setVisible(value.toBool());
break;
default:
break;
}
});
connect(m_reverse, &QToolButton::clicked, this, &PropertyDirectionControl::buttonClicked); connect(m_reverse, &QToolButton::clicked, this, &PropertyDirectionControl::buttonClicked);
connect(m_forward, &QToolButton::clicked, this, &PropertyDirectionControl::buttonClicked); connect(m_forward, &QToolButton::clicked, this, &PropertyDirectionControl::buttonClicked);
} }

Datei anzeigen

@ -27,8 +27,27 @@ PropertyLineEdit::PropertyLineEdit(Property& property, QWidget* parent) :
QLineEdit(parent), QLineEdit(parent),
m_property{property} m_property{property}
{ {
Q_ASSERT(m_property.type() == PropertyType::String); Q_ASSERT(m_property.type() == ValueType::String);
setEnabled(m_property.getAttributeBool(AttributeName::Enabled, true));
setVisible(m_property.getAttributeBool(AttributeName::Visible, true));
setText(m_property.toString()); setText(m_property.toString());
connect(&m_property, &Property::valueChangedString, this, &PropertyLineEdit::setText); connect(&m_property, &Property::valueChangedString, this, &PropertyLineEdit::setText);
connect(&m_property, &Property::attributeChanged,
[this](AttributeName name, const QVariant& value)
{
switch(name)
{
case AttributeName::Enabled:
setEnabled(value.toBool());
break;
case AttributeName::Visible:
setVisible(value.toBool());
break;
default:
break;
}
});
connect(this, &PropertyLineEdit::textEdited, &m_property, &Property::setValueString); connect(this, &PropertyLineEdit::textEdited, &m_property, &Property::setValueString);
} }

Datei anzeigen

@ -27,9 +27,28 @@ PropertySpinBox::PropertySpinBox(AbstractProperty& property, QWidget* parent) :
QSpinBox(parent), QSpinBox(parent),
m_property{property} m_property{property}
{ {
Q_ASSERT(m_property.type() == PropertyType::Integer); Q_ASSERT(m_property.type() == ValueType::Integer);
setEnabled(m_property.getAttributeBool(AttributeName::Enabled, true));
setVisible(m_property.getAttributeBool(AttributeName::Visible, true));
setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max()); setRange(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
setValue(m_property.toInt()); setValue(m_property.toInt());
connect(&m_property, &AbstractProperty::valueChangedInt, this, &PropertySpinBox::setValue); connect(&m_property, &AbstractProperty::valueChangedInt, this, &PropertySpinBox::setValue);
connect(&m_property, &AbstractProperty::attributeChanged,
[this](AttributeName name, const QVariant& value)
{
switch(name)
{
case AttributeName::Enabled:
setEnabled(value.toBool());
break;
case AttributeName::Visible:
setVisible(value.toBool());
break;
default:
break;
}
});
connect(this, QOverload<int>::of(&PropertySpinBox::valueChanged), &m_property, &AbstractProperty::setValueInt); connect(this, QOverload<int>::of(&PropertySpinBox::valueChanged), &m_property, &AbstractProperty::setValueInt);
} }

Datei anzeigen

@ -27,8 +27,25 @@ PropertyTextEdit::PropertyTextEdit(Property& property, QWidget* parent) :
QTextEdit(parent), QTextEdit(parent),
m_property{property} m_property{property}
{ {
Q_ASSERT(m_property.type() == PropertyType::String); Q_ASSERT(m_property.type() == ValueType::String);
setPlainText(m_property.toString()); setPlainText(m_property.toString());
connect(&m_property, &Property::valueChangedString, this, &PropertyTextEdit::setPlainText); connect(&m_property, &Property::valueChangedString, this, &PropertyTextEdit::setPlainText);
connect(&m_property, &Property::attributeChanged,
[this](AttributeName name, const QVariant& value)
{
switch(name)
{
case AttributeName::Enabled:
setEnabled(value.toBool());
break;
case AttributeName::Visible:
setVisible(value.toBool());
break;
default:
break;
}
});
connect(this, &PropertyTextEdit::textChanged, [this](){ m_property.setValueString(toPlainText()); }); connect(this, &PropertyTextEdit::textChanged, [this](){ m_property.setValueString(toPlainText()); });
} }

Datei anzeigen

@ -43,7 +43,8 @@ SOURCES += \
src/widget/propertylineedit.cpp \ src/widget/propertylineedit.cpp \
src/widget/propertyspinbox.cpp \ src/widget/propertyspinbox.cpp \
src/widget/propertydirectioncontrol.cpp \ src/widget/propertydirectioncontrol.cpp \
src/widget/propertytextedit.cpp src/widget/propertytextedit.cpp \
src/subwindow/objecteditsubwindow.cpp
HEADERS += \ HEADERS += \
src/mainwindow.hpp \ src/mainwindow.hpp \
@ -77,7 +78,8 @@ HEADERS += \
src/widget/propertylineedit.hpp \ src/widget/propertylineedit.hpp \
src/widget/propertyspinbox.hpp \ src/widget/propertyspinbox.hpp \
src/widget/propertydirectioncontrol.hpp \ src/widget/propertydirectioncontrol.hpp \
src/widget/propertytextedit.hpp src/widget/propertytextedit.hpp \
src/subwindow/objecteditsubwindow.hpp
RESOURCES += \ RESOURCES += \
dark.qrc dark.qrc

Datei anzeigen

@ -0,0 +1,15 @@
#include "abstractattribute.hpp"
#include "interfaceitem.hpp"
#include "object.hpp"
AbstractAttribute::AbstractAttribute(InterfaceItem& item, AttributeName name, ValueType type) :
m_item{item},
m_name{name},
m_type{type}
{
}
void AbstractAttribute::changed()
{
m_item.object().attributeChanged(*this);
}

Datei anzeigen

@ -0,0 +1,32 @@
#ifndef ABSTRACTATTRIBUTE_HPP
#define ABSTRACTATTRIBUTE_HPP
#include <string>
#include <enum/attributename.hpp>
#include <enum/valuetype.hpp>
class InterfaceItem;
class AbstractAttribute
{
protected:
InterfaceItem& m_item;
const AttributeName m_name;
const ValueType m_type;
void changed();
public:
AbstractAttribute(InterfaceItem& item, AttributeName name, ValueType type);
inline InterfaceItem& item() const { return m_item; }
inline AttributeName name() const { return m_name; }
inline ValueType type() const { return m_type; }
virtual bool toBool() const = 0;
virtual int64_t toInt64() const = 0;
virtual double toDouble() const = 0;
virtual std::string toString() const = 0;
};
#endif

Datei anzeigen

@ -29,5 +29,5 @@ void AbstractProperty::changed()
{ {
std::cout << "AbstractProperty::changed" << std::endl; std::cout << "AbstractProperty::changed" << std::endl;
m_object.propertyChanged(m_object, *this); m_object.propertyChanged(*this);
} }

Datei anzeigen

@ -24,7 +24,7 @@
#define SERVER_CORE_ABSTRACTPROPERTY_HPP #define SERVER_CORE_ABSTRACTPROPERTY_HPP
#include "interfaceitem.hpp" #include "interfaceitem.hpp"
#include <enum/propertytype.hpp> #include <enum/valuetype.hpp>
#include "propertyflags.hpp" #include "propertyflags.hpp"
#include "objectptr.hpp" #include "objectptr.hpp"
#include <cassert> #include <cassert>
@ -33,18 +33,18 @@
class AbstractProperty : public InterfaceItem class AbstractProperty : public InterfaceItem
{ {
protected: protected:
const PropertyType m_type; const ValueType m_type;
PropertyFlags m_flags; PropertyFlags m_flags;
void changed(); void changed();
public: public:
AbstractProperty(Object& object, const std::string& name, PropertyType type, PropertyFlags flags) : AbstractProperty(Object& object, const std::string& name, ValueType type, PropertyFlags flags) :
InterfaceItem{object, name}, InterfaceItem{object, name},
m_type{type}, m_type{type},
m_flags{flags} m_flags{flags}
{ {
assert(type != PropertyType::Invalid); assert(type != ValueType::Invalid);
assert(is_access_valid(flags) && is_store_valid(flags)); assert(is_access_valid(flags) && is_store_valid(flags));
} }
@ -63,7 +63,7 @@ class AbstractProperty : public InterfaceItem
return true;//!is_empty(m_flags & PropertyFlags::WriteOnly); return true;//!is_empty(m_flags & PropertyFlags::WriteOnly);
} }
PropertyType type() const ValueType type() const
{ {
return m_type; return m_type;
} }

Datei anzeigen

@ -0,0 +1,51 @@
#ifndef INTERFACEITEMATTRIBUTE_HPP
#define INTERFACEITEMATTRIBUTE_HPP
#include "abstractattribute.hpp"
#include "to.hpp"
#include "valuetypetraits.hpp"
template<typename T>
class Attribute : public AbstractAttribute
{
protected:
T m_value;
public:
Attribute(InterfaceItem& item, AttributeName name, const T& value) :
AbstractAttribute{item, name, value_type_v<T>},
m_value{value}
{
}
bool toBool() const final
{
return to<bool>(m_value);
}
int64_t toInt64() const final
{
return to<int64_t>(m_value);
}
double toDouble() const final
{
return to<double>(m_value);
}
std::string toString() const final
{
return to<std::string>(m_value);
}
void setValue(const T& value)
{
if(m_value != value)
{
m_value = value;
changed();
}
}
};
#endif

Datei anzeigen

@ -36,7 +36,8 @@ IdObject::IdObject(const std::weak_ptr<World> world, const std::string& _id) :
return true; return true;
}} }}
{ {
m_interfaceItems.add(id); m_interfaceItems.add(id)
.addAttributeEnabled(false);
} }
IdObject::~IdObject() IdObject::~IdObject()
@ -50,3 +51,8 @@ void IdObject::addToWorld()
if(auto world = m_world.lock()) if(auto world = m_world.lock())
world->m_objects.emplace(id, weak_from_this()); world->m_objects.emplace(id, weak_from_this());
} }
void IdObject::modeChanged(TraintasticMode mode)
{
id.setAttributeEnabled(mode == TraintasticMode::Edit);
}

Datei anzeigen

@ -25,6 +25,7 @@
#include "object.hpp" #include "object.hpp"
#include "property.hpp" #include "property.hpp"
#include <enum/traintasticmode.hpp>
#define CREATE(T) \ #define CREATE(T) \
static std::shared_ptr<T> create(const std::weak_ptr<World>& world, const std::string& _id) \ static std::shared_ptr<T> create(const std::weak_ptr<World>& world, const std::string& _id) \
@ -43,6 +44,7 @@ class IdObject : public Object
IdObject(const std::weak_ptr<World> world, const std::string& _id); IdObject(const std::weak_ptr<World> world, const std::string& _id);
void addToWorld(); void addToWorld();
void modeChanged(TraintasticMode mode) override;
public: public:
Property<std::string> id; Property<std::string> id;

Datei anzeigen

@ -23,15 +23,36 @@
#ifndef SERVER_CORE_INTERFACEITEM_HPP #ifndef SERVER_CORE_INTERFACEITEM_HPP
#define SERVER_CORE_INTERFACEITEM_HPP #define SERVER_CORE_INTERFACEITEM_HPP
#include <unordered_map>
#include <string> #include <string>
#include <memory>
#include "attribute.hpp"
#include <enum/category.hpp>
class Object; class Object;
class InterfaceItem class InterfaceItem
{ {
public:
using Attributes = std::unordered_map<AttributeName, std::unique_ptr<AbstractAttribute>>;
protected: protected:
Object& m_object; Object& m_object;
const std::string m_name; const std::string m_name;
Attributes m_attributes;
template<typename T>
InterfaceItem& addAttribute(AttributeName name, const T& value)
{
m_attributes.emplace(name, std::make_unique<Attribute<T>>(*this, name, value));
return *this;
}
template<typename T>
void setAttribute(AttributeName name, const T& value)
{
static_cast<Attribute<T>*>(m_attributes[name].get())->setValue(value);
}
public: public:
InterfaceItem(Object& object, const std::string& name) : InterfaceItem(Object& object, const std::string& name) :
@ -53,6 +74,17 @@ class InterfaceItem
{ {
return m_name; return m_name;
} }
const Attributes& attributes() const
{
return m_attributes;
}
inline InterfaceItem& addAttributeCategory(Category value) { return addAttribute(AttributeName::Category, value); }
inline InterfaceItem& addAttributeEnabled(bool value) { return addAttribute(AttributeName::Enabled, value); }
inline InterfaceItem& addAttributeVisible(bool value) { return addAttribute(AttributeName::Visible, value); }
inline void setAttributeEnabled(bool value) { setAttribute(AttributeName::Enabled, value); }
}; };
#endif #endif

Datei anzeigen

@ -22,6 +22,7 @@
#include "interfaceitems.hpp" #include "interfaceitems.hpp"
#include "interfaceitem.hpp" #include "interfaceitem.hpp"
#include <algorithm>
InterfaceItem* InterfaceItems::find(const std::string& name) const InterfaceItem* InterfaceItems::find(const std::string& name) const
{ {
@ -29,8 +30,16 @@ InterfaceItem* InterfaceItems::find(const std::string& name) const
return (it != m_items.end()) ? &it->second : nullptr; return (it != m_items.end()) ? &it->second : nullptr;
} }
void InterfaceItems::add(InterfaceItem& item) InterfaceItem& InterfaceItems::add(InterfaceItem& item)
{ {
m_items.emplace(item.name(), item); m_items.emplace(item.name(), item);
m_itemOrder.push_back(item.name()); m_itemOrder.push_back(item.name());
return item;
}
InterfaceItem& InterfaceItems::insertBefore(InterfaceItem& item, const InterfaceItem& before)
{
m_items.emplace(item.name(), item);
m_itemOrder.insert(std::find(m_itemOrder.begin(), m_itemOrder.end(), before.name()), item.name());
return item;
} }

Datei anzeigen

@ -44,7 +44,9 @@ class InterfaceItems
const std::list<std::string>& names() const { return m_itemOrder; } const std::list<std::string>& names() const { return m_itemOrder; }
InterfaceItem* find(const std::string& name) const; InterfaceItem* find(const std::string& name) const;
void add(InterfaceItem& item);
InterfaceItem& add(InterfaceItem& item);
InterfaceItem& insertBefore(InterfaceItem& item, const InterfaceItem& before);
inline InterfaceItem& operator[](const std::string& name) const { return m_items.at(name); } inline InterfaceItem& operator[](const std::string& name) const { return m_items.at(name); }
}; };

Datei anzeigen

@ -26,6 +26,7 @@
#include "objectptr.hpp" #include "objectptr.hpp"
#include <boost/signals2/signal.hpp> #include <boost/signals2/signal.hpp>
#include "interfaceitems.hpp" #include "interfaceitems.hpp"
#include <enum/traintasticmode.hpp>
#define CLASS_ID(id) \ #define CLASS_ID(id) \
public: \ public: \
@ -34,17 +35,23 @@
class AbstractMethod; class AbstractMethod;
class AbstractProperty; class AbstractProperty;
class AbstractAttribute;
class Object : public std::enable_shared_from_this<Object> class Object : public std::enable_shared_from_this<Object>
{ {
friend class World;
protected: protected:
InterfaceItems m_interfaceItems; InterfaceItems m_interfaceItems;
//void log(LogLevel level, const std::string& message) const; //void log(LogLevel level, const std::string& message) const;
//inline void logError(const std::string& message) const { log(LogLevel::Error, message); } //inline void logError(const std::string& message) const { log(LogLevel::Error, message); }
virtual void modeChanged(TraintasticMode) {}
public: public:
boost::signals2::signal<void (Object& object, AbstractProperty&)> propertyChanged; boost::signals2::signal<void (AbstractProperty&)> propertyChanged;
boost::signals2::signal<void (AbstractAttribute&)> attributeChanged;
Object(); Object();
virtual ~Object(); virtual ~Object();

Datei anzeigen

@ -39,7 +39,7 @@ class ObjectProperty : public AbstractProperty
public: public:
ObjectProperty(Object* object, const std::string& name, const std::shared_ptr<T>& value, PropertyFlags flags) : ObjectProperty(Object* object, const std::string& name, const std::shared_ptr<T>& value, PropertyFlags flags) :
AbstractProperty(*object, name, PropertyType::Object, flags), AbstractProperty(*object, name, ValueType::Object, flags),
m_value{value} m_value{value}
{ {
} }

Datei anzeigen

@ -24,7 +24,7 @@
#define SERVER_CORE_PROPERTY_HPP #define SERVER_CORE_PROPERTY_HPP
#include "abstractproperty.hpp" #include "abstractproperty.hpp"
#include "propertytypetraits.hpp" #include "valuetypetraits.hpp"
#include "to.hpp" #include "to.hpp"
#include <functional> #include <functional>
#include <enum/enum.hpp> #include <enum/enum.hpp>
@ -43,7 +43,7 @@ class Property : public AbstractProperty
public: public:
Property(Object* object, const std::string& name, const T& value, PropertyFlags flags) : Property(Object* object, const std::string& name, const T& value, PropertyFlags flags) :
AbstractProperty(*object, name, property_type<T>::value, flags), AbstractProperty(*object, name, value_type<T>::value, flags),
m_value{value} m_value{value}
{ {
//static_assert(property_type<T>::value != PropertyType::Invalid); //static_assert(property_type<T>::value != PropertyType::Invalid);
@ -90,6 +90,15 @@ class Property : public AbstractProperty
throw invalid_value_error(); throw invalid_value_error();
} }
void setValueInternal(T value)
{
if(m_value != value)
{
m_value = value;
changed();
}
}
operator const T&() const operator const T&() const
{ {
return m_value; return m_value;

Datei anzeigen

@ -25,6 +25,7 @@
#include "traintastic.hpp" #include "traintastic.hpp"
#include "client.hpp" #include "client.hpp"
#include "abstractproperty.hpp" #include "abstractproperty.hpp"
#include "abstractattribute.hpp"
#include <enum/interfaceitemtype.hpp> #include <enum/interfaceitemtype.hpp>
#include "tablemodel.hpp" #include "tablemodel.hpp"
#include "world.hpp" #include "world.hpp"
@ -162,6 +163,8 @@ bool Session::processMessage(const Message& message)
Handle handle = message.read<Handle>(); Handle handle = message.read<Handle>();
Traintastic::instance->console->debug(m_client->m_id, "ReleaseObject: " + std::to_string(handle)); Traintastic::instance->console->debug(m_client->m_id, "ReleaseObject: " + std::to_string(handle));
m_handles.removeHandle(handle); m_handles.removeHandle(handle);
m_propertyChanged.erase(handle);
m_attributeChanged.erase(handle);
break; break;
} }
case Message::Command::ObjectSetProperty: case Message::Command::ObjectSetProperty:
@ -172,21 +175,21 @@ bool Session::processMessage(const Message& message)
{ {
try try
{ {
switch(message.read<PropertyType>()) switch(message.read<ValueType>())
{ {
case PropertyType::Boolean: case ValueType::Boolean:
property->fromBool(message.read<bool>()); property->fromBool(message.read<bool>());
break; break;
case PropertyType::Integer: case ValueType::Integer:
property->fromInt64(message.read<int64_t>()); property->fromInt64(message.read<int64_t>());
break; break;
case PropertyType::Float: case ValueType::Float:
property->fromDouble(message.read<double>()); property->fromDouble(message.read<double>());
break; break;
case PropertyType::String: case ValueType::String:
property->fromString(message.read<std::string>()); property->fromString(message.read<std::string>());
break; break;
} }
@ -194,7 +197,7 @@ bool Session::processMessage(const Message& message)
catch(const std::exception&) catch(const std::exception&)
{ {
// set property failed, send changed event with current value: // set property failed, send changed event with current value:
objectPropertyChanged(*object, *property); objectPropertyChanged(*property);
} }
} }
} }
@ -239,7 +242,8 @@ void Session::writeObject(Message& message, const ObjectPtr& object)
handle = m_handles.addItem(object); handle = m_handles.addItem(object);
m_propertyChanged.emplace(handle, object->propertyChanged.connect(std::bind(&Session::objectPropertyChanged, this, std::placeholders::_1, std::placeholders::_2))); m_propertyChanged.emplace(handle, object->propertyChanged.connect(std::bind(&Session::objectPropertyChanged, this, std::placeholders::_1)));
m_attributeChanged.emplace(handle, object->attributeChanged.connect(std::bind(&Session::objectAttributeChanged, this, std::placeholders::_1)));
message.write(handle); message.write(handle);
message.write(object->getClassId()); message.write(object->getClassId());
@ -261,28 +265,28 @@ void Session::writeObject(Message& message, const ObjectPtr& object)
message.write(property->type()); message.write(property->type());
switch(property->type()) switch(property->type())
{ {
case PropertyType::Boolean: case ValueType::Boolean:
message.write(property->toBool()); message.write(property->toBool());
break; break;
case PropertyType::Enum: case ValueType::Enum:
message.write(property->toInt64()); message.write(property->toInt64());
message.write(property->enumName()); message.write(property->enumName());
break; break;
case PropertyType::Integer: case ValueType::Integer:
message.write(property->toInt64()); message.write(property->toInt64());
break; break;
case PropertyType::Float: case ValueType::Float:
message.write(property->toDouble()); message.write(property->toDouble());
break; break;
case PropertyType::String: case ValueType::String:
message.write(property->toString()); message.write(property->toString());
break; break;
case PropertyType::Object: case ValueType::Object:
{ {
ObjectPtr obj = property->toObject(); ObjectPtr obj = property->toObject();
// TODO: assert(!obj || dynamic_cast<IdObject*>(obj.get())); // TODO: assert(!obj || dynamic_cast<IdObject*>(obj.get()));
@ -298,6 +302,41 @@ void Session::writeObject(Message& message, const ObjectPtr& object)
} }
} }
message.writeBlock(); // attributes
for(const auto& it : item.attributes())
{
const AbstractAttribute& attribute = *it.second;
message.writeBlock(); // attribute
message.write(attribute.name());
message.write(attribute.type());
switch(attribute.type())
{
case ValueType::Boolean:
message.write(attribute.toBool());
break;
case ValueType::Enum:
case ValueType::Integer:
message.write(attribute.toInt64());
break;
case ValueType::Float:
message.write(attribute.toDouble());
break;
case ValueType::String:
message.write(attribute.toString());
break;
default:
assert(false);
break;
}
message.writeBlockEnd(); // end attribute
}
message.writeBlockEnd(); // end attributes
message.writeBlockEnd(); // end item message.writeBlockEnd(); // end item
} }
message.writeBlockEnd(); // end items message.writeBlockEnd(); // end items
@ -322,32 +361,63 @@ void Session::writeTableModel(Message& message, const TableModelPtr& model)
message.writeBlockEnd(); // end model message.writeBlockEnd(); // end model
} }
void Session::objectPropertyChanged(Object& object, AbstractProperty& property) void Session::objectPropertyChanged(AbstractProperty& property)
{ {
std::cout << "objectPropertyChanged " << property.name() << std::endl; std::cout << "objectPropertyChanged " << property.name() << std::endl;
auto event = Message::newEvent(Message::Command::ObjectPropertyChanged); auto event = Message::newEvent(Message::Command::ObjectPropertyChanged);
event->write(m_handles.getHandle(object.shared_from_this())); event->write(m_handles.getHandle(property.object().shared_from_this()));
event->write(property.name()); event->write(property.name());
event->write(property.type()); event->write(property.type());
switch(property.type()) switch(property.type())
{ {
case PropertyType::Boolean: case ValueType::Boolean:
event->write(property.toBool()); event->write(property.toBool());
break; break;
case PropertyType::Enum: case ValueType::Enum:
case PropertyType::Integer: case ValueType::Integer:
event->write(property.toInt64()); event->write(property.toInt64());
break; break;
case PropertyType::Float: case ValueType::Float:
event->write(property.toDouble()); event->write(property.toDouble());
break; break;
case PropertyType::String: case ValueType::String:
event->write(property.toString()); event->write(property.toString());
break; break;
} }
m_client->sendMessage(std::move(event)); m_client->sendMessage(std::move(event));
} }
void Session::objectAttributeChanged(AbstractAttribute& attribute)
{
std::cout << "objectAttributeChanged " << attribute.item().name() << "." << (int)attribute.name() << std::endl;
auto event = Message::newEvent(Message::Command::ObjectAttributeChanged);
event->write(m_handles.getHandle(attribute.item().object().shared_from_this()));
event->write(attribute.item().name());
event->write(attribute.name());
event->write(attribute.type());
switch(attribute.type())
{
case ValueType::Boolean:
event->write(attribute.toBool());
break;
case ValueType::Enum:
case ValueType::Integer:
//event->write(attribute.toInt64());
break;
case ValueType::Float:
//event->write(attribute.toDouble());
break;
case ValueType::String:
//event->write(attribute.toString());
break;
}
m_client->sendMessage(std::move(event));
}

Datei anzeigen

@ -33,6 +33,7 @@
class Client; class Client;
class AbstractProperty; class AbstractProperty;
class AbstractAttribute;
class Session : public std::enable_shared_from_this<Session> class Session : public std::enable_shared_from_this<Session>
{ {
@ -46,13 +47,15 @@ class Session : public std::enable_shared_from_this<Session>
boost::uuids::uuid m_uuid; boost::uuids::uuid m_uuid;
Handles m_handles; Handles m_handles;
std::unordered_map<Handle, boost::signals2::connection> m_propertyChanged; std::unordered_map<Handle, boost::signals2::connection> m_propertyChanged;
std::unordered_map<Handle, boost::signals2::connection> m_attributeChanged;
bool processMessage(const Message& message); bool processMessage(const Message& message);
void writeObject(Message& message, const ObjectPtr& object); void writeObject(Message& message, const ObjectPtr& object);
void writeTableModel(Message& message, const TableModelPtr& model); void writeTableModel(Message& message, const TableModelPtr& model);
void objectPropertyChanged(Object& object, AbstractProperty& property); void objectPropertyChanged(AbstractProperty& property);
void objectAttributeChanged(AbstractAttribute& attribute);
public: public:
Session(const std::shared_ptr<Client>& client); Session(const std::shared_ptr<Client>& client);

Datei anzeigen

@ -50,7 +50,7 @@ Traintastic::Traintastic(const std::filesystem::path& dataDir) :
{ {
assert(world); assert(world);
console->info(id, "Mode changed to <TODO> " + std::to_string((int)value)); console->info(id, "Mode changed to <TODO> " + std::to_string((int)value));
//world->modeChanged(value); world->modeChanged(value);
}, },
[this](TraintasticMode& newValue) [this](TraintasticMode& newValue)
{ {

Datei anzeigen

@ -1,5 +1,5 @@
/** /**
* server/src/core/propertytypetraits.hpp * server/src/core/valuetypetraits.hpp
* *
* This file is part of the traintastic source code. * This file is part of the traintastic source code.
* *
@ -20,22 +20,25 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#ifndef SERVER_CORE_PROPERTYTYPETRAITS_HPP #ifndef SERVER_CORE_VALUETYPETRAITS_HPP
#define SERVER_CORE_PROPERTYTYPETRAITS_HPP #define SERVER_CORE_VALUETYPETRAITS_HPP
#include <enum/propertytype.hpp> #include <enum/valuetype.hpp>
#include "objectptr.hpp" #include "objectptr.hpp"
template<typename T> template<typename T>
struct property_type struct value_type
{ {
static constexpr PropertyType value = static constexpr ValueType value =
std::is_same<T, bool>::value ? PropertyType::Boolean : ( std::is_same_v<T, bool> ? ValueType::Boolean : (
std::is_enum<T>::value ? PropertyType::Enum : ( std::is_enum_v<T> ? ValueType::Enum : (
std::is_integral<T>::value ? PropertyType::Integer : ( std::is_integral_v<T> ? ValueType::Integer : (
std::is_floating_point<T>::value ? PropertyType::Float : ( std::is_floating_point_v<T> ? ValueType::Float : (
std::is_same<T, std::string>::value ? PropertyType::String : ( std::is_same_v<T, std::string> ? ValueType::String : (
PropertyType::Invalid))))); ValueType::Invalid)))));
}; };
template<typename T>
inline constexpr ValueType value_type_v = value_type<T>::value;
#endif #endif

Datei anzeigen

@ -103,6 +103,14 @@ ObjectPtr World::getObject(const std::string& _id) const
return ObjectPtr(); return ObjectPtr();
} }
void World::modeChanged(TraintasticMode mode)
{
Traintastic::instance->console->debug(id, "World::modeChanged");
for(auto& it : m_objects)
it.second.lock()->modeChanged(mode);
}
void World::load() void World::load()
{ {
std::ifstream file(m_filename); std::ifstream file(m_filename);
@ -218,7 +226,7 @@ void World::save()
for(auto& item : object->interfaceItems()) for(auto& item : object->interfaceItems())
if(AbstractProperty* property = dynamic_cast<AbstractProperty*>(&item.second)) if(AbstractProperty* property = dynamic_cast<AbstractProperty*>(&item.second))
{ {
if(property->type() == PropertyType::Object) if(property->type() == ValueType::Object)
{ {
if(IdObject* idObject = dynamic_cast<IdObject*>(property->toObject().get())) if(IdObject* idObject = dynamic_cast<IdObject*>(property->toObject().get()))
objectData[property->name()] = idObject->id.toJSON(); objectData[property->name()] = idObject->id.toJSON();

Datei anzeigen

@ -37,6 +37,7 @@
class World : public Object class World : public Object
{ {
friend class IdObject; friend class IdObject;
friend class Traintastic;
protected: protected:
static const std::string id; static const std::string id;
@ -47,6 +48,7 @@ class World : public Object
boost::uuids::uuid m_uuid; boost::uuids::uuid m_uuid;
std::unordered_map<std::string, std::weak_ptr<Object>> m_objects; std::unordered_map<std::string, std::weak_ptr<Object>> m_objects;
void modeChanged(TraintasticMode mode);
void load(); void load();
public: public:

Datei anzeigen

@ -40,7 +40,8 @@ CommandStation::CommandStation(const std::weak_ptr<World>& world, const std::str
m_interfaceItems.add(online); m_interfaceItems.add(online);
m_interfaceItems.add(status); m_interfaceItems.add(status);
m_interfaceItems.add(decoders); m_interfaceItems.add(decoders);
m_interfaceItems.add(notes); m_interfaceItems.add(notes)
.addAttributeCategory(Category::Notes);
} }
const std::shared_ptr<Decoder>& CommandStation::getDecoder(DecoderProtocol protocol, uint16_t address, bool longAddress) const const std::shared_ptr<Decoder>& CommandStation::getDecoder(DecoderProtocol protocol, uint16_t address, bool longAddress) const

Datei anzeigen

@ -39,14 +39,16 @@
#define Z21_LAN_X_UNKNOWN_COMMAND 0x82 #define Z21_LAN_X_UNKNOWN_COMMAND 0x82
#define Z21_LAN_X_BC_STOPPED 0x81 #define Z21_LAN_X_BC_STOPPED 0x81
#define Z21_LAN_X_LOCO_INFO 0xEF #define Z21_LAN_X_LOCO_INFO 0xEF
#define Z21_LAN_SET_BROADCASTFLAGS 0x50
#define Z21_LAN_GET_BROADCASTFLAGS 0x51
#define Z21_LAN_SYSTEMSTATE_DATACHANGED 0x84 #define Z21_LAN_SYSTEMSTATE_DATACHANGED 0x84
#define Z21_LAN_SYSTEMSTATE_GETDATA 0x85 #define Z21_LAN_SYSTEMSTATE_GETDATA 0x85
#define Z21_HWT_Z21_OLD 0x00000200 //!< „black Z21” (hardware variant from 2012) #define Z21_HWT_Z21_OLD 0x00000200 //!< „black Z21” (hardware variant from 2012)
#define Z21_HWT_Z21_NEW 0x00000201 //!< „black Z21”(hardware variant from 2013) #define Z21_HWT_Z21_NEW 0x00000201 //!< „black Z21”(hardware variant from 2013)
#define Z21_HWT_SMARTRAIL 0x00000202 //!< SmartRail (from 2012) #define Z21_HWT_SMARTRAIL 0x00000202 //!< SmartRail (from 2012)
#define Z21_HWT_z21_SMALL 0x00000203 //!< „white z21” starter set variant (from 2013) #define Z21_HWT_Z21_SMALL 0x00000203 //!< „white z21” starter set variant (from 2013)
#define Z21_HWT_z21_START 0x00000204 //!< „z21 start” starter set variant (from 2016) #define Z21_HWT_Z21_START 0x00000204 //!< „z21 start” starter set variant (from 2016)
#define Z21_CENTRALSTATE_EMERGENCYSTOP 0x01 //!< The emergency stop is switched on #define Z21_CENTRALSTATE_EMERGENCYSTOP 0x01 //!< The emergency stop is switched on
#define Z21_CENTRALSTATE_TRACKVOLTAGEOFF 0x02 //!< The track voltage is switched off #define Z21_CENTRALSTATE_TRACKVOLTAGEOFF 0x02 //!< The track voltage is switched off
@ -153,6 +155,23 @@ struct z21_lan_x_set_track_power_on : z21_lan_x
} }
} __attribute__((packed)); } __attribute__((packed));
struct z21_lan_x_get_loco_info : z21_lan_x
{
uint8_t db0;
uint8_t addressHigh;
uint8_t addressLow;
uint8_t checksum;
z21_lan_x_get_loco_info() :
db0{0xF0}
{
dataLen = sizeof(z21_lan_x_get_loco_info);
header = Z21_LAN_X;
xheader = 0xE3;
}
} __attribute__((packed));
//static_assert(sizeof(z21_lan_x_get_loco_info) == 0x07);
struct z21_lan_x_loco_info : z21_lan_x struct z21_lan_x_loco_info : z21_lan_x
{ {
uint8_t addressHigh; uint8_t addressHigh;
@ -197,6 +216,29 @@ struct z21_lan_systemstate_getdata : z21_lan_header
} __attribute__((packed)); } __attribute__((packed));
static_assert(sizeof(z21_lan_systemstate_getdata) == 0x04); static_assert(sizeof(z21_lan_systemstate_getdata) == 0x04);
struct z21_lan_set_broadcastflags : z21_lan_header
{
uint32_t broadcastFlags; // LE
z21_lan_set_broadcastflags(uint32_t _broadcastFlags = 0) :
broadcastFlags{_broadcastFlags}
{
dataLen = sizeof(z21_lan_set_broadcastflags);
header = Z21_LAN_SET_BROADCASTFLAGS;
}
} __attribute__((packed));
static_assert(sizeof(z21_lan_set_broadcastflags) == 0x08);
struct z21_lan_get_broadcastflags : z21_lan_header
{
z21_lan_get_broadcastflags()
{
dataLen = sizeof(z21_lan_get_broadcastflags);
header = Z21_LAN_GET_BROADCASTFLAGS;
}
} __attribute__((packed));
static_assert(sizeof(z21_lan_get_broadcastflags) == 0x04);
struct z21_lan_systemstate_datachanged : z21_lan_header struct z21_lan_systemstate_datachanged : z21_lan_header
{ {
int16_t mainCurrent; //!< Current on the main track in mA int16_t mainCurrent; //!< Current on the main track in mA

Datei anzeigen

@ -63,33 +63,43 @@ Z21::Z21(const std::weak_ptr<World>& world, const std::string& _id) :
m_socket{Traintastic::instance->ioContext()}, m_socket{Traintastic::instance->ioContext()},
hostname{this, "hostname", "", PropertyFlags::AccessWCC}, hostname{this, "hostname", "", PropertyFlags::AccessWCC},
port{this, "port", 21105, PropertyFlags::AccessWCC}, port{this, "port", 21105, PropertyFlags::AccessWCC},
serialNumber{this, "serial_number", 0, PropertyFlags::AccessRRR}, serialNumber{this, "serial_number", "", PropertyFlags::AccessRRR},
hardwareType{this, "hardware_type", "", PropertyFlags::AccessRRR}, hardwareType{this, "hardware_type", "", PropertyFlags::AccessRRR},
firmwareVersion{this, "firmware_version", "", PropertyFlags::AccessRRR}, firmwareVersion{this, "firmware_version", "", PropertyFlags::AccessRRR},
emergencyStop{this, "emergency_stop", false, PropertyFlags::TODO, emergencyStop{this, "emergency_stop", false, PropertyFlags::TODO,
[this](bool value) [this](bool value)
{ {
if(value) if(online && value)
send(z21_lan_x_set_stop()); send(z21_lan_x_set_stop());
}}, }},
trackVoltageOff{this, "track_voltage_off", false, PropertyFlags::TODO, trackVoltageOff{this, "track_voltage_off", false, PropertyFlags::TODO,
[this](bool value) [this](bool value)
{
if(online)
{ {
if(value) if(value)
send(z21_lan_x_set_track_power_off()); send(z21_lan_x_set_track_power_off());
else else
send(z21_lan_x_set_track_power_on()); send(z21_lan_x_set_track_power_on());
}
}} }}
{ {
name = "Z21"; name = "Z21";
m_interfaceItems.add(hostname); m_interfaceItems.insertBefore(hostname, notes)
m_interfaceItems.add(port); .addAttributeEnabled(true);
m_interfaceItems.add(serialNumber); m_interfaceItems.insertBefore(port, notes)
m_interfaceItems.add(hardwareType); .addAttributeEnabled(true);
m_interfaceItems.add(firmwareVersion); m_interfaceItems.insertBefore(serialNumber, notes)
m_interfaceItems.add(emergencyStop); .addAttributeCategory(Category::Info);
m_interfaceItems.add(trackVoltageOff); m_interfaceItems.insertBefore(hardwareType, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(firmwareVersion, notes)
.addAttributeCategory(Category::Info);
m_interfaceItems.insertBefore(emergencyStop, notes)
.addAttributeEnabled(false);
m_interfaceItems.insertBefore(trackVoltageOff, notes)
.addAttributeEnabled(false);
} }
bool Z21::isDecoderSupported(Decoder& decoder) const bool Z21::isDecoderSupported(Decoder& decoder) const
@ -194,13 +204,41 @@ bool Z21::setOnline(bool& value)
Traintastic::instance->console->error(id, "socket.bind: " + ec.message()); Traintastic::instance->console->error(id, "socket.bind: " + ec.message());
return false; return false;
} }
receive();
send(z21_lan_set_broadcastflags(/*0x00010000 |*/ 0x00000100 | 0x00000001));
// try to communicate with Z21 // try to communicate with Z21
send(z21_lan_get_broadcastflags());
send(z21_lan_get_serial_number()); send(z21_lan_get_serial_number());
send(z21_lan_get_hwinfo()); send(z21_lan_get_hwinfo());
send(z21_lan_systemstate_getdata()); send(z21_lan_systemstate_getdata());
/*
for(auto& decoder : decoders)
{
z21_lan_x_get_loco_info cmd;
send(cmd);
}
*/
hostname.setAttributeEnabled(false);
port.setAttributeEnabled(false);
emergencyStop.setAttributeEnabled(true);
trackVoltageOff.setAttributeEnabled(true);
} }
else if(m_socket.is_open() && !value) else if(m_socket.is_open() && !value)
{ {
send(z21_lan_logoff());
serialNumber = "";
hardwareType = "";
firmwareVersion = "";
hostname.setAttributeEnabled(true);
port.setAttributeEnabled(true);
emergencyStop.setAttributeEnabled(false);
trackVoltageOff.setAttributeEnabled(false);
m_socket.close(); m_socket.close();
} }
return true; return true;
@ -221,9 +259,9 @@ void Z21::receive()
case Z21_LAN_GET_SERIAL_NUMBER: case Z21_LAN_GET_SERIAL_NUMBER:
{ {
EventLoop::call( EventLoop::call(
[this, value=static_cast<const z21_lan_get_serial_number_reply*>(cmd)->serialNumber]() [this, value=std::to_string(static_cast<const z21_lan_get_serial_number_reply*>(cmd)->serialNumber)]()
{ {
serialNumber = value; serialNumber.setValueInternal(value);
}); });
break; break;
} }
@ -243,10 +281,10 @@ void Z21::receive()
case Z21_HWT_SMARTRAIL: case Z21_HWT_SMARTRAIL:
hwType = "SmartRail (from 2012)"; hwType = "SmartRail (from 2012)";
break; break;
case Z21_HWT_z21_SMALL: case Z21_HWT_Z21_SMALL:
hwType = "White Z21 (starter set variant from 2013)"; hwType = "White Z21 (starter set variant from 2013)";
break; break;
case Z21_HWT_z21_START : case Z21_HWT_Z21_START :
hwType = "Z21 start (starter set variant from 2016)"; hwType = "Z21 start (starter set variant from 2016)";
break; break;
default: default:
@ -259,8 +297,8 @@ void Z21::receive()
EventLoop::call( EventLoop::call(
[this, hwType, fwVersion]() [this, hwType, fwVersion]()
{ {
hardwareType = hwType; hardwareType.setValueInternal(hwType);
firmwareVersion = fwVersion; firmwareVersion.setValueInternal(fwVersion);
}); });
break; break;
} }
@ -294,13 +332,13 @@ void Z21::receive()
if((speedStepMode == 0 && decoder->speedSteps == 14) || if((speedStepMode == 0 && decoder->speedSteps == 14) ||
(speedStepMode == 2 && decoder->speedSteps == 28) || (speedStepMode == 2 && decoder->speedSteps == 28) ||
(speedStepMode == 4 && decoder->speedSteps == 126)) (speedStepMode == 4 && decoder->speedSteps == 126))
decoder->speedStep = speedStep; decoder->speedStep.setValueInternal(speedStep);
for(auto& function : *decoder->functions) for(auto& function : *decoder->functions)
{ {
const uint8_t number = function->number; const uint8_t number = function->number;
if(number <= 28) if(number <= 28)
function->value = functions & (1 << number); function->value.setValueInternal(functions & (1 << number));
} }
} }
}); });
@ -315,7 +353,7 @@ void Z21::receive()
EventLoop::call( EventLoop::call(
[this]() [this]()
{ {
emergencyStop = true; emergencyStop.setValueInternal(true);
}); });
break; break;
@ -331,8 +369,8 @@ void Z21::receive()
EventLoop::call( EventLoop::call(
[this, state]() [this, state]()
{ {
emergencyStop = state.centralState & Z21_CENTRALSTATE_EMERGENCYSTOP; emergencyStop.setValueInternal(state.centralState & Z21_CENTRALSTATE_EMERGENCYSTOP);
trackVoltageOff = state.centralState & Z21_CENTRALSTATE_TRACKVOLTAGEOFF; trackVoltageOff.setValueInternal(state.centralState & Z21_CENTRALSTATE_TRACKVOLTAGEOFF);
}); });
break; break;
} }

Datei anzeigen

@ -56,7 +56,7 @@ class Z21 : public CommandStation
Property<std::string> hostname; Property<std::string> hostname;
Property<uint16_t> port; Property<uint16_t> port;
Property<uint32_t> serialNumber; Property<std::string> serialNumber;
Property<std::string> hardwareType; Property<std::string> hardwareType;
Property<std::string> firmwareVersion; Property<std::string> firmwareVersion;
Property<bool> emergencyStop; Property<bool> emergencyStop;

Datei anzeigen

@ -81,13 +81,20 @@ Decoder::Decoder(const std::weak_ptr<World>& world, const std::string& _id) :
notes{this, "notes", "", PropertyFlags::AccessWWW} notes{this, "notes", "", PropertyFlags::AccessWWW}
{ {
m_interfaceItems.add(name); m_interfaceItems.add(name);
m_interfaceItems.add(commandStation); m_interfaceItems.add(commandStation)
m_interfaceItems.add(protocol); .addAttributeEnabled(false);
m_interfaceItems.add(address); m_interfaceItems.add(protocol)
m_interfaceItems.add(emergencyStop); .addAttributeEnabled(false);
m_interfaceItems.add(direction); m_interfaceItems.add(address)
m_interfaceItems.add(speedSteps); .addAttributeEnabled(false);
m_interfaceItems.add(speedStep); m_interfaceItems.add(emergencyStop)
.addAttributeEnabled(false);
m_interfaceItems.add(direction)
.addAttributeEnabled(false);
m_interfaceItems.add(speedSteps)
.addAttributeEnabled(false);
m_interfaceItems.add(speedStep)
.addAttributeEnabled(false);
m_interfaceItems.add(functions); m_interfaceItems.add(functions);
m_interfaceItems.add(notes); m_interfaceItems.add(notes);
} }
@ -101,6 +108,20 @@ const std::shared_ptr<DecoderFunction>& Decoder::getFunction(uint32_t number) co
return DecoderFunction::null; return DecoderFunction::null;
} }
void Decoder::modeChanged(TraintasticMode mode)
{
IdObject::modeChanged(mode);
commandStation.setAttributeEnabled(mode == TraintasticMode::Edit);
protocol.setAttributeEnabled(mode == TraintasticMode::Edit);
address.setAttributeEnabled(mode == TraintasticMode::Edit);
speedSteps.setAttributeEnabled(mode == TraintasticMode::Edit);
speedStep.setAttributeEnabled(mode == TraintasticMode::Run);
if(mode == TraintasticMode::Edit)
speedStep = 0;
}
void Decoder::changed(DecoderChangeFlags changes, uint32_t functionNumber) void Decoder::changed(DecoderChangeFlags changes, uint32_t functionNumber)
{ {
if(commandStation) if(commandStation)

Datei anzeigen

@ -46,6 +46,7 @@ class Decoder : public IdObject
friend class DecoderFunction; friend class DecoderFunction;
protected: protected:
void modeChanged(TraintasticMode mode) final;
void changed(DecoderChangeFlags changes, uint32_t functionNumber = 0); void changed(DecoderChangeFlags changes, uint32_t functionNumber = 0);
public: public:

Datei anzeigen

@ -0,0 +1,6 @@
#ifndef ATTRIBUTES_HPP
#define ATTRIBUTES_HPP
#endif // ATTRIBUTES_HPP

Datei anzeigen

@ -0,0 +1,38 @@
/**
* shared/src/enum/propertytype.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 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 SHARED_ENUM_ATTIRBUTE_HPP
#define SHARED_ENUM_ATTIRBUTE_HPP
#include <cstdint>
enum class AttributeName : uint16_t
{
Visible = 0,
Enabled = 1,
Min = 2,
Max = 3,
Category = 4,
};
#endif

37
shared/src/enum/category.hpp Normale Datei
Datei anzeigen

@ -0,0 +1,37 @@
/**
* shared/src/enum/category.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 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 SHARED_ENUM_CATEGORY_HPP
#define SHARED_ENUM_CATEGORY_HPP
#include <cstdint>
enum class Category : uint16_t
{
General = 0,
Notes = 1,
Status = 2,
Info = 3,
};
#endif

Datei anzeigen

@ -1,5 +1,5 @@
/** /**
* shared/src/enum/propertytype.hpp * shared/src/enum/valuetype.hpp
* *
* This file is part of the traintastic source code. * This file is part of the traintastic source code.
* *
@ -20,12 +20,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#ifndef SHARED_ENUM_PROPERTYTYPE_HPP #ifndef SHARED_ENUM_VALUETYPE_HPP
#define SHARED_ENUM_PROPERTYTYPE_HPP #define SHARED_ENUM_VALUETYPE_HPP
#include <cstdint> #include <cstdint>
enum class PropertyType : uint8_t enum class ValueType : uint8_t
{ {
Invalid = 0, Invalid = 0,
Boolean = 1, Boolean = 1,

Datei anzeigen

@ -59,12 +59,14 @@ class Message
ReleaseObject = 15, ReleaseObject = 15,
ObjectSetProperty = 16, ObjectSetProperty = 16,
ObjectPropertyChanged = 17, ObjectPropertyChanged = 17,
GetTableModel = 18, ObjectAttributeChanged = 18,
ReleaseTableModel = 19,
TableModelColumnHeadersChanged = 20, GetTableModel = 19,
TableModelRowCountChanged = 21, ReleaseTableModel = 20,
TableModelSetRegion = 22, TableModelColumnHeadersChanged = 21,
TableModelUpdateRegion = 23, TableModelRowCountChanged = 22,
TableModelSetRegion = 23,
TableModelUpdateRegion = 24,
Discover = 255, Discover = 255,
}; };