[board] New turnout edit dialog with icon of turnout (UI tryout)

Dieser Commit ist enthalten in:
Reinder Feenstra 2025-10-20 11:15:51 +02:00
Ursprung aa06dc912e
Commit 298c050bd0
15 geänderte Dateien mit 534 neuen und 10 gelöschten Zeilen

Datei anzeigen

@ -52,6 +52,7 @@
#include "../widget/objectlist/interfacelistwidget.hpp"
#include "../widget/objectlist/throttleobjectlistwidget.hpp"
#include "../widget/outputmapwidget.hpp"
#include "../widget/tile/tilewidget.hpp"
#include "../widget/throttle/throttlebutton.hpp"
#include "../widget/throttle/throttlewidget.hpp"
#include "../wizard/newboardwizard.hpp"
@ -570,8 +571,8 @@ void ScreenShotDialog::start()
{
if(auto* w = getSubWindow(QStringLiteral("turnout_1")))
{
w->resize(400, 300);
auto* map = static_cast<OutputMapWidget*>(static_cast<QTabWidget*>(w->widget()->layout()->itemAt(0)->widget())->widget(1)->layout()->itemAt(0)->widget());
w->resize(400, 350);
auto* map = static_cast<OutputMapWidget*>(static_cast<TileWidget*>(w->widget())->m_tabs->widget(0));
map->m_object->getObjectProperty("interface")->setByObjectId("loconet_1");
return true;
}
@ -582,11 +583,13 @@ void ScreenShotDialog::start()
{
if(auto* w = getSubWindow(QStringLiteral("turnout_1")))
{
saveWidgetImage(w, QStringLiteral("getting-started/turnout-general.png"));
static_cast<QTabWidget*>(w->widget()->layout()->itemAt(0)->widget())->setCurrentIndex(1);
saveWidgetImage(w, QStringLiteral("getting-started/turnout-output-mapping.png"));
w->close();
return true;
auto* map = static_cast<OutputMapWidget*>(static_cast<TileWidget*>(w->widget())->m_tabs->widget(0));
if(map->m_object->getObjectProperty("interface")->hasObject())
{
saveWidgetImage(w, QStringLiteral("getting-started/turnout-general.png"));
w->close();
return true;
}
}
return false;
});

Datei anzeigen

@ -0,0 +1,37 @@
/**
* This file is part of Traintastic,
* see <https://github.com/traintastic/traintastic>.
*
* Copyright (C) 2025 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 "settabwidget.hpp"
#include <cassert>
#include <QTabWidget>
void setTabWidget(QTabWidget* tabWidget, int tabIndex, QWidget* widget)
{
assert(tabWidget);
assert(tabIndex >= 0 && tabIndex < tabWidget->count());
assert(widget);
const int currentIndex = tabWidget->currentIndex();
const auto tabIcon = tabWidget->tabIcon(tabIndex);
const auto tabText = tabWidget->tabText(tabIndex);
tabWidget->removeTab(tabIndex);
tabWidget->insertTab(tabIndex, widget, tabIcon, tabText);
tabWidget->setCurrentIndex(currentIndex);
}

Datei anzeigen

@ -0,0 +1,30 @@
/**
* This file is part of Traintastic,
* see <https://github.com/traintastic/traintastic>.
*
* Copyright (C) 2025 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_UTILS_SETTABWIDGET_HPP
#define TRAINTASTIC_CLIENT_UTILS_SETTABWIDGET_HPP
class QWidget;
class QTabWidget;
void setTabWidget(QTabWidget* tabWidget, int tabIndex, QWidget* widget);
#endif

Datei anzeigen

@ -0,0 +1,58 @@
/**
* This file is part of Traintastic,
* see <https://github.com/traintastic/traintastic>.
*
* Copyright (C) 2025 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 "createform.hpp"
#include <QFormLayout>
#include "../network/object.hpp"
#include "createwidget.hpp"
#include "interfaceitemnamelabel.hpp"
QLayout* createFormLayout(Object& object, std::initializer_list<QString> items, QWidget* parent)
{
auto* form = new QFormLayout();
for(const auto& name : items)
{
if(auto* item = object.getInterfaceItem(name))
{
form->addRow(new InterfaceItemNameLabel(*item, parent), createWidget(*item, parent));
}
}
if(!form->isEmpty())
{
return form;
}
delete form;
return nullptr;
}
QWidget* createFormWidget(Object& object, std::initializer_list<QString> items, QWidget* parent)
{
if(auto* form = createFormLayout(object, items, parent))
{
auto* w = new QWidget(parent);
w->setLayout(form);
return w;
}
return nullptr;
}

Datei anzeigen

@ -0,0 +1,35 @@
/**
* This file is part of Traintastic,
* see <https://github.com/traintastic/traintastic>.
*
* Copyright (C) 2025 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_CREATEFORM_HPP
#define TRAINTASTIC_CLIENT_WIDGET_CREATEFORM_HPP
#include <initializer_list>
#include <QString>
class QLayout;
class QWidget;
class Object;
QLayout* createFormLayout(Object& object, std::initializer_list<QString> items, QWidget* parent = nullptr);
QWidget* createFormWidget(Object& object, std::initializer_list<QString> items, QWidget* parent = nullptr);
#endif

Datei anzeigen

@ -30,9 +30,11 @@
#include "object/luascripteditwidget.hpp"
#include "object/objecteditwidget.hpp"
#include "object/itemseditwidget.hpp"
#include "tile/turnouttilewidget.hpp"
#include "inputmonitorwidget.hpp"
#include "outputkeyboardwidget.hpp"
#include "outputmapwidget.hpp"
#include "propertycheckbox.hpp"
#include "propertycombobox.hpp"
#include "propertydoublespinbox.hpp"
#include "propertyspinbox.hpp"
@ -85,6 +87,10 @@ QWidget* createWidgetIfCustom(const ObjectPtr& object, QWidget* parent)
return new ListWidget(object, parent);
else if(classId == "marklin_can_locomotive_list")
return new MarklinCANLocomotiveListWidget(object, parent);
else if(object->classId().startsWith("board_tile.rail.turnout"))
{
return new TurnoutTileWidget(object, parent);
}
else
return nullptr;
}
@ -126,7 +132,7 @@ QWidget* createWidget(Property& property, QWidget* parent)
switch(property.type())
{
case ValueType::Boolean:
break; // TODO
return new PropertyCheckBox(property, parent);
case ValueType::Enum:
if(property.enumName() == "pair_output_action")

Datei anzeigen

@ -0,0 +1,92 @@
/**
* This file is part of Traintastic,
* see <https://github.com/traintastic/traintastic>.
*
* Copyright (C) 2025 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 "tileimagewidget.hpp"
#include <QPainter>
#include "../../board/boardcolorscheme.hpp"
#include "../../board/getboardcolorscheme.hpp"
#include "../../board/tilepainter.hpp"
#include "../../settings/boardsettings.hpp"
TileImageWidget::TileImageWidget(QWidget* parent)
: QWidget(parent)
, m_colorScheme{getBoardColorScheme(BoardSettings::instance().colorScheme.value())}
{
connect(&BoardSettings::instance(), &BoardSettings::changed, this, qOverload<>(&TileImageWidget::update));
}
int TileImageWidget::heightForWidth(int w) const
{
return w;
}
bool TileImageWidget::hasHeightForWidth() const
{
return true;
}
QSize TileImageWidget::minimumSizeHint() const
{
return {64, 64};
}
void TileImageWidget::setTileId(TileId value)
{
if(m_tileId != value)
{
m_tileId = value;
update();
}
}
void TileImageWidget::setTurnoutPosition(TurnoutPosition value)
{
if(m_turnoutPosition != value)
{
m_turnoutPosition = value;
update();
}
}
void TileImageWidget::paintEvent(QPaintEvent* /*event*/)
{
const int margin = 1;
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.fillRect(rect(), m_colorScheme->background);
if(m_tileId != TileId::None)
{
const auto tileRect = rect().adjusted(margin, margin, -margin, -margin);
painter.setClipRect(tileRect);
TilePainter tilePainter(painter, tileRect.height(), *m_colorScheme);
if(isRailTurnout(m_tileId))
{
tilePainter.drawTurnout(m_tileId, tileRect, TileRotate::Deg0, TurnoutPosition::Unknown, m_turnoutPosition);
}
else
{
tilePainter.draw(m_tileId, tileRect, TileRotate::Deg0);
}
}
}

Datei anzeigen

@ -0,0 +1,52 @@
/**
* This file is part of Traintastic,
* see <https://github.com/traintastic/traintastic>.
*
* Copyright (C) 2025 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_TILE_TILEIMAGEWIDGET_HPP
#define TRAINTASTIC_CLIENT_WIDGET_TILE_TILEIMAGEWIDGET_HPP
#include <QWidget>
#include <traintastic/board/tileid.hpp>
#include <traintastic/enum/turnoutposition.hpp>
struct BoardColorScheme;
class TileImageWidget : public QWidget
{
private:
const BoardColorScheme* m_colorScheme;
TileId m_tileId = TileId::None;
TurnoutPosition m_turnoutPosition = TurnoutPosition::Unknown;
protected:
void paintEvent(QPaintEvent* event) final;
public:
explicit TileImageWidget(QWidget* parent = nullptr);
int heightForWidth(int w) const final;
bool hasHeightForWidth() const final;
QSize minimumSizeHint() const final;
void setTileId(TileId value);
void setTurnoutPosition(TurnoutPosition value);
};
#endif

Datei anzeigen

@ -0,0 +1,62 @@
/**
* This file is part of Traintastic,
* see <https://github.com/traintastic/traintastic>.
*
* Copyright (C) 2025 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 "tilewidget.hpp"
#include <QGridLayout>
#include <QTabWidget>
#include "../../network/object.hpp"
#include "../../network/property.hpp"
#include "../interfaceitemnamelabel.hpp"
#include "../createwidget.hpp"
#include "tileimagewidget.hpp"
TileWidget::TileWidget(ObjectPtr object, QWidget* parent)
: QWidget(parent)
, m_object{std::move(object)}
, m_tabs{new QTabWidget(this)}
, m_image{new TileImageWidget(this)}
{
auto* grid = new QGridLayout();
grid->setContentsMargins(2, 2, 2, 2);
if(auto* tileId = m_object->getProperty(QStringLiteral("tile_id"))) [[likely]]
{
m_image->setTileId(tileId->toEnum<TileId>());
}
grid->addWidget(m_image, 0, 0, 2, 1);
if(auto* name = m_object->getProperty(QStringLiteral("name"))) [[likely]]
{
grid->addWidget(new InterfaceItemNameLabel(*name, this), 0, 1);
grid->addWidget(createWidget(*name, this), 0, 2);
connect(name, &AbstractProperty::valueChangedString, this, &TileWidget::setWindowTitle);
setWindowTitle(name->toString());
}
if(auto* id = m_object->getProperty(QStringLiteral("id"))) [[likely]]
{
grid->addWidget(new InterfaceItemNameLabel(*id, this), 1, 1);
grid->addWidget(createWidget(*id, this), 1, 2);
}
grid->addWidget(m_tabs, 2, 0, 1, 3);
setLayout(grid);
}

Datei anzeigen

@ -0,0 +1,44 @@
/**
* This file is part of Traintastic,
* see <https://github.com/traintastic/traintastic>.
*
* Copyright (C) 2025 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_TILE_TILEWIDGET_HPP
#define TRAINTASTIC_CLIENT_WIDGET_TILE_TILEWIDGET_HPP
#include <QWidget>
#include "../../network/objectptr.hpp"
class QTabWidget;
class TileImageWidget;
class TileWidget : public QWidget
{
friend class ScreenShotDialog;
protected:
ObjectPtr m_object;
QTabWidget* m_tabs;
TileImageWidget* m_image;
public:
explicit TileWidget(ObjectPtr object, QWidget* parent = nullptr);
};
#endif

Datei anzeigen

@ -0,0 +1,65 @@
/**
* This file is part of Traintastic,
* see <https://github.com/traintastic/traintastic>.
*
* Copyright (C) 2025 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 "turnouttilewidget.hpp"
#include <QTabWidget>
#include <traintastic/locale/locale.hpp>
#include "../../network/error.hpp"
#include "../../network/object.hpp"
#include "../../network/objectproperty.hpp"
#include "../../network/property.hpp"
#include "../../utils/settabwidget.hpp"
#include "../outputmapwidget.hpp"
#include "../interfaceitemnamelabel.hpp"
#include "../createform.hpp"
#include "tileimagewidget.hpp"
TurnoutTileWidget::TurnoutTileWidget(ObjectPtr object, QWidget* parent)
: TileWidget(std::move(object), parent)
{
if(auto* position = m_object->getProperty("position")) [[likely]]
{
m_image->setTurnoutPosition(position->toEnum<TurnoutPosition>());
connect(position, &Property::valueChanged,
[this, position]()
{
m_image->setTurnoutPosition(position->toEnum<TurnoutPosition>());
});
}
if(auto* outputMap = m_object->getObjectProperty(QStringLiteral("output_map"))) [[likely]]
{
const int tabIndex = m_tabs->addTab(new QWidget(this), outputMap->displayName());
(void)outputMap->getObject(
[this, tabIndex](const ObjectPtr& obj, std::optional<const Error> /*error*/)
{
if(obj) [[likely]]
{
setTabWidget(m_tabs, tabIndex, new OutputMapWidget(obj, this));
}
});
}
if(auto* w = createFormWidget(*m_object, {QStringLiteral("dual_motor")}, this))
{
m_tabs->addTab(w, Locale::tr("category:options"));
}
}

Datei anzeigen

@ -0,0 +1,33 @@
/**
* This file is part of Traintastic,
* see <https://github.com/traintastic/traintastic>.
*
* Copyright (C) 2025 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_TILE_TURNOUTTILEWIDGET_HPP
#define TRAINTASTIC_CLIENT_WIDGET_TILE_TURNOUTTILEWIDGET_HPP
#include "tilewidget.hpp"
class TurnoutTileWidget : public TileWidget
{
public:
explicit TurnoutTileWidget(ObjectPtr object, QWidget* parent = nullptr);
};
#endif

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2024 Reinder Feenstra
* Copyright (C) 2024-2025 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,6 +22,7 @@
#include "turnoutsliprailtile.hpp"
#include "../../../../core/attributes.hpp"
#include "../../../../utils/category.hpp"
std::optional<OutputActionValue> TurnoutSlipRailTile::getDefaultActionValue(TurnoutPosition turnoutPosition, OutputType outputType, size_t outputIndex)
{
@ -66,6 +67,7 @@ TurnoutSlipRailTile::TurnoutSlipRailTile(World& world, std::string_view _id, Til
dualMotorChanged();
}}
{
Attributes::addCategory(dualMotor, Category::options);
Attributes::addDisplayName(dualMotor, "board_tile.rail.turnout_slip:dual_motor");
m_interfaceItems.add(dualMotor);
}

Datei anzeigen

@ -3,7 +3,7 @@
*
* This file is part of the traintastic source code.
*
* Copyright (C) 2021-2022 Reinder Feenstra
* Copyright (C) 2021-2025 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,6 +32,7 @@ namespace Category
constexpr std::string_view info = "category:info";
constexpr std::string_view log = "category:log";
constexpr std::string_view network = "category:network";
constexpr std::string_view options = "category:options";
constexpr std::string_view trains = "category:trains";
}

Datei anzeigen

@ -6825,5 +6825,9 @@
{
"term": "qtapp.settings.board:grid_edit_mode",
"definition": "Grid (edit mode)"
},
{
"term": "category:options",
"definition": "Options"
}
]