Commit cbca2815 authored by Guenter Schwann's avatar Guenter Schwann
Browse files

663 Add DVBus entity

parent 71fb6bac
Pipeline #5660 passed with stage
in 12 minutes and 6 seconds
......@@ -7,6 +7,8 @@ target_sources(${LIB_NAME} PRIVATE
connectionvalidator.h
dvboard.cpp
dvboard.h
dvbus.cpp
dvbus.h
dvcommonprops.cpp
dvcommonprops.h
dvconnection.cpp
......
/*
Copyright (C) 2021 European Space Agency - <maxime.perrotin@esa.int>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program. If not, see <https://www.gnu.org/licenses/lgpl-2.1.html>.
*/
#include "dvbus.h"
#include "dvconnection.h"
#include "dvdevice.h"
#include <QSet>
namespace dvm {
DVBus::DVBus(DVObject *parent)
: DVObject(DVObject::Type::Bus, {}, parent)
{
}
void DVBus::setConnections(const QList<DVConnection *> &connections)
{
QSet<DVDevice *> devices;
for (DVConnection *connection : connections) {
devices.insert(connection->sourceDevice());
devices.insert(connection->targetDevice());
}
for (DVDevice *dev : devices) {
m_devices << QPointer<DVDevice>(dev);
}
}
QList<DVDevice *> DVBus::connectedDevices() const
{
QList<DVDevice *> devices;
for (const QPointer<DVDevice> &dev : m_devices) {
if (!dev.isNull()) {
devices << dev.data();
}
}
return devices;
}
QString DVBus::qualifier() const
{
if (!m_devices.isEmpty() && m_devices.first()) {
return m_devices.first()->qualifier();
}
return "";
}
} // namespace dvm
/*
Copyright (C) 2021 European Space Agency - <maxime.perrotin@esa.int>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program. If not, see <https://www.gnu.org/licenses/lgpl-2.1.html>.
*/
#pragma once
#include "dvobject.h"
#include <QPointer>
namespace dvm {
class DVConnection;
class DVDevice;
class DVBus : public DVObject
{
Q_OBJECT
public:
explicit DVBus(DVObject *parent = nullptr);
void setConnections(const QList<DVConnection *> &connections);
QList<DVDevice *> connectedDevices() const;
QString qualifier() const;
private:
QList<QPointer<DVDevice>> m_devices;
};
} // namespace dvm
......@@ -44,8 +44,8 @@ DVConnection::DVConnection(DVDevice *sourceDev, DVDevice *targetDev, DVObject *p
setEntityAttribute(meta::Props::token(meta::Props::Token::to_node), targetDev->node()->title());
setEntityAttribute(meta::Props::token(meta::Props::Token::to_port), targetDev->portName());
}
if (sourceDev && targetDev && sourceDev->busName() == targetDev->busName()) {
setEntityAttribute(meta::Props::token(meta::Props::Token::to_bus), targetDev->busName());
if (sourceDev && targetDev && sourceDev->qualifier() == targetDev->qualifier()) {
setEntityAttribute(meta::Props::token(meta::Props::Token::to_bus), targetDev->qualifier());
}
}
......@@ -82,7 +82,7 @@ bool DVConnection::postInit()
}
const QList<QPointer<DVDevice>> nodeDevices = node->devices();
auto it = std::find_if(nodeDevices.cbegin(), nodeDevices.cend(), [portName, busName](DVDevice *dev) {
return dev->portName() == portName && dev->busName() == busName;
return dev->portName() == portName && dev->qualifier() == busName;
});
if (it == nodeDevices.cend()) {
shared::ErrorHub::addError(shared::ErrorItem::Error,
......
......@@ -49,6 +49,11 @@ DVDevice::DVDevice(DVObject *parent)
Q_EMIT portChanged(this->portName());
}
});
connect(this, &shared::VEObject::attributeChanged, this, [this](const QString &name) {
if (name == meta::Props::token(meta::Props::Token::requires_bus_access)) {
Q_EMIT qualifierChanged(this->qualifier());
}
});
}
DVNode *DVDevice::node() const
......@@ -66,12 +71,12 @@ void DVDevice::setPortName(const QString &name)
setEntityAttribute(meta::Props::token(meta::Props::Token::port), name);
}
QString DVDevice::busName() const
QString DVDevice::qualifier() const
{
return entityAttributeValue(meta::Props::token(meta::Props::Token::requires_bus_access)).toString();
}
void DVDevice::setBusName(const QString &name)
void DVDevice::setQualifier(const QString &name)
{
setEntityAttribute(meta::Props::token(meta::Props::Token::requires_bus_access), name);
}
......
......@@ -27,6 +27,7 @@ class DVDevice : public DVObject
{
Q_OBJECT
Q_PROPERTY(QString portName READ portName WRITE setPortName NOTIFY portChanged)
Q_PROPERTY(QString qualifier READ qualifier WRITE setQualifier NOTIFY qualifierChanged)
public:
explicit DVDevice(const DVPort &port, DVObject *parent = nullptr);
explicit DVDevice(DVObject *parent = nullptr);
......@@ -36,11 +37,12 @@ public:
QString portName() const;
void setPortName(const QString &name);
QString busName() const;
void setBusName(const QString &name);
QString qualifier() const;
void setQualifier(const QString &name);
Q_SIGNALS:
void portChanged(const QString &port);
void qualifierChanged(const QString &qualifier);
};
} // namespace dvm
......@@ -18,6 +18,7 @@
#include "dvmodel.h"
#include "common.h"
#include "dvbus.h"
#include "dvconnection.h"
#include "dvdevice.h"
#include "dvfunction.h"
......@@ -35,10 +36,17 @@ namespace dvm {
DVModel::DVModel(QObject *parent)
: shared::VEModel(parent)
{
connect(this, &DVModel::objectsAdded, this, &DVModel::onObjectsAdded);
connect(this, &DVModel::objectRemoved, this, &DVModel::onObjectRemoved);
}
DVModel::~DVModel() { }
DVObject *DVModel::getObject(const shared::Id &id) const
{
return qobject_cast<DVObject *>(shared::VEModel::getObject(id));
}
DVObject *DVModel::getObjectByName(const QString &name, DVObject::Type type, Qt::CaseSensitivity caseSensitivity) const
{
if (name.isEmpty())
......@@ -54,6 +62,14 @@ DVObject *DVModel::getObjectByName(const QString &name, DVObject::Type type, Qt:
return nullptr;
}
void DVModel::clear()
{
// Avoid calling resetBuses() again and again
disconnect(this, &DVModel::objectRemoved, this, &DVModel::onObjectRemoved);
VEModel::clear();
connect(this, &DVModel::objectRemoved, this, &DVModel::onObjectRemoved);
}
/*!
Returns all connections that are connected to teh given \p device
*/
......@@ -206,9 +222,41 @@ bool DVModel::addObjectImpl(shared::VEObject *obj)
return false;
}
DVObject *DVModel::getObject(const shared::Id &id) const
void DVModel::resetBuses()
{
return qobject_cast<DVObject *>(shared::VEModel::getObject(id));
// Remove old buses
disconnect(this, &DVModel::objectRemoved, this, &DVModel::onObjectRemoved);
for (DVBus *bus : allObjectsByType<DVBus>()) {
removeObject(bus);
}
// Add buses
QList<QList<DVConnection *>> clusters = connectionClusters();
int idx = 1;
for (const QList<DVConnection *> &cluster : clusters) {
auto bus = new DVBus();
bus->setConnections(cluster);
bus->setTitle(QString("bus_%1").arg(idx));
addObject(bus);
++idx;
}
connect(this, &DVModel::objectRemoved, this, &DVModel::onObjectRemoved);
}
void DVModel::onObjectsAdded(const QVector<shared::Id> &objectsIds)
{
for (const shared::Id &id : objectsIds) {
DVObject *obj = getObject(id);
if (obj && obj->type() == dvm::DVObject::Type::Connection) {
resetBuses();
return;
}
}
}
void DVModel::onObjectRemoved()
{
resetBuses();
}
} // namespace dvm
......@@ -42,6 +42,8 @@ public:
DVObject *getObject(const shared::Id &id) const override;
DVObject *getObjectByName(const QString &name, DVObject::Type type, Qt::CaseSensitivity caseSensitivity) const;
void clear() override;
QList<DVConnection *> connections(DVDevice *device) const;
QList<DVConnection *> connections(DVNode *node) const;
DVConnection *connectionByName(const QString &name) const;
......@@ -53,6 +55,12 @@ public:
QList<DVFunction *> functions(DVNode *node) const;
bool addObjectImpl(shared::VEObject *obj) override;
void resetBuses();
protected Q_SLOTS:
void onObjectsAdded(const QVector<shared::Id> &objectsIds);
void onObjectRemoved();
};
} // namespace dvm
......@@ -47,6 +47,7 @@ public:
Device,
Connection,
Message,
Bus,
};
Q_ENUM(Type)
......
......@@ -5,6 +5,7 @@
<qresource prefix="/toolbar">
<file>icns/asn1.png</file>
<file>icns/board.svg</file>
<file>icns/bus.svg</file>
<file>icns/comment.svg</file>
<file>icns/connection_group.svg</file>
<file>icns/connection.svg</file>
......
......@@ -42,21 +42,21 @@ QString DVExporter::defaultTemplatePath() const
bool DVExporter::exportObjects(
const QList<shared::VEObject *> &objects, QBuffer *outBuffer, const QString &templatePath)
{
const QHash<QString, QVariant> dvObjects = exportObjects(objects);
const QHash<QString, QVariant> dvObjects = collectObjects(objects);
return exportData(dvObjects, templatePath, outBuffer);
}
bool DVExporter::exportObjectsInteractively(
const QList<shared::VEObject *> &objects, const QString &outPath, const QString &templatePath, QWidget *root)
{
const QHash<QString, QVariant> dvObjects = exportObjects(objects);
const QHash<QString, QVariant> dvObjects = collectObjects(objects);
return exportData(dvObjects, outPath, templatePath, InteractionPolicy::Interactive, root);
}
bool DVExporter::exportObjectsSilently(
const QList<shared::VEObject *> &objects, const QString &outPath, const QString &templatePath)
{
const QHash<QString, QVariant> dvObjects = exportObjects(objects);
const QHash<QString, QVariant> dvObjects = collectObjects(objects);
return exportData(dvObjects, outPath, templatePath, InteractionPolicy::Silently);
}
......@@ -79,6 +79,8 @@ QString DVExporter::groupName(const shared::VEObject *object) const
return QStringLiteral("Nodes");
case dvm::DVObject::Type::Connection:
return QStringLiteral("Connections");
case dvm::DVObject::Type::Bus:
return QStringLiteral("Buses");
default:
return {};
}
......@@ -86,29 +88,4 @@ QString DVExporter::groupName(const shared::VEObject *object) const
return {};
}
QHash<QString, QVariant> DVExporter::exportObjects(const QList<shared::VEObject *> &objects) const
{
if (objects.isEmpty()) {
return {};
}
QHash<QString, QVariant> exObjects = collectObjects(objects);
auto model = qobject_cast<dvm::DVModel *>(objects.first()->model());
if (model) {
QVariantList buses;
QList<QList<dvm::DVConnection *>> clusters = model->connectionClusters();
for (const QList<dvm::DVConnection *> &cluster : clusters) {
if (cluster.isEmpty()) {
continue;
}
ExportableDVBus bus;
bus.setName(cluster.first()->sourceNode()->title() + "_" + cluster.first()->sourceDevice()->title());
bus.setQualifier(cluster.first()->sourceDevice()->busName());
buses.append(QVariant::fromValue(bus));
}
exObjects["Buses"] = buses;
}
return exObjects;
}
} // namespace dve
......@@ -51,8 +51,6 @@ private:
*/
QVariant createFrom(const shared::VEObject *object) const override;
QString groupName(const shared::VEObject *object) const override;
QHash<QString, QVariant> exportObjects(const QList<shared::VEObject *> &objects) const;
};
} // namespace dve
......@@ -17,9 +17,9 @@
#include "dvtreeviewmodel.h"
#include "dvmodel.h"
#include "commands/cmdentityattributechange.h"
#include "commandsstackbase.h"
#include "dvmodel.h"
#include "dvnamevalidator.h"
namespace dve {
......@@ -41,6 +41,10 @@ void DVTreeViewModel::updateItemData(QStandardItem *item, shared::VEObject *obje
QPixmap pix;
switch (obj->type()) {
case dvm::DVObject::Type::Bus: {
static const QPixmap icon = QIcon(QLatin1String(":/toolbar/icns/bus.svg")).pixmap(16, 16);
pix = icon;
} break;
case dvm::DVObject::Type::Connection: {
static const QPixmap icon = QIcon(QLatin1String(":/toolbar/icns/connection.svg")).pixmap(16, 16);
pix = icon;
......@@ -74,7 +78,7 @@ void DVTreeViewModel::updateItemData(QStandardItem *item, shared::VEObject *obje
QStandardItem *DVTreeViewModel::createItem(shared::VEObject *obj)
{
QStandardItem *item = shared::AbstractVisualizationModel::createItem(obj);
connect(obj, &shared::VEObject::attributeChanged, this, [this](const QString &attrName){
connect(obj, &shared::VEObject::attributeChanged, this, [this](const QString &attrName) {
if (attrName == dvm::meta::Props::token(dvm::meta::Props::Token::name)) {
updateItem();
}
......@@ -83,7 +87,8 @@ QStandardItem *DVTreeViewModel::createItem(shared::VEObject *obj)
return item;
}
void DVTreeViewModel::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
void DVTreeViewModel::onDataChanged(
const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
if (!m_commandsStack) {
return;
......@@ -101,9 +106,8 @@ void DVTreeViewModel::onDataChanged(const QModelIndex &topLeft, const QModelInde
const QString name = dvm::DVNameValidator::encodeName(obj->type(), item->text());
if (name != obj->title()) {
if (dvm::DVNameValidator::isAcceptableName(obj, name)) {
const QVariantHash attributes = {
{ dvm::meta::Props::token(dvm::meta::Props::Token::name), name }
};
const QVariantHash attributes = { { dvm::meta::Props::token(dvm::meta::Props::Token::name),
name } };
auto attributesCmd = new shared::cmd::CmdEntityAttributeChange(obj, attributes);
m_commandsStack->push(attributesCmd);
} else {
......@@ -116,5 +120,4 @@ void DVTreeViewModel::onDataChanged(const QModelIndex &topLeft, const QModelInde
}
}
} // namespace dve
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.0"
width="228.24799"
height="228.092"
viewBox="0 0 228.248 228.092"
id="Layer_1"
xml:space="preserve"
sodipodi:docname="bus.svg"
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
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"><sodipodi:namedview
id="namedview5"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="2.6344141"
inkscape:cx="210.29344"
inkscape:cy="113.87731"
inkscape:window-width="2560"
inkscape:window-height="1369"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1"
width="288.24799px" /><defs
id="defs1337" />
<path
d="M 227.37112,114.054 198.89804,84.556108 198.84488,105.12875 75.670612,105.771 100.37509,53.159 c 2.10243,-3.397 5.17657,-9.40509 8.00628,-9.53709 11.44737,0 18.24534,-0.006 20.74764,-0.016 1.69615,9.741 7.73828,11.374297 13.15463,11.374297 6.85206,0 13.60113,-4.511418 13.60113,-18.328418 0,-13.823 -6.42077,-20.64318 -13.27332,-20.64318 -5.41635,0 -11.78629,1.344301 -13.48244,11.077301 l -20.50455,-0.007 c -5.55724,0 -11.703675,9.77109 -15.40999,16.97609 0.101206,-0.214 0.206378,-0.442 -0.0056,0.004 -0.07843,0.178 -26.210607,55.814 -26.210607,55.814 -2.097981,3.392 -4.847332,5.76 -7.675065,5.896 l -7.370477,-0.33951 C 50.050083,86.31649 37.688298,81.534318 27.644384,81.534318 16.193053,81.534318 3.9165771,90.967 3.9165771,114.043 c 0,23.083 12.8998189,32.46736 24.3511499,32.46736 10.045898,0 20.983248,-4.74842 22.88577,-23.87742 L 59.07327,122.297 c 0.0362,-0.002 0.07243,0.004 0.109139,0 h 31.189906 c 2.822277,0.145 5.568155,2.516 7.664164,5.912 0,0 26.060771,60.23987 26.141631,60.41987 0.20935,0.447 0.10518,0.214 0.002,0.004 3.70631,7.204 9.53195,13.346 15.09017,13.346 l 19.76039,-0.009 0.0656,12.16913 28.66184,0.0128 v -41.79761 l -28.66184,-0.0128 -0.0656,13.11548 c 0,0 -5.20449,-0.019 -20.00248,-0.019 -2.83022,-0.131 -5.58403,-2.511 -7.68549,-5.908 L 106.6983,122.3 l 91.96454,-0.58162 0.53191,21.43535 z"
id="path1334"
style="stroke-width:0.704339"
sodipodi:nodetypes="cccccccssscccccccssscscccccccccccccccccc" />
</svg>
......@@ -78,6 +78,7 @@ shared::ui::VEInteractiveObject *DVItemModel::createItem(shared::Id objectId)
return new DVConnectionGraphicsItem(connectionEntity, startItem, endItem, parentItem);
}
} break;
case dvm::DVObject::Type::Bus:
case dvm::DVObject::Type::Message: {
break;
}
......
......@@ -17,26 +17,28 @@
#include "exportabledvbus.h"
namespace dve {
#include "dvbus.h"
#include "dvdevice.h"
QString ExportableDVBus::name() const
{
return m_name;
}
namespace dve {
void ExportableDVBus::setName(const QString &name)
ExportableDVBus::ExportableDVBus(const dvm::DVObject *dvObject)
: ExportableDVObject(dvObject)
{
m_name = name;
}
QString ExportableDVBus::qualifier() const
{
return m_qualifier;
return exportedObject<dvm::DVBus>()->qualifier();
;
}
void ExportableDVBus::setQualifier(const QString &name)
QVariantList ExportableDVBus::devices() const
{
m_qualifier = name;
QVariantList devices;
for (const dvm::DVDevice *device : exportedObject<dvm::DVBus>()->connectedDevices())
devices << createFrom(device);
return devices;
}
} // namespace dve
......@@ -17,26 +17,26 @@
#pragma once
#include <QObject>
#include "exportabledvobject.h"
namespace dvm {
class DVObject;
}
namespace dve {
class ExportableDVBus
class ExportableDVBus : public ExportableDVObject
{
Q_GADGET
Q_PROPERTY(QString name READ name)
Q_PROPERTY(QString qualifier READ qualifier)
Q_PROPERTY(QVariantList devices READ devices)
public:
QString name() const;
void setName(const QString &name);
explicit ExportableDVBus(const dvm::DVObject *dvObject = nullptr);
QString qualifier() const;
void setQualifier(const QString &name);
private:
QString m_name;
QString m_qualifier;
QVariantList devices() const;
};
} // namespace dve
......
......@@ -80,6 +80,8 @@ QString ExportableDVConnection::toPort() const
QString ExportableDVConnection::busName() const
{
/// @todo get the name of the DVbus instead
dvm::DVConnection *connection = const_cast<dvm::DVConnection *>(exportedObject<dvm::DVConnection>());
dvm::DVDevice *device = connection->sourceDevice();
dvm::DVModel *model = device ? device->model() : nullptr;
......@@ -88,13 +90,15 @@ QString ExportableDVConnection::busName() const
}
QList<QList<dvm::DVConnection *>> clusters = model->connectionClusters();
auto it = std::find_if(clusters.begin(), clusters.end(),
[&connection](QList<dvm::DVConnection *> cluster) { return cluster.contains(connection); });
if (it == clusters.end()) {
return {};
int count = 1;
for (const QList<dvm::DVConnection *> &cluster : clusters) {
if (cluster.contains(connection)) {
break;
}
++count;
}
return it->first()->sourceNode()->title() + "_" + it->first()->sourceDevice()->title();
return QString("bus_%1").arg(count);
}
} // namespace dve
......@@ -18,6 +18,7 @@
#include "exportabledvdevice.h"