Redesigned interface list widget, it now embeds the interface settings.
Dieser Commit ist enthalten in:
Ursprung
2ceae8ec9d
Commit
8fd5ac3d1f
94
client/gfx/dark/circle/add.svg
Normale Datei
94
client/gfx/dark/circle/add.svg
Normale Datei
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="96"
|
||||
height="96"
|
||||
viewBox="0 0 25.399999 25.400001"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||
sodipodi:docname="add.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="14.375"
|
||||
inkscape:cy="40.446429"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3713"
|
||||
spacingx="0.26458333"
|
||||
empspacing="4" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-nc/4.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-nc/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:prohibits
|
||||
rdf:resource="http://creativecommons.org/ns#CommercialUse" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-271.59998)">
|
||||
<circle
|
||||
style="fill:#ea80fc;fill-opacity:1;stroke:none;stroke-width:2.51975;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="path252"
|
||||
cx="12.7"
|
||||
cy="284.29996"
|
||||
r="12.7" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 12.7,274.77498 c -1.172633,0 -2.116667,0.94403 -2.116667,2.11666 v 5.29167 H 5.2916667 c -1.1726347,0 -2.1166667,0.94404 -2.1166667,2.11667 0,1.17263 0.944032,2.11667 2.1166667,2.11667 h 5.2916663 v 5.29167 c 0,1.17263 0.944034,2.11666 2.116667,2.11666 1.172633,0 2.116666,-0.94403 2.116666,-2.11666 v -5.29167 h 5.291667 c 1.172635,0 2.116667,-0.94404 2.116667,-2.11667 0,-1.17263 -0.944032,-2.11667 -2.116667,-2.11667 h -5.291667 v -5.29167 c 0,-1.17263 -0.944033,-2.11666 -2.116666,-2.11666 z"
|
||||
id="rect843"
|
||||
sodipodi:nodetypes="sscssscssscssscss" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Nachher Breite: | Höhe: | Größe: 3.5 KiB |
@ -94,5 +94,6 @@
|
||||
<file>board_tile.misc.label.svg</file>
|
||||
<file>clear_persistent_variables.svg</file>
|
||||
<file>swap.svg</file>
|
||||
<file>circle/add.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2020-2024 Reinder Feenstra
|
||||
* Copyright (C) 2020-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
|
||||
@ -23,6 +23,7 @@
|
||||
#include "createwidget.hpp"
|
||||
#include "list/marklincanlocomotivelistwidget.hpp"
|
||||
#include "objectlist/boardlistwidget.hpp"
|
||||
#include "objectlist/interfacelistwidget.hpp"
|
||||
#include "objectlist/throttleobjectlistwidget.hpp"
|
||||
#include "objectlist/trainlistwidget.hpp"
|
||||
#include "object/luascripteditwidget.hpp"
|
||||
@ -47,8 +48,10 @@ QWidget* createWidgetIfCustom(const ObjectPtr& object, QWidget* parent)
|
||||
{
|
||||
const QString& classId = object->classId();
|
||||
|
||||
if(classId == "command_station_list")
|
||||
return new ObjectListWidget(object, parent); // todo remove
|
||||
if(classId == "list.interface")
|
||||
{
|
||||
return new InterfaceListWidget(object, parent);
|
||||
}
|
||||
else if(classId == "decoder_list")
|
||||
return new ThrottleObjectListWidget(object, parent); // todo remove
|
||||
else if(classId == "controller_list")
|
||||
|
||||
111
client/src/widget/objectlist/interfacelistwidget.cpp
Normale Datei
111
client/src/widget/objectlist/interfacelistwidget.cpp
Normale Datei
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* client/src/widget/objectlist/interfacelistwidget.cpp
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* 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 "interfacelistwidget.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QItemDelegate>
|
||||
#include <QListView>
|
||||
#include <QMenu>
|
||||
#include <QPainter>
|
||||
|
||||
#include <traintastic/enum/interfacestate.hpp>
|
||||
#include <traintastic/locale/locale.hpp>
|
||||
|
||||
#include "../../theme/theme.hpp"
|
||||
#include "../../mainwindow.hpp"
|
||||
|
||||
class InterfaceListItemDelegate : public QItemDelegate
|
||||
{
|
||||
public:
|
||||
inline InterfaceListItemDelegate(QListView* parent)
|
||||
: QItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
inline void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const final
|
||||
{
|
||||
static const QSize classIconSize{40, 40};
|
||||
static const QSize stateIconSize{16, 16};
|
||||
|
||||
auto* model = qobject_cast<QListView*>(parent())->model();
|
||||
const auto id = model->data(model->index(index.row(), 0)).toString().prepend('#');
|
||||
const auto name = model->data(model->index(index.row(), 1)).toString();
|
||||
const auto state = model->data(model->index(index.row(), 2)).toString();
|
||||
const auto classId = model->data(model->index(index.row(), 3)).toString();
|
||||
|
||||
const auto r = option.rect.adjusted(5, 5, -5, -5);
|
||||
const int iconOffset = (r.height() - classIconSize.height()) / 2;
|
||||
|
||||
const auto palette = QApplication::palette();
|
||||
|
||||
QTextOption textOption;
|
||||
textOption.setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
|
||||
const auto classIcon = Theme::getIconForClassId(classId);
|
||||
if(!classIcon.isNull())
|
||||
{
|
||||
painter->drawPixmap(r.topLeft() + QPoint(iconOffset, iconOffset), classIcon.pixmap(classIconSize));
|
||||
}
|
||||
|
||||
painter->setPen(palette.color(QPalette::Disabled, QPalette::Text));
|
||||
painter->drawText(r.adjusted((classIcon.isNull() ? 0 : r.height() + 10), r.height() / 2, 0, 0), id, textOption);
|
||||
|
||||
painter->setPen(palette.color(QPalette::Active, QPalette::Text));
|
||||
painter->drawText(r.adjusted((classIcon.isNull() ? 0 : r.height() + 10), 0, 0, -r.height() / 2), name, textOption);
|
||||
|
||||
textOption.setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
const auto stateText = Locale::tr(QString(EnumName<InterfaceState>::value).append(":").append(state));
|
||||
const auto stateRect = r.adjusted(0, r.height() / 2, 0, 0);
|
||||
const auto stateTextWidth = qCeil(painter->boundingRect(stateRect, stateText, textOption).width());
|
||||
painter->drawText(stateRect, stateText, textOption);
|
||||
|
||||
auto stateIcon = QIcon(Theme::getIconFile(QString("interface_state.").append(state)));
|
||||
painter->drawPixmap(
|
||||
stateRect.topRight() - QPoint(stateTextWidth + stateIconSize.width() + 5, -(stateRect.height() - stateIconSize.height()) / 2),
|
||||
stateIcon.pixmap(stateIconSize));
|
||||
|
||||
painter->setPen(QColor(0x80, 0x80, 0x80, 0x30));
|
||||
painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
|
||||
}
|
||||
|
||||
inline QSize sizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const final
|
||||
{
|
||||
return QSize(-1, 50);
|
||||
}
|
||||
};
|
||||
|
||||
InterfaceListWidget::InterfaceListWidget(const ObjectPtr& object, QWidget* parent)
|
||||
: StackedObjectListWidget(object, parent)
|
||||
{
|
||||
m_list->setItemDelegate(new InterfaceListItemDelegate(m_list));
|
||||
|
||||
if(m_createMenu) /*[[likely]]*/
|
||||
{
|
||||
m_createMenu->addSeparator();
|
||||
m_createMenu->addAction(Theme::getIcon("wizard"), Locale::tr("list:setup_using_wizard") + "...",
|
||||
[]()
|
||||
{
|
||||
MainWindow::instance->showAddInterfaceWizard();
|
||||
});
|
||||
}
|
||||
}
|
||||
34
client/src/widget/objectlist/interfacelistwidget.hpp
Normale Datei
34
client/src/widget/objectlist/interfacelistwidget.hpp
Normale Datei
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* client/src/widget/objectlist/interfacelistwidget.hpp
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* 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_OBJECTLIST_INTERFACELISTWIDGET_HPP
|
||||
#define TRAINTASTIC_CLIENT_WIDGET_OBJECTLIST_INTERFACELISTWIDGET_HPP
|
||||
|
||||
#include "stackedobjectlistwidget.hpp"
|
||||
|
||||
class InterfaceListWidget : public StackedObjectListWidget
|
||||
{
|
||||
public:
|
||||
explicit InterfaceListWidget(const ObjectPtr& object, QWidget* parent = nullptr);
|
||||
};
|
||||
|
||||
#endif
|
||||
246
client/src/widget/objectlist/stackedobjectlistwidget.cpp
Normale Datei
246
client/src/widget/objectlist/stackedobjectlistwidget.cpp
Normale Datei
@ -0,0 +1,246 @@
|
||||
/**
|
||||
* client/src/widget/objectlist/stackedobjectlistwidget.cpp
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* 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 "stackedobjectlistwidget.hpp"
|
||||
|
||||
#include <QEvent>
|
||||
#include <QLabel>
|
||||
#include <QListView>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QStackedWidget>
|
||||
#include <QToolBar>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <traintastic/locale/locale.hpp>
|
||||
|
||||
#include "../createwidget.hpp"
|
||||
#include "../tablewidget.hpp"
|
||||
#include "../methodicon.hpp"
|
||||
#include "../../network/object.hpp"
|
||||
#include "../../network/method.hpp"
|
||||
#include "../../network/connection.hpp"
|
||||
#include "../../network/error.hpp"
|
||||
#include "../../network/callmethod.hpp"
|
||||
#include "../../network/tablemodel.hpp"
|
||||
#include "../../theme/theme.hpp"
|
||||
#include "../../misc/methodaction.hpp"
|
||||
|
||||
StackedObjectListWidget::StackedObjectListWidget(const ObjectPtr& object, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_object{object}
|
||||
, m_navBar{new QToolBar(this)}
|
||||
, m_stack{new QStackedWidget(this)}
|
||||
, m_list{new QListView(this)}
|
||||
, m_requestId{Connection::invalidRequestId}
|
||||
{
|
||||
m_navBar->hide();
|
||||
|
||||
m_navBar->addAction(Theme::getIcon("previous_page"), Locale::tr("stacked_object_list:back"), this, &StackedObjectListWidget::back);
|
||||
|
||||
m_navLabel = new QLabel(this);
|
||||
m_navLabel->setAlignment(Qt::AlignCenter);
|
||||
m_navLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
m_navLabel->show();
|
||||
m_navBar->addWidget(m_navLabel);
|
||||
|
||||
if(auto* method = object->getMethod("delete"))
|
||||
{
|
||||
m_actionRemove = new MethodAction(Theme::getIcon("delete"), *method,
|
||||
[this]()
|
||||
{
|
||||
if(!m_listObjectId.isEmpty())
|
||||
{
|
||||
callMethod(m_actionRemove->method(), nullptr, m_listObjectId);
|
||||
back();
|
||||
}
|
||||
});
|
||||
m_navBar->addAction(m_actionRemove);
|
||||
}
|
||||
|
||||
connect(m_stack, &QStackedWidget::currentChanged,
|
||||
[this](int index)
|
||||
{
|
||||
m_navBar->setVisible(index > 0);
|
||||
});
|
||||
|
||||
m_requestId = object->connection()->getTableModel(object,
|
||||
[this](const TableModelPtr& tableModel, std::optional<const Error> error)
|
||||
{
|
||||
m_requestId = Connection::invalidRequestId;
|
||||
|
||||
if(tableModel)
|
||||
{
|
||||
m_tableModel = tableModel;
|
||||
m_list->setModel(m_tableModel.get());
|
||||
connect(m_tableModel.get(), &TableModel::modelReset,
|
||||
[this]()
|
||||
{
|
||||
m_tableModel->setRegion(0, m_tableModel->columnCount(), 0, m_tableModel->rowCount());
|
||||
});
|
||||
m_tableModel->setRegion(0, m_tableModel->columnCount(), 0, m_tableModel->rowCount());
|
||||
}
|
||||
else if(error)
|
||||
{
|
||||
QMessageBox::critical(this, "Error", error->toString());
|
||||
}
|
||||
});
|
||||
|
||||
if(auto* create = object->getMethod("create"))
|
||||
{
|
||||
if(create->argumentTypes().size() == 0) // Create method witout argument
|
||||
{
|
||||
m_create = new MethodIcon(*create, Theme::getIcon("circle/add"), m_list);
|
||||
}
|
||||
else if(create->argumentTypes().size() == 1)
|
||||
{
|
||||
m_createMenu = new QMenu(this);
|
||||
m_createMenu->installEventFilter(this);
|
||||
|
||||
QStringList classList = create->getAttribute(AttributeName::ClassList, QVariant()).toStringList();
|
||||
for(const QString& classId : classList)
|
||||
{
|
||||
QAction* action = m_createMenu->addAction(Locale::tr("class_id:" + classId));
|
||||
action->setData(classId);
|
||||
connect(action, &QAction::triggered, this,
|
||||
[this, create, action]()
|
||||
{
|
||||
cancelRequest();
|
||||
|
||||
m_requestId = create->call(action->data().toString(),
|
||||
[this](const ObjectPtr& addedObject, std::optional<const Error> error)
|
||||
{
|
||||
m_requestId = Connection::invalidRequestId;
|
||||
|
||||
if(addedObject)
|
||||
{
|
||||
show(addedObject);
|
||||
}
|
||||
else if(error)
|
||||
{
|
||||
QMessageBox::critical(this, "Error", error->toString());
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
m_create = new MethodIcon(*create, Theme::getIcon("circle/add"),
|
||||
[this]()
|
||||
{
|
||||
m_createMenu->popup(m_create->mapToGlobal(m_create->rect().topRight()));
|
||||
}, m_list);
|
||||
}
|
||||
|
||||
m_create->setEnabled(create->getAttributeBool(AttributeName::Enabled, true));
|
||||
if(!create->getAttributeBool(AttributeName::Visible, true))
|
||||
{
|
||||
m_create->hide();
|
||||
}
|
||||
|
||||
m_list->installEventFilter(this);
|
||||
m_create->installEventFilter(this);
|
||||
}
|
||||
|
||||
m_list->setSelectionMode(QListView::NoSelection);
|
||||
connect(m_list, &QListView::clicked,
|
||||
[this](const QModelIndex &index)
|
||||
{
|
||||
if(!m_tableModel) /*[[unlikely]]*/
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cancelRequest();
|
||||
|
||||
m_requestId = m_object->connection()->getObject(m_tableModel->getRowObjectId(index.row()),
|
||||
[this](const ObjectPtr& selectedObject, std::optional<const Error> error)
|
||||
{
|
||||
m_requestId = Connection::invalidRequestId;
|
||||
|
||||
if(selectedObject)
|
||||
{
|
||||
show(selectedObject);
|
||||
}
|
||||
else if(error)
|
||||
{
|
||||
QMessageBox::critical(this, "Error", error->toString());
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
m_stack->addWidget(m_list);
|
||||
|
||||
auto* l = new QVBoxLayout();
|
||||
l->setContentsMargins(0, 0, 0, 0);
|
||||
l->addWidget(m_navBar);
|
||||
l->addWidget(m_stack);
|
||||
setLayout(l);
|
||||
}
|
||||
|
||||
StackedObjectListWidget::~StackedObjectListWidget()
|
||||
{
|
||||
cancelRequest();
|
||||
}
|
||||
|
||||
bool StackedObjectListWidget::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
if(m_create && ((object == m_list && event->type() == QEvent::Resize) || (object == m_create && event->type() == QEvent::Show)))
|
||||
{
|
||||
auto pnt = m_create->rect().bottomRight();
|
||||
pnt = m_list->rect().bottomRight() - pnt - pnt / 3;
|
||||
m_create->move(pnt.x(), pnt.y());
|
||||
}
|
||||
if(m_createMenu && object == m_createMenu && event->type() == QEvent::Show)
|
||||
{
|
||||
m_createMenu->move(m_createMenu->pos() - QPoint{m_createMenu->width(), m_createMenu->height()});
|
||||
return true;
|
||||
}
|
||||
return QWidget::eventFilter(object, event);
|
||||
}
|
||||
|
||||
void StackedObjectListWidget::cancelRequest()
|
||||
{
|
||||
if(m_requestId != Connection::invalidRequestId)
|
||||
{
|
||||
m_object->connection()->cancelRequest(m_requestId);
|
||||
}
|
||||
}
|
||||
|
||||
void StackedObjectListWidget::back()
|
||||
{
|
||||
if(m_stack->currentIndex() > 0)
|
||||
{
|
||||
m_listObjectId.clear();
|
||||
delete m_stack->currentWidget();
|
||||
}
|
||||
}
|
||||
|
||||
void StackedObjectListWidget::show(const ObjectPtr& listObject)
|
||||
{
|
||||
if(auto* w = createWidget(listObject, this)) /*[[likely]]*/
|
||||
{
|
||||
m_listObjectId = listObject->getPropertyValueString("id");
|
||||
connect(w, &QWidget::windowTitleChanged, m_navLabel, &QLabel::setText);
|
||||
m_navLabel->setText(w->windowTitle());
|
||||
m_stack->setCurrentIndex(m_stack->addWidget(w));
|
||||
}
|
||||
}
|
||||
65
client/src/widget/objectlist/stackedobjectlistwidget.hpp
Normale Datei
65
client/src/widget/objectlist/stackedobjectlistwidget.hpp
Normale Datei
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* client/src/widget/objectlist/stackedobjectlistwidget.hpp
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* 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_OBJECTLIST_STACKEDOBJECTLISTWIDGET_HPP
|
||||
#define TRAINTASTIC_CLIENT_WIDGET_OBJECTLIST_STACKEDOBJECTLISTWIDGET_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "../../network/objectptr.hpp"
|
||||
#include "../../network/tablemodelptr.hpp"
|
||||
|
||||
class QToolBar;
|
||||
class QStackedWidget;
|
||||
class QListView;
|
||||
class QLabel;
|
||||
class MethodIcon;
|
||||
class MethodAction;
|
||||
|
||||
class StackedObjectListWidget : public QWidget
|
||||
{
|
||||
protected:
|
||||
ObjectPtr m_object;
|
||||
TableModelPtr m_tableModel;
|
||||
QToolBar* m_navBar;
|
||||
QLabel* m_navLabel;
|
||||
QStackedWidget* m_stack;
|
||||
QListView* m_list;
|
||||
MethodIcon* m_create = nullptr;
|
||||
QMenu* m_createMenu = nullptr;
|
||||
MethodAction* m_actionRemove = nullptr;
|
||||
QString m_listObjectId;
|
||||
int m_requestId;
|
||||
|
||||
void cancelRequest();
|
||||
|
||||
void back();
|
||||
void show(const ObjectPtr& listObject);
|
||||
|
||||
bool eventFilter(QObject* object, QEvent* event) override;
|
||||
|
||||
public:
|
||||
explicit StackedObjectListWidget(const ObjectPtr& object, QWidget* parent = nullptr);
|
||||
~StackedObjectListWidget() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -3,7 +3,7 @@
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2021,2023 Reinder Feenstra
|
||||
* Copyright (C) 2021,2023,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
|
||||
@ -27,6 +27,7 @@
|
||||
|
||||
constexpr uint32_t columnId = 0;
|
||||
constexpr uint32_t columnName = 1;
|
||||
constexpr uint32_t columnClassId = 3;
|
||||
|
||||
bool InterfaceListTableModel::isListedProperty(std::string_view name)
|
||||
{
|
||||
@ -43,6 +44,7 @@ InterfaceListTableModel::InterfaceListTableModel(InterfaceList& list) :
|
||||
DisplayName::Object::id,
|
||||
DisplayName::Object::name,
|
||||
DisplayName::Interface::status,
|
||||
"class_id"
|
||||
});
|
||||
}
|
||||
|
||||
@ -61,10 +63,15 @@ std::string InterfaceListTableModel::getText(uint32_t column, uint32_t row) cons
|
||||
return interface.name;
|
||||
|
||||
case columnStatus:
|
||||
if(const auto* it = EnumValues<InterfaceState>::value.find(interface.status->state); it != EnumValues<InterfaceState>::value.end())
|
||||
return std::string("$").append(EnumName<InterfaceState>::value).append(":").append(it->second).append("$");
|
||||
if(const auto* it = EnumValues<InterfaceState>::value.find(interface.status->state); it != EnumValues<InterfaceState>::value.end()) [[likely]]
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
break;
|
||||
|
||||
case columnClassId:
|
||||
return std::string{interface.getClassId()};
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren