toolbar: added Lua status widget

only visible if scriptlist isn't empty
Dieser Commit ist enthalten in:
Reinder Feenstra 2023-06-08 00:23:09 +02:00
Ursprung 3f13578832
Commit a032935294
9 geänderte Dateien mit 324 neuen und 10 gelöschten Zeilen

Datei anzeigen

@ -30,6 +30,7 @@
#include "../network/objectvectorproperty.hpp"
#include "../settings/statusbarsettings.hpp"
#include "../widget/status/interfacestatuswidget.hpp"
#include "../widget/status/luastatuswidget.hpp"
MainWindowStatusBar::MainWindowStatusBar(MainWindow& mainWindow)
: QStatusBar(&mainWindow)
@ -141,7 +142,12 @@ void MainWindowStatusBar::updateStatuses()
return;
for(const auto& object : objects)
m_statuses->layout()->addWidget(new InterfaceStatusWidget(object, this));
{
if(object->classId() == "status.interface")
m_statuses->layout()->addWidget(new InterfaceStatusWidget(object, this));
else if(object->classId() == "status.lua")
m_statuses->layout()->addWidget(new LuaStatusWidget(object, this));
}
});
}
}

Datei anzeigen

@ -0,0 +1,110 @@
/**
* client/src/widget/status/luastatuswidget.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "luastatuswidget.hpp"
#include <QHBoxLayout>
#include <QSvgWidget>
#include <QLabel>
#include <QResizeEvent>
#include <traintastic/enum/interfacestate.hpp>
#include <traintastic/locale/locale.hpp>
#include "../../network/object.hpp"
#include "../../network/property.hpp"
#include "../../theme/theme.hpp"
LuaStatusWidget::LuaStatusWidget(const ObjectPtr& object, QWidget* parent)
: QWidget(parent)
, m_object{object}
, m_svg{new QSvgWidget(this)}
, m_runningLabel{new QLabel(this)}
, m_errorLabel{new QLabel(this)}
{
assert(m_object);
assert(m_object->classId() == "status.lua");
m_svg->load(Theme::getIconFile("lua"));
m_errorLabel->setStyleSheet("QLabel { color: #DC143C; }");
auto* l = new QHBoxLayout();
l->setMargin(0);
l->addWidget(m_svg);
l->addWidget(m_runningLabel);
l->addWidget(m_errorLabel);
setLayout(l);
if(auto* property = m_object->getProperty("label"); property)
connect(property, &Property::valueChanged, this, &LuaStatusWidget::labelChanged);
if(auto* property = m_object->getProperty("running"); property)
connect(property, &Property::valueChanged, this, &LuaStatusWidget::runningChanged);
if(auto* property = m_object->getProperty("error"); property)
connect(property, &Property::valueChanged, this, &LuaStatusWidget::errorChanged);
runningChanged();
errorChanged();
}
void LuaStatusWidget::labelChanged()
{
QString label;
if(auto* property = m_object->getProperty("label"); property)
label = Locale::instance->parse(property->toString());
if(auto* property = m_object->getProperty("running"); property)
{
label.append("\n").append(Locale::tr("status.lua:x_running").arg(property->toInt()));
}
if(auto* property = m_object->getProperty("error"); property)
{
label.append("\n").append(Locale::tr("status.lua:x_in_error").arg(property->toInt()));
}
setToolTip(label);
}
void LuaStatusWidget::runningChanged()
{
m_runningLabel->setText(QString::number(m_object->getPropertyValueInt("running", 0)));
labelChanged();
}
void LuaStatusWidget::errorChanged()
{
const int error = m_object->getPropertyValueInt("error", 0);
m_errorLabel->setVisible(error > 0);
if(m_errorLabel->isVisible())
m_errorLabel->setText(QString("(%1)").arg(error));
labelChanged();
}
void LuaStatusWidget::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
// force same height/width for image as height:
const int sz = event->size().height();
m_svg->setMinimumSize(sz, sz);
m_svg->setMaximumSize(sz, sz);
}

Datei anzeigen

@ -0,0 +1,51 @@
/**
* client/src/widget/status/luastatuswidget.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_CLIENT_WIDGET_STATUS_LUASTATUSWIDGET_HPP
#define TRAINTASTIC_CLIENT_WIDGET_STATUS_LUASTATUSWIDGET_HPP
#include <QWidget>
#include "../../network/objectptr.hpp"
class QSvgWidget;
class QLabel;
class LuaStatusWidget : public QWidget
{
private:
ObjectPtr m_object;
QSvgWidget* m_svg;
QLabel* m_runningLabel;
QLabel* m_errorLabel;
void labelChanged();
void runningChanged();
void errorChanged();
protected:
void resizeEvent(QResizeEvent* event) override;
public:
explicit LuaStatusWidget(const ObjectPtr& object, QWidget* parent = nullptr);
};
#endif

Datei anzeigen

@ -148,8 +148,37 @@ void Script::updateEnabled()
void Script::setState(LuaScriptState value)
{
const LuaScriptState oldValue = state;
if(oldValue == value)
return;
state.setValueInternal(value);
updateEnabled();
// update global lua status:
{
auto& status = m_world.luaScripts->status;
if(oldValue == LuaScriptState::Running) // was running
{
assert(status->running != 0);
status->running.setValueInternal(status->running - 1);
}
if(oldValue == LuaScriptState::Error) // was error
{
assert(status->error != 0);
status->error.setValueInternal(status->error - 1);
}
if(state == LuaScriptState::Running) // is running
{
status->running.setValueInternal(status->running + 1);
}
if(state == LuaScriptState::Error) // is error
{
status->error.setValueInternal(status->error + 1);
}
}
}
void Script::startSandbox()

Datei anzeigen

@ -24,18 +24,20 @@
#include "scriptlisttablemodel.hpp"
#include "../world/getworld.hpp"
#include "../core/attributes.hpp"
#include "../core/objectproperty.tpp"
#include "../utils/displayname.hpp"
namespace Lua {
ScriptList::ScriptList(Object& _parent, std::string_view parentPropertyName) :
ObjectList<Script>(_parent, parentPropertyName),
create{*this, "create",
[this]()
{
auto& world = getWorld(parent());
return Script::create(world, world.getUniqueId("script"));
}}
ScriptList::ScriptList(Object& _parent, std::string_view parentPropertyName)
: ObjectList<Script>(_parent, parentPropertyName)
, status{this, "status", nullptr, PropertyFlags::ReadOnly | PropertyFlags::NoStore | PropertyFlags::SubObject | PropertyFlags::NoScript}
, create{*this, "create",
[this]()
{
auto& world = getWorld(parent());
return Script::create(world, world.getUniqueId("script"));
}}
, delete_{*this, "delete", std::bind(&ScriptList::deleteMethodHandler, this, std::placeholders::_1)}
, startAll{*this, "start_all",
[this]()
@ -52,6 +54,8 @@ ScriptList::ScriptList(Object& _parent, std::string_view parentPropertyName) :
script->stop();
}}
{
status.setValueInternal(std::make_shared<LuaStatus>(*this, status.name()));
const bool editable = contains(getWorld(parent()).state.value(), WorldState::Edit);
Attributes::addDisplayName(create, DisplayName::List::create);
@ -62,11 +66,18 @@ ScriptList::ScriptList(Object& _parent, std::string_view parentPropertyName) :
Attributes::addEnabled(delete_, editable);
m_interfaceItems.add(delete_);
Attributes::addEnabled(startAll, false);
m_interfaceItems.add(startAll);
Attributes::addEnabled(stopAll, false);
m_interfaceItems.add(stopAll);
}
ScriptList::~ScriptList()
{
getWorld(parent()).statuses.removeInternal(status.value());
}
TableModelPtr ScriptList::getModel()
{
return std::make_shared<ScriptListTableModel>(*this);
@ -82,6 +93,26 @@ void ScriptList::worldEvent(WorldState state, WorldEvent event)
Attributes::setEnabled(delete_, editable);
}
void ScriptList::objectAdded(const std::shared_ptr<Script>& /*object*/)
{
if(m_items.size() == 1)
{
Attributes::setEnabled(startAll, true);
Attributes::setEnabled(stopAll, true);
getWorld(parent()).statuses.appendInternal(status.value());
}
}
void ScriptList::objectRemoved(const std::shared_ptr<Script>& /*object*/)
{
if(empty())
{
Attributes::setEnabled(startAll, false);
Attributes::setEnabled(stopAll, false);
getWorld(parent()).statuses.removeInternal(status.value());
}
}
bool ScriptList::isListedProperty(std::string_view name)
{
return ScriptListTableModel::isListedProperty(name);

Datei anzeigen

@ -24,26 +24,32 @@
#define TRAINTASTIC_SERVER_LUA_SCRIPTLIST_HPP
#include "../core/objectlist.hpp"
#include "../core/objectproperty.hpp"
#include "../core/method.hpp"
#include "script.hpp"
#include "../status/luastatus.hpp"
namespace Lua {
class ScriptList : public ObjectList<Script>
class ScriptList final : public ObjectList<Script>
{
protected:
void worldEvent(WorldState state, WorldEvent event) final;
void objectAdded(const std::shared_ptr<Script>& /*object*/) final;
void objectRemoved(const std::shared_ptr<Script>& /*object*/) final;
bool isListedProperty(std::string_view name) final;
public:
CLASS_ID("lua.script_list")
::ObjectProperty<LuaStatus> status;
::Method<std::shared_ptr<Script>()> create;
::Method<void(const std::shared_ptr<Script>&)> delete_;
::Method<void()> startAll;
::Method<void()> stopAll;
ScriptList(Object& _parent, std::string_view parentPropertyName);
~ScriptList() final;
TableModelPtr getModel() final;
};

Datei anzeigen

@ -0,0 +1,34 @@
/**
* server/src/status/luastatus.cpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "luastatus.hpp"
LuaStatus::LuaStatus(Object& parent_, std::string_view parentPropertyName_)
: Status(parent_, parentPropertyName_)
, running(this, "running", 0, PropertyFlags::ReadOnly | PropertyFlags::NoStore | PropertyFlags::NoScript)
, error(this, "error", 0, PropertyFlags::ReadOnly | PropertyFlags::NoStore | PropertyFlags::NoScript)
{
label.setValueInternal("$world:lua_scripts$");
m_interfaceItems.add(running);
m_interfaceItems.add(error);
}

Datei anzeigen

@ -0,0 +1,39 @@
/**
* server/src/status/luastatus.hpp
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2023 Reinder Feenstra
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef TRAINTASTIC_SERVER_STATUS_LUASTATUS_HPP
#define TRAINTASTIC_SERVER_STATUS_LUASTATUS_HPP
#include "status.hpp"
class LuaStatus : public Status
{
CLASS_ID("status.lua")
public:
Property<uint32_t> running;
Property<uint32_t> error;
LuaStatus(Object& parent_, std::string_view parentPropertyName_);
};
#endif

Datei anzeigen

@ -4910,5 +4910,13 @@
"term_plural": "",
"reference": "",
"comment": ""
},
{
"term": "status.lua:x_running",
"definition": "%1 running"
},
{
"term": "status.lua:x_in_error",
"definition": "%1 in error"
}
]