Dieser Commit ist enthalten in:
reinder 2020-04-29 15:42:30 +02:00
Ursprung e8172078d6
Commit 0b800ef124
165 geänderte Dateien mit 3175 neuen und 390 gelöschten Zeilen

2
.gitignore vendored
Datei anzeigen

@ -40,3 +40,5 @@
.build*
build*
CMakeLists.txt.*
*~*
.vscode

Datei anzeigen

@ -25,9 +25,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="46.002732"
inkscape:cy="45.48465"
inkscape:zoom="7.919596"
inkscape:cx="33.328085"
inkscape:cy="30.22358"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="true"
@ -51,7 +51,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
<cc:license
rdf:resource="http://creativecommons.org/licenses/by-nc/4.0/" />
</cc:Work>
@ -104,5 +104,10 @@
d="m 20.108333,286.41665 c -2.303233,-0.10271 -3.014867,3.1754 -0.78079,3.91852 2.232157,0.99084 3.0625,-2.19831 1.497019,-3.42866 -0.199377,-0.2124 -0.44335,-0.38535 -0.716229,-0.48986 z"
id="path2025"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:#003380;fill-opacity:1;stroke:#003380;stroke-width:1.41118586;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 16.933332,280.77231 c -0.859926,0 -1.552214,0.69228 -1.552214,1.55222 v 4.65664 h -4.656644 c -0.8599264,0 -1.5522144,0.69225 -1.5522144,1.55218 0,0.85996 0.692288,1.55219 1.5522144,1.55219 h 4.656644 v 4.65665 c 0,0.85991 0.692288,1.5522 1.552214,1.5522 0.85993,0 1.552218,-0.69229 1.552218,-1.5522 v -4.65665 h 4.656642 c 0.859928,0 1.552215,-0.69225 1.552215,-1.55219 0,-0.85993 -0.692287,-1.55218 -1.552215,-1.55218 H 18.48555 v -4.65664 c 0,-0.85994 -0.692288,-1.55222 -1.552218,-1.55222 z"
id="rect843" />
</g>
</svg>

Vorher

Breite:  |  Höhe:  |  Größe: 5.4 KiB

Nachher

Breite:  |  Höhe:  |  Größe: 6.1 KiB

Datei anzeigen

@ -42,6 +42,7 @@
#include <QDesktopServices>
#include <locale/locale.hpp>
#include <codename.hpp>
#define SETTING_PREFIX "mainwindow/"
#define SETTING_GEOMETRY SETTING_PREFIX "geometry"
@ -91,7 +92,9 @@ MainWindow::MainWindow(QWidget* parent) :
if(Method* method = traintastic->getMethod("new_world"))
method->call();
});
m_actionNewWorld->setShortcut(QKeySequence::New);
m_actionLoadWorld = menu->addAction(QIcon(":/dark/world_load.svg"), Locale::tr("qtapp.mainmenu:load_world") + "...", this, &MainWindow::loadWorld);
m_actionLoadWorld->setShortcut(QKeySequence::Open);
m_actionSaveWorld = menu->addAction(QIcon(":/dark/world_save.svg"), Locale::tr("qtapp.mainmenu:save_world"),
[this]()
{
@ -99,11 +102,12 @@ MainWindow::MainWindow(QWidget* parent) :
if(Method* method = m_world->getMethod("save"))
method->call();
});
m_actionSaveWorld->setShortcut(QKeySequence::Save);
menu->addSeparator();
m_actionImportWorld = menu->addAction(QIcon(":/dark/world_import.svg"), Locale::tr("qtapp.mainmenu:import_world") + "...", this, &MainWindow::importWorld);
m_actionExportWorld = menu->addAction(QIcon(":/dark/world_export.svg"), Locale::tr("qtapp.mainmenu:export_world") + "...", this, &MainWindow::exportWorld);
menu->addSeparator();
menu->addAction(Locale::tr("qtapp.mainmenu:quit"), this, &MainWindow::close);
menu->addAction(Locale::tr("qtapp.mainmenu:quit"), this, &MainWindow::close)->setShortcut(QKeySequence::Quit);
menu = menuBar()->addMenu(Locale::tr("qtapp.mainmenu:view"));
actFullScreen = menu->addAction(Locale::tr("qtapp.mainmenu:fullscreen"), this, &MainWindow::toggleFullScreen);
@ -112,11 +116,12 @@ MainWindow::MainWindow(QWidget* parent) :
m_menuObjects = menuBar()->addMenu(Locale::tr("qtapp.mainmenu:objects"));
menu = m_menuObjects->addMenu(QIcon(":/dark/hardware.svg"), Locale::tr("qtapp.mainmenu:hardware"));
menu->addAction(Locale::tr("world:command_stations") + "...", [this](){ showObject("world.command_stations"); });
menu->addAction(Locale::tr("world:decoders") + "...", [this](){ showObject("world.decoders"); });
menu->addAction(Locale::tr("world:inputs") + "...", [this](){ showObject("world.inputs"); });
menu->addAction(Locale::tr("world:command_stations") + "...", [this](){ showObject("world.command_stations", Locale::tr("world:command_stations")); });
menu->addAction(Locale::tr("world:decoders") + "...", [this](){ showObject("world.decoders", Locale::tr("world:decoders")); });
menu->addAction(Locale::tr("world:inputs") + "...", [this](){ showObject("world.inputs", Locale::tr("world:inputs")); });
menu->addAction(Locale::tr("world:controllers") + "...", [this](){ showObject("world.controllers", Locale::tr("world:controllers")); });
m_menuObjects->addAction(Locale::tr("world:clock") + "...", [this](){ showObject("world.clock"); });
m_menuObjects->addAction(QIcon(":/dark/lua.svg"), Locale::tr("world:lua_scripts") + "...", [this](){ showObject("world.lua_scripts"); });
m_menuObjects->addAction(QIcon(":/dark/lua.svg"), Locale::tr("world:lua_scripts") + "...", [this](){ showObject("world.lua_scripts", Locale::tr("world:lua_scripts")); });
menu = menuBar()->addMenu(Locale::tr("qtapp.mainmenu:tools"));
menu->addAction(Locale::tr("qtapp.mainmenu:settings") + "...")->setEnabled(false);
@ -126,7 +131,7 @@ MainWindow::MainWindow(QWidget* parent) :
m_actionServerConsole->setShortcut(Qt::Key_F12);
menu = menuBar()->addMenu(Locale::tr("qtapp.mainmenu:help"));
menu->addAction(Locale::tr("qtapp.mainmenu:help"), [](){ QDesktopServices::openUrl("https://traintastic.org/manual?version=" + QApplication::applicationVersion()); })->setShortcut(Qt::Key_F1);
menu->addAction(Locale::tr("qtapp.mainmenu:help"), [](){ QDesktopServices::openUrl("https://traintastic.org/manual?version=" + QApplication::applicationVersion()); })->setShortcut(QKeySequence::HelpContents);
//menu->addSeparator();
//menu->addAction(Locale::tr("qtapp.mainmenu:about_qt") + "...", qApp, &QApplication::aboutQt);
menu->addAction(Locale::tr("qtapp.mainmenu:about") + "...", this, &MainWindow::showAbout);
@ -224,16 +229,10 @@ void MainWindow::connectToServer()
connect(m_connection.data(), &Connection::worldChanged,
[this]()
{
m_world = m_connection->world();
if(m_world)
{
if(AbstractProperty* edit = m_world->getProperty("edit"))
connect(edit, &AbstractProperty::valueChangedBool, m_actionEdit, &QAction::setChecked);
}
worldChanged();
updateActions();
});
worldChanged();
clientStateChanged();
}
}
@ -257,16 +256,16 @@ void MainWindow::closeEvent(QCloseEvent* event)
QMainWindow::closeEvent(event);
}
/*void MainWindow::setMode(TraintasticMode value)
void MainWindow::worldChanged()
{
if(!m_connection)
return;
m_world = m_connection->world();
if(m_connection->state() == Connection::State::Connected && m_connection->traintastic())
m_connection->traintastic()->getProperty("mode")->setValueInt64(static_cast<int64_t>(value));
else
updateModeActions();
}*/
if(m_world)
{
if(AbstractProperty* edit = m_world->getProperty("edit"))
connect(edit, &AbstractProperty::valueChangedBool, m_actionEdit, &QAction::setChecked);
}
}
void MainWindow::loadWorld()
{
@ -348,11 +347,13 @@ void MainWindow::showObject(const ObjectPtr& object)
m_mdiArea->setActiveSubWindow(m_mdiSubWindows[id]);
}
void MainWindow::showObject(const QString& id)
void MainWindow::showObject(const QString& id, const QString& title)
{
if(!m_mdiSubWindows.contains(id))
{
QMdiSubWindow* window = new ObjectSubWindow(m_connection, id);
if(!title.isEmpty())
window->setWindowTitle(title);
m_mdiSubWindows[id] = window;
m_mdiArea->addSubWindow(window);
window->setAttribute(Qt::WA_DeleteOnClose);
@ -366,7 +367,7 @@ void MainWindow::showObject(const QString& id)
void MainWindow::showAbout()
{
QMessageBox::about(this, tr("About Traintastic"),
"<h2>Traintastic <small>v" + QApplication::applicationVersion() + "</small></h2>"
"<h2>Traintastic v" + QApplication::applicationVersion() + " <small>" TRAINTASTIC_CODENAME "</small></h2>"
"<p>Copyright &copy; 2019-2020 Reinder Feenstra</p>"
"<p>This program is free software; you can redistribute it and/or"
" modify it under the terms of the GNU General Public License"

Datei anzeigen

@ -65,7 +65,7 @@ class MainWindow : public QMainWindow
QByteArray m_beforeFullScreenGeometry;
void closeEvent(QCloseEvent* event) final;
void setMode(TraintasticMode value);
void worldChanged();
protected slots:
void disconnectFromServer();
@ -89,7 +89,7 @@ class MainWindow : public QMainWindow
public slots:
void connectToServer();
void showObject(const ObjectPtr& object);
void showObject(const QString& id);
void showObject(const QString& id, const QString& title = "");
};
#endif

Datei anzeigen

@ -66,5 +66,6 @@ void ObjectSubWindow::setObject(const ObjectPtr& object)
{
setWidget(createWidget(object));
connect(widget(), &QWidget::windowTitleChanged, this, &ObjectSubWindow::setWindowTitle);
setWindowTitle(widget()->windowTitle());
if(!widget()->windowTitle().isEmpty())
setWindowTitle(widget()->windowTitle());
}

Datei anzeigen

@ -42,6 +42,8 @@ QWidget* createWidgetIfCustom(const ObjectPtr& object, QWidget* parent)
return new DecoderFunctionListWidget(object, parent);
else if(classId == "input_list")
return new InputListWidget(object, parent);
else if(classId == "controller_list")
return new ObjectListWidget(object, parent);
else if(classId == "lua.script_list")
return new LuaScriptListWidget(object, parent);
else if(classId == "console")

Datei anzeigen

@ -93,6 +93,13 @@ ObjectListWidget::ObjectListWidget(const ObjectPtr& object, QWidget* parent) :
});
});
m_actionAdd->setEnabled(method->getAttributeBool(AttributeName::Enabled, true));
connect(method, &Method::attributeChanged,
[this](AttributeName name, QVariant value)
{
if(name == AttributeName::Enabled)
m_actionAdd->setEnabled(value.toBool());
});
}
}

7
doc/css/bootstrap.min.css vendored Normale Datei

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -0,0 +1,15 @@
body {
background: #DCDCDC;
}
div#body {
max-width: 1200px;
margin: 0 auto 0 auto;
}
div#content {
border-left: #BEBEBE 1px solid;
border-right: #BEBEBE 1px solid;
background: white;
padding: 1em;
}

56
doc/data/pages.json Normale Datei
Datei anzeigen

@ -0,0 +1,56 @@
{
"id": "index",
"md_file": "index.md",
"sub_pages": [
{
"id": "installation",
"md_file": "installation.md"
},
{
"id": "getting_started",
"md_file": "gettingstarted.md"
},
{
"id": "hardware",
"md_file": "hardware.md",
"sub_pages": [
{
"id": "command_stations",
"md_file": "commandstations.md",
"sub_pages": [
{
"id": "dr5000",
"md_file": "dr5000.md"
},
{
"id": "intellibox",
"md_file": "intellibox.md"
},
{
"id": "z21",
"md_file": "z21.md"
}
]
},
{
"id": "decoder",
"md_file": "decoder.md",
"sub_pages": [
{
"id": "function",
"md_file": "decoderfunction.md"
}
]
}
]
},
{
"id": "lua",
"md_file": "lua.md"
},
{
"id": "command_line_options",
"md_file": "commandlineoptions.md"
}
]
}

Datei anzeigen

@ -0,0 +1,162 @@
{
"columns": [
{
"label": {
"en-us": "Command station",
"nl-nl": "Centrale"
}
},
{
"label": {
"en-us": "Interface"
}
},
{
"label": {
"en-us": "Features",
},
"columns": [
{
"label": {
"en-us": "Decoder control"
}
},
{
"label": {
"en-us": "Decoder programming"
}
},
{
"label": "S88"
}
]
},
{
"label": {
"en-us": "Operating system",
},
"columns": [
{
"label": "Windows"
},
{
"label": "Linux"
}
]
}
],
"rows": [
[
{
"text": "Digikeijs DR5000"
},
{
"text": "LAN/Z21"
},
{
"icon": "checkmark_green"
},
{
"icon": "x_red"
},
{
"icon": "checkmark_green"
},
{
"icon": "checkmark_green"
}
],
[
{
"text": "Roco 10764"
},
{
"text": "XpressNet"
},
{
"icon": "checkmark_green"
},
{
"icon": "x_red"
},
{
"label": "-"
},
{
"icon": "checkmark_green"
},
{
"icon": "checkmark_green"
}
],
[
{
"text": "Roco/Fleischmann Z21"
},
{
"text": "LAN/Z21"
},
{
"icon": "checkmark_green"
},
{
"icon": "x_red"
},
{
"icon": "checkmark_green"
},
{
"icon": "checkmark_green"
}
],
[
{
"text": "Uhlenbrock Intellibox (IB)"
},
[
{
"text": {
"en-us": "Serial/P50X",
"nl-nl": "Serieel/P50X"
}
},
{
"text": "Loconet"
}
],
{
"icon": "checkmark_green"
},
{
"icon": "x_red"
},
[
{
"icon": "checkmark_green"
},
{
"icon": "questionmark_blue"
}
]
[
{
"icon": "checkmark_green"
},
{
}
],
[
{
"icon": "checkmark_green"
},
{
}
]
]
],
"footnotes": {
"1": ""
}
}

Datei anzeigen

@ -1 +1,5 @@
= Command line options
# Command line options

15
doc/en-us/commandstations.md Normale Datei
Datei anzeigen

@ -0,0 +1,15 @@
# Command stations
## Supported command stations
{table:supportedcommandstations}
### Loconet
### XpressNet

1
doc/en-us/decoder.md Normale Datei
Datei anzeigen

@ -0,0 +1 @@
# Decoder

Datei anzeigen

@ -0,0 +1 @@
# Decoder function

2
doc/en-us/dr5000.md Normale Datei
Datei anzeigen

@ -0,0 +1,2 @@
# Digikeijs DR5000

Datei anzeigen

@ -1 +1 @@
= Getting started
# Getting started

3
doc/en-us/hardware.md Normale Datei
Datei anzeigen

@ -0,0 +1,3 @@
# Hardware
- [objects/hardware/commandstations.md](Command stations)
- [objects/hardware/decoders.md](Decoders)

2
doc/en-us/index.md Normale Datei
Datei anzeigen

@ -0,0 +1,2 @@
# Traintastic manual

Datei anzeigen

@ -1,5 +1,5 @@
= Installation
# Installation
== Windows
## Windows
== Linux
## Linux

2
doc/en-us/intellibox.md Normale Datei
Datei anzeigen

@ -0,0 +1,2 @@
# Uhlenbrock Intellibox

Datei anzeigen

@ -1 +1 @@
= Lua scripting
# Lua scripting

Datei anzeigen

@ -1,5 +0,0 @@
= Objects
== Hardware
- [objects/hardware/commandstations.md](Command stations)
- [objects/hardware/decoders.md](Decoders)

Datei anzeigen

@ -1,2 +0,0 @@
= Command stations

Datei anzeigen

@ -1,2 +0,0 @@
= Digikeijs DR5000

Datei anzeigen

@ -1,2 +0,0 @@
= Roco/Fleischmann Z21

Datei anzeigen

@ -1 +0,0 @@
= Decoder

Datei anzeigen

@ -1 +0,0 @@
= Decoder function

2
doc/en-us/z21.md Normale Datei
Datei anzeigen

@ -0,0 +1,2 @@
# Roco/Fleischmann Z21

13
doc/en-us/z21app.md Normale Datei
Datei anzeigen

@ -0,0 +1,13 @@
# Z21 app
## Known issues
1. Locomotive status updates slow.
Reason: If the traintastic-server is restarted or the Z21 app controller is temparary deacribated, it looses the client registtation ans it will no longer receive update.
Solution: Restart the Z21 app on your phone/tablet, the it wil re-register and everything should work as expected.

Datei anzeigen

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
height="172.0002"
width="172.0002"
viewBox="-15 -190 172.0002 172.0002"
version="1.1"
id="ProfielUIC60E2">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<desc
id="desc2">
Op basis van 'Profilehandbuch_Section_Programme', van VoestAlpine Schienen GMBH
</desc>
<path
d="m -1.9999008,-190 a 2,2 0 0 0 -2,2 v 5.81552 a 4,4 0 0 0 3.71501198,3.98984 l 15.73981082,1.12427 a 40,40 0 0 1 10.819841,2.30661 l 28.223767,10.26319 a 7,7 0 0 1 4.263605,4.41055 35,35 0 0 1 0.7875,2.81061 120,120 0 0 1 3.200464,27.52941 v 32.000001 a 120,120 0 0 1 -3.200465,27.529412 35,35 0 0 1 -0.787499,2.810609 7,7 0 0 1 -4.263605,4.41055 l -18.576167,6.75497 a 3,3 0 0 0 -1.971027,2.969193 l 1.048763,20.975266 a 13,13 0 0 0 9.972669,11.99639 80,80 0 0 0 15.799331,2.129409 300,300 0 0 0 20.456,0 80,80 0 0 0 15.79933,-2.129409 13,13 0 0 0 9.972671,-11.99639 l 1.04876,-20.975266 a 3,3 0 0 0 -1.97102,-2.969193 l -18.576172,-6.75497 a 7,7 0 0 1 -4.263605,-4.41055 35,35 0 0 1 -0.7875,-2.810609 120,120 0 0 1 -3.200464,-27.529412 V -129.75 a 120,120 0 0 1 3.200464,-27.52941 35,35 0 0 1 0.7875,-2.81061 7,7 0 0 1 4.263605,-4.41055 l 28.223772,-10.26319 a 40,40 0 0 1 10.81984,-2.30661 l 15.73981,-1.12427 a 4,4 0 0 0 3.71501,-3.98984 V -188 a 2,2 0 0 0 -2,-2 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="Profiel" />
</svg>

Nachher

Breite:  |  Höhe:  |  Größe: 1.9 KiB

7
doc/js/bootstrap.min.js vendored Normale Datei

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

2
doc/js/jquery-3.4.1.slim.min.js vendored Normale Datei

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

5
doc/js/popper.min.js vendored Normale Datei

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

10
doc/template/footer.html vendored Normale Datei
Datei anzeigen

@ -0,0 +1,10 @@
</div>
<div id="footer" class="text-center text-light bg-dark py-2">
<small>Copyright &copy; 2019-${year}</small>
</div>
</div>
<script src="${js_path}jquery-3.4.1.slim.min.js"></script>
<script src="${js_path}popper.min.js"></script>
<script src="${js_path}bootstrap.min.js"></script>
</body>
</html>

41
doc/template/header.html vendored Normale Datei
Datei anzeigen

@ -0,0 +1,41 @@
<!doctype html>
<html lang="${language}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="${css_path}bootstrap.min.css">
<link rel="stylesheet" href="${css_path}traintastic-manual.css">
</head>
<body>
<nav class="navbar navbar-dark bg-dark navbar-expand-lg">
<a class="navbar-brand" href="/"><img src="${gfx_path}traintastic-logo-white.svg" width="30" height="30" class="d-inline-block align-top" alt=""> Traintastic ${nav_manual}</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<!--div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class="nav-link" href="/usb-xpressnet-interface">USB XpressNet interface</a></li>
</ul>
</div-->
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
<li class="nav-item dropdown">
<a class="nav-item nav-link dropdown-toggle mr-md-2" href="#" id="languages" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
${language}
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="languages">
${language_menu}
</div>
</li>
<!-- VERSION_BEGIN -->
<li class="navbar-text">
v?.?.?
</li>
<!-- VERSION_END -->
<li class="nav-item">
<a class="nav-link p-2" href="https://github.com/traintastic/traintastic" target="_blank" rel="noopener" aria-label="GitHub"><svg class="navbar-nav-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 499.36" focusable="false"><title>GitHub</title><path d="M256 0C114.64 0 0 114.61 0 256c0 113.09 73.34 209 175.08 242.9 12.8 2.35 17.47-5.56 17.47-12.34 0-6.08-.22-22.18-.35-43.54-71.2 15.49-86.2-34.34-86.2-34.34-11.64-29.57-28.42-37.45-28.42-37.45-23.27-15.84 1.73-15.55 1.73-15.55 25.69 1.81 39.21 26.38 39.21 26.38 22.84 39.12 59.92 27.82 74.5 21.27 2.33-16.54 8.94-27.82 16.25-34.22-56.84-6.43-116.6-28.43-116.6-126.49 0-27.95 10-50.8 26.35-68.69-2.63-6.48-11.42-32.5 2.51-67.75 0 0 21.49-6.88 70.4 26.24a242.65 242.65 0 0 1 128.18 0c48.87-33.13 70.33-26.24 70.33-26.24 14 35.25 5.18 61.27 2.55 67.75 16.41 17.9 26.31 40.75 26.31 68.69 0 98.35-59.85 120-116.88 126.32 9.19 7.9 17.38 23.53 17.38 47.41 0 34.22-.31 61.83-.31 70.23 0 6.85 4.61 14.81 17.6 12.31C438.72 464.97 512 369.08 512 256.02 512 114.62 397.37 0 256 0z" fill="currentColor" fill-rule="evenodd"></path></svg></a>
</li>
</ul>
</nav>
<div id="body">
<div id="content">

Datei anzeigen

@ -2,10 +2,12 @@
:address=Address
:command_station=Command station
:controllers=Controllers
:emergency_stop=Emergency stop
:id=Id
:name=Name
:notes=Notes
:track_power=Track power
clock:day=Day
clock:hour=Hour
@ -14,7 +16,9 @@ clock:month=Month
clock:multiplier=Multiplier
clock:year=Year
decoder_function_list:add=Add
decoder_function_list:add=Add function
decoder_list:add=Add
hardware.command_station.li10x:baudrate=Baudrate
hardware.command_station.li10x:decoders=Decoders
@ -46,6 +50,11 @@ hardware.command_station.z21:vcc_voltage=VCC voltage
hardware.command_station:online=Online
hardware.command_station:status=Status
hardware.controller.z21_app:active=Active
hardware.controller.z21_app:port=Port
hardware.controller:active=Active
hardware.decoder:direction=Direction
hardware.decoder:functions=Functions
hardware.decoder:protocol=Protocol

Datei anzeigen

@ -14,6 +14,8 @@ clock:month=Maand
clock:multiplier=Vermenigvuldiger
clock:year=Jaar
decoder_function_list:add=Functie toevoegen
hardware.command_station.li10x:baudrate=Baudrate
hardware.command_station.li10x:decoders=Decoders
hardware.command_station.li10x:online=Online

Datei anzeigen

@ -28,6 +28,8 @@ file(GLOB SOURCES
"src/enum/*.hpp"
"src/hardware/commandstation/*.hpp"
"src/hardware/commandstation/*.cpp"
"src/hardware/controller/*.hpp"
"src/hardware/controller/*.cpp"
"src/hardware/decoder/*.hpp"
"src/hardware/decoder/*.cpp"
"src/hardware/input/*.hpp"
@ -37,6 +39,7 @@ file(GLOB SOURCES
"src/lua/*.hpp"
"src/lua/*.cpp"
"src/utils/*.hpp"
"src/utils/*.cpp"
"thirdparty/boost/libs/program_options/src/*.cpp")
add_executable(traintastic-server ${SOURCES})

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* 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
@ -22,8 +22,8 @@
#include "clock.hpp"
Clock::Clock(Object& parent, const std::string& parentPropertyName) :
SubObject(parent, parentPropertyName),
Clock::Clock(Object& _parent, const std::string& parentPropertyName) :
SubObject(_parent, parentPropertyName),
year{this, "year", 2020, PropertyFlags::ReadWrite | PropertyFlags::StoreState},
month{this, "month", 1, PropertyFlags::ReadWrite | PropertyFlags::StoreState},
day{this, "day", 1, PropertyFlags::ReadWrite | PropertyFlags::StoreState},

Datei anzeigen

@ -39,7 +39,7 @@ class Clock : public SubObject
Property<uint16_t> multiplier;
Clock(Object& parent, const std::string& parentPropertyName);
Clock(Object& _parent, const std::string& parentPropertyName);
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -1,7 +1,7 @@
/**
* Traintastic
*
* Copyright (C) 2019 Reinder Feenstra <reinderfeenstra@gmail.com>
* Copyright (C) 2019-2020 Reinder Feenstra <reinderfeenstra@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -20,12 +20,13 @@
#include "idobject.hpp"
#include "traintastic.hpp"
#include "console.hpp"
#include "world.hpp"
IdObject::IdObject(const std::weak_ptr<World> world, const std::string& _id) :
IdObject::IdObject(const std::weak_ptr<World>& world, std::string_view _id) :
Object{},
m_world{world},
id{this, "id", _id, PropertyFlags::ReadWrite | PropertyFlags::Store, nullptr,
id{this, "id", std::string(_id.data(), _id.size()), PropertyFlags::ReadWrite | PropertyFlags::Store, nullptr,
[this](std::string& value)
{
auto& m = Traintastic::instance->world->m_objects;
@ -37,8 +38,11 @@ IdObject::IdObject(const std::weak_ptr<World> world, const std::string& _id) :
return true;
}}
{
auto w = world.lock();
const bool editable = w && contains(w->state.value(), WorldState::Edit);
m_interfaceItems.add(id)
.addAttributeEnabled(false);
.addAttributeEnabled(editable);
}
IdObject::~IdObject()
@ -59,3 +63,38 @@ void IdObject::worldEvent(WorldState state, WorldEvent event)
id.setAttributeEnabled(contains(state, WorldState::Edit));
}
void IdObject::logDebug(const std::string& message)
{
Traintastic::instance->console->debug(id, message);
}
void IdObject::logInfo(const std::string& message)
{
Traintastic::instance->console->info(id, message);
}
void IdObject::logNotice(const std::string& message)
{
Traintastic::instance->console->notice(id, message);
}
void IdObject::logWarning(const std::string& message)
{
Traintastic::instance->console->warning(id, message);
}
void IdObject::logError(const std::string& message)
{
Traintastic::instance->console->error(id, message);
}
void IdObject::logCritical(const std::string& message)
{
Traintastic::instance->console->critical(id, message);
}
void IdObject::logFatal(const std::string& message)
{
Traintastic::instance->console->fatal(id, message);
}

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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
@ -28,7 +28,7 @@
#include <enum/traintasticmode.hpp>
#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, std::string_view _id) \
{ \
auto obj = std::make_shared<T>(world, _id); \
obj->addToWorld(); \
@ -42,10 +42,18 @@ class IdObject : public Object
protected:
std::weak_ptr<World> m_world;
IdObject(const std::weak_ptr<World> world, const std::string& _id);
IdObject(const std::weak_ptr<World>& world, std::string_view _id);
virtual void addToWorld();
void worldEvent(WorldState state, WorldEvent event) override;
void logDebug(const std::string& message);
void logInfo(const std::string& message);
void logNotice(const std::string& message);
void logWarning(const std::string& message);
void logError(const std::string& message);
void logCritical(const std::string& message);
void logFatal(const std::string& message);
public:
Property<std::string> id;

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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
@ -57,6 +57,12 @@ class Object : public std::enable_shared_from_this<Object>
Object();
virtual ~Object();
template <typename Derived>
inline std::shared_ptr<const Derived> shared_ptr() const
{
return std::static_pointer_cast<const Derived>(shared_from_this());
}
template <typename Derived>
std::shared_ptr<Derived> shared_ptr()
{

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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
@ -59,8 +59,8 @@ class ObjectList : public SubObject, public Table
public:
Property<uint32_t> length;
ObjectList(Object& parent, const std::string& parentPropertyName) :
SubObject{parent, parentPropertyName},
ObjectList(Object& _parent, const std::string& parentPropertyName) :
SubObject{_parent, parentPropertyName},
length{this, "length", 0, PropertyFlags::ReadOnly}
{
}
@ -80,7 +80,7 @@ class ObjectList : public SubObject, public Table
return m_items[index];
}
void add(const std::shared_ptr<T>& object)
void addObject(const std::shared_ptr<T>& object)
{
m_items.push_back(object);
m_propertyChanged.emplace(object.get(), object->propertyChanged.connect(
@ -102,7 +102,7 @@ class ObjectList : public SubObject, public Table
rowCountChanged();
}
void remove(const std::shared_ptr<T>& object)
void removeObject(const std::shared_ptr<T>& object)
{
auto it = std::find(m_items.begin(), m_items.end(), object);
if(it != m_items.end())

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -1,7 +1,7 @@
/**
* Traintastic
*
* Copyright (C) 2019 Reinder Feenstra <reinderfeenstra@gmail.com>
* Copyright (C) 2019-2020 Reinder Feenstra <reinderfeenstra@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -20,7 +20,7 @@
#include "output.hpp"
Output::Output(const std::weak_ptr<World> world, const std::string& _id) :
Output::Output(const std::weak_ptr<World> world, std::string_view _id) :
IdObject{world, _id},
value{this, "value", false, PropertyFlags::ReadWrite, std::bind(&Output::valueChanged, this, std::placeholders::_1), std::bind(&Output::setValue, this, std::placeholders::_1)}
{

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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
@ -34,7 +34,7 @@ class Output : public IdObject
public:
Property<bool> value;
Output(const std::weak_ptr<World> world, const std::string& _id);
Output(const std::weak_ptr<World> world, std::string_view _id);
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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
@ -53,7 +53,7 @@ bool Session::processMessage(const Message& message)
{
switch(message.command())
{
case Message::Command::CreateObject:
/*case Message::Command::CreateObject:
{
std::string classId;
std::string id;
@ -73,7 +73,7 @@ bool Session::processMessage(const Message& message)
m_client->sendMessage(Message::newErrorResponse(message.command(), message.requestId(), Message::ErrorCode::UnknownClassId));
return true;
}
}*/
case Message::Command::GetObject:
{
std::string id;

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* 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
@ -24,9 +24,9 @@
#include "idobject.hpp"
#include "world.hpp"
SubObject::SubObject(Object &parent, const std::string &parentPropertyName) :
SubObject::SubObject(Object& _parent, const std::string& parentPropertyName) :
Object(),
m_parent{parent},
m_parent{_parent},
m_parentPropertyName{parentPropertyName}
{
}

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* 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
@ -32,7 +32,7 @@ class SubObject : public Object
const std::string& m_parentPropertyName;
public:
SubObject(Object& parent, const std::string& parentPropertyName);
SubObject(Object& _parent, const std::string& parentPropertyName);
Object& parent() const { return m_parent; }
std::string id() const;

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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
@ -31,6 +31,7 @@
#include "client.hpp"
#include "world.hpp"
#include "worldlist.hpp"
#include "worldloader.hpp"
using nlohmann::json;
@ -202,7 +203,8 @@ void Traintastic::loadWorld(const std::filesystem::path& path)
{
try
{
world = World::load(path / "traintastic.json");
world = WorldLoader(path / "traintastic.json").world();
//World::load(path / "traintastic.json");
}
catch(const std::exception& e)
{

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -26,6 +26,7 @@
#include <boost/uuid/string_generator.hpp>
#include <boost/uuid/uuid_io.hpp>
#include "traintastic.hpp"
#include "worldsaver.hpp"
@ -36,6 +37,7 @@
#include "../hardware/input/loconetinput.hpp"
#include "../hardware/decoder/decoder.hpp"
#include "../hardware/controller/z21app.hpp"
using nlohmann::json;
@ -62,6 +64,7 @@ void World::init(const std::shared_ptr<World>& world)
world->commandStations.setValueInternal(std::make_shared<CommandStationList>(*world, world->commandStations.name()));
world->decoders.setValueInternal(std::make_shared<DecoderList>(*world, world->decoders.name()));
world->inputs.setValueInternal(std::make_shared<InputList>(*world, world->inputs.name()));
world->controllers.setValueInternal(std::make_shared<ControllerList>(*world, world->controllers.name()));
world->clock.setValueInternal(std::make_shared<Clock>(*world, world->clock.name()));
world->luaScripts.setValueInternal(std::make_shared<Lua::ScriptList>(*world, world->luaScripts.name()));
}
@ -74,6 +77,7 @@ World::World() :
commandStations{this, "command_stations", nullptr, PropertyFlags::ReadOnly | PropertyFlags::SubObject},
decoders{this, "decoders", nullptr, PropertyFlags::ReadOnly | PropertyFlags::SubObject},
inputs{this, "inputs", nullptr, PropertyFlags::ReadOnly | PropertyFlags::SubObject},
controllers{this, "controllers", nullptr, PropertyFlags::ReadOnly | PropertyFlags::SubObject},
clock{this, "clock", nullptr, PropertyFlags::ReadOnly | PropertyFlags::SubObject},
luaScripts{this, "lua_scripts", nullptr, PropertyFlags::ReadOnly | PropertyFlags::SubObject},
state{this, "state", WorldState::TrackPowerOff, PropertyFlags::ReadOnly},
@ -116,6 +120,18 @@ World::World() :
save{*this, "save",
[this]()
{
try
{
WorldSaver saver(*this);
Traintastic::instance->console->notice(classId, "Saved world " + name.value());
}
catch(const std::exception& e)
{
Traintastic::instance->console->critical(classId, std::string("Saving world failed: ").append(e.what()));
}
/*
json objects = json::array();
for(auto& it : m_objects)
if(ObjectPtr object = it.second.lock())
@ -134,6 +150,7 @@ World::World() :
}
else
Traintastic::instance->console->critical(classId, "Can't write to world file");
*/
}}
{
m_interfaceItems.add(name);
@ -142,6 +159,7 @@ World::World() :
m_interfaceItems.add(commandStations);
m_interfaceItems.add(decoders);
m_interfaceItems.add(inputs);
m_interfaceItems.add(controllers);
m_interfaceItems.add(clock);
m_interfaceItems.add(luaScripts);
@ -172,14 +190,14 @@ std::string World::getUniqueId(const std::string& prefix) const
return id;
}
ObjectPtr World::createObject(const std::string& classId, const std::string& _id)
/*
ObjectPtr World::createObject(const std::string& classId, std::string_view _id)
{
if(classId == Hardware::Decoder::classId)
return std::dynamic_pointer_cast<Object>(Hardware::Decoder::create(shared_ptr<World>(), getUniqueId("decoder")));
else
return ObjectPtr();
}
}*/
bool World::isObject(const std::string& _id) const
{
@ -202,6 +220,7 @@ ObjectPtr World::getObject(const std::string& _id) const
void World::event(WorldEvent event)
{
const WorldState st = state;
worldEvent(st, event);
for(auto& it : m_objects)
it.second.lock()->worldEvent(st, event);
}
@ -211,9 +230,12 @@ void World::load()
std::ifstream file(m_filename);
if(file.is_open())
{
json world = json::parse(file);
m_uuid = boost::uuids::string_generator()(std::string(world["uuid"]));
name = world[name.name()];
json data = json::parse(file);
m_uuid = boost::uuids::string_generator()(std::string(data["uuid"]));
name = data[name.name()];
json objects = data["objects"];
@ -227,7 +249,7 @@ void World::load()
std::weak_ptr<World> w = shared_ptr<World>();
#if 1
#if 0
auto cs = Hardware::CommandStation::Z21::create(w, "cs1");
//cs->hostname = "192.168.1.2";
cs->hostname = "192.168.16.254";
@ -250,7 +272,7 @@ void World::load()
#endif
cs->xpressnet->commandStation = XpressNetCommandStation::Roco10764;
#endif
commandStations->add(cs);
commandStations->addObject(cs);
{
@ -309,22 +331,22 @@ void World::load()
dec->address = 3311;
dec->longAddress = true;
dec->speedSteps = 126;
for(int i = 0; i <= 20; i++)
dec->functions->add();
/*
{
auto f = Hardware::DecoderFunction::create(*dec, "dec_br211_f0");
auto f = dec->functions->add();
f->number = 0;
f->name = "Light";
dec->functions->add(f);
f->m_decoder = dec.get();
}
{
auto f = Hardware::DecoderFunction::create(w, "dec_br211_f1");
auto f = dec->functions->add();
f->number = 1;
f->name = "Sound";
dec->functions->add(f);
f->m_decoder = dec.get();
}*/
}
*/
}
//cs->online = true;
@ -362,11 +384,16 @@ void World::load()
" console.debug(event)\n"
" console.debug(event == enum.world_event.TRACK_POWER_ON)\n"
"end\n";
luaScripts->add(script);
luaScripts->addObject(script);
}
{
auto z21app = Hardware::Controller::Z21App::create(w, "z21app");
z21app->commandStation = cs;
z21app->active = true;
controllers->addObject(z21app);
}
@ -383,6 +410,9 @@ json World::saveObject(const ObjectPtr& object)
objectData["class_id"] = object->getClassId();
if(Hardware::DecoderFunction* function = dynamic_cast<Hardware::DecoderFunction*>(object.get()))
objectData["decoder"] = function->decoder().id.toJSON();
for(auto& item : object->interfaceItems())
if(AbstractProperty* property = dynamic_cast<AbstractProperty*>(&item.second))
{

Datei anzeigen

@ -37,14 +37,19 @@
#include "../hardware/commandstation/commandstationlist.hpp"
#include "../hardware/decoder/decoderlist.hpp"
#include "../hardware/input/inputlist.hpp"
#include "../hardware/controller/controllerlist.hpp"
#include "../lua/scriptlist.hpp"
//class CommandStationList;
//class DecoderList;
class WorldLoader;
class World : public Object
{
friend class IdObject;
friend class Traintastic;
friend class WorldLoader;
friend class WorldSaver;
protected:
static void init(const std::shared_ptr<World>& world);
@ -70,6 +75,7 @@ class World : public Object
ObjectProperty<CommandStationList> commandStations;
ObjectProperty<DecoderList> decoders;
ObjectProperty<InputList> inputs;
ObjectProperty<ControllerList> controllers;
ObjectProperty<Clock> clock;
ObjectProperty<Lua::ScriptList> luaScripts;
@ -87,8 +93,8 @@ class World : public Object
const boost::uuids::uuid& uuid() const { return m_uuid; }
std::string getUniqueId(const std::string& prefix) const;
ObjectPtr createObject(const std::string& classId, const std::string& _id = "");
bool isObject(const std::string& _id) const;
//ObjectPtr createObject(const std::string& classId, std::string_view _id = "");
bool isObject(const std::string&_id) const;
ObjectPtr getObject(const std::string& _id) const;
};

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -0,0 +1,102 @@
#include "worldloader.hpp"
#include <fstream>
#include <boost/uuid/string_generator.hpp>
#include "world.hpp"
#include "../hardware/commandstation/li10x.hpp"
#include "../hardware/commandstation/usbxpressnetinterface.hpp"
#include "../hardware/commandstation/z21.hpp"
#include "../hardware/controller/z21app.hpp"
#include "../hardware/decoder/decoder.hpp"
#include "../hardware/decoder/decoderfunction.hpp"
#include "../lua/script.hpp"
using nlohmann::json;
WorldLoader::WorldLoader(const std::filesystem::path& filename) :
m_world{World::create()}
{
std::ifstream file(filename);
if(!file.is_open())
throw std::runtime_error("can't open " + filename.string());
json data = json::parse(file);;
m_world->m_filename = filename;
m_world->m_uuid = boost::uuids::string_generator()(std::string(data["uuid"]));
m_world->name = data[m_world->name.name()];
// create a list of all objects
for(json object : data["objects"])
{
if(auto it = object.find("id"); it != object.end())
m_objects.insert({it.value().get<std::string>(), {object, nullptr, false}});
else
throw std::runtime_error("id missing");
}
// then create all objects
for(auto& it : m_objects)
if(!it.second.object)
createObject(it.second);
// and finally load their data
for(auto& it : m_objects)
if(!it.second.loaded)
loadObject(it.second);
}
void WorldLoader::createObject(ObjectData& objectData)
{
assert(!objectData.object);
std::string_view classId = objectData.json["class_id"];
std::string_view id = objectData.json["id"];
// TODO some kind of class list !!
if(classId == Hardware::CommandStation::LI10x::classId)
objectData.object = Hardware::CommandStation::LI10x::create(m_world, id);
else if(classId == Hardware::CommandStation::USBXpressNetInterface::classId)
objectData.object = Hardware::CommandStation::USBXpressNetInterface::create(m_world, id);
else if(classId == Hardware::CommandStation::Z21::classId)
objectData.object = Hardware::CommandStation::Z21::create(m_world, id);
else if(classId == Hardware::Controller::Z21App::classId)
objectData.object = Hardware::Controller::Z21App::create(m_world, id);
else if(classId == Hardware::Decoder::classId)
objectData.object = Hardware::Decoder::create(m_world, id);
else if(classId == Lua::Script::classId)
objectData.object = Lua::Script::create(m_world, id);
else if(classId == Hardware::DecoderFunction::classId)
{
//objectData.object = Hardware::Decoder::create(m_world, id);
}
if(!objectData.object)
{};//m_objects.insert(id, object);
}
void WorldLoader::loadObject(ObjectData& objectData)
{
/*assert*/if(!objectData.object)return;
assert(!objectData.loaded);
Object& object = *objectData.object;
for(auto& [name, value] : objectData.json.items())
if(AbstractProperty* property = object.getProperty(name))
if(property->type() == ValueType::Object)
{
//hier voor objecten wat anders doen
}
else
property->fromJSON(value);
objectData.loaded = true;
//objectData.object->loaded();
}
/*
std::shared_ptr<Object> WorldLoader::getObject(std::string_view id)
{
}
*/

Datei anzeigen

@ -0,0 +1,36 @@
#ifndef WORLDLOADER_HPP
#define WOLRDLOADER_HPP
#include <memory>
#include <string>
#include <unordered_map>
#include <nlohmann/json.hpp>
#include "stdfilesystem.hpp"
class Object;
class World;
class WorldLoader
{
private:
struct ObjectData
{
nlohmann::json json;
std::shared_ptr<Object> object;
bool loaded;
};
std::shared_ptr<World> m_world;
std::unordered_map<std::string, ObjectData> m_objects;
void createObject(ObjectData& objectData);
void loadObject(ObjectData& objectData);
public:
WorldLoader(const std::filesystem::path& filename);
std::shared_ptr<World> world() { return m_world; }
};
#endif

Datei anzeigen

@ -0,0 +1,69 @@
#include "worldsaver.hpp"
#include <fstream>
#include <boost/uuid/uuid_io.hpp>
#include "world.hpp"
using nlohmann::json;
WorldSaver::WorldSaver(const World& world)
{
json objects = json::array();
for(auto& it : world.m_objects)
if(ObjectPtr object = it.second.lock())
objects.push_back(saveObject(object));
json data;
data["uuid"] = to_string(world.m_uuid);
data[world.name.name()] = world.name.value();
data[world.scale.name()] = world.scale.value();
data["objects"] = objects;
std::ofstream file(world.m_filename);
if(file.is_open())
{
file << data.dump(2);
//Traintastic::instance->console->notice(classId, "Saved world " + name.value());
}
else
throw std::runtime_error("file not open");
//Traintastic::instance->console->critical(classId, "Can't write to world file");
}
json WorldSaver::saveObject(const ObjectPtr& object)
{
json objectData;
objectData["class_id"] = object->getClassId();
if(Hardware::DecoderFunction* function = dynamic_cast<Hardware::DecoderFunction*>(object.get()))
objectData["decoder"] = function->decoder().id.toJSON();
for(auto& item : object->interfaceItems())
if(AbstractProperty* property = dynamic_cast<AbstractProperty*>(&item.second))
{
if(!property->isStoreable())
continue;
if(property->type() == ValueType::Object)
{
if(ObjectPtr value = property->toObject())
{
if(IdObject* idObject = dynamic_cast<IdObject*>(value.get()))
objectData[property->name()] = idObject->id.toJSON();
else if(SubObject* subObject = dynamic_cast<SubObject*>(value.get()))
{
if((property->flags() & PropertyFlags::SubObject) == PropertyFlags::SubObject)
objectData[property->name()] = saveObject(value);
else
objectData[property->name()] = subObject->id();
}
}
else
objectData[property->name()] = nullptr;
}
else
objectData[property->name()] = property->toJSON();
}
return objectData;
}

Datei anzeigen

@ -0,0 +1,23 @@
#ifndef WORLDSAVER_HPP
#define WOLRDSAVER_HPP
//#include <memory>
//#include <string>
//#include <unordered_map>
#include <nlohmann/json.hpp>
#include "objectptr.hpp"
//#include "stdfilesystem.hpp"
//class Object;
class World;
class WorldSaver
{
private:
nlohmann::json saveObject(const ObjectPtr& object);
public:
WorldSaver(const World& world);
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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
@ -29,9 +29,9 @@
NLOHMANN_JSON_SERIALIZE_ENUM(DecoderProtocol,
{
{DecoderProtocol::None, "none"},
{DecoderProtocol::DCC, "dcc"},
{DecoderProtocol::Custom, "custom"},
{DecoderProtocol::None, "NONE"},
{DecoderProtocol::DCC, "DCC"},
{DecoderProtocol::Custom, "CUSTOM"},
})
LUA_ENUM_VALUES(DecoderProtocol, 3,

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2020 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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
@ -21,6 +21,8 @@
*/
#include "commandstation.hpp"
#include "commandstationlist.hpp"
#include "commandstationlisttablemodel.hpp"
#include <functional>
#include "../../core/world.hpp"
#include "../decoder/decoder.hpp"
@ -28,7 +30,7 @@
namespace Hardware::CommandStation {
CommandStation::CommandStation(const std::weak_ptr<World>& world, const std::string& _id) :
CommandStation::CommandStation(const std::weak_ptr<World>& world, std::string_view _id) :
IdObject(world, _id),
name{this, "name", "", PropertyFlags::ReadWrite | PropertyFlags::Store},
online{this, "online", false, PropertyFlags::ReadWrite | PropertyFlags::StoreState,
@ -50,9 +52,11 @@ CommandStation::CommandStation(const std::weak_ptr<World>& world, const std::str
trackVoltageOffChanged(value);
}},
decoders{this, "decoders", nullptr, PropertyFlags::ReadOnly | PropertyFlags::Store | PropertyFlags::SubObject},
controllers{this, "controllers", nullptr, PropertyFlags::ReadOnly | PropertyFlags::Store | PropertyFlags::SubObject},
notes{this, "notes", "", PropertyFlags::ReadWrite | PropertyFlags::Store}
{
decoders.setValueInternal(std::make_shared<DecoderList>(*this, decoders.name()));
controllers.setValueInternal(std::make_shared<ControllerList>(*this, controllers.name()));
m_interfaceItems.add(name)
.addAttributeEnabled(false);
@ -64,17 +68,33 @@ CommandStation::CommandStation(const std::weak_ptr<World>& world, const std::str
.addAttributeEnabled(false)
.addAttributeObjectEditor(false);
m_interfaceItems.add(decoders);
m_interfaceItems.add(controllers);
m_interfaceItems.add(notes);
}
void CommandStation::addToWorld()
{
IdObject::addToWorld();
if(auto world = m_world.lock())
world->commandStations->addObject(shared_ptr<CommandStation>());
}
void CommandStation::worldEvent(WorldState state, WorldEvent event)
{
IdObject::worldEvent(state, event);
name.setAttributeEnabled(contains(state, WorldState::Edit));
if(event == WorldEvent::EmergencyStop)
emergencyStop = true;
else if(event == WorldEvent::TrackPowerOff)
trackVoltageOff = true;
else if(event == WorldEvent::TrackPowerOn)
trackVoltageOff = false;
}
const std::shared_ptr<Decoder>& CommandStation::getDecoder(DecoderProtocol protocol, uint16_t address, bool longAddress) const
const std::shared_ptr<Hardware::Decoder>& CommandStation::getDecoder(DecoderProtocol protocol, uint16_t address, bool longAddress) const
{
auto it = std::find_if(decoders->begin(), decoders->end(), [=](auto& decoder){ return decoder->protocol == protocol && decoder->address == address && decoder->longAddress == longAddress; });
if(it != decoders->end())
@ -82,4 +102,23 @@ const std::shared_ptr<Decoder>& CommandStation::getDecoder(DecoderProtocol proto
return Decoder::null;
}
void CommandStation::emergencyStopChanged(bool value)
{
for(auto& controller : *controllers)
controller->emergencyStopChanged(value);
}
void CommandStation::trackVoltageOffChanged(bool value)
{
for(auto& controller : *controllers)
controller->trackPowerChanged(!value);
}
void CommandStation::decoderChanged(const Hardware::Decoder& decoder, Hardware::DecoderChangeFlags changes, uint32_t functionNumber)
{
for(auto& controller : *controllers)
controller->decoderChanged(decoder, changes, functionNumber);
}
}

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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
@ -29,6 +29,7 @@
#include <enum/decoderprotocol.hpp>
class DecoderList;
class ControllerList;
namespace Hardware {
class Decoder;
@ -42,25 +43,27 @@ class CommandStation : public IdObject
friend class ::Hardware::Decoder;
protected:
void addToWorld() final;
void worldEvent(WorldState state, WorldEvent event) override;
virtual bool setOnline(bool& value) = 0;
virtual void emergencyStopChanged(bool value) = 0;
virtual void trackVoltageOffChanged(bool value) = 0;
virtual void emergencyStopChanged(bool value);
virtual void trackVoltageOffChanged(bool value);
//virtual bool isDecoderSupported(Decoder& decoder) const = 0;
virtual void decoderChanged(const Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber) = 0;
const std::shared_ptr<Decoder>& getDecoder(DecoderProtocol protocol, uint16_t address, bool longAddress) const;
virtual void decoderChanged(const Hardware::Decoder& decoder, DecoderChangeFlags changes, uint32_t functionNumber);
public:
CommandStation(const std::weak_ptr<World>& world, const std::string& _id);
CommandStation(const std::weak_ptr<World>& world, std::string_view _id);
Property<std::string> name;
Property<bool> online;
Property<bool> emergencyStop;
Property<bool> trackVoltageOff;
ObjectProperty<DecoderList> decoders;
ObjectProperty<ControllerList> controllers;
Property<std::string> notes;
const std::shared_ptr<Hardware::Decoder>& getDecoder(DecoderProtocol protocol, uint16_t address, bool longAddress) const;
};
}

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2019 Reinder Feenstra
* 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
@ -25,8 +25,8 @@
using Hardware::CommandStation::CommandStation;
CommandStationList::CommandStationList(Object& parent, const std::string& parentPropertyName) :
ObjectList<CommandStation>(parent, parentPropertyName)
CommandStationList::CommandStationList(Object& _parent, const std::string& parentPropertyName) :
ObjectList<CommandStation>(_parent, parentPropertyName)
{
}

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen