Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,126 @@
/**
* @RDE_HEADER@
* The ApproachingPointsDialog shows a list of approaching points
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2018-01-17
*/
#include "ism_approaching_point_list_dialog.h"
#include "ui_ism_approaching_point_list_dialog.h"
#include "ism_approaching_point_list_dialog_model.h"
#include "ism_edit_approaching_point_dialog.h"
#include <LtsSession/lts_session_data.h>
#include <LtsPrinting/printing.h>
#include <QTreeView>
namespace InfrastructureManagement
{
ApproachingPointsDialog::ApproachingPointsDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_session(session)
, m_ui(new Ui::ApproachingPointsDialog)
, m_model(nullptr)
, m_menuGroup(menuGroup)
, m_logger(getLogger("ApproachingPointsDialog"))
{
m_ui->setupUi(this);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &ApproachingPointsDialog::onPrint);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Approach_Points"));
}
ApproachingPointsDialog::~ApproachingPointsDialog()
{
delete m_ui;
}
void ApproachingPointsDialog::retranslate()
{
translate(m_ui, tr("Approaching Points"));
}
void ApproachingPointsDialog::tableColumnOrganiserSetting()
{
//LtsColumnOrganiser
m_ui->approachingPointsView->setColumnsOrganiserEnabled(identifier(), true);
}
bool ApproachingPointsDialog::init(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMap)
{
m_ftc = ftc;
m_sitMapIfc = sitMap;
delete m_model;
m_model = new ApproachingPointsDialogModel(this);
if (!m_model->initModel(dtc))
{
ERROR_LOG(m_logger) << "Could not init model";
delete m_model;
m_model = nullptr;
return false;
}
m_ui->approachingPointsView->setModel(m_model);
connect(m_ui->approachingPointsView, &LtsDataView::LtsDataView::signalDoubleClicked,
this, &ApproachingPointsDialog::onItemDoubleClicked);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &ApproachingPointsDialog::onItemDoubleClicked);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Add, true);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &ApproachingPointsDialog::onAddApproachingPoint);
#ifndef LTS_DEBUG
m_ui->approachingPointsView->hideColumn(ApproachingPointsDialogModel::Columns::Id);
#endif
return true;
}
void ApproachingPointsDialog::onItemDoubleClicked()
{
QModelIndex currentIndex = m_ui->approachingPointsView->currentIndex();
if (!currentIndex.isValid())
return;
EditApproachingPointDialog *dialog = new EditApproachingPointDialog(this);
MainStructureElement approachingPoint = m_model->getRowData(currentIndex.row());
if (!dialog->init(m_ftc, m_sitMapIfc, approachingPoint))
{
delete dialog;
return;
}
addDialog(dialog, m_menuGroup, QStringLiteral("EditApproachingPoint%1").arg(approachingPoint.id()), LtsWidgets::LayoutArea::eDialogTab);
}
void ApproachingPointsDialog::onPrint()
{
LtsPrinting::printView(m_session, this, m_ui->approachingPointsView->treeView() );
}
void ApproachingPointsDialog::onAddApproachingPoint()
{
QModelIndex currentIndex = m_ui->approachingPointsView->currentIndex();
EditApproachingPointDialog *dialog = new EditApproachingPointDialog(this);
MainStructureElement approachingPoint = m_model->getRowData(currentIndex.row());
approachingPoint.id(0);
if (!dialog->init(m_ftc, m_sitMapIfc, approachingPoint))
{
delete dialog;
return;
}
addDialog(dialog, m_menuGroup, QStringLiteral("AddApproachingPoint"), LtsWidgets::LayoutArea::eDialogTab);
}
} // namespace InfrastructureManagement
@@ -0,0 +1,72 @@
/**
* @RDE_HEADER@
* The ApproachingPointsDialog shows a list of approaching points
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2018-01-17
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <InfrastructureManagement/logger.h>
#include <memory>
namespace Ui
{
class ApproachingPointsDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace SituationMap
{
class ForeignGuiInterface;
}
namespace InfrastructureManagement
{
namespace Interface
{
class Dtc;
class Ftc;
}
class ApproachingPointsDialogModel;
class ApproachingPointsDialog
: public LtsWidgets::LtsDialog
{
Q_OBJECT
public:
explicit ApproachingPointsDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
~ApproachingPointsDialog();
bool init(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMap);
private Q_SLOTS:
void onItemDoubleClicked();
void onPrint();
void onAddApproachingPoint();
private:
void retranslate() override;
void tableColumnOrganiserSetting() override;
LtsSession::LtsSession *m_session;
Ui::ApproachingPointsDialog *m_ui;
ApproachingPointsDialogModel *m_model;
QString m_menuGroup;
std::shared_ptr<Interface::Ftc> m_ftc;
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapIfc;
LOGGER_T m_logger;
}; // class ApproachingPointsDialogModel
} // namespace InfrastructureManagement
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ApproachingPointsDialog</class>
<widget class="QWidget" name="ApproachingPointsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>630</width>
<height>328</height>
</rect>
</property>
<property name="windowTitle">
<string>Approaching Points</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="LtsDataView::LtsDataView" name="approachingPointsView"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,114 @@
/**
* @RDE_HEADER@
* The ApproachingPointsDialogModel provides data for ApproachingPointsDialog
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2018-01-17
*/
#include "ism_approaching_point_list_dialog_model.h"
#include <InfrastructureManagement/ism_data_plugin_interface.h>
#include <InfrastructureManagement/ism_translation.h>
#include <LtsSession/lts_session.h>
#include <QDateTime>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <QJsonObject>
#include <QJsonDocument>
namespace InfrastructureManagement
{
ApproachingPointsDialogModel::ApproachingPointsDialogModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<MainStructureElement>({tr("Id"),
tr("Name"),
tr("Description"),
tr("Position"),
tr("Departure Direction"),
tr("Special Type"),
tr("Properties")},
parent)
, m_logger(getLogger("ApproachingPointsDialogModel"))
{
}
QVariant ApproachingPointsDialogModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole || !indexIsValid(index))
return QVariant();
const MainStructureElement &currentPoint = m_vecData.at(index.row());
switch (index.column())
{
case Id:
return currentPoint.id();
case Name:
return QString::fromStdString(currentPoint.name());
case Description:
{
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(currentPoint.description()));
const QString jsonKey = QLatin1String("description");
if (!doc.isObject())
return QVariant();
return doc.object().value(jsonKey).toString();
}
case Position:
return LtsCoordTrans::mgrsFromGeographic(currentPoint.geoPosition().lon(), currentPoint.geoPosition().lat());
case Orientation:
return calculateCardinalDirection(currentPoint.angle());
}
return QVariant();
}
bool ApproachingPointsDialogModel::initModel(const std::shared_ptr<Interface::Dtc> &dtc)
{
connect(dtc.get(), &Interface::Dtc::mainStructureElementChanged,
this, &ApproachingPointsDialogModel::onDataChanged);
auto cb = [this](const InfrastructureManagement::MainStructureElement &mse)
{
onDataChanged(mse, DataModification::eAdded);
};
dtc->mainStructureElements(cb);
INFO_LOG(m_logger) << "initModel successful";
return true;
}
QString ApproachingPointsDialogModel::calculateCardinalDirection(double degree, bool longVersion) const
{
int value = (int) ((degree / 45) + 0.5) % 8;
switch (value)
{
case 0:
return longVersion ? tr("North") : tr("N");
case 1:
return longVersion ? tr("North-East") : tr("NE");
case 2:
return longVersion ? tr("East") : tr("E");
case 3:
return longVersion ? tr("South-East") : tr("SE");
case 4:
return longVersion ? tr("South") : tr("S");
case 5:
return longVersion ? tr("South-West") : tr("SW");
case 6:
return longVersion ? tr("West") : tr("W");
case 7:
return longVersion ? tr("North-West") : tr("NW");
}
return QString();
}
bool ApproachingPointsDialogModel::isFiltered(const InfrastructureManagement::MainStructureElement &data, DataModification modType) const
{
Q_UNUSED(modType);
return (data.structureElementTypeId() != InfrastructureManagement::StructureElementType::ApproachingPoint);
}
} // namespace InfrastructureManagement
@@ -0,0 +1,47 @@
/**
* @RDE_HEADER@
* The ApproachingPointsDialogModel provides data for ApproachingPointsDialog
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2018-01-17
*/
#pragma once
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
#include <LtsWidgets/lts_abstract_table_model.h>
namespace InfrastructureManagement
{
class ApproachingPointsDialogModel : public LtsWidgets::LtsAbstractTableModel<MainStructureElement>
{
Q_OBJECT
public:
explicit ApproachingPointsDialogModel(QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role) const override final;
bool initModel(const std::shared_ptr<Interface::Dtc> &dtc);
QString calculateCardinalDirection(double degree, bool longVersion = true) const;
enum Columns
{
Id,
Name,
Description,
Position,
Orientation
};
protected:
bool isFiltered(const InfrastructureManagement::MainStructureElement &data, DataModification modType) const override;
private: // attributes
LOGGER_T m_logger;
}; // class ApproachingPointsDialogModel
} // namespace InfrastructureManagement
@@ -0,0 +1,142 @@
/**
* @RDE_HEADER@
* The EditApproachingPointDialog offers an UI to edit an Approaching Point
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2018-01-17
*/
#include "ism_edit_approaching_point_dialog.h"
#include "ui_ism_edit_approaching_point_dialog.h"
#include <LtsSession/lts_session.h>
#include <InfrastructureManagement/ism_translation.h>
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <QJsonDocument>
namespace InfrastructureManagement
{
EditApproachingPointDialog::EditApproachingPointDialog(QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_ui(new Ui::EditApproachingPointDialog)
, m_ftc(nullptr)
, m_sitMapGuiIfc(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("EditApproachingPointDialog"))
{
m_ui->setupUi(this);
fillCbDepartureDirection();
m_uiRequirements->addRequirement({m_ui->lblPosition, [this]() { return !m_ui->positionEdit->coordinate().isNull(); }});
m_uiRequirements->addRequirement({m_ui->lblName, [this]() { return !m_ui->leName->text().isEmpty(); }});
connect(m_ui->pbClear, &QPushButton::clicked,
m_ui->positionEdit, &LtsCoordWidget::LtsCoordWidget::clear);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Approach_Points"));
}
EditApproachingPointDialog::~EditApproachingPointDialog()
{
delete m_ui;
}
void EditApproachingPointDialog::retranslate()
{
translate(m_ui, m_approachingPoint, tr("Approaching Point"));
}
bool EditApproachingPointDialog::init(const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMap,
const MainStructureElement &approachingPoint)
{
m_ftc = ftc;
m_sitMapGuiIfc = sitMap;
if (m_sitMapGuiIfc)
connect(m_ui->pbPosition, &QPushButton::clicked, this, &EditApproachingPointDialog::getPosition);
else
m_ui->pbPosition->setEnabled(false);
setData(approachingPoint);
return true;
}
bool EditApproachingPointDialog::apply()
{
return m_requestHelper->startSingleRequest([this]()
{
MainStructureElementModifyRequest request;
request.id(m_approachingPoint.id());
request.name(m_ui->leName->text().toStdString());
request.angle(m_ui->cbDepartureDirection->currentData().toDouble());
request.properties("{}");
request.structureElementId(m_approachingPoint.structureElementId());
request.structureElementTypeId(InfrastructureManagement::StructureElementType::ApproachingPoint);
QJsonObject objDescription;
objDescription.insert(QLatin1String("description"), m_ui->leDescription->text());
request.description(QJsonDocument(objDescription).toJson(QJsonDocument::Compact).toStdString());
const Core::GeoPosition pos(m_ui->positionEdit->coordinate().x(),m_ui->positionEdit->coordinate().y(), 0);
request.geoPosition(pos);
// fill in structure element (only one, needed for mse/se relationsships)
if (m_approachingPoint.id() == 0)
{
StructureElement seData;
seData.name(request.name());
seData.displayName(request.name());
seData.structureElementTypeId(InfrastructureManagement::StructureElementType::ApproachingPoint);
seData.mountingPointTypeId(InfrastructureManagement::MountingPointType::Unknown);
seData.properties("{}");
request.elements().resize(1, seData);
request.childParentRelations().resize(1, -1);
}
return m_ftc->mainStructureElementModifyRequest(request, this);
});
}
void EditApproachingPointDialog::fillCbDepartureDirection()
{
m_ui->cbDepartureDirection->insertItem(0,tr("North"),0);
m_ui->cbDepartureDirection->insertItem(1,tr("North-East"),45);
m_ui->cbDepartureDirection->insertItem(2,tr("East"),90);
m_ui->cbDepartureDirection->insertItem(3,tr("South-East"),135);
m_ui->cbDepartureDirection->insertItem(4,tr("South"),180);
m_ui->cbDepartureDirection->insertItem(5,tr("South-West"),225);
m_ui->cbDepartureDirection->insertItem(6,tr("West"),270);
m_ui->cbDepartureDirection->insertItem(7,tr("North-West"),315);
}
void EditApproachingPointDialog::setData(const MainStructureElement &approachingPoint)
{
m_approachingPoint = approachingPoint;
m_ui->leName->setText(QString::fromStdString(m_approachingPoint.name()));
QJsonObject objDescription = QJsonDocument::fromJson(QByteArray::fromStdString(m_approachingPoint.description())).object();
QString strDescription = objDescription.value(QLatin1String("description")).toString();
m_ui->leDescription->setText(strDescription);
QPointF pos(m_approachingPoint.geoPosition().lon(), m_approachingPoint.geoPosition().lat());
if (!pos.isNull())
m_ui->positionEdit->setCoordinate(pos);
m_ui->cbDepartureDirection->setCurrentIndex( (int) ((approachingPoint.angle() / 45) + 0.5) % 8);
}
void EditApproachingPointDialog::getPosition()
{
if (!m_sitMapGuiIfc) //sanity
return;
m_sitMapGuiIfc->getCoordinate(m_ui->positionEdit, SLOT(setCoordinate(QPointF)), nullptr);
}
} // namespace InfrastructureManagement
@@ -0,0 +1,72 @@
/**
* @RDE_HEADER@
* The EditApproachingPointDialog offers an UI to edit an Approaching Point
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2018-01-17
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <InfrastructureManagement/ism_ftc.h>
#include <InfrastructureManagement/logger.h>
#include <LtsUtilsGuiDds/request_helper.h>
namespace LtsWidgets
{
class LtsProgressDialogHelper;
}
namespace Ui
{
class EditApproachingPointDialog;
}
namespace SituationMap
{
class ForeignGuiInterface;
}
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
class EditApproachingPointDialog
: public LtsWidgets::LtsDialog
, protected Interface::Ftc::MainStructureElementModifyReplyHandler
{
Q_OBJECT
public:
explicit EditApproachingPointDialog(QWidget *parent = nullptr);
~EditApproachingPointDialog();
bool init(const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMap,
const MainStructureElement &approachingPoint = MainStructureElement());
void onMainStructureElementModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private slots:
void getPosition();
private:
void retranslate() override;
void fillCbDepartureDirection();
void setData(const MainStructureElement &approachingPoint);
bool apply() override final;
Ui::EditApproachingPointDialog *m_ui;
std::shared_ptr<Interface::Ftc> m_ftc;
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
MainStructureElement m_approachingPoint;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
}; // class EditApproachingPointDialog
} // namespace InfrastructureManagement
@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditApproachingPointDialog</class>
<widget class="QWidget" name="EditApproachingPointDialog">
<property name="windowTitle">
<string notr="true">Edit Approaching Point</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="lblDescription">
<property name="text">
<string>Description:</string>
</property>
</widget>
</item>
<item row="1" column="2" colspan="2">
<widget class="QLineEdit" name="leDescription"/>
</item>
<item row="3" column="2" colspan="2">
<widget class="LtsWidgets::LtsComboBox" name="cbDepartureDirection"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblPosition">
<property name="text">
<string>Position:</string>
</property>
</widget>
</item>
<item row="2" column="2">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="LtsCoordWidget::LtsCoordWidget" name="positionEdit"/>
</item>
<item>
<widget class="QPushButton" name="pbPosition">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/position.svg</normaloff>:/style/position.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbClear">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/remove.svg</normaloff>:/style/remove.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="lblOrientation">
<property name="text">
<string>Departure Direction:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2" colspan="2">
<widget class="QLineEdit" name="leName"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblName">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsCoordWidget::LtsCoordWidget</class>
<extends>QWidget</extends>
<header>LtsCoordTrans/lts_coord_widget.h</header>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>leName</tabstop>
<tabstop>leDescription</tabstop>
<tabstop>positionEdit</tabstop>
<tabstop>pbPosition</tabstop>
<tabstop>pbClear</tabstop>
<tabstop>cbDepartureDirection</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,866 @@
/**
* @RDE_HEADER@
* The AssetListDialog shows how many assets are needed for a specific schedule, needed elsewhere,
* totally possessed, free, and missing
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#include "ism_asset_list_dialog.h"
#include "ui_ism_asset_list_dialog.h"
#include "ism_asset_list_dialog_model.h"
#include <InfrastructureManagement/ism_operator_rights.h>
#include <InfrastructureManagement/ism_translation.h>
#include <ComponentMonitor/cmo.hpp>
#include <LtsSession/lts_session_data.h>
#include <LtsPrinting/printing.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QFileDialog>
#include <QTreeView>
#include <QTextStream>
#include <QMenu>
#include <QAction>
#include <QTimer>
#include <vector>
namespace InfrastructureManagement
{
static QHash<int, QString> &INSTRUMENTATION_ASSET_STATES()
{
static QHash<int, QString> s_ret
{
{InstrumentationAssetState_def::Unmounted, QLatin1String("Unmounted")},
{InstrumentationAssetState_def::Mounted, QLatin1String("Mounted")},
{InstrumentationAssetState_def::Defect, QLatin1String("Defect")}
};
return s_ret;
}
AssetListDialog::AssetListDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_session(session)
, m_model(nullptr)
, m_menuGroup(menuGroup)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper())
, m_ui(new Ui::AssetListDialog)
, m_logger(getLogger("AssetListDialog"))
{
m_ui->setupUi(this);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &AssetListDialog::onPrint);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Asset_List"));
}
AssetListDialog::~AssetListDialog()
{
if (m_hostsForUpdateNotifiy)
m_hostsForUpdateNotifiy->stop();
if(m_editAssetDialog!=nullptr)
{
m_editAssetDialog->deleteLater();
}
delete m_ui;
delete m_model;
}
void AssetListDialog::retranslate()
{
translate(m_ui, tr("Asset List"));
}
bool AssetListDialog::apply()
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Export)->setEnabled(true);
bool enabled = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::SystemConfiguration);
m_buttonBox->getButton(LtsWidgets::DialogButton::Import)->setEnabled(enabled);
InstrumentationAsset asset;
for (int i = 0; i < m_model->rowCount(); ++i)
{
if (!rowContainsAlteredData(m_model->alteredRows().at(i)))
continue;
asset = m_model->getRowData(i);
InstrumentationAssetModifyRequest request(asset.id(),
asset.name(),
asset.mountingPointTypeId(),
asset.barcode(),
asset.hostname(),
asset.properties(),
asset.assetStateId(),
asset.lastUpdated(),
asset.availableInExercise());
m_requestHelper->addRequest([request, this]()
{
return m_ftc->instrumentationAssetModifyRequest(request, this);
});
}
m_model->removeBackgroundHighlighting();
bool ret = m_requestHelper->startRequests();
if(ret)
{
m_hasImportedAsset = false;
}
return ret;
}
void AssetListDialog::tableColumnOrganiserSetting()
{
//LtsColumnOrganiser
m_ui->assetListView->setColumnsOrganiserEnabled(identifier(), true);
}
/**
* @brief AssetListDialog::getExportString
* @param exp enum class, that informs about the selected filtering option.
* @param type gives the selected type in case of filtering by specific type, otherwise it is empty and unused.
* @return a vector containing all filtered rows as string
*/
QVector<QString> AssetListDialog::getExportString(const AssetFilterDialog::Export &exp, const QString &type) const
{
QVector<QString> vecOut;
switch (exp)
{
// ----- CASE ALL -----
case AssetFilterDialog::Export::eAll:
{
vecOut.reserve(m_model->rowCount());
for (int i = 0; i < m_model->rowCount(); ++i)
vecOut << exportData(m_model->getRowData(i));
break;
}// all end
// ----- CASE SELECTED -----
case AssetFilterDialog::Export::eSelected:
{
const auto idxList = m_ui->assetListView->selectedRows();
vecOut.reserve(idxList.size());
for (const QModelIndex &idx : idxList)
vecOut << exportData(m_model->getRowData(idx.row()));
break;
} // selected end
// ----- CASE SPECIFIC TYPE -----
case AssetFilterDialog::Export::eSpecificType:
{
vecOut.reserve(m_model->rowCount() / 10);
for (int i = 0; i < m_model->rowCount(); ++i)
{
const InstrumentationAsset &ia = m_model->getRowData(i);
if (toString(ia.mountingPointTypeId()) == type)
vecOut << exportData(ia);
}
break;
} // specific type end
} // switch end
return vecOut;
}
/**
* @brief AssetListDialog::exportData
* creates a string from the given InstrumentationAsset.
* @param ia InstrumentationAsset contains several propertys.
* @param separator the separator that is going to separate several items in the string.
* @return contains every property of the given InstrumentationAsset, separated by the given separator.
* @see importData()
*/
QString AssetListDialog::exportData(const InstrumentationAsset &ia, const QString &separator)
{
const QByteArray &properties = QByteArray::fromRawData(ia.properties().c_str(), ia.properties().size());
const QJsonDocument doc(QJsonDocument::fromJson(properties));
const QJsonObject obj(doc.object());
const QString &name = QString::fromStdString(ia.name());
const int nameSep = name.lastIndexOf(QLatin1Char('_'));
const QString &dmc = QString::fromStdString(ia.barcode());
const QString &tkz = name.mid(0, nameSep);
const QString &snr = nameSep >= 0 ? name.mid(nameSep + 1) : QString();
const QString &mac = obj.value(QStringLiteral("mac")).toString();
const QString &status = INSTRUMENTATION_ASSET_STATES().value(ia.assetStateId().underlying());
const QString &bz = ia.isUsed() ? QStringLiteral("Mounted") : QStringLiteral("Unmounted");
const QString &oc = QString::number(obj.value(QStringLiteral("opticalCode")).toInt());
const QString &ls = obj.value(QStringLiteral("hasSpeaker")).toBool() ? QStringLiteral("1") : QStringLiteral("0");
const QString &mf = obj.value(QStringLiteral("hasMicrophone")).toBool() ? QStringLiteral("1") : QStringLiteral("0");
const QString &vapix = obj.value(QStringLiteral("type")).toString() == QStringLiteral("vapix") ? QStringLiteral("1") : QStringLiteral("0");
const QString &user = obj.value(QStringLiteral("username")).toString();
const QString &pass = obj.value(QStringLiteral("password")).toString();
const QString &props = QString::fromUtf8(properties);
const QString &lastMod = QDateTime::fromMSecsSinceEpoch(ia.lastUpdated()).toString();
return QStringList({dmc, tkz, snr, mac, status, bz, oc, ls, mf, vapix, user, pass, props, lastMod}).join(separator);
}
static std::string unquote(const QStringRef &in)
{
if (!in.startsWith(QLatin1Char('"')) && !in.endsWith(QLatin1Char('"')))
return in.toString().toStdString();
QString out = in.mid(1, in.length() - 2).toString();
out.replace(QStringLiteral("\"\""), QStringLiteral("\""));
return out.toStdString();
}
/**
* @brief AssetListDialog::importData
* creates an InstrumentationAsset from the given stringlist.
* @param segments list of all segments of an InstrumentationAsset.
* @return InstrumentationAsset.
* @see exportData()
*/
static inline void setJson(QJsonObject &obj, const QString &key, bool bVal)
{
if (!bVal)
obj.remove(key);
else
obj[key] = bVal;
}
static inline void setJson(QJsonObject &obj, const QString &key, const QStringRef &val)
{
if (val.isEmpty())
obj.remove(key);
else
obj[key] = val.toString();
}
static inline void setJson(QJsonObject &obj, const QString &key, const QString &val)
{
setJson(obj, key, QStringRef(&val));
}
InstrumentationAsset AssetListDialog::importData(const QVector<QStringRef> &segments, bool *bOk) const
{
if (bOk)
*bOk = true;
const int len = segments.size();
const QStringRef &dmc = segments.at(0);
const QStringRef &tkz = segments.at(1);
const QStringRef &snr = segments.at(2);
const QStringRef &mac = segments.at(3);
const QStringRef &status = segments.at(4);
//const QString &bz = segments.at(5);
const QStringRef &oc = segments.at(6);
const QStringRef &ls = segments.at(7);
const QStringRef &mf = segments.at(8);
const QStringRef &vapix = segments.at(9);
const QStringRef &user = len > 10 ? segments.at(10) : QStringRef();
const QStringRef &pass = len > 11 ? segments.at(11) : QStringRef();
const QStringRef &props = len > 12 ? segments.at(12) : QStringRef();
//const QString &lastMod = len > 13 ? segments.at(13) : QStringRef();
const QJsonDocument doc(QJsonDocument::fromJson(props.toUtf8()));
QJsonObject obj(doc.object());
setJson(obj, QStringLiteral("mac"), mac);
setJson(obj, QStringLiteral("opticalCode"), oc);
setJson(obj, QStringLiteral("hasSpeaker"), (ls.isEmpty() || ls == QLatin1String("0")) ? false : true);
setJson(obj, QStringLiteral("hasMicrophone"), (mf.isEmpty() || mf == QLatin1String("0")) ? false : true);
setJson(obj, QStringLiteral("type"), (vapix.isEmpty() || vapix == QLatin1String("0")) ? QString() : QStringLiteral("vapix"));
setJson(obj, QStringLiteral("username"), user);
setJson(obj, QStringLiteral("password"), pass);
const std::string snrStd = unquote(snr);
const std::string tkzStd = unquote(tkz);
InstrumentationAsset asset;
asset.barcode() = unquote(dmc);
asset.name() = snrStd.empty() ? tkzStd : std::string(tkzStd + '_' + snrStd);
asset.assetStateId(static_cast<InstrumentationAssetState_def::type>(INSTRUMENTATION_ASSET_STATES().key(status.toString())));
asset.properties() = QJsonDocument(obj).toJson(QJsonDocument::Compact).constData();
// mountingPointTypeId is in DataMatrixCode
if (dmc.startsWith(QLatin1String("GSM")))
asset.mountingPointTypeId(MountingPointType::BuildingSensorModule);
else if (dmc.startsWith(QLatin1String("KAA")))
asset.mountingPointTypeId(MountingPointType_def::OutdoorCamera);
else if (dmc.startsWith(QLatin1String("KAI")))
asset.mountingPointTypeId(MountingPointType_def::IndoorCamera);
else if (dmc.startsWith(QLatin1String("OPS")))
asset.mountingPointTypeId(MountingPointType_def::IndoorIPS);
else if (dmc.startsWith(QLatin1String("WD_")))
asset.mountingPointTypeId(MountingPointType_def::EffectGenerationControlUnit);
else
{
if (bOk)
*bOk = false;
WARNING_LOG(m_logger) << "Could not determine mounting point type from barcode: " << dmc.toString();
}
return asset;
}
/**
* @brief AssetListDialog::updateInstrumentationAsset
* compares the name and the mountingPointTypeId of given InstrumentationAsset asset with the ones of every InstrumentationAsset that
* is already present in the model and if it is found, it is gonna update.
* @param asset InstrumentationAsset.
* @return true on found and updated, false on unlocated.
*/
bool AssetListDialog::updateInstrumentationAsset(const InstrumentationAsset &asset) const
{
InstrumentationAsset ia = asset;
int rowCount = m_model->rowCount();
for (int i = 0; i < rowCount; ++i)
{
InstrumentationAsset iaModelSide = m_model->getRowData(i);
if ((iaModelSide.name() == ia.name()) &&
(iaModelSide.mountingPointTypeId() == ia.mountingPointTypeId()))
{
ia.id(iaModelSide.id());
QHash<int, bool> alteredCells;
QHash<int, QString> alteredValues;
// NAME
if (ia.name() != iaModelSide.name())
{
alteredCells.insert(AssetListDialogModel::NAME, true);
alteredValues.insert(AssetListDialogModel::NAME, m_model->data(m_model->index(i, AssetListDialogModel::NAME), Qt::DisplayRole).toString());
}
else
{
alteredCells.insert(AssetListDialogModel::NAME, false);
alteredValues.insert(AssetListDialogModel::NAME, QString::fromStdString(ia.name()));
}
// TYPE
if (ia.mountingPointTypeId() != iaModelSide.mountingPointTypeId())
{
alteredCells.insert(AssetListDialogModel::TYPE, true);
alteredValues.insert(AssetListDialogModel::TYPE, m_model->data(m_model->index(i, AssetListDialogModel::TYPE), Qt::DisplayRole).toString());
}
else
{
alteredCells.insert(AssetListDialogModel::TYPE, false);
alteredValues.insert(AssetListDialogModel::TYPE, QString::fromStdString(ia.name()));
}
// BARCODE
if (ia.barcode() != iaModelSide.barcode())
{
alteredCells.insert(AssetListDialogModel::BARCODE, true);
alteredValues.insert(AssetListDialogModel::BARCODE, m_model->data(m_model->index(i, AssetListDialogModel::BARCODE), Qt::DisplayRole).toString());
}
else
{
alteredCells.insert(AssetListDialogModel::BARCODE, false);
alteredValues.insert(AssetListDialogModel::BARCODE, QString::fromStdString(ia.name()));
}
// HOSTNAME
if (ia.hostname() != iaModelSide.hostname())
{
alteredCells.insert(AssetListDialogModel::HOSTNAME, true);
alteredValues.insert(AssetListDialogModel::HOSTNAME, m_model->data(m_model->index(i, AssetListDialogModel::HOSTNAME), Qt::DisplayRole).toString());
}
else
{
alteredCells.insert(AssetListDialogModel::HOSTNAME, false);
alteredValues.insert(AssetListDialogModel::HOSTNAME, QString::fromStdString(ia.name()));
}
// PROPERTIES
if (ia.properties() != iaModelSide.properties())
{
alteredCells.insert(AssetListDialogModel::PROPERTIES, true);
alteredValues.insert(AssetListDialogModel::PROPERTIES, m_model->data(m_model->index(i, AssetListDialogModel::PROPERTIES), Qt::DisplayRole).toString());
}
else
{
alteredCells.insert(AssetListDialogModel::PROPERTIES, false);
alteredValues.insert(AssetListDialogModel::PROPERTIES, QString::fromStdString(ia.name()));
}
m_model->setAlteredCells(i, alteredCells);
// for(const int col : m_model->previousValues(i).keys())
// alteredValues.insert(col, m_model->data(m_model->index(i, col), Qt::DisplayRole).toString());
m_model->setPreviousValues(i, alteredValues);
ia.assetStateId(iaModelSide.assetStateId());
ia.lastUpdated(iaModelSide == ia ? iaModelSide.lastUpdated() : QDateTime::currentMSecsSinceEpoch());
m_model->setRowData(i, ia);
return true;
}
}
return false;
}
/**
* @brief AssetListDialog::onSelectionChanged
* is called on selection-change of the listview.
* @param selected a list of all selected items; unused.
* @param deselected a list of all deselected items; unused.
*/
void AssetListDialog::onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
Q_UNUSED(selected);
Q_UNUSED(deselected);
bool enabled = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::SystemConfiguration);
if (m_ui->assetListView->selectionModel()->selectedRows().size() < 1)
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(false);
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setEnabled(false);
}
else
{
if(m_ui->assetListView->selectionModel()->selectedRows().size() == 1)
{
InstrumentationAsset asset = m_model->assetByIndex(m_ui->assetListView->currentIndex());
StructureElement se;
if(m_dtc->getStructureElementInMntPointAssetByAssetId(asset.id(), se) && enabled)
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setEnabled(true);
}
else
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setEnabled(false);
}
}
else
{
if (enabled)
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setEnabled(true);
}
if (enabled)
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(true);
}
}
bool AssetListDialog::init(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ComponentMonitor::Interface::Dtc> cmoDtc,
const std::shared_ptr<ComponentMonitor::Interface::Ftc> cmoFtc
)
{
m_dtc = dtc;
m_ftc = ftc;
m_cmoDtc = cmoDtc;
m_cmoFtc = cmoFtc;
if (!m_ftc->enableStructureElementModify())
{
ERROR_LOG(m_logger) << "Could not enable FT StructureElementModify of ISM";
return false;
}
if (!m_ftc->enableMountingPointAssetModify())
{
ERROR_LOG(m_logger) << "Could not enable FT MountingPointAssetModify of ISM";
return false;
}
if (!m_ftc->enableMountingPointAssetRemove())
{
ERROR_LOG(m_logger) << "Could not enable FT MountingPointAssetRemove of ISM";
return false;
}
if (!m_ftc->enableInstrumentationAssetModify())
{
ERROR_LOG(m_logger) << "Could not enable FT InstrumentationAssetModify of ISM";
return false;
}
if (!m_ftc->enableInstrumentationAssetUnmount())
{
ERROR_LOG(m_logger) << "Could not enable FT InstrumentationAssetUnmount of ISM";
return false;
}
if (!m_cmoFtc->enableTriggerUpdate())
{
ERROR_LOG(m_logger) << "Could not enable FT TriggerUpdate of CMO";
return false;
}
if(m_ftc->enableInstrumentationAssetSetState() == false)
{
ERROR_LOG(m_logger)<<"Couldn't enable InstrumentationAssetSetState";
return false;
}
delete m_model;
m_model = new AssetListDialogModel(this);
connect(m_model, &AssetListDialogModel::dataAvailable, this, &AssetListDialog::enaDisaBtnBoxBtns);
if (!m_model->initModel(m_dtc, m_cmoDtc))
{
ERROR_LOG(m_logger) << "Could not init model";
delete m_model;
m_model = nullptr;
return false;
}
m_ui->assetListView->setModel(m_model);
m_ui->assetListView->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
// connect(m_ui->assetListView, &LtsDataView::LtsDataView::signalDoubleClicked,
// this, &AssetListDialog::onItemDoubleClicked);
connect(m_ui->assetListView, &LtsDataView::LtsDataView::selectionChanged,
this, &AssetListDialog::onSelectionChanged);
connect(m_requestHelper, &LtsUtils::RequestHelper::signalQuitLoop, m_model, [this]()
{
m_model->initModel(m_dtc, m_cmoDtc);
});
// delay trigger update buttonbox to void multiple calls
m_updateBtnBoxBtns = new QTimer(this);
m_updateBtnBoxBtns->setSingleShot(true);
m_updateBtnBoxBtns->setInterval(1000);
connect(m_updateBtnBoxBtns, &QTimer::timeout, this, &AssetListDialog::onInstrumentationAssetChanged);
connect(m_dtc.get(), &Interface::Dtc::instrumentationAssetChanged,
this, [&]{ m_updateBtnBoxBtns->start(); }, Qt::UniqueConnection);
//
// ContextMen
m_actionMenu = new QMenu(this);
m_updateAction = new QAction(tr("Trigger Reachability Update"), this);
m_actionMenu->addAction(m_updateAction);
connect(m_updateAction, &QAction::triggered, this, &AssetListDialog::onReachabilityUpdateAction);
m_ui->assetListView->setContextMenuPolicyPerView(LtsDataView::LtsDataView::Page::TABLE, Qt::CustomContextMenu);
connect(m_ui->assetListView, &LtsDataView::LtsDataView::signalContextMenuRequested,
this, &AssetListDialog::onCustomContextMenuRequested);
if (!m_hostsForUpdateNotifiy)
{
m_hostsForUpdateNotifiy = new QTimer(this);
m_hostsForUpdateNotifiy->setSingleShot(true);
m_hostsForUpdateNotifiy->setInterval(1000);
connect(m_hostsForUpdateNotifiy, &QTimer::timeout,
this, &AssetListDialog::onHostsForUpdateNotifyTimeout);
}
// ButtonBox
if (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::SystemConfiguration))
{
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load, this, &AssetListDialog::onUnmountButtonClicked);
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Unmount"));
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setEnabled(false);
m_buttonBox->setIcon(LtsWidgets::DialogButton::Load, QIcon(QLatin1String("icon:fixed_video_announcement.svg")));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &AssetListDialog::onSetStateButtonClicked);
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setText(tr("Set State"));
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(false);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Import, this, &AssetListDialog::onImportClicked);
}
m_buttonBox->connectButton(LtsWidgets::DialogButton::Export, this, &AssetListDialog::onExportClicked);
#ifndef LTS_DEBUG
m_ui->assetListView->hideColumn(AssetListDialogModel::Columns::ID);
#endif
return true;
}
void AssetListDialog::onSetStateButtonClicked()
{
const QModelIndexList indexList = m_ui->assetListView->selectedRows();
if (indexList.isEmpty())
return;
if(m_hasImportedAsset)
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Save imported assets first before changing state."),
tr("Set Asset State"), LtsWidgets::Behaviour::Modal, LtsWidgets::Button::Yes);
return;
}
// const QString identifier = QStringLiteral("Assets: Set State");
std::vector<InstrumentationAsset> assets;
assets.reserve(indexList.size());
for(QModelIndex index: qAsConst(indexList))
{
InstrumentationAsset asset = m_model->assetByIndex(index);
assets.push_back(asset);
}
QScopedPointer<EditAssetDialog> editAssetDialog (new EditAssetDialog(this, m_ftc, assets));
editAssetDialog->exec();
}
void AssetListDialog::onPrint()
{
LtsPrinting::printView(m_session, this, m_ui->assetListView->treeView());
}
void AssetListDialog::enaDisaBtnBoxBtns(const bool b)
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Export)->setEnabled(b);
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(b);
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(b);
}
void AssetListDialog::onInstrumentationAssetChanged()
{
// refresh selection buttons
onSelectionChanged(QItemSelection(), QItemSelection());
}
bool AssetListDialog::rowContainsAlteredData(const QHash<int, bool> &data)
{
for (const bool b : data)
{
if (b)
return true;
}
return false;
}
/**
* @brief AssetListDialog::onImportClicked
* is called by clicking on Import-button and inserts all InstrumentationAssets of a selected file.
* @see onExportClicked()
*/
void AssetListDialog::onImportClicked()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Import"), QString(),
tr("CSV-Files (*.csv)"));
if (fileName.isEmpty())
return;
QFile file(fileName);
if (!file.open(QFile::ReadOnly))
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot open file '%1': %2").arg(file.fileName(), file.errorString()));
return;
}
QTextStream in(&file);
in.setLocale(QLocale::c());
// first get the header data
QString header = in.readLine();
Q_UNUSED(header);
bool bOk;
while (!in.atEnd())
{
const QString line = in.readLine();
QVector<QStringRef> segments = line.splitRef(QLatin1Char(';'));
if (segments.size() < 10)
{
WARNING_LOG(m_logger) << "Skipping line '" << line << "' - to few data";
continue;
}
const InstrumentationAsset ia = importData(segments, &bOk);
if (!bOk)
continue;
if (updateInstrumentationAsset(ia))
continue;
m_model->insertRow(ia, true);
m_hasImportedAsset = true;
QHash<int, bool> alteredCells;
for (int i = 0; i < segments.size(); ++i)
alteredCells.insert(m_model->rowCount() - 1, true);
m_model->setAlteredCells(m_model->rowCount() - 1, alteredCells);
QHash<int, QString> previousValues;
for (int i = 0; i <= AssetListDialogModel::Columns::LAST_UPDATED; ++i)
{
QModelIndex idx = m_model->index(m_model->rowCount() - 1, i);
previousValues[m_model->rowCount() - 1] = m_model->data(idx, Qt::DisplayRole).toString();
}
m_model->setPreviousValues(m_model->rowCount() - 1, previousValues);
}
file.close();
m_buttonBox->getButton(LtsWidgets::DialogButton::Export)->setEnabled(false);
m_buttonBox->getButton(LtsWidgets::DialogButton::Import)->setEnabled(false);
slotChangesMade();
}
/**
* @brief AssetListDialog::onExportClicked
* is called by clicking on the Export-button and opens a new window to set several filters
* that decide which items are going to get exported.
* @see onFilterSelected()
* @see onImportClicked()
*/
void AssetListDialog::onExportClicked()
{
AssetFilterDialog *filterDialog = new AssetFilterDialog(m_model, this);
if (!filterDialog->init(m_ui->assetListView->selectionModel()->selectedRows().size() > 0))
{
ERROR_LOG(m_logger) << "Unexpected error";
return;
}
filterDialog->fillAssetComboBoxes();
connect(filterDialog, &AssetFilterDialog::exportFilterSelected, this, &AssetListDialog::onFilterSelected);
filterDialog->show();
}
void AssetListDialog::onUnmountButtonClicked()
{
if (m_ui->assetListView->selectionModel()->selectedRows().size() < 1)
return;
LtsWidgets::Button button = LtsWidgets::LtsMessageDialog::showMessage(
this, tr("Do you really want to unmount selected asset(s)?"), tr("Unmount Assets"), LtsWidgets::Behaviour::Modal,
{ LtsWidgets::Button::Yes, LtsWidgets::Button::No });
if (button == LtsWidgets::Button::Yes)
{
// get asset id of all selected assets;
const QModelIndexList indexList = m_ui->assetListView->selectedRows();
for(QModelIndex index: indexList)
{
InstrumentationAsset asset = m_model->assetByIndex(index);
if(asset.id() > 0 )
{
StructureElement se;
if(m_dtc->getStructureElementInMntPointAssetByAssetId(asset.id(), se) == false)
{
WARNING_LOG(m_logger)<<" asset not mounted. name: "<<asset.name()<< " id: "<<asset.id();
continue;
}
InstrumentationAssetUnmountRequest req(asset.id());
m_requestHelper->addRequest([req, this]()
{
return m_ftc->instrumentationAssetUnmountRequest(req, this);
});
}
}
if(m_requestHelper->hasRequests() &&
m_requestHelper->startRequests() == false)
{
ERROR_LOG(m_logger)<<" Couldn't unmount selected assets";
}
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load,false);
}
}
/**
* @brief AssetListDialog::onFilterSelected
* is called by clicking on the Ok-button in the filter window.
* @param exp enum class, that informs about the selected filtering option.
* @param type gives the selected type in case of filtering by specific type, otherwise it is empty and unused.
* @see onExportClicked()
*/
void AssetListDialog::onFilterSelected(const AssetFilterDialog::Export &exp, const QString &type)
{
QString fileName = QFileDialog::getSaveFileName(this, tr("Export"),
QString(),
tr("CSV-Files (*.csv)"));
if (fileName.isEmpty())
return;
QFile file(fileName);
if (!file.open(QFile::WriteOnly))
{
LtsWidgets::LtsMessageDialog::showMessage(this,
tr("Cannot save file '%1': %2").arg(file.fileName(),
file.errorString()));
return;
}
QTextStream out(&file);
out.setLocale(QLocale::c());
const QStringList headerNames = { QStringLiteral("Data Matrix Code"),
QStringLiteral("TKZ"),
QStringLiteral("SNr"),
QStringLiteral("MAC"),
QStringLiteral("Status"),
QStringLiteral("Bauzustand"),
QStringLiteral("UCATT Code"),
QStringLiteral("Lautsprecher"),
QStringLiteral("Mikrofon"),
QStringLiteral("Vapix Protokoll"),
QStringLiteral("Bentuzername"),
QStringLiteral("Passwort"),
QStringLiteral("Properties"),
QStringLiteral("Last updated") };
out << headerNames.join(QLatin1Char(';')) << "\n";
QVector<QString> vecStr;
if (exp == AssetFilterDialog::Export::eSpecificType)
vecStr = getExportString(exp, type);
else
vecStr = getExportString(exp);
for (int i = 0; i < vecStr.size(); ++i)
{
if (!vecStr.at(i).isEmpty())
out << vecStr.at(i) << "\n";
}
file.close();
}
void AssetListDialog::onCustomContextMenuRequested(const QPoint &globalPos, const QModelIndex &indexSrc)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START, indexSrc" << indexSrc.row();
if (!indexSrc.isValid())
return;
if (!m_model || !m_updateAction)
return;
m_updateAction->setEnabled(m_model->triggerUpdateRequestUseful(indexSrc));
m_actionMenu->exec(globalPos);
}
void AssetListDialog::onReachabilityUpdateAction()
{
const QModelIndexList &mil = m_ui->assetListView->selectedRows();
QIcon icon;
QString str;
for (const QModelIndex &il : qAsConst(mil))
{
const InstrumentationAsset ia = m_model->getRowData(il.row());
bool bhasHostnameForTriggerUpdate = m_model->getReachable(ia, icon, str);
if (bhasHostnameForTriggerUpdate)
{
m_hostsForUpdate.insert(QString::fromStdString(ia.hostname()));
DEBUG_LOG(m_logger) << LOGFUNCTION << " trigger update for " << ia;
}
} // for
m_hostsForUpdateNotifiy->start(); // restart
}
void AssetListDialog::onHostsForUpdateNotifyTimeout()
{
INFO_LOG(m_logger) << LOGFUNCTION << " START, hostsForUpdate.size() = " << m_hostsForUpdate.size();
if (!m_cmoFtc)
return;
if (m_hostsForUpdate.isEmpty())
return;
for (auto item : qAsConst(m_hostsForUpdate))
DEBUG_LOG(m_logger) << LOGFUNCTION << " host = " << item;
// start request now and trigger update:
std::vector<std::string> hostnameStd;
hostnameStd.reserve(m_hostsForUpdate.size());
for (const QString &item : qAsConst(m_hostsForUpdate))
if( std::find(hostnameStd.begin(), hostnameStd.end(), item.toStdString()) == hostnameStd.end())
hostnameStd.push_back(item.toStdString());
ComponentMonitor::TriggerUpdate request;
request.hostnames(hostnameStd);
DEBUG_LOG(m_logger) << LOGFUNCTION << " TriggerUpdate - request = " << request;
m_requestHelper->addRequest([request, this]()
{
return m_cmoFtc->triggerUpdateRequest(request, this);
});
m_requestHelper->startRequests();
// cleanup in any case:
m_hostsForUpdate.clear();
}
} // namespace InfrastructureManagement
@@ -0,0 +1,117 @@
/**
* @RDE_HEADER@
* The AssetListDialog shows how many assets are needed for a specific schedule, needed elsewhere,
* totally possessed, free, and missing
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <LtsWidgets/lts_frameless_dialog.h>
#include <AssetList/ism_filter_asset_dialog.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/ism_ftc.h>
#include <ComponentMonitor/cmo_data_plugin_interface.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include "ism_edit_asset_dialog.h"
#include <QSet>
namespace Ui
{
class AssetListDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
class AssetListDialogModel;
class AssetListDialog
: public LtsWidgets::LtsDialog
, protected Interface::Ftc::InstrumentationAssetModifyReplyHandler
, protected Interface::Ftc::InstrumentationAssetUnmountReplyHandler
, protected Interface::Ftc::StructureElementModifyReplyHandler
, protected Interface::Ftc::MountingPointAssetModifyReplyHandler
, protected Interface::Ftc::MountingPointAssetRemoveReplyHandler
, protected ComponentMonitor::Interface::Ftc::TriggerUpdateReplyHandler
{
Q_OBJECT
public:
explicit AssetListDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
~AssetListDialog();
bool init(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ComponentMonitor::Interface::Dtc> cmoDtc,
const std::shared_ptr<ComponentMonitor::Interface::Ftc> cmoFtc);
void onInstrumentationAssetModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onInstrumentationAssetUnmountReply(const Core::FunctionReplyObject &replyObject) override final {m_requestHelper->requestReply(replyObject);}
void onStructureElementModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onMountingPointAssetModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onMountingPointAssetRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
// CMO:
void onTriggerUpdateReply(const Core::FunctionReplyObject &reply) override final { m_requestHelper->requestReply(reply); }
private Q_SLOTS:
void onSetStateButtonClicked();
void onPrint();
void onImportClicked();
void onExportClicked();
void onUnmountButtonClicked();
void onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
void onFilterSelected(const AssetFilterDialog::Export &exp, const QString &type = QString());
void onCustomContextMenuRequested(const QPoint &globalPos, const QModelIndex &indexSrc);
void onReachabilityUpdateAction();
void onHostsForUpdateNotifyTimeout();
void onInstrumentationAssetChanged();
private:
void retranslate() override;
bool apply() override final;
void tableColumnOrganiserSetting() override;
QVector<QString> getExportString(const AssetFilterDialog::Export &exp, const QString &type = QString()) const;
static QString exportData(const InstrumentationAsset &ia, const QString &separator = QLatin1String(";"));
InstrumentationAsset importData(const QVector<QStringRef> &segments, bool *bOk) const;
bool updateInstrumentationAsset(const InstrumentationAsset &asset) const;
void enaDisaBtnBoxBtns(const bool b);
static bool rowContainsAlteredData(const QHash<int, bool> &data);
EditAssetDialog *m_editAssetDialog{nullptr};
LtsSession::LtsSession *m_session;
AssetListDialogModel *m_model;
QString m_menuGroup;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
std::shared_ptr<ComponentMonitor::Interface::Dtc> m_cmoDtc; // CMO ComponentMonitor
std::shared_ptr<ComponentMonitor::Interface::Ftc> m_cmoFtc; // CMO ComponentMonitor
LtsUtils::RequestHelper *m_requestHelper;
Ui::AssetListDialog *m_ui;
bool m_hasImportedAsset{false};
// CustomContextMenu
QMenu *m_actionMenu{nullptr};
QAction *m_updateAction{nullptr};
QSet<QString> m_hostsForUpdate;
QTimer *m_hostsForUpdateNotifiy{nullptr};
QTimer *m_updateBtnBoxBtns{nullptr};
LOGGER_T m_logger;
}; // class AssetListDialogModel
} // namespace InfrastructureManagement
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AssetListDialog</class>
<widget class="QWidget" name="AssetListDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>630</width>
<height>328</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Asset Stocks</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="LtsDataView::LtsDataView" name="assetListView"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,499 @@
/**
* @RDE_HEADER@
* The AssetListDialogModel provices data for AssetListDialog
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#include "ism_asset_list_dialog_model.h"
#include <InfrastructureManagement/ism_translation.h>
#include <InfrastructureManagement/Shared/ism_mounting_point.h>
#include <ComponentMonitor/cmo_data_plugin_interface.h>
#include <LtsWidgets/lts_column_filter_proxy_model.h>
#include <QDateTime>
#include <QBrush>
#include <QSet>
#include <QTimer>
#include <QDebug>
namespace InfrastructureManagement
{
AssetListDialogModel::AssetListDialogModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<InstrumentationAsset>(
{
tr("Id"),
tr("Name"),
tr("Type"),
tr("State"),
tr("Reachability"),
tr("Barcode"),
tr("Hostname"),
tr("Mounting point"),
tr("Properties"),
tr("Last updated")
},
parent)
, m_dtc(nullptr)
, m_reachabilityGreen(QLatin1String("icon:green_light.svg"))
, m_reachabilityYellow(QLatin1String("icon:yellow_light.svg"))
, m_reachabilityOrange(QLatin1String("icon:orange_light.svg"))
, m_reachabilityRed(QLatin1String("icon:red_light.svg"))
, m_alteredCells()
, m_alteredValues()
, m_updateFilterTimer(new QTimer(this))
, m_logger(getLogger("AssetListDialogModel"))
{
m_intactStr = tr("Intact");
updateFilterStates();
updateFilterTypes();
// // updateFilterReachability();
m_updateFilterTimer->setInterval(100);
m_updateFilterTimer->setSingleShot(true);
connect(m_updateFilterTimer, &QTimer::timeout,
this, &AssetListDialogModel::onUpdateFilter, Qt::UniqueConnection);
}
QVariant AssetListDialogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
{
switch (section)
{
case TYPE:
return m_cbxFilterType;
case STATE:
return m_cbxFilterState;
case REACHABILITY:
return m_cbxFilterReachability;
default:
break;
}
}
return LtsWidgets::LtsAbstractTableModel<InstrumentationAsset>::headerData(section, orientation, role);
}
QVariant AssetListDialogModel::data(const QModelIndex &index, int role) const
{
if ((role != Qt::DisplayRole &&
role != Qt::BackgroundRole &&
role != Qt::ToolTipRole &&
role != Qt::DecorationRole &&
role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
|| !indexIsValid(index))
return QVariant();
const InstrumentationAsset &currentAsset = m_vecData.at(index.row());
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case ID:
return currentAsset.id();
case NAME:
return QString::fromStdString(currentAsset.name());
case TYPE:
return toString(currentAsset.mountingPointTypeId());
case BARCODE:
return QString::fromStdString(currentAsset.barcode());
case HOSTNAME:
return QString::fromStdString(currentAsset.hostname());
case MOUNTINGPOINT:
{
StructureElement se;
if (m_dtc->getStructureElementInMntPointAssetByAssetId(currentAsset.id(), se) && se.id() > 0 )
{
return QString::fromStdString(se.displayName());
}
else
{
return QStringLiteral("-");
}
}
case PROPERTIES:
return QString::fromStdString(currentAsset.properties());
case STATE:
{
const InstrumentationAssetState_def::type &currAssetState = currentAsset.assetStateId().underlying();
if(currAssetState == InstrumentationAssetState_def::Unmounted || currAssetState == InstrumentationAssetState_def::Mounted)
{
return m_intactStr;
}
else
{
return toString(currentAsset.assetStateId());
}
//return toString(currentAsset.assetStateId());
}
case REACHABILITY:
{
QIcon icon;
QString str;
getReachable(currentAsset, icon, str);
return str;
}
case LAST_UPDATED:
return QDateTime::fromMSecsSinceEpoch(currentAsset.lastUpdated());
}
}
if (role == Qt::ToolTipRole)
{
if (index.column() == REACHABILITY)
{
if (triggerUpdateRequestUseful(currentAsset))
{
return QDateTime::fromSecsSinceEpoch(m_reachabilityLastCheck[currentAsset.id()]);
}
}
const auto cont = m_alteredValues.value(index.row());
if (!cont.value(index.column()).isEmpty())
return tr("Previous: %1").arg(m_alteredValues.at(index.row()).value(index.column()));
}
if (role == Qt::BackgroundRole)
{
const auto cont = m_alteredCells.value(index.row());
if (cont.value(index.column()))
return QBrush(QColor(Qt::red));
}
if (role == Qt::DecorationRole)
{
if (index.column() == REACHABILITY)
{
QIcon icon;
QString str;
getReachable(currentAsset, icon, str);
return icon;
}
}
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
{
switch (index.column())
{
case TYPE:
return currentAsset.mountingPointTypeId().underlying();
case STATE:
if(currentAsset.assetStateId().underlying() == InstrumentationAssetState::Mounted ||
currentAsset.assetStateId().underlying() == InstrumentationAssetState::Unmounted)
{
return m_intactStr;
}
else
return currentAsset.assetStateId().underlying();
case REACHABILITY:
{
QIcon icon;
QString str;
const InstrumentationAsset &innerCurrentAsset = m_vecData.at(index.row());
getReachable(innerCurrentAsset, icon, str);
return str;
}
default:
break;
}
}
return QVariant();
}
inline bool isMptRelevant(MountingPointType_def::type type)
{
return ((type == MountingPointType_def::IndoorCamera) ||
(type == MountingPointType_def::OutdoorCamera) ||
(type == MountingPointType_def::EffectGenerationControlUnit) ||
(type == MountingPointType_def::BuildingSensorModule)
);
}
bool AssetListDialogModel::getReachable(const InstrumentationAsset &currentAsset,
QIcon &iconOut, QString &stringOut) const
{
bool bEnableTriggerUpdate = false;
const bool bIsRelevant = isMptRelevant(currentAsset.mountingPointTypeId().underlying());
if (bIsRelevant)
{
const bool bIsMounted = currentAsset.assetStateId().underlying() == InfrastructureManagement::InstrumentationAssetState_def::Mounted;
if (bIsMounted)
{
if (m_cmoDtc)
{
const ComponentMonitor::ComponentStatus &cs = m_cmoDtc->componentStatus(currentAsset.id());
const ComponentMonitor::ComponentState state = cs.state();
switch (state.underlying()) {
case ComponentMonitor::ComponentState_def::Undefined:
iconOut = m_reachabilityOrange;
stringOut = tr("Undefined");
break;
case ComponentMonitor::ComponentState_def::Reachable:
iconOut = m_reachabilityGreen;
stringOut = tr("Reachable");
break;
case ComponentMonitor::ComponentState_def::Unreachable:
iconOut = m_reachabilityRed;
stringOut = tr("Unreachable");
break;
default:
// empty
break;
}
}
bEnableTriggerUpdate = true;
} else {
// GUEZE-1566: keine gelbe Ampel
// iconOut = m_reachabilityYellow;
// GUEZE-1566
stringOut = QStringLiteral("-");
}
} else { // if (bIsRelevant)
// Icon stays empty
iconOut = QIcon();
stringOut = QStringLiteral("-");
}
return bEnableTriggerUpdate;
}
bool AssetListDialogModel::triggerUpdateRequestUseful(const QModelIndex &index) const
{
if (!index.isValid())
return false;
const InstrumentationAsset &currentAsset = getRowData(index.row());
return triggerUpdateRequestUseful(currentAsset);
}
bool AssetListDialogModel::triggerUpdateRequestUseful(const InstrumentationAsset &currentAsset) const
{
// GUEZE-1490:
static QString dummyStr;
static QIcon dummyIcon;
bool bEnableTriggerUpdate = getReachable(currentAsset, dummyIcon, dummyStr);
return bEnableTriggerUpdate;
}
void AssetListDialogModel::onUpdateFilter()
{
// // updateFilterStates content does not change
updateFilterTypes();
updateFilterReachability();
}
void AssetListDialogModel::onComponentStatusChanged(const ComponentMonitor::ComponentStatus &data, DataModification modType)
{
// handle eRemoved also
Q_UNUSED(modType);
const int row = findRowForId(data.id()); // ComponentStatus.id == InstrumentationAsset.id
if (row < 0)
return;
// For Tooltip:
m_reachabilityLastCheck[data.id()] = data.last_check();
const auto idx(index(row, REACHABILITY));
emit dataChanged(idx, idx, {Qt::DisplayRole, Qt::BackgroundRole, Qt::DecorationRole, Qt::ToolTipRole});
m_updateFilterTimer->start();
}
bool AssetListDialogModel::initModel(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<ComponentMonitor::Interface::Dtc> &cmoDtc)
{
m_dtc = dtc;
m_cmoDtc = cmoDtc;
if (!m_dtc->enableInstrumentationAsset())
{
ERROR_LOG(m_logger) << "Could not enable Datatopic InstrumentationAsset of the Data Topic Client";
return false;
}
if (!m_cmoDtc->enableComponentStatus())
{
ERROR_LOG(m_logger) << "Could not enable Datatopic enableComponentStatus of cmo";
return false;
}
disconnect(m_dtc.get(), &Interface::Dtc::instrumentationAssetChanged, this, &AssetListDialogModel::onDataChanged);
clear();
m_vecData.clear();
connect(m_dtc.get(), &Interface::Dtc::instrumentationAssetChanged,
this, &AssetListDialogModel::onDataChanged);
auto cb = [this](const InfrastructureManagement::InstrumentationAsset & data)
{
// avoid display information of following mountinhPointTypes
if(data.mountingPointTypeId() == MountingPointType::MeteoDataUnit ||
data.mountingPointTypeId() == MountingPointType::BuildingControlUnit /*||
data.mountingPointTypeId() == MountingPointType::OutdoorIPS */)
{
return;
}
insertRow(data, true);
QHash<int, bool> alteredCells;
for (int i = 0; i <= LAST_UPDATED; ++i)
alteredCells.insert(i, false);
m_alteredCells.append(alteredCells);
QHash<int, QString> previousValues;
for (int i = 0; i <= LAST_UPDATED; ++i)
previousValues[i] = QString();
m_alteredValues.append(previousValues);
};
m_dtc->instrumentationAssets(cb);
emit dataAvailable(m_vecData.size() > 0);
if (m_cmoDtc)
{
connect(m_cmoDtc.get(), &ComponentMonitor::Interface::Dtc::componentStatusChanged,
this, &AssetListDialogModel::onComponentStatusChanged, Qt::UniqueConnection);
auto compStatCb = [this](const ComponentMonitor::ComponentStatus &data)
{
onComponentStatusChanged(data, DataModification::eAdded);
};
m_cmoDtc->componentStatuss(compStatCb);
}
connect(this, &AssetListDialogModel::rowsInserted, this, &AssetListDialogModel::onUpdateFilter);
connect(this, &AssetListDialogModel::rowsRemoved, this, &AssetListDialogModel::onUpdateFilter);
connect(this, &AssetListDialogModel::modelReset, this, &AssetListDialogModel::onUpdateFilter);
onUpdateFilter();
INFO_LOG(m_logger) << "initModel successfull";
return true;
}
InstrumentationAsset AssetListDialogModel::assetByIndex(const QModelIndex &index) const
{
if (!indexIsValid(index))
return InstrumentationAsset();
return getRowData(index.row());
}
void AssetListDialogModel::insertRow(const InstrumentationAsset &asset, bool b)
{
Q_UNUSED(b);
LtsWidgets::LtsAbstractTableModel<InstrumentationAsset>::insertRow(asset);
m_alteredCells.resize(rowCount());
}
void AssetListDialogModel::setAlteredCells(const int row, const QHash<int, bool> &data)
{
if (data.isEmpty() || row < 0 || row >= m_alteredCells.size())
return;
m_alteredCells[row] = data;
}
void AssetListDialogModel::removeBackgroundHighlighting()
{
for (int i = 0; i < this->rowCount(); ++i)
{
for (int j = 0; j < this->columnCount(); ++j)
m_alteredCells[i].insert(j, false);
}
}
void AssetListDialogModel::updateFilterStates()
{
LtsWidgets::ComboboxFilterContent cfc;
LtsWidgets::ComboboxFilterData cfd;
const auto states = {
InstrumentationAssetState::Mounted,
//InstrumentationAssetState::Unmounted, // mounted and unmounted will are displayed as "intact" in asset list dialog
InstrumentationAssetState::Defect,
};
for (const auto es : states)
{
if(es == InstrumentationAssetState::Mounted ||
es == InstrumentationAssetState::Unmounted)
{
cfd.data = m_intactStr;
cfd.text = m_intactStr;
}
else
{
cfd.data = es;
cfd.text = toString(es);
}
cfc.data.push_back(cfd);
}
cfc.sortItems = false;
m_cbxFilterState = cfc.toVariant();
}
void AssetListDialogModel::updateFilterTypes()
{
LtsWidgets::ComboboxFilterContent cfc;
LtsWidgets::ComboboxFilterData cfd;
QSet<InfrastructureManagement::MountingPointType> types;
for (const auto &r : qAsConst(m_vecData))
types.insert(r.mountingPointTypeId());
for (const auto es : qAsConst(types))
{
if(es == MountingPointType::MeteoDataUnit ||
es == MountingPointType::BuildingControlUnit /*||
es == MountingPointType::OutdoorIPS*/ )
{
continue;
}
cfd.data = es.underlying();
cfd.text = toString(es);
cfc.data.push_back(cfd);
}
cfc.sortItems = true;
m_cbxFilterType = cfc.toVariant();
}
void AssetListDialogModel::updateFilterReachability()
{
LtsWidgets::ComboboxFilterContent cfc;
LtsWidgets::ComboboxFilterData cfd;
QMap<QString, QIcon> values;
for (const auto &item : qAsConst(m_vecData))
{
QIcon icon;
QString str;
getReachable(item, icon, str);
values.insert(str, icon);
}
QMapIterator<QString, QIcon> it(values);
while (it.hasNext())
{
it.next();
cfd.data = it.key();
cfd.text = it.key();
cfd.icon = it.value();
cfc.data.push_back(cfd);
}
// for (const QPair<QIcon, QString> &val : qAsConst(values))
// {
// cfd.data = val.first;
// cfd.text = val.first;
// cfd.icon = val.second;
// cfc.data.push_back(cfd);
// }
cfc.sortItems = true;
m_cbxFilterReachability = cfc.toVariant();
}
} // namespace InfrastructureManagement
@@ -0,0 +1,91 @@
/**
* @RDE_HEADER@
* The AssetListDialogModel provices data for AssetListDialog
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#pragma once
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
#include <ComponentMonitor/cmo_data_plugin_interface.h>
#include <LtsWidgets/lts_abstract_table_model.h>
namespace InfrastructureManagement
{
class AssetListDialogModel final : public LtsWidgets::LtsAbstractTableModel<InstrumentationAsset>
{
Q_OBJECT
public:
explicit AssetListDialogModel(QObject *parent = nullptr);
enum Columns
{
ID = 0,
NAME,
TYPE,
STATE,
REACHABILITY,
BARCODE,
HOSTNAME,
MOUNTINGPOINT,
PROPERTIES,
LAST_UPDATED
};
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool initModel(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<ComponentMonitor::Interface::Dtc> &cmoDtc);
InstrumentationAsset assetByIndex(const QModelIndex &index) const;
QVector<QHash<int, bool>> alteredRows() const { return m_alteredCells; }
void setAlteredCells(const int row, const QHash<int, bool> &data);
QHash<int, QString> previousValues(const int row) const { return m_alteredValues[row]; }
void setPreviousValues(const int row, const QHash<int, QString> &value) { m_alteredValues.insert(row, value); }
void removeBackgroundHighlighting();
void insertRow(const InstrumentationAsset &asset, bool b);
void updateFilterStates();
void updateFilterTypes();
void updateFilterReachability();
bool getReachable(const InstrumentationAsset &currentAsset,
QIcon &iconOut, QString &stringOut) const;
bool triggerUpdateRequestUseful(const QModelIndex &index) const;
bool triggerUpdateRequestUseful(const InstrumentationAsset &currentAsset) const;
private Q_SLOTS:
void onUpdateFilter();
void onComponentStatusChanged(const ComponentMonitor::ComponentStatus &data, DataModification modType);
signals:
void dataAvailable(bool b);
private: // attributes
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<ComponentMonitor::Interface::Dtc> m_cmoDtc; // CMO ComponentMonitor
QIcon m_reachabilityGreen;
QIcon m_reachabilityYellow;
QIcon m_reachabilityOrange;
QIcon m_reachabilityRed;
QVector<QHash<int, bool>> m_alteredCells;
QVector<QHash<int, QString>> m_alteredValues;
QVariant m_cbxFilterType;
QVariant m_cbxFilterState;
QVariant m_cbxFilterReachability;
QHash<int, long long> m_reachabilityLastCheck; // SECONDS since Epoch
QTimer *m_updateFilterTimer{nullptr};
QString m_intactStr;
LOGGER_T m_logger;
}; // class AssetListDialogModel
} // namespace InfrastructureManagement
@@ -0,0 +1,127 @@
/**
* @RDE_HEADER@
* The EditAssetDialog offers an UI to edit the attributes of an instrumentaion asset
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-16
*/
#include "ism_edit_asset_dialog.h"
#include "ui_ism_edit_asset_dialog.h"
#include "ism_set_properties_dialog.h"
#include <InfrastructureManagement/ism_translation.h>
namespace InfrastructureManagement
{
/*!
* \brief EditAssetDialog::EditAssetDialog
* \param parent
* \param ftc
* \param assets
*/
EditAssetDialog::EditAssetDialog(QWidget *parent, const std::shared_ptr<Interface::Ftc> &ftc, const std::vector<InstrumentationAsset> &assets)
: LtsWidgets::LtsFramelessDialog(parent, LtsWidgets::Behaviour::Modal)
, m_ui(new Ui::EditAssetDialog)
, m_ftc(ftc)
, m_asset(assets)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("EditAssetDialog"))
{
m_ui->setupUi(this);
for(auto const &asset: assets)
{
m_ui->listWidget->addItem(QString::fromStdString(asset.name()));
}
connect(m_ui->toIntactBtn, &QPushButton::clicked, this, &EditAssetDialog::slotSetAssetToIntact);
connect(m_ui->toDefectBtn, &QPushButton::clicked, this, &EditAssetDialog::slotSetAssetToDefect);
connect(m_ui->cancelBtn, &QPushButton::clicked, this, &EditAssetDialog::slotClose);
}
/*!
* \brief EditAssetDialog::~EditAssetDialog
*/
EditAssetDialog::~EditAssetDialog()
{
delete m_requestHelper;
delete m_ui;
}
/*!
* \brief EditAssetDialog::slotSetAssetToIntact
* Setting the asset state to 'Intact' means setting the state to umounted
*/
void EditAssetDialog::slotSetAssetToIntact()
{
const InstrumentationAssetState newState = InstrumentationAssetState::type::Unmounted;
apply(newState);
slotClose();
}
/*!
* \brief EditAssetDialog::slotSetAssetToDefect
* Setting the asset state to 'defect' => asset will be unmounted and state will be set to defect
*/
void EditAssetDialog::slotSetAssetToDefect()
{
const InstrumentationAssetState newState = InstrumentationAssetState::type::Defect;
apply(newState);
slotClose();
}
/*!
* \brief EditAssetDialog::slotClose
* this Method close the modal dialog
*/
void EditAssetDialog::slotClose()
{
close();
}
/*!
* \brief EditAssetDialog::apply
* Apply the defined state to selected assets
* \param newState
* \return
*/
bool EditAssetDialog::apply(const InstrumentationAssetState newState)
{
const QString stateStr = (newState==InstrumentationAssetState::Mounted || newState==InstrumentationAssetState::Unmounted) ? tr("Intact") : tr("Defect");
LtsWidgets::Button button = LtsWidgets::LtsMessageDialog::showMessage(
this, tr(""), tr("Do you really want to apply \"%1\" state ?").arg(stateStr), LtsWidgets::Behaviour::Modal,
{ LtsWidgets::Button::Yes, LtsWidgets::Button::No }
);
if (button == LtsWidgets::Button::Yes)
{
InstrumentationAssetSetStateRequest req;
for(const auto &asset : qAsConst(m_asset))
{
if (asset.id() == -1)
{
continue;
}
if (asset.assetStateId() == newState)
{
continue;
}
// if state is mounted or unmounted and the aim state is intact nothing will be done
if (((asset.assetStateId() == InstrumentationAssetState::Mounted) || (asset.assetStateId() == InstrumentationAssetState::Unmounted)) &&
(newState == InstrumentationAssetState::Unmounted)) // state intact
{
continue;
}
req.id(asset.id());
req.instrumentationAssetStateId(newState);
m_requestHelper->addRequest([req, this]()
{
return m_ftc->instrumentationAssetSetStateRequest(req, this);
});
}
return m_requestHelper->startRequests();
}
return false;
}
} // namespace InfrastructureManagement
@@ -0,0 +1,63 @@
/**
* @RDE_HEADER@
* The EditAssetDialog offers an UI to edit the attributes of an instrumentaion asset
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-16
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <InfrastructureManagement/ism_ftc.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
#include <LtsUtilsGuiDds/request_helper.h>
namespace LtsWidgets
{
class LtsProgressDialogHelper;
}
namespace Ui
{
class EditAssetDialog;
}
namespace InfrastructureManagement
{
class EditAssetDialog
: public LtsWidgets::LtsFramelessDialog
, protected Interface::Ftc::InstrumentationAssetModifyReplyHandler
, protected Interface::Ftc::InstrumentationAssetSetStateReplyHandler
, protected Interface::Ftc::StructureElementModifyReplyHandler
, protected Interface::Ftc::InstrumentationAssetRemoveReplyHandler
{
Q_OBJECT
public:
explicit EditAssetDialog(QWidget *parent,const std::shared_ptr<Interface::Ftc> &ftc, const std::vector<InstrumentationAsset> &assets);
~EditAssetDialog();
void onStructureElementModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onInstrumentationAssetRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onInstrumentationAssetSetStateReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onInstrumentationAssetModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private slots:
void slotSetAssetToIntact();
void slotSetAssetToDefect();
void slotClose();
private:
bool apply(const InstrumentationAssetState newState) ;
Ui::EditAssetDialog *m_ui;
std::shared_ptr<Interface::Ftc> m_ftc;
std::vector<InstrumentationAsset> m_asset;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
}; // class EditAssetDialog
} // namespace InfrastructureManagement
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditAssetDialog</class>
<widget class="QWidget" name="EditAssetDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>414</width>
<height>328</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Set Asset State</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Set State for following Assets:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QListWidget" name="listWidget">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="toIntactBtn">
<property name="text">
<string>to Intact</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="toDefectBtn">
<property name="text">
<string>to Defect</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancelBtn">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,101 @@
/**
* @RDE_HEADER@
* The AssetFilterDialog shows options to export items, filtering items by certain criteria
* $Id: ism_asset_list_dialog.h 37724 2017-12-07 11:54:11Z bueltel $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/InfrastructureManagement/Gui/ResourceManagement/AssetList/ism_asset_list_dialog.h $
* $Author: bueltel $
* Created by Malte Schroeder, NLSE, 2018-06-16
*/
#include "ism_filter_asset_dialog.h"
#include "ui_ism_filter_asset_dialog.h"
#include <InfrastructureManagement/ism_translation.h>
#include <InfrastructureManagement/Shared/ism_mounting_point.h>
namespace InfrastructureManagement
{
/**
* @brief AssetFilterDialog::AssetFilterDialog
* The AssetFilterDialog shows options to export items, filtering items by certain criteria
* @param model
* @param parent
*/
AssetFilterDialog::AssetFilterDialog(AssetListDialogModel *model, QWidget *parent)
: LtsWidgets::LtsFramelessDialog(parent)
, m_model(model)
, m_ui(new Ui::AssetFilterDialog)
, m_logger(getLogger("AssetFilterDialog"))
{
setAttribute(Qt::WA_DeleteOnClose, true);
m_ui->setupUi(this);
}
AssetFilterDialog::~AssetFilterDialog()
{
delete m_ui;
}
bool AssetFilterDialog::init(bool selectedItems)
{
m_ui->buttonBox->setButtonVisible(LtsWidgets::DialogButton::Ok);
m_ui->buttonBox->setButtonVisible(LtsWidgets::DialogButton::Close);
m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(false);
m_ui->rbSelectedItems->setEnabled(selectedItems);
m_ui->cmbType->setEnabled(false);
connect(m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Ok), &QPushButton::clicked, this, &AssetFilterDialog::onPbOk);
connect(m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Close), &QPushButton::clicked, this, &AssetFilterDialog::close);
connect(m_ui->rbAll, &QRadioButton::toggled, this, &AssetFilterDialog::onRbToggled);
connect(m_ui->rbSelectedItems, &QRadioButton::toggled, this, &AssetFilterDialog::onRbToggled);
connect(m_ui->rbType, &QRadioButton::toggled, this, &AssetFilterDialog::onRbToggled);
connect(m_ui->cmbType, static_cast<void (LtsWidgets::LtsComboBox::*)(int)>(&LtsWidgets::LtsComboBox::currentIndexChanged), this, [ = ]()
{
onRbToggled (m_ui->cmbType->currentIndex() != 0 && m_ui->rbType->isChecked());
});
return true;
}
/**
* @brief AssetFilterDialog::fillAssetComboBoxes
* examines every row of the model and inserts the types onefold in the combobox
*/
void AssetFilterDialog::fillAssetComboBoxes()
{
QSet<InfrastructureManagement::MountingPointType> types;
types.reserve(20);
for (int i = 0; i < m_model->rowCount(); ++i)
types += m_model->getRowData(i).mountingPointTypeId();
m_ui->cmbType->addItem(QLatin1String("---"));
for (const auto &type : qAsConst(types))
m_ui->cmbType->addItem(InfrastructureManagement::toString(type), type.underlying());
m_ui->cmbType->setCurrentIndex(0);
}
void AssetFilterDialog::onPbOk()
{
if (m_ui->rbAll->isChecked())
emit exportFilterSelected(Export::eAll);
else if (m_ui->rbSelectedItems->isChecked())
emit exportFilterSelected(Export::eSelected);
else if (m_ui->rbType->isChecked())
emit exportFilterSelected(Export::eSpecificType, m_ui->cmbType->currentText());
}
void AssetFilterDialog::onRbToggled(bool b)
{
if (m_ui->rbAll->isChecked() ||
m_ui->rbSelectedItems->isChecked() ||
m_ui->rbType->isChecked())
{
m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(b);
if (m_ui->rbType->isChecked() && m_ui->cmbType->currentIndex() == 0)
m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(false);
m_ui->cmbType->setEnabled(m_ui->rbType->isChecked());
}
}
}
@@ -0,0 +1,52 @@
/**
* @RDE_HEADER@
* The AssetFilterDialog shows options to export items, filtering items by certain criteria
* $Id: ism_asset_list_dialog.h 37724 2017-12-07 11:54:11Z bueltel $
* $HeadURL: svn://slssvn/TDS/branches/product/devel/trunk/Lts/Plugins/InfrastructureManagement/Gui/ResourceManagement/AssetList/ism_asset_list_dialog.h $
* $Author: bueltel $
* Created by Malte Schroeder, NLSE, 2018-06-16
*/
#pragma once
#include "ism_asset_list_dialog_model.h"
#include <LtsWidgets/lts_frameless_dialog.h>
#include <LtsWidgets/lts_combo_box.h>
namespace Ui
{
class AssetFilterDialog;
}
namespace InfrastructureManagement
{
class AssetFilterDialog : public LtsWidgets::LtsFramelessDialog
{
Q_OBJECT
public:
explicit AssetFilterDialog(AssetListDialogModel *model, QWidget *parent = nullptr);
~AssetFilterDialog();
bool init(bool selectedItems);
void fillAssetComboBoxes();
enum class Export
{
eAll,
eSelected,
eSpecificType
};
signals:
void exportFilterSelected(const Export &ex, const QString &type = QString());
private slots:
void onPbOk();
void onRbToggled(bool b);
private:
AssetListDialogModel *m_model;
Ui::AssetFilterDialog *m_ui;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AssetFilterDialog</class>
<widget class="LtsWidgets::LtsFramelessDialog" name="AssetFilterDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>363</width>
<height>144</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="1">
<widget class="LtsWidgets::LtsDialogButtonBox" name="buttonBox"/>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="rbType">
<property name="text">
<string>Specific Type:</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="LtsWidgets::LtsComboBox" name="cmbType"/>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="rbAll">
<property name="text">
<string>All</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="rbSelectedItems">
<property name="text">
<string>Selected Ite&amp;ms</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsDialogButtonBox</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_dialog_button_box.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsFramelessDialog</class>
<extends>QDialog</extends>
<header>LtsWidgets/lts_frameless_dialog.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,163 @@
/**
* @RDE_HEADER@
* The SetPropertiesDialog offers an UI to edit the properties of an instrumentation asset
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-16
*/
#include "ism_set_properties_dialog.h"
#include "ui_ism_set_properties_dialog.h"
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QLabel>
#include <QtWidgets/QHBoxLayout>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
using namespace InfrastructureManagement;
SetPropertiesDialog::SetPropertiesDialog(QLineEdit *lineEdit, QWidget *parent)
: LtsWidgets::LtsFramelessDialog(parent)
, m_ui(new Ui::SetPropertiesDialog)
, m_lineEdit(lineEdit)
, m_logger(getLogger("SetPropertiesDialog"))
{
m_ui->setupUi(this);
init();
}
SetPropertiesDialog::~SetPropertiesDialog()
{
delete m_ui;
}
void SetPropertiesDialog::init()
{
m_ui->buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &SetPropertiesDialog::onAddClicked);
// nicht über connectButton - gibt sonst komische Message-Boxes
connect(m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Ok), &QPushButton::clicked,
this, &SetPropertiesDialog::onOkClicked);
connect(m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Close), &QPushButton::clicked,
this, &SetPropertiesDialog::reject);
m_ui->buttonBox->getButton(LtsWidgets::DialogButton::Close)->setText(tr("Cancel")); //
m_ui->scrollArea->widget()->setLayout(m_ui->vlScrollBar);
if (!m_lineEdit->text().isEmpty())
{
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(m_lineEdit->text().toUtf8(), &error);
if (error.error != QJsonParseError::NoError)
{
ERROR_LOG(m_logger) << error.errorString();
return;
}
if (!doc.isObject())
{
ERROR_LOG(m_logger) << "Properties String is no JSON-Object";
return;
}
QJsonObject obj = doc.object();
for (auto it = obj.constBegin(); it != obj.constEnd(); ++it)
addProperty(it.key(), it.value().toVariant());
}
}
void SetPropertiesDialog::onOkClicked()
{
QJsonObject obj;
for (auto it = m_properties.constBegin(); it != m_properties.constEnd(); ++it)
{
QString propVal(it.value()->text());
QJsonValue jsonVal;
switch (propValType(propVal))
{
case PropValType::INT:
jsonVal = propVal.toInt();
break;
case PropValType::DOUBLE:
jsonVal = propVal.toDouble();
break;
case PropValType::BOOL:
{
if (propVal.toLower() == QStringLiteral("true"))
jsonVal = true;
if (propVal.toLower() == QStringLiteral("false"))
jsonVal = false;
break;
}
case PropValType::STRING:
default:
jsonVal = propVal;
}
obj.insert(it.key()->text(), jsonVal);
}
m_lineEdit->setText(QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact)));
close();
}
void SetPropertiesDialog::onAddClicked()
{
addProperty(tr("name"), tr("value"));
}
void SetPropertiesDialog::addProperty(const QString &propName, const QVariant &propValue)
{
QHBoxLayout *layout = new QHBoxLayout;
QLineEdit *lePropName = new QLineEdit(propName, this);
QLineEdit *lePropVal = new QLineEdit(propValue.toString(), this);
QPushButton *pbRemove = new QPushButton(this);
QLabel *colon = new QLabel(QStringLiteral(":"), this);
pbRemove->setText(tr("remove"));
layout->addWidget(lePropName);
layout->addWidget(colon);
layout->addWidget(lePropVal);
layout->addWidget(pbRemove);
m_properties.insert(lePropName, lePropVal);
m_ui->vlPorts->addLayout(layout);
connect(pbRemove, &QPushButton::clicked,
this, [=]()
{
m_ui->vlPorts->removeItem(layout);
m_properties.remove(lePropName);
delete lePropName;
delete lePropVal;
delete colon;
pbRemove->deleteLater();
});
}
SetPropertiesDialog::PropValType SetPropertiesDialog::propValType(const QString &prop)
{
bool isOk;
(void)prop.toInt(&isOk);
if (isOk)
return PropValType::INT;
(void)prop.toDouble(&isOk);
if (isOk)
return PropValType::DOUBLE;
if (prop.toLower() == QStringLiteral("true") || prop.toLower() == QStringLiteral("false"))
return PropValType::BOOL;
return PropValType::STRING;
}
@@ -0,0 +1,58 @@
/**
* @RDE_HEADER@
* The SetPropertiesDialog offers an UI to edit the properties of an instrumentation asset
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-16
*/
#pragma once
#include <LtsWidgets/lts_frameless_dialog.h>
#include <InfrastructureManagement/logger.h>
#include <QtCore/QMap>
class QLineEdit;
namespace Ui
{
class SetPropertiesDialog;
}
namespace InfrastructureManagement
{
class SetPropertiesDialog
: public LtsWidgets::LtsFramelessDialog
{
Q_OBJECT
public:
explicit SetPropertiesDialog(QLineEdit *lineEdit, QWidget *parent = nullptr);
~SetPropertiesDialog();
private:
void init();
private Q_SLOTS:
void onOkClicked();
void onAddClicked();
private: // other
enum class PropValType
{
INT,
DOUBLE,
BOOL,
STRING
};
private: // methods
void addProperty(const QString &propName, const QVariant &propValue);
PropValType propValType(const QString &prop);
private: // attributes
Ui::SetPropertiesDialog *m_ui;
QMap<QLineEdit *, QLineEdit *> m_properties; // <propname, propval>
QLineEdit *m_lineEdit;
LOGGER_T m_logger;
}; // class SetPropertiesDialog
} // namespace InfrastructureManagement
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SetPropertiesDialog</class>
<widget class="QWidget" name="SetPropertiesDialog">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
<property name="windowTitle">
<string notr="true">Set Ports</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>313</width>
<height>153</height>
</rect>
</property>
<widget class="QWidget" name="verticalLayoutWidget_2">
<property name="geometry">
<rect>
<x>340</x>
<y>80</y>
<width>160</width>
<height>80</height>
</rect>
</property>
<layout class="QVBoxLayout" name="vlScrollBar">
<item>
<layout class="QVBoxLayout" name="vlPorts"/>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsDialogButtonBox</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_dialog_button_box.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,126 @@
#
# $Id$
# $HeadURL$
# $Author$
#
# Created by Mike Wille, SLSE, 2016-10-28
#
SET(src
ExerciseAssignment/ism_exercise_assignment_dialog.cpp
ExerciseAssignment/ism_exercise_assignment_dialog_model.cpp
ExerciseAssignment/ism_exercise_assignment_dialog_requesters.cpp
ExerciseAssignment/ism_exercise_assignment_dialog_proxy_model.cpp
Overview/ism_overview_dialog.cpp
Overview/ism_overview_dialog_model.cpp
Overview/ism_overview_mounting_point_list_dialog.cpp
Overview/ism_overview_mounting_point_list_model.cpp
Overview/ism_overview_conflicts_dialog.cpp
Overview/ism_overview_conflicts_model.cpp
AssetList/ism_asset_list_dialog_model.cpp
AssetList/ism_asset_list_dialog.cpp
AssetList/ism_edit_asset_dialog.cpp
AssetList/ism_filter_asset_dialog.cpp
AssetList/ism_set_properties_dialog.cpp
MountingPointInfo/ism_mounting_point_info_dialog.cpp
MountingPointMapSelection/ism_dds_selector.cpp
MountingPointMapSelection/ism_selector.cpp
MountingPointList/ism_mounting_point_list_dialog.cpp
MountingPointList/ism_mounting_point_list_dialog_model.cpp
MountingPointList/ism_mounting_point_list_dialog_checkbox_delegate.cpp
MountingPointList/ism_mounting_point_list_dialog_checkbox_proxy_model.cpp
MountingPointList/ism_mounting_point_list_dialog_list_sort_model.cpp
ApproachingPoints/ism_approaching_point_list_dialog_model.cpp
ApproachingPoints/ism_approaching_point_list_dialog.cpp
ApproachingPoints/ism_edit_approaching_point_dialog.cpp
# ScheduleDifferences ersetzt durch neuen VollständigkeitsCheck:
# Overview/ism_overview_mounting_point_list{model, dialog}
# ScheduleDifferences/ism_schedule_differences_list_dialog.cpp
# ScheduleDifferences/ism_schedule_differences_list_model.cpp
ism_resource_gui_plugin.cpp
ism_resource_gui_plugin.h
ism_building_mount_point_dialog.cpp
ism_building_mount_point_model.cpp
ism_plan_dialog.cpp
ism_plan_edit_dialog.cpp
ism_plan_dialog_model.cpp
#Timeline/ism_plan_tln_delegate.cpp
#Timeline/ism_plan_tln_delegate.h
#Timeline/ism_plan_tln_dialog.cpp
#Timeline/ism_plan_tln_dialog.h
#Timeline/ism_plan_tln_model.cpp
#Timeline/ism_plan_tln_model.h
PlanChooser/plan_chooser.cpp
PlanChooser/new_plan_dialog.cpp
CustomViews/ism_schedule.cpp
)
NGL_WRAP_UI(src
Overview/ism_overview_dialog.ui
Overview/ism_overview_mounting_point_list_dialog.ui
Overview/ism_overview_conflicts_dialog.ui
AssetList/ism_asset_list_dialog.ui
AssetList/ism_edit_asset_dialog.ui
AssetList/ism_filter_asset_dialog.ui
AssetList/ism_set_properties_dialog.ui
MountingPointInfo/ism_mounting_point_info_dialog.ui
MountingPointList/ism_mounting_point_list_dialog.ui
# ScheduleDifferences/ism_schedule_differences_list_dialog.ui
ism_building_mount_point_dialog.ui
ism_plan_dialog.ui
ism_plan_edit_dialog.ui
#Timeline/ism_plan_tln_dialog.ui
PlanChooser/plan_chooser.ui
PlanChooser/new_plan_dialog.ui
CustomViews/ism_schedule.ui
ApproachingPoints/ism_approaching_point_list_dialog.ui
ApproachingPoints/ism_edit_approaching_point_dialog.ui
ExerciseAssignment/ism_exercise_assignment_dialog.ui
)
NGL_ADD_LIBRARY(WS IsmResGuiPlugin MODULE ${src})
NGL_TARGET_LINK_LIBRARIES(IsmResGuiPlugin
LtsPrinting
NGLLogger
nglwidgets
ngltools
LtsSession
LtsSessionData
LtsNotification
AvmDataPluginInterface
IsmResGuiPluginInterface
IsmDataPluginInterface
IsmShared
Qt5::Widgets
LtsWidgets
LtsDataView
LtsUtilsCore # json
LtsUtilsGuiDds
LtsCoordTrans
ltsCoordWidget
SituationMapGuiPluginInterface
situationMap
LtsUtilsGuiConnectDialog
LtsUtilsSettings
#LtsTimeline
LtsSessionDataDds
ExmDataPluginInterface
CmoDataPluginInterface
)
NGL_INSTALL_TARGET(IsmResGuiPlugin)
@@ -0,0 +1,77 @@
/**
* @RDE_HEADER@
* CustomView for Exercises
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2016-04-08
*/
#include "ism_schedule.h"
#include "ui_ism_schedule.h"
#include "ism_plan_dialog_model.h"
#include <ngltools/ngltools_dtg.h>
#include <QDateTime>
namespace InfrastructureManagement
{
CustomViewSchedule::CustomViewSchedule(QWidget *parent)
: AbstractDisplayWidget(parent)
, m_ui(new Ui::CustomViewSchedule)
, m_logger(getLogger("CustomViewSchedule"))
{
m_ui->setupUi(this);
}
CustomViewSchedule::~CustomViewSchedule()
{
delete m_ui;
}
bool CustomViewSchedule::init(const QModelIndex &idx)
{
if (!idx.isValid())
return false;
const QString msName = rowData(idx, InfrastructureManagement::PlanDialogModel::NAME).toString();
m_ui->lblName->setText(msName);
int msId = rowData(idx, InfrastructureManagement::PlanDialogModel::ID).toInt();
if (msId == 0)
{
m_ui->lblName->setWordWrap(true);
m_ui->lbCreated->hide();
m_ui->lblCreated->hide();
m_ui->lbBegin->hide();
m_ui->lblBegin->hide();
m_ui->lbEnd->hide();
m_ui->lblEnd->hide();
m_ui->lblStatus->hide();
}
else
{
m_ui->lbCreated->hide();
m_ui->lblCreated->hide();
#ifndef LTS_DEBUG
// m_ui->lblCreated->setVisible(true); // Should not be visible in Release build, but it is
// m_ui->lbCreated->setVisible(true);
#endif
m_ui->lblCreated->setText(rowData(idx, InfrastructureManagement::PlanDialogModel::CREATED).toString());
m_ui->lblBegin->setText(rowData(idx, InfrastructureManagement::PlanDialogModel::START).toString());
m_ui->lblEnd->setText(rowData(idx, InfrastructureManagement::PlanDialogModel::END).toString());
m_ui->lblStatus->setText(rowData(idx, InfrastructureManagement::PlanDialogModel::STATUS).toString());
QPalette p = m_ui->lblStatus->palette();
QColor newCol = rowData(idx, PlanDialogModel::STATUS, Qt::TextColorRole).value<QColor>();
p.setColor(m_ui->lblStatus->backgroundRole(), newCol);
p.setColor(m_ui->lblStatus->foregroundRole(), newCol);
m_ui->lblStatus->setPalette(p);
}
return true;
}
} // namespace InfrastructureManagement
@@ -0,0 +1,33 @@
/**
* @RDE_HEADER@
* CustomView for Exercises
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2016-04-08
*/
#pragma once
#include <Viewer/LtsDataView/abstract_display_widget.h>
#include <InfrastructureManagement/logger.h>
namespace Ui
{
class CustomViewSchedule;
}
namespace InfrastructureManagement
{
class CustomViewSchedule final : public LtsDataView::AbstractDisplayWidget
{
Q_OBJECT
public:
explicit CustomViewSchedule(QWidget *parent = nullptr);
~CustomViewSchedule();
bool init(const QModelIndex &idx) override;
private:
Ui::CustomViewSchedule* m_ui;
LOGGER_T m_logger;
};
} // namespace
@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CustomViewSchedule</class>
<widget class="QWidget" name="CustomViewSchedule">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>258</width>
<height>133</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lblName">
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="toolTip">
<string notr="true"/>
</property>
<property name="text">
<string notr="true">&lt;Schedule Name&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="lbCreated">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Created:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblCreated">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string notr="true">&lt;Created Date&gt;</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lbBegin">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Begin:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="lblBegin">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="toolTip">
<string notr="true"/>
</property>
<property name="text">
<string notr="true">&lt;Begin Date&gt;</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lbEnd">
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>End:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="lblEnd">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="toolTip">
<string notr="true"/>
</property>
<property name="text">
<string notr="true">&lt;End Date&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="lblStatus">
<property name="text">
<string notr="true">&lt;Status&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,390 @@
/**
* @RDE_HEADER@
* The ExerciseAssignmentDialog shows how many assets are needed for a specific schedule, needed elsewhere,
* totally possessed, free, and missing
* $Id: ism_exercise_assignment_dialog.cpp 57783 2022-08-03 11:07:05Z ojog_i $
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/22_09_resmgmt2.0/Lts/Plugins/InfrastructureManagement/Gui/AudioVideoConfig/ExerciseAssignment/ism_exercise_assignment_dialog.cpp $
* $Author: ojog_i $
* Created by Hannes Baeuerle, SLSE, 2017-06-29
* Refreshed by Mike Wille, SLTE, 2022-09-26
*/
#include "ism_exercise_assignment_dialog.h"
#include "ui_ism_exercise_assignment_dialog.h"
#include "ism_exercise_assignment_dialog_requesters.h"
#include "ism_exercise_assignment_dialog_proxy_model.h"
#include <LtsUtilsCore/json_object.h>
#include <ExerciseManagement/exm_data_plugin_interface.h>
#include <InfrastructureManagement/ism_data_plugin_interface.h>
#include <LtsSession/lts_session.h>
#include <LtsPrinting/printing.h>
#include <LtsWidgets/lts_overlay_loading.h>
#include <LtsUtilsSettings/settings.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
using namespace LtsUtils;
using namespace LtsWidgets;
namespace InfrastructureManagement
{
ExerciseAssignmentDialog::ExerciseAssignmentDialog(LtsSession::LtsSession *session, QWidget *parent) noexcept(false)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_session(session)
, m_ui(new Ui::ExerciseAssignmentDialog)
, m_model(nullptr)
, m_modelAssignedFilter(new ExerciseAssignmentDialogModelFilterProxy(this))
, m_modelUnassignedFilter(new ExerciseAssignmentDialogModelFilterProxy(this))
, m_logger(getLogger("ExerciseAssignmentDialog"))
{
m_ui->setupUi(this);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &ExerciseAssignmentDialog::onPrint);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Exercise_Assignment"));
std::shared_ptr<ExerciseManagement::Interface::Dtc> exmDtc;
if (!m_session->getDtc<DataInterface>(m_dtc) ||
!m_session->getFtc<DataInterface>(m_ftc) ||
!m_session->getDtc<ExerciseManagement::DataInterface>(exmDtc))
throw std::exception();
if (!m_ftc->enableMainStructureElementModify())
{
ERROR_LOG(m_logger) << "Could not enable FT MainStructureElementModify of ISM";
throw std::exception();
}
if (!exmDtc->enableExercise())
{
ERROR_LOG(m_logger) << "Could not enable DT Exercise of EXM";
throw std::exception();
}
// Add all available exercises to comboBox (do not add deleted or terminated exercises)
exmDtc->exercises([this](const ExerciseManagement::Exercise &data)
{
if (data.isDeleted())
return;
switch(data.state().underlying())
{
case ExerciseManagement::ExerciseState_def::Created:
case ExerciseManagement::ExerciseState_def::Started:
case ExerciseManagement::ExerciseState_def::Paused:
case ExerciseManagement::ExerciseState_def::Stopped:
{
m_exercises.insert(data.id(), data);
break;
}
default:
return;
}
});
for (const auto &exercise : qAsConst(m_exercises))
m_ui->cbExercises->addItem(QString::fromStdString(exercise.name()), exercise.id());
if (m_ui->cbExercises->count() == 0)
{
setEnabled(false);
setUnchangeable();
m_buttonBox->getButton(LtsWidgets::DialogButton::Print)->setEnabled(false);
return;
}
else
m_ui->label->setVisible(false);
m_model = new ExerciseAssignmentDialogModel(m_exercises, this);
// set initial exercise filter to the assigned exercises so that only buildings for exercise x are visible
auto exerciseChangedFn = [this](int index = -1)
{
Q_UNUSED(index);
m_modelAssignedFilter->setExerciseId(m_ui->cbExercises->currentData().toInt());
//m_ui->assignedExercises->expandAll();
};
connect(m_ui->cbExercises, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, exerciseChangedFn);
exerciseChangedFn();
// NOT live, otherwise:
connect(m_dtc.get(), &Interface::Dtc::mainStructureElementChanged,
this, &ExerciseAssignmentDialog::onMainStructureElementChanged);
auto cb = [this](const InfrastructureManagement::MainStructureElement &mse)
{
onMainStructureElementChanged(mse, DataModification::eAdded);
};
m_dtc->mainStructureElements(cb);
m_modelUnassignedFilter->setSourceModel(m_model);
m_ui->availableExercises->setModel(m_modelUnassignedFilter);
m_ui->availableExercises->setSortingEnabled(true);
m_ui->availableExercises->sortByColumn(0, Qt::SortOrder::AscendingOrder);
m_ui->availableExercises->setDragEnabled(true);
m_ui->availableExercises->viewport()->setAcceptDrops(true);
// m_ui->availableExercises->setDropIndicatorShown(true);
m_ui->availableExercises->setDragDropMode(QAbstractItemView::DragDrop);
m_ui->availableExercises->setDefaultDropAction(Qt::DropAction::MoveAction);
m_modelAssignedFilter->setSourceModel(m_model);
m_ui->assignedExercises->setModel(m_modelAssignedFilter);
m_ui->assignedExercises->setSortingEnabled(true);
m_ui->assignedExercises->sortByColumn(0, Qt::SortOrder::AscendingOrder);
m_ui->assignedExercises->setDragEnabled(true);
m_ui->assignedExercises->viewport()->setAcceptDrops(true);
// m_ui->assignedExercises->setDropIndicatorShown(true);
m_ui->assignedExercises->setDragDropMode(QAbstractItemView::DragDrop);
m_ui->assignedExercises->setDefaultDropAction(Qt::DropAction::MoveAction);
connect(m_modelAssignedFilter, &ExerciseAssignmentDialogModelFilterProxy::doRefilter,
this, &ExerciseAssignmentDialog::onUnassignedNeedsUpdate);
connect(m_modelUnassignedFilter, &ExerciseAssignmentDialogModelFilterProxy::doRefilter,
this, &ExerciseAssignmentDialog::onAssignedNeedsUpdate);
}
ExerciseAssignmentDialog::~ExerciseAssignmentDialog()
{
delete m_ui;
}
void ExerciseAssignmentDialog::onUnassignedNeedsUpdate(const QSet<QModelIndex> &setToExpand)
{
m_modelUnassignedFilter->invalidate();
for(auto indexToExpand : setToExpand)
m_ui->assignedExercises->expand(m_modelAssignedFilter->mapFromSource(indexToExpand));
slotChangesMade();
}
void ExerciseAssignmentDialog::onAssignedNeedsUpdate(const QSet<QModelIndex> &setToExpand)
{
m_modelAssignedFilter->invalidate();
for(auto indexToExpand : setToExpand)
m_ui->availableExercises->expand(m_modelUnassignedFilter->mapFromSource(indexToExpand));
slotChangesMade();
}
void ExerciseAssignmentDialog::retranslate()
{
translate(m_ui, tr("Exercise Assignment"));
}
void ExerciseAssignmentDialog::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType)
{
auto seti = mse.structureElementTypeId();
if (seti != StructureElementType::Building &&
seti != StructureElementType::Announcement)
return;
// read exercise id and add to assigned exercises
QString displayName(m_dtc->getBuildingDisplayName(mse.id()));
if (displayName.isEmpty())
displayName = QString::fromStdString(mse.name());
int exerciseId;
try
{
exerciseId = JsonObject::fromJson(mse.properties()).value<JsonArray>(QStringLiteral("available_in_exercise")).at<int>(0); // get exercise id from properties json
}
catch(...)
{
exerciseId = 0;
}
if (!m_exercises.contains(exerciseId)) // if building is part of a deleted / terminated exercise, just add it to the unassigned buildings model
exerciseId = 0;
if (modType == DataModification::eModified)
m_model->updateMse(mse.id(), mse.groupId(), displayName, exerciseId);
else if (modType == DataModification::eAdded)
m_model->addMse(mse.id(), mse.groupId(), displayName, exerciseId);
else
m_model->removeMse(mse.id());
}
bool ExerciseAssignmentDialog::apply()
{
// XXX: HACK we don't know if user pressed ok or apply - apply() has to emidiately return, but the operation is async... so mimic ok/apply later, based on what was clicked
bool wasOkay = (sender() == static_cast<QObject *>(m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)));
LtsOverlayLoading *lol = new LtsOverlayLoading;
setOverlay(lol);
MSEModifyRequestCollector *collector = new MSEModifyRequestCollector(m_ftc, this);
{
QPushButton *pbCancel = new QPushButton;
pbCancel->setText(tr("Cancel"));
connect(pbCancel, &QPushButton::clicked,
this, [pbCancel, collector, lol]()
{
collector->cancel();
lol->setText(tr("Canceling ..."));
pbCancel->setEnabled(false);
});
qobject_cast<QVBoxLayout *>(lol->layout())->addWidget(pbCancel, 0, Qt::AlignmentFlag::AlignCenter);
}
const QVector<RequestInfos> &requestInfos = m_model->getRequestInfos();
for (const RequestInfos &ri : qAsConst(requestInfos))
{
MainStructureElementModifyRequest request;
MainStructureElement &mse = request;
mse = m_dtc->mainStructureElement(ri.mseId);
QJsonObject root;
try
{
root = JsonObject::fromJson(mse.properties()).object();
}
catch (...)
{
ERROR_LOG(m_logger) << "can't parse json for mseId " << ri.mseId << " and excId " << ri.exerciseId << " - using new json";
Q_ASSERT(false);
}
if (LtsUtils::ProjectSettings::getInstance()->value(QStringLiteral("ism"), QStringLiteral("enableSetRecordingDialog")).toBool())
setRecording(mse,ri.exerciseId != 0);
if (ri.exerciseId != 0)
root[QStringLiteral("available_in_exercise")] = QJsonArray({{ri.exerciseId}});
else
root.remove(QStringLiteral("available_in_exercise"));
mse.properties(QString::fromUtf8(QJsonDocument(root).toJson()).toStdString());
collector->addRequest(ri, request);
}
int initialCount = collector->count();
const QString leText(QStringLiteral("%1<br />%3 / %2").arg(tr("Assigning building(s) to exercise(s)")).arg(initialCount));
lol->setText(leText.arg(0));
connect(collector, &MSEModifyRequestCollector::requestComplete,
this, [collector, lol, leText, initialCount]()
{
lol->setText(leText.arg(initialCount - collector->count()));
});
connect(collector, &MSEModifyRequestCollector::finished,
this, [this, collector, wasOkay, lol](bool canceled)
{
unsetOverlay();
lol->deleteLater();
collector->deleteLater();
int failedCount = collector->failedCount();
if (failedCount > 0)
{
new LtsWidgets::LtsMessageDialogNew(this, tr("Error: %1 building(s) could not be assigned!").arg(failedCount));
return;
}
if (canceled)
return;
__unchange__(); // 'apply' behaviour
if (!wasOkay) // 'ok' behaviour
return;
closeRequest(); // we 'unchanged', so it will close directly
});
collector->go();
return false; // our request is async, say false, show a blocking dialog and do ok-/apply-button stuff later
}
/*!
* \brief ExerciseAssignmentDialog::setRecoding
* The property of an element with type indoorcamera or outdoorcamera can be updated
* \param mse
* \param state
*/
void ExerciseAssignmentDialog::setRecording(MainStructureElement &mse, bool state)
{
for(auto &el : mse.elements())
{
if(el.mountingPointTypeId() != MountingPointType::IndoorCamera &&
el.mountingPointTypeId() != MountingPointType::OutdoorCamera)
continue;
QJsonDocument propsDoc = QJsonDocument::fromJson(QByteArray::fromStdString(el.properties()));
QJsonObject propsObj;
if (propsDoc.isObject()) // if the given properties are no valid JSON object, the properties will be made from scratch
propsObj = propsDoc.object();
propsObj.insert(QLatin1String("record"), state);
el.properties(QJsonDocument(propsObj).toJson(QJsonDocument::Compact).toStdString());
}
}
void ExerciseAssignmentDialog::onPrint()
{
QTreeView tv;
tv.setModel(m_model);
tv.expandAll();
LtsPrinting::printView(m_session, this, &tv);
}
} // namespace InfrastructureManagement
//
@@ -0,0 +1,69 @@
/**
* @RDE_HEADER@
* The AssetListDialog shows how many assets are needed for a specific schedule, needed elsewhere,
* totally possessed, free, and missing
* $Id: ism_exercise_assignment_dialog.h 45935 2019-03-08 08:36:11Z ehrlicher $
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/22_09_resmgmt2.0/Lts/Plugins/InfrastructureManagement/Gui/AudioVideoConfig/ExerciseAssignment/ism_exercise_assignment_dialog.h $
* $Author: ehrlicher $
* Created by Hannes Baeuerle, SLSE, 2017-06-29
* Refreshed by Mike Wille, SLTE, 2022-09-26
*/
#pragma once
#include <ExerciseManagement/exm_dtc.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/ism_ftc.h>
#include <InfrastructureManagement/logger.h>
#include <LtsWidgets/lts_dialog.h>
namespace Ui
{
class ExerciseAssignmentDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
class ExerciseAssignmentDialogModel;
class ExerciseAssignmentDialogModelFilterProxy;
class ExerciseAssignmentDialog
: public LtsWidgets::LtsDialog
{
Q_OBJECT
public:
explicit ExerciseAssignmentDialog(LtsSession::LtsSession *session, QWidget *parent = nullptr) noexcept(false);
~ExerciseAssignmentDialog();
private slots:
void onUnassignedNeedsUpdate(const QSet<QModelIndex> &setToExpand);
void onAssignedNeedsUpdate(const QSet<QModelIndex> &setToExpand);
void onPrint();
private:
void onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &mse, DataModification modType);
void retranslate() override;
bool apply() override;
void setRecording(MainStructureElement &mse, bool state);
private:
LtsSession::LtsSession *m_session;
Ui::ExerciseAssignmentDialog *m_ui;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
ExerciseAssignmentDialogModel *m_model;
ExerciseAssignmentDialogModelFilterProxy *m_modelAssignedFilter;
ExerciseAssignmentDialogModelFilterProxy *m_modelUnassignedFilter;
QMap<qint32, ExerciseManagement::Exercise> m_exercises;
LOGGER_T m_logger;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ExerciseAssignmentDialog</class>
<widget class="QWidget" name="ExerciseAssignmentDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>953</width>
<height>681</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; color:#aa0000;&quot;&gt;WARNING: There are no exercises available. You can't assign buildings.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="1" column="2">
<layout class="QGridLayout" name="gridLayout"/>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="lbExercises">
<property name="text">
<string>Assign to exercise:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbExercises">
<property name="currentText">
<string notr="true"/>
</property>
<property name="const" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QTreeView" name="availableExercises">
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragDrop</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::CopyAction</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QTreeView" name="assignedExercises">
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragDrop</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::CopyAction</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,353 @@
/**
* @RDE_HEADER@
* $Id: $
* $HeadURL: $
* $Author: $
*
* Created by Mike Wille, SLTE, 2022-09-27
*/
#include "ism_exercise_assignment_dialog_model.h"
#include <QFont>
#include <QGuiApplication>
#include <InfrastructureManagement/ism_translation.h>
#ifdef LTS_DEBUG
#include <QTimer> // ftc delay
#endif
namespace InfrastructureManagement
{
ExerciseAssignmentDialogModel::ExerciseAssignmentDialogModel(const QMap<qint32, ExerciseManagement::Exercise> &exercises, QObject *parent) noexcept(false)
: QAbstractItemModel(parent)
, m_rootItem(new TreeItem(0, 0, tr("InvisibleRootItem"), -1))
, m_exercises(exercises)
, m_logger(getLogger("ExerciseAssignmentDialogModel"))
{
for (int it = BuildingGroup_def::UnknownGroup;
it <= BuildingGroup_def::Salchau; // WARNING: Change this, when enum changes!
++it)
{
m_rootItem->appendChild(new TreeItem(0, it, toString(static_cast<BuildingGroup_def::type>(it)), -1, m_rootItem));
}
}
ExerciseAssignmentDialogModel::~ExerciseAssignmentDialogModel()
{
delete m_rootItem;
}
void ExerciseAssignmentDialogModel::addMse(int mseId, int sectionId, const QString &displayName, int exerciseId)
{
const QList<TreeItem*> &childItems = m_rootItem->childItems();
for (auto sectionItem : qAsConst(childItems))
{
if (sectionItem->sectionId() == sectionId)
{
beginInsertRows(index(sectionItem), sectionItem->childCount(), sectionItem->childCount());
sectionItem->appendChild(new TreeItem(mseId, sectionId, displayName, exerciseId, sectionItem));
endInsertRows();
return;
}
}
ERROR_LOG(m_logger) << "Did not find section with enum value " << sectionId;
return;
}
void ExerciseAssignmentDialogModel::updateMse(int mseId, int sectionId, const QString &displayName, int exerciseId)
{
// Todo: Change of display name or moving to another section not yet implemented
Q_UNUSED(sectionId);
Q_UNUSED(displayName);
QModelIndex mi = findItemByMseId(mseId);
TreeItem* item = treeItem(mi);
if (!item)
return;
if (exerciseId != item->originalExerciseId())
{
item->setOriginalExerciseId(exerciseId);
emit dataChanged(mi, mi);
}
}
void ExerciseAssignmentDialogModel::removeMse(int mseId)
{
QModelIndex mi = findItemByMseId(mseId);
TreeItem* item = treeItem(mi);
if (!item)
return;
TreeItem* parent = item->parentItem();
if (!parent)
return;
beginRemoveRows(index(parent),item->childNumber(),item->childNumber());
parent->removeChild(item->childNumber());
endRemoveRows();
}
Qt::DropActions ExerciseAssignmentDialogModel::supportedDropActions() const
{
return Qt::MoveAction;
}
QVariant ExerciseAssignmentDialogModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() ||
(role != Qt::DisplayRole
&& role != Qt::FontRole)
)
return {};
TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
if (!item)
return {};
if (role == Qt::FontRole)
{
if (item->originalExerciseId() == item->exerciseId())
return {};
QFont f;
f.setBold(true);
return f;
}
if (role == Qt::DisplayRole)
{
if (index.column() == 0)
return item->displayName();
if (index.column() == 1)
{
const int exerciseId = item->exerciseId();
if (exerciseId < 0)
return {};
if (exerciseId == 0)
return QStringLiteral("-");
return QString::fromStdString(m_exercises.value(exerciseId).name());
}
}
return {};
}
QVariant ExerciseAssignmentDialogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation != Qt::Orientation::Horizontal || role != Qt::DisplayRole)
return QAbstractItemModel::headerData(section, orientation, role);
if (section == 0)
return tr("Building");
if (section == 1)
return tr("Assigned Exercises");
return {};
}
QModelIndex ExerciseAssignmentDialogModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return {};
TreeItem *parentItem;
if (!parent.isValid())
parentItem = m_rootItem;
else
parentItem = static_cast<TreeItem*>(parent.internalPointer());
TreeItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
return {};
}
QModelIndex ExerciseAssignmentDialogModel::parent(const QModelIndex &mi) const
{
if (!mi.isValid())
return {};
TreeItem *childItem = static_cast<TreeItem*>(mi.internalPointer());
TreeItem *parentItem = childItem->parentItem();
return index(parentItem);
}
QModelIndex ExerciseAssignmentDialogModel::index(TreeItem *item) const
{
if (item == m_rootItem || !item)
return {};
return createIndex(item->childNumber(),0,item);
}
int ExerciseAssignmentDialogModel::rowCount(const QModelIndex &parent) const
{
TreeItem *parentItem;
if (!parent.isValid())
parentItem = m_rootItem;
else
parentItem = treeItem(parent);
return parentItem->childCount();
}
QSet<int> ExerciseAssignmentDialogModel::childMses(const QModelIndex &mi, int exerciseId) const
{
QSet<int> mses;
const QList<TreeItem*> &childItems = treeItem(mi)->childItems();
for(auto myChild : qAsConst(childItems))
{
if (myChild->exerciseId() == exerciseId)
mses << myChild->mseId();
}
return mses;
}
TreeItem *ExerciseAssignmentDialogModel::treeItem(const QModelIndex &index) const
{
return static_cast<TreeItem*>(index.internalPointer());
}
QModelIndex ExerciseAssignmentDialogModel::findItemByMseId(int mseId) const
{
// This only works as long as first level is section and second level is Building!
// Otherwise we need to go into recursion!
const QList<TreeItem*> &childItems = m_rootItem->childItems();
for (auto sectionItem : qAsConst(childItems))
{
const QList<TreeItem*> &sectionChildItems= sectionItem->childItems();
for (auto mseItem : qAsConst(sectionChildItems))
{
if (mseItem->mseId() == mseId)
return index(mseItem);
}
}
return {};
}
void ExerciseAssignmentDialogModel::setExerciseId(const QModelIndex &mi, int exerciseId)
{
TreeItem *ti = treeItem(mi);
if (!ti)
return;
ti->setExerciseId(exerciseId);
emit dataChanged(mi, mi, {Qt::DisplayRole, Qt::FontRole});
}
QVector<RequestInfos> ExerciseAssignmentDialogModel::getRequestInfos(bool all) const
{
QVector<RequestInfos> requestInfos;
m_rootItem->getAllUnderlyingRequestInfos(requestInfos, all);
return requestInfos;
}
TreeItem::TreeItem(int mseId, int sectionId, const QString &displayName, int exerciseId, TreeItem *parentItem)
: m_mseId(mseId)
, m_sectionId(sectionId)
, m_displayName(displayName)
, m_exerciseId(exerciseId)
, m_originalExerciseId(exerciseId)
, m_parentItem(parentItem)
{
}
TreeItem::~TreeItem()
{
qDeleteAll(m_childItems);
}
void TreeItem::appendChild(TreeItem *child)
{
m_childItems.append(child);
}
TreeItem *TreeItem::child(int row)
{
if (row < 0 || row >= m_childItems.size())
return nullptr;
return m_childItems.at(row);
}
int TreeItem::childNumber() const
{
if (m_parentItem)
return m_parentItem->childItems().indexOf(const_cast<TreeItem*>(this));
return 0;
}
int TreeItem::childCount() const
{
return m_childItems.count();
}
void TreeItem::removeChild(int id)
{
delete(m_childItems.value(id));
m_childItems.removeAt(id);
}
void TreeItem::getAllUnderlyingRequestInfos(QVector<RequestInfos> &requestInfos, bool all) const
{
const QList<TreeItem*> &childItemsRef = childItems();
for (auto myChild : qAsConst(childItemsRef))
{
if (all || (myChild->exerciseId() != myChild->originalExerciseId()))
requestInfos.append({myChild->mseId(), myChild->exerciseId()});
myChild->getAllUnderlyingRequestInfos(requestInfos, all);
}
}
} // namespace InfrastructureManagement
//
@@ -0,0 +1,109 @@
/**
* @RDE_HEADER@
* $Id: $
* $HeadURL: $
* $Author: $
*
* Created by Mike Wille, SLTE, 2022-09-27
*/
#pragma once
#include <InfrastructureManagement/logger.h>
#include <ExerciseManagement/exm.hpp>
#include <QAbstractItemModel>
#include <QSet>
namespace InfrastructureManagement
{
/// RequestInfos
struct RequestInfos
{
int mseId;
int exerciseId;
};
// class ExerciseAssignmentDialogModel;
class TreeItem
{
public:
explicit TreeItem(int mseId, int sectionId, const QString &displayName, int exerciseId, TreeItem *parentItem = nullptr);
~TreeItem();
void appendChild(TreeItem *child);
void removeChild(int id);
TreeItem* child(int row);
int childNumber() const;
int childCount() const;
const QList<TreeItem*> childItems() const { return m_childItems; }
int sectionId() const { return m_sectionId; }
int mseId() const { return m_mseId; }
QString displayName() const { return m_displayName; }
void setExerciseId(int exerciseId) { m_exerciseId = exerciseId; }
int exerciseId() const { return m_exerciseId; }
void setOriginalExerciseId(int exerciseId) { m_originalExerciseId = exerciseId; }
int originalExerciseId() const { return m_originalExerciseId; }
TreeItem* parentItem() { return m_parentItem; }
void getAllUnderlyingRequestInfos(QVector<RequestInfos> &requestInfos, bool all = false) const;
private:
int m_mseId;
int m_sectionId;
QString m_displayName;
int m_exerciseId;
int m_originalExerciseId;
QList<TreeItem*> m_childItems;
TreeItem* m_parentItem;
};
/// ExerciseAssignmentDialogModel
class ExerciseAssignmentDialogModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit ExerciseAssignmentDialogModel(const QMap<qint32, ExerciseManagement::Exercise> &exercises, QObject *parent = nullptr) noexcept(false);
~ExerciseAssignmentDialogModel();
void addMse(int mseId, int sectionId, const QString &displayName, int exerciseId);
void updateMse(int mseId, int sectionId, const QString &displayName, int exerciseId);
void removeMse(int mseId);
QModelIndex findItemByMseId(int mseId) const;
void setExerciseId(const QModelIndex &mi, int exerciseId);
int exerciseId(const QModelIndex &mi) const { return treeItem(mi) ? treeItem(mi)->exerciseId() : -1; }
int mseId(const QModelIndex &mi) const { return treeItem(mi) ? treeItem(mi)->mseId() : 0; }
QVector<RequestInfos> getRequestInfos(bool all = false) const;
QSet<int> childMses(const QModelIndex &mi, int exerciseId) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
protected:
int rowCount(const QModelIndex &parent = {}) const override;
QVariant data(const QModelIndex &index, int role) const override;
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
QModelIndex parent(const QModelIndex &index) const override;
int columnCount(const QModelIndex &) const override { return 2; }
Qt::DropActions supportedDropActions() const override;
private:
TreeItem* treeItem(const QModelIndex &index) const;
QModelIndex index(TreeItem *item) const;
TreeItem* m_rootItem;
QMap<qint32, ExerciseManagement::Exercise> m_exercises;
LOGGER_T m_logger;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,183 @@
/**
* @RDE_HEADER@
* $Id: $
* $HeadURL: $
* $Author: $
*
* Created by Mike Wille, SLTE, 2022-09-27
*/
#include "ism_exercise_assignment_dialog_proxy_model.h"
#include "ism_exercise_assignment_dialog_model.h"
#include <QMimeData>
namespace InfrastructureManagement
{
void ExerciseAssignmentDialogModelFilterProxy::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<ExerciseAssignmentDialogModel *>(sourceModel);
Q_ASSERT(m_sourceModel != nullptr);
QSortFilterProxyModel::setSourceModel(sourceModel);
}
void ExerciseAssignmentDialogModelFilterProxy::setExerciseId(int exerciseId)
{
m_exerciseId = exerciseId;
invalidateFilter();
}
bool ExerciseAssignmentDialogModelFilterProxy::filterAcceptsRow(const int sourceRow, const QModelIndex &sourceParent) const
{
const QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent);
if (!sourceIndex.isValid())
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
// Parents are true automatically...
if (m_sourceModel->mseId(sourceIndex) == 0)
return false;
return (m_sourceModel->exerciseId(sourceIndex) == m_exerciseId);
}
bool ExerciseAssignmentDialogModelFilterProxy::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
return QString::localeAwareCompare(sourceModel()->data(left).toString(), sourceModel()->data(right).toString()) < 0;
}
QVariant ExerciseAssignmentDialogModelFilterProxy::headerData(int section, Qt::Orientation orientation, int role) const
{
if (section == 0 && orientation == Qt::Orientation::Horizontal && role == Qt::DisplayRole)
return m_exerciseId > 0 ? tr("Assigned Buildings") : tr("Unassigned Buildings");
return m_sourceModel->headerData(section, orientation, role);
}
QMimeData *ExerciseAssignmentDialogModelFilterProxy::mimeData(const QModelIndexList &indexes) const
{
QJsonObject root;
QJsonArray mseIds;
for(const QModelIndex mi : indexes)
{
QModelIndex miSource = mapToSource(mi);
int mseId = m_sourceModel->mseId(miSource);
if (mseId <= 0)
{
const QSet<int> childMses = m_sourceModel->childMses(miSource, m_exerciseId);
for (int mse : qAsConst(childMses))
mseIds << mse;
}
else
mseIds << mseId;
}
root[QStringLiteral("eams")] = mseIds;
root[QStringLiteral("oldExerciseId")] = m_exerciseId;
QMimeData *mimeData = new QMimeData;
mimeData->setData(QStringLiteral("rheinmetall/exercise-assignment"), QJsonDocument(root).toJson());
return mimeData;
}
Qt::ItemFlags ExerciseAssignmentDialogModelFilterProxy::flags(const QModelIndex &index) const
{
Qt::ItemFlags f = Qt::ItemIsDropEnabled | QAbstractItemModel::flags(index);
if (index.isValid())
f |= Qt::ItemIsDragEnabled;
return f;
}
bool ExerciseAssignmentDialogModelFilterProxy::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
if (!canDropMimeData(data, action, row, column, parent))
return false;
const JsonObject root(JsonObject::fromJson(data->data(QStringLiteral("rheinmetall/exercise-assignment"))));
const JsonArray eams(root.value<JsonArray>(QStringLiteral("eams")));
QSet<QModelIndex> setToExpand;
const QVector<int> &eamsVec = eams.toVector<int>();
for (int mseId : qAsConst(eamsVec))
{
QModelIndex sourceMi = m_sourceModel->findItemByMseId(mseId);
setToExpand.insert(sourceMi.parent());
if (sourceMi.isValid())
m_sourceModel->setExerciseId(sourceMi, m_exerciseId);
}
// Don't know why we have to do this, as always "dataChanged()" is emitted...
invalidateFilter();
emit doRefilter(setToExpand);
return true;
}
Qt::DropActions ExerciseAssignmentDialogModelFilterProxy::supportedDropActions() const
{
return Qt::MoveAction;
}
bool ExerciseAssignmentDialogModelFilterProxy::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(row)
Q_UNUSED(column)
Q_UNUSED(parent)
if (action != supportedDropActions())
return false;
const JsonObject root(JsonObject::fromJson(data->data(QStringLiteral("rheinmetall/exercise-assignment"))));
int oldExerciseId = root.value<int>(QStringLiteral("oldExerciseId"));
return oldExerciseId != m_exerciseId;
}
} // namespace InfrastructureManagement
//
@@ -0,0 +1,122 @@
/**
* @RDE_HEADER@
* $Id: $
* $HeadURL: $
* $Author: $
*
* Created by Mike Wille, SLTE, 2022-09-27
*/
#pragma once
#include <InfrastructureManagement/logger.h>
#include <QSortFilterProxyModel>
#include <LtsUtilsCore/json_object.h>
using namespace LtsUtils;
namespace InfrastructureManagement
{
class ExerciseAssignmentDialogModel;
/// ExerciseAssignmentDialogModelFilterProxy
class ExerciseAssignmentDialogModelFilterProxy : public QSortFilterProxyModel
{
Q_OBJECT
public:
ExerciseAssignmentDialogModelFilterProxy(QObject *parent)
: QSortFilterProxyModel(parent)
, m_exerciseId(0)
, m_logger(getLogger("ExerciseAssignmentDialogModelFilterProxy"))
{
setRecursiveFilteringEnabled(true);
}
void setSourceModel(QAbstractItemModel *sourceModel) override;
void setExerciseId(int exerciseId);
signals:
void doRefilter(const QSet<QModelIndex> &setToExpand);
protected:
bool filterAcceptsRow(const int sourceRow, const QModelIndex &sourceParent) const override;
bool lessThan(const QModelIndex &left, const QModelIndex &rioght) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
int columnCount(const QModelIndex &) const override { return 1; }
QMimeData* mimeData(const QModelIndexList &_indexes) const override;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
Qt::DropActions supportedDropActions() const override;
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override;
QStringList mimeTypes() const override
{
return { QStringLiteral("rheinmetall/exercise-assignment") };
}
class ExerciseAssignmentMime
{
public:
ExerciseAssignmentMime(const JsonObject &root) noexcept(false) // drop
: m_mseId(root.value<int>(QStringLiteral("mseId")))
{}
ExerciseAssignmentMime(int mseId) noexcept(false) // drag
: m_mseId(mseId)
{}
QJsonObject toJson() const
{
return { { QStringLiteral("mseId"), m_mseId } };
}
int mseId() const { return m_mseId; }
private:
int m_mseId;
};
private:
int m_exerciseId;
ExerciseAssignmentDialogModel *m_sourceModel;
LOGGER_T m_logger;
};
} // namespace InfrastructureManagement
//
@@ -0,0 +1,119 @@
/**
* @RDE_HEADER@
* $Id: $
* $HeadURL: $
* $Author: $
*
* Created by Mike Wille, SLTE, 2022-09-27
*/
#include "ism_exercise_assignment_dialog_requesters.h"
#include "ism_exercise_assignment_dialog_model.h"
#include <QFont>
#include <QGuiApplication>
#include <QMimeData>
#ifdef LTS_DEBUG
#include <QTimer> // ftc delay
#endif
namespace InfrastructureManagement
{
/// MSEModifyRequestCollector
void MSEModifyRequestCollector::next()
{
if (m_requests.isEmpty())
{
emit finished(m_canceled);
return;
}
MSEModifyRequester *requester = new MSEModifyRequester;
const QPair<RequestInfos, MainStructureElementModifyRequest> request(m_requests.takeFirst());
connect(requester, &MSEModifyRequester::finished,
this, [this](const QString &msg)
{
bool failed = (!msg.isEmpty());
if (failed)
{
m_failedCount++;
}
else
{
// ri.model->unchange(ri.rowId);
}
emit requestComplete(failed);
if (m_canceled)
m_requests.clear();
next();
});
auto go = [this, request, requester]()
{
m_ftc->mainStructureElementModifyRequest(request.second, requester);
};
#ifdef LTS_DEBUG
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ControlModifier))
{
QTimer::singleShot(3000, this, go);
return;
}
#endif
go();
}
} // namespace InfrastructureManagement
//
@@ -0,0 +1,132 @@
/**
* @RDE_HEADER@
* $Id: $
* $HeadURL: $
* $Author: $
*
* Created by Mike Wille, SLTE, 2022-09-27
*/
#pragma once
#include "ism_exercise_assignment_dialog_model.h"
#include <InfrastructureManagement/ism_ftc.h>
#include <QObject>
#include <QVector>
#include <QPair>
namespace InfrastructureManagement
{
/// MSEModifyRequester
class MSEModifyRequester : public QObject,
public Interface::Ftc::MainStructureElementModifyReplyHandler
{
Q_OBJECT
public:
MSEModifyRequester()
: QObject() // do NOT parent!
{}
void onMainStructureElementModifyReply(const Core::FunctionReplyObject &reply) override
{
if (reply.error())
emit finished(reply.translated());
else
emit finished({});
deleteLater();
}
signals:
void finished(const QString &msg);
};
/// MSEModifyRequestCollector
class MSEModifyRequestCollector : public QObject
{
Q_OBJECT
public:
MSEModifyRequestCollector(std::shared_ptr<Interface::Ftc> &ftc, QObject *parent)
: QObject(parent)
, m_ftc(ftc)
{}
void addRequest(const RequestInfos &requestInfos, const MainStructureElementModifyRequest &request)
{
m_requests += QPair<RequestInfos, MainStructureElementModifyRequest>(requestInfos, request);
}
void cancel()
{
m_canceled = true;
}
void go()
{
next();
}
int count() const
{
return m_requests.count();
}
int failedCount() const
{
return m_failedCount;
}
private slots:
void next();
signals:
void finished(bool canceled);
void requestComplete(bool failed);
private:
QVector<QPair<RequestInfos, MainStructureElementModifyRequest> > m_requests;
std::shared_ptr<Interface::Ftc> m_ftc;
bool m_canceled = false;
int m_failedCount = 0;
};
} // namespace InfrastructureManagement
//
@@ -0,0 +1,382 @@
/**
* @RDE_HEADER@
* The MountingPointInfoDialog shows information about a single mounting point
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2017-01-12
*/
#include "ism_mounting_point_info_dialog.h"
#include "ui_ism_mounting_point_info_dialog.h"
#include <InfrastructureManagement/ism_translation.h>
#include <InfrastructureManagement/Shared/ism_mounting_point.h>
#include <AudioVideoManagement/ava_session.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
namespace InfrastructureManagement
{
MountingPointInfoDialog::MountingPointInfoDialog(int32_t mountingPointId, int32_t scheduleId, const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_ui(new Ui::MountingPointInfoDialog)
, m_mountingPointId(mountingPointId)
, m_assetId(-1)
, m_scheduleId(scheduleId)
, m_menuGroup(menuGroup)
, m_dtc(nullptr)
, m_ismIfc(nullptr)
, m_avmIfc(nullptr)
, m_logger(getLogger("MountingPointInfoDialog"))
{
m_ui->setupUi(this);
m_ui->gbxAsset->hide();
}
MountingPointInfoDialog::~MountingPointInfoDialog()
{
delete m_ui;
qDeleteAll(m_dynamicAssetPropLabels);
}
void MountingPointInfoDialog::retranslate()
{
//nfrastructureManagement::InstrumentationAsset ia = m_dtc->instrumentationAsset(m_mountingPointId);
StructureElement se;
m_dtc->getStructureElementById(m_mountingPointId, se);
QString seName = QString::fromStdString(se.displayName()).trimmed();
QString lbName;
// display name is composed by mse name and se name => se.displayname
// when se.displayname is empty > we will manually compose it.
if(seName.isEmpty())
{
MainStructureElement mse= m_dtc->mainStructureElement(se.mainStructureElementId());
lbName = QString::fromStdString(mse.name()) + QStringLiteral(" - ") + QString::fromStdString(se.name());
}
else
{
lbName = seName.replace(QStringLiteral("bldg_"), QStringLiteral(""));
}
translate(m_ui, lbName);
}
bool MountingPointInfoDialog::init(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &dtc,
const std::shared_ptr<ForeignDataInterface> &ismIfc,
const std::shared_ptr<AudioVideoManagement::ForeignDataInterface> &avmIfc)
{
DEBUG_LOG(m_logger) << "Initializing MountingPointInfoDialog ...";
disconnect();
m_dtc = dtc;
m_ismIfc = ismIfc;
m_avmIfc = avmIfc;
StructureElement mountingPointData;
if (!(dtc != nullptr &&
m_dtc->enableInstrumentationAsset() &&
m_dtc->enableMountingPointAsset() &&
m_dtc->enableMainStructureElement() &&
m_dtc->enableMainSchedule() &&
m_dtc->waitForHistoricalDataInstrumentationAsset(10000) &&
m_dtc->waitForHistoricalDataMountingPointAsset(10000) &&
m_dtc->waitForHistoricalDataMainStructureElement(10000) &&
m_dtc->waitForHistoricalDataMainSchedule(10000) &&
m_dtc->getStructureElementById(m_mountingPointId, mountingPointData) &&
connect(m_dtc.get(), &Interface::Dtc::instrumentationAssetChanged,
this, &MountingPointInfoDialog::onInstrumentationAssetChanged) &&
connect(m_dtc.get(), &Interface::Dtc::mountingPointAssetChanged,
this, &MountingPointInfoDialog::onMountingPointAssetChanged) &&
connect(m_dtc.get(), &Interface::Dtc::mainScheduleChanged,
this, &MountingPointInfoDialog::onMainScheduleChanged)
))
return false;
m_ui->lblNameEntry->setText(QString::fromStdString(mountingPointData.name()));
m_ui->lblTypeEntry->setText(toString(mountingPointData.mountingPointTypeId()));
if (mountingPointData.mountingPointTypeId() != MountingPointType::OutdoorCamera &&
mountingPointData.mountingPointTypeId() != MountingPointType::MeteoDataUnit &&
mountingPointData.mountingPointTypeId() != MountingPointType::VirtualIPS)
{
// searching path backwards until we find a building structure element
QMap<StructureElementType, QString> names;
for (int parentId = mountingPointData.path().size() - 1; parentId >= 0; --parentId)
{
StructureElement parent;
m_dtc->getStructureElementById(mountingPointData.path().at(parentId), parent);
names[parent.structureElementTypeId()] = QString::fromStdString(parent.displayName().size() > 0 ? parent.displayName() : parent.name());
if (StructureElementType::Building == parent.structureElementTypeId().underlying())
break;
}
// Building lbl
m_ui->lblBuildingEntry->setText(names.value(StructureElementType::Building));
m_ui->lblPosition->hide();
m_ui->lblPositionEntry->hide();
// Floor lbl
if (names.contains(StructureElementType::Floor))
m_ui->lblFloorEntry->setText(names.value(StructureElementType::Floor));
else
{
m_ui->lblFloorEntry->hide();
m_ui->lblFloor->hide();
}
// Room lbl
if (names.contains(StructureElementType::Room))
m_ui->lblRoomEntry->setText(names.value(StructureElementType::Room));
else
{
m_ui->lblRoomEntry->hide();
m_ui->lblRoom->hide();
}
}
else
{
// hide what isn't needed
m_ui->lblBuildingEntry->hide();
m_ui->lblBuilding->hide();
m_ui->lblFloorEntry->hide();
m_ui->lblFloor->hide();
m_ui->lblRoomEntry->hide();
m_ui->lblRoom->hide();
MainStructureElement mainStructure = m_dtc->mainStructureElement(mountingPointData.mainStructureElementId());
m_ui->lblPositionEntry->setText(LtsCoordTrans::mgrsFromGeographic(mainStructure.geoPosition().lon(),
mainStructure.geoPosition().lat()));
}
if (mountingPointData.mountingPointTypeId() == MountingPointType::OutdoorCamera ||
mountingPointData.mountingPointTypeId() == MountingPointType::IndoorCamera)
{
connect(m_ui->pbShowStream, &QToolButton::clicked, this, &MountingPointInfoDialog::onShowStream);
m_ui->pbShowStream->setVisible(m_avmIfc->hasAvsSession() && m_avmIfc->avaSession()->isEstablished());
m_ui->pbAnnouncement->hide();
}
else
{
connect(m_ui->pbAnnouncement, &QToolButton::clicked, this, &MountingPointInfoDialog::onAnnouncement);
m_ui->pbShowStream->hide();
m_ui->pbAnnouncement->setVisible(m_avmIfc->hasAvsSession() && m_avmIfc->avaSession()->isEstablished());
}
setIsIncluded(m_dtc->mainSchedule(m_scheduleId));
// set the asset (if possible)
QMap<qint32, MountingPointAsset> mpAssets = m_dtc->mountingPointAssets();
for (auto it = mpAssets.begin(); it != mpAssets.end(); ++it)
{
if (it.value().structureElementId() == m_mountingPointId)
{
showAsset(m_dtc->instrumentationAsset(it.value().assetId()));
break;
}
}
switch (mountingPointData.mountingPointTypeId().underlying())
{
case InfrastructureManagement::MountingPointType::BuildingSensorModule:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Building_Sensor_Module"));
break;
case InfrastructureManagement::MountingPointType::BuildingControlUnit:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Building_Control_Unit"));
break;
case InfrastructureManagement::MountingPointType::OutdoorCamera:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Outdoor_Camera"));
break;
case InfrastructureManagement::MountingPointType::IndoorCamera:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Indoor_Camera"));
break;
case InfrastructureManagement::MountingPointType::OutdoorIPS:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Outdoor_IPS"));
break;
case InfrastructureManagement::MountingPointType::IndoorIPS:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Indoor_IPS"));
break;
case InfrastructureManagement::MountingPointType::MeteoDataUnit:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Meteo_Data_Unit"));
break;
case InfrastructureManagement::MountingPointType::AnnouncementUnit:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Announcement_Unit"));
break;
case InfrastructureManagement::MountingPointType::VirtualIPS:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Virtual_IPS"));
break;
case InfrastructureManagement::MountingPointType::EffectGenerationControlUnit:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Effect_Generation_Control_Unit"));
break;
case InfrastructureManagement::MountingPointType::BuildingNetworkSwitch:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Building_Network_Switch_Control_Unit"));
break;
case InfrastructureManagement::MountingPointType::OutdoorControlUnit:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Outdoor_Control_Unit"));
break;
case InfrastructureManagement::MountingPointType::Unknown:
default:
WARNING_LOG(m_logger) << "Unknown MountingPointType found for assetId " << m_assetId << ": " << toString(mountingPointData.mountingPointTypeId());
break;
} // switch
DEBUG_LOG(m_logger) << "Initializing MountingPointInfoDialog done :)";
return true;
}
void MountingPointInfoDialog::onInstrumentationAssetChanged(const InfrastructureManagement::InstrumentationAsset &data, DataModification modType)
{
if (data.id() != m_assetId)
return;
if (modType == DataModification::eRemoved)
removeAsset();
else
showAsset(data);
}
void MountingPointInfoDialog::onMountingPointAssetChanged(const InfrastructureManagement::MountingPointAsset &data, DataModification modType)
{
if (data.structureElementId() != m_mountingPointId)
return;
if (modType == DataModification::eRemoved)
removeAsset();
else
showAsset(m_dtc->instrumentationAsset(data.assetId()));
}
void MountingPointInfoDialog::onMainScheduleChanged(const InfrastructureManagement::MainSchedule &data, DataModification modType)
{
if (data.id() != m_scheduleId ||
modType != DataModification::eModified)
return;
setIsIncluded(data);
}
void MountingPointInfoDialog::onShowStream() const
{
if (!m_avmIfc)
{
ERROR_LOG(m_logger) << "m_avmIfc is not loaded.";
return;
}
m_avmIfc->showCamera(/*m_session->baseLayoutWidget()*/nullptr, m_mountingPointId);
}
void MountingPointInfoDialog::onAnnouncement() const
{
if (!m_avmIfc)
{
ERROR_LOG(m_logger) << "m_avmIfc is not loaded.";
return;
}
m_avmIfc->showAnnouncementUnit(m_mountingPointId);
}
void MountingPointInfoDialog::showAsset(const InfrastructureManagement::InstrumentationAsset &asset)
{
removeAsset();
DEBUG_LOG(m_logger) << "Showing new asset";
m_assetId = asset.id();
addAssetProperty(tr("Name"), QString::fromStdString(asset.name()));
addAssetProperty(tr("State"), toString(asset.assetStateId()));
addAssetProperty(tr("Hostname"), QString::fromStdString(asset.hostname()));
addAssetProperty(tr("Barcode"), QString::fromStdString(asset.barcode()));
const QJsonObject dynamicProps(QJsonDocument::fromJson(QByteArray::fromStdString(asset.properties())).object());
for (auto it = dynamicProps.begin(); it != dynamicProps.end(); ++it)
{
if (it.key() == QStringLiteral("hasSpeaker") && it.value() == true)
{
// Show Button Announcement
connect(m_ui->pbAnnouncement, &QToolButton::clicked, this, &MountingPointInfoDialog::onAnnouncement);
m_ui->pbAnnouncement->setVisible(m_avmIfc->hasAvsSession() && m_avmIfc->avaSession()->isEstablished());
}
addAssetProperty(it.key(), jsonValToString(it.value()));
}
m_ui->gbxAsset->show();
}
void MountingPointInfoDialog::removeAsset()
{
DEBUG_LOG(m_logger) << "Removing asset information";
m_assetId = -1;
m_ui->gbxAsset->hide();
for (QLabel *lbl : qAsConst(m_dynamicAssetPropLabels))
m_ui->gbxAsset->layout()->removeWidget(lbl);
qDeleteAll(m_dynamicAssetPropLabels);
m_dynamicAssetPropLabels.clear();
}
void MountingPointInfoDialog::addAssetProperty(const QString &propName, const QString &propValue)
{
DEBUG_LOG(m_logger) << "Adding asset property "
<< propName
<< ':'
<< propValue;
QLabel *lblPropName = new LtsWidgets::LtsElidedLabel(propName + QLatin1Char(':'));
QLabel *lblPropValue = new QLabel(propValue);
m_dynamicAssetPropLabels.append(lblPropName);
m_dynamicAssetPropLabels.append(lblPropValue);
QGridLayout *assetsLayout = static_cast<QGridLayout *>(m_ui->gbxAsset->layout());
int row = assetsLayout->rowCount();
assetsLayout->addWidget(lblPropName, row, 0);
assetsLayout->addWidget(lblPropValue, row, 1);
}
void MountingPointInfoDialog::setIsIncluded(const MainSchedule &schedule)
{
for (const MountingPointPlan &currentPlan : schedule.elements())
{
if (currentPlan.structureElementId() == m_mountingPointId)
{
m_ui->lblIncludedEntry->setText(tr("Yes"));
return;
}
}
m_ui->lblIncludedEntry->setText(tr("No"));
}
QString MountingPointInfoDialog::jsonValToString(const QJsonValue &val) const
{
switch (val.type())
{
case QJsonValue::Bool:
case QJsonValue::Double:
case QJsonValue::String:
return val.toVariant().toString();
case QJsonValue::Array:
return QString::fromUtf8(QJsonDocument(val.toArray()).toJson(QJsonDocument::Compact));
case QJsonValue::Object:
return QString::fromUtf8(QJsonDocument(val.toObject()).toJson(QJsonDocument::Compact));
case QJsonValue::Null:
case QJsonValue::Undefined:
default:
return QString();
}
}
} // namespace InfrastructureManagement
@@ -0,0 +1,69 @@
/**
* @RDE_HEADER@
* The MountingPointInfoDialog shows information about a single mounting point
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2017-01-12
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <Plugins/AudioVideoManagement/avm_data_plugin_interface.h>
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <InfrastructureManagement/logger.h>
class QJsonValue;
class QLabel;
namespace Ui
{
class MountingPointInfoDialog;
}
namespace InfrastructureManagement
{
class MountingPointInfoDialog
: public LtsWidgets::LtsDialog
{
Q_OBJECT
public:
explicit MountingPointInfoDialog(int32_t mountingPointId, int32_t scheduleId, const QString &menuGroup, QWidget *parent = nullptr);
~MountingPointInfoDialog();
bool init(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<InfrastructureManagement::ForeignDataInterface> &ismIfc,
const std::shared_ptr<AudioVideoManagement::ForeignDataInterface> &avmIfc);
private Q_SLOTS:
void onInstrumentationAssetChanged(const InfrastructureManagement::InstrumentationAsset &data, DataModification modType);
void onMountingPointAssetChanged(const InfrastructureManagement::MountingPointAsset &data, DataModification modType);
void onMainScheduleChanged(const InfrastructureManagement::MainSchedule &data, DataModification modType);
void onShowStream() const;
void onAnnouncement() const;
private: // methods
void retranslate() override;
void showAsset(const InfrastructureManagement::InstrumentationAsset &asset);
void removeAsset();
void addAssetProperty(const QString &propName, const QString &propValue);
void setIsIncluded(const MainSchedule &schedule);
QString jsonValToString(const QJsonValue &val) const;
private: // attributes
Ui::MountingPointInfoDialog *m_ui;
int32_t m_mountingPointId;
int32_t m_assetId;
int32_t m_scheduleId;
QString m_menuGroup;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> m_ismIfc;
std::shared_ptr<AudioVideoManagement::ForeignDataInterface> m_avmIfc;
QVector<QLabel *> m_dynamicAssetPropLabels;
LOGGER_T m_logger;
}; // class MountingPointInfoDialog
} // namespace InfrastructureManagement
@@ -0,0 +1,223 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MountingPointInfoDialog</class>
<widget class="QWidget" name="MountingPointInfoDialog">
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="7" column="0" colspan="2">
<widget class="LtsWidgets::LtsElidedLabel" name="lblPosition">
<property name="text">
<string>Position:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QToolButton" name="pbAnnouncement">
<property name="maximumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../Styles/Light/resources/rme_light_style.qrc">
<normaloff>:/style/announcement_menu.svg</normaloff>:/style/announcement_menu.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QToolButton" name="pbShowStream">
<property name="maximumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset resource="../../../../Styles/Light/resources/rme_light_style.qrc">
<normaloff>:/style/video_menu.svg</normaloff>:/style/video_menu.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="LtsWidgets::LtsElidedLabel" name="lblBuilding">
<property name="text">
<string>Building:</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="LtsWidgets::LtsElidedLabel" name="lblIncluded">
<property name="text">
<string>Included:</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="LtsWidgets::LtsElidedLabel" name="lblRoom">
<property name="text">
<string>Room:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="4">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lblIcon">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="5" column="0" colspan="2">
<widget class="LtsWidgets::LtsElidedLabel" name="lblFloor">
<property name="text">
<string>Floor:</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="LtsWidgets::LtsElidedLabel" name="lblType">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QLabel" name="lblNameEntry">
<property name="text">
<string notr="true">&lt;NAME&gt;</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="lblTypeEntry">
<property name="text">
<string notr="true">&lt;TYPE&gt;</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="4">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="8" column="0" colspan="4">
<widget class="QGroupBox" name="gbxAsset">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Equipped asset</string>
</property>
<layout class="QGridLayout" name="gridLayout"/>
</widget>
</item>
<item row="7" column="2" colspan="2">
<widget class="QLabel" name="lblPositionEntry">
<property name="text">
<string notr="true">&lt;POSITION&gt;</string>
</property>
</widget>
</item>
<item row="6" column="2" colspan="2">
<widget class="QLabel" name="lblRoomEntry">
<property name="text">
<string notr="true">&lt;ROOM&gt;</string>
</property>
</widget>
</item>
<item row="5" column="2" colspan="2">
<widget class="QLabel" name="lblFloorEntry">
<property name="text">
<string notr="true">&lt;FLOOR&gt;</string>
</property>
</widget>
</item>
<item row="4" column="2" colspan="2">
<widget class="QLabel" name="lblBuildingEntry">
<property name="text">
<string notr="true">&lt;TYPE&gt;</string>
</property>
</widget>
</item>
<item row="3" column="2" colspan="2">
<widget class="QLabel" name="lblIncludedEntry">
<property name="text">
<string notr="true">&lt;INCLUDED&gt;</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsElidedLabel</class>
<extends>QLabel</extends>
<header>LtsWidgets/lts_elided_label.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../../../Styles/Light/resources/rme_light_style.qrc"/>
</resources>
<connections/>
</ui>
@@ -0,0 +1,811 @@
/**
* @RDE_HEADER@
* The MountingPointListDialog shows how many assets are needed for a specific schedule, needed elsewhere,
* totally possessed, free, and missing
* Modified version using the checkStateProxyModel to allow setting via the checkboxes of the tree structure hjl 5/19
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#include "ism_mounting_point_list_dialog.h"
#include "ui_ism_mounting_point_list_dialog.h"
#include "ism_mounting_point_list_dialog_model.h"
#include "ism_mounting_point_list_dialog_checkbox_proxy_model.h"
#include "ism_mounting_point_list_dialog_checkbox_delegate.h"
#include "ism_mounting_point_list_dialog_list_sort_model.h"
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsUtilsCore/dds_vector.h>
#include <InfrastructureManagement/ism_translation.h>
#include <InfrastructureManagement/ism_operator_rights.h>
#include <InfrastructureManagement/Shared/ism_mounting_point.h>
#include <FilterManagement/flt_building_cmpnt_helper.h> // getVisibleTypesOfFilter
#include <SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <SituationMap/Map/map.h>
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <LtsPrinting/printing.h>
#include <QItemDelegate>
#include <QTreeView>
#include <QListWidget>
#include <QMenu>
#include <QHeaderView>
#include <QScrollBar>
#include <QTimer>
using namespace LtsWidgets;
namespace InfrastructureManagement
{
/// DummyLtsColumnFilterProxyModel
class DummyLtsColumnFilterProxyModel : public LtsColumnFilterProxyModel
{
Q_OBJECT
public:
void setColumnStringFilter(const QString &, int ) override {}
void setColumnDataFilter(const QVariant &newFilterData, int column) override
{
emit signalSetColumnDataFilter(newFilterData, column);
}
bool filterAcceptsRow(int /*source_row*/, const QModelIndex &/*source_parent*/) const override
{
return true;
}
signals:
void signalSetColumnDataFilter(const QVariant &newFilterData, int column);
};
/// MountingPointListDialog
MountingPointListDialog::MountingPointListDialog(const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_menuGroup(menuGroup)
, m_ismGuiIfc(nullptr)
, m_mapGuiInterface(nullptr)
, m_typeFilterColumn(0)
, m_typeFilterRow(0)
, m_ddsSelector(nullptr)
, m_scheduleId(-1)
, m_ui(new Ui::MountingPointListDialog)
, m_logger(getLogger("MountingPointListDialog"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_ui->setupUi(this);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Mounting_Point_List"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &MountingPointListDialog::onPrint);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
MountingPointListDialog::~MountingPointListDialog()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_mapGuiInterface->removeObjectIndicator();
m_mapGuiInterface->setSkipMapObjectSelectionDialog(false);
if (m_ismGuiIfc)
m_ismGuiIfc->setSelector(nullptr);
if (m_buildingComponentSettings)
m_buildingComponentSettings->removeChangedCallback(this);
m_mapGuiInterface->setResourceManagerMode(m_oldResourceManagerMode);
delete m_ui;
delete m_ddsSelector;
delete m_requestHelper;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void MountingPointListDialog::retranslate()
{
translate(m_ui, m_dtc->mainSchedule(m_scheduleId), tr("Mounting Point List"));
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Unmount"));
}
bool MountingPointListDialog::init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignDataInterface> &dataInterface,
InfrastructureManagement::ForeignResourceManagementGuiInterface *ismGuiIfc,
const std::shared_ptr<SituationMap::ForeignGuiInterface> &mapIfc,
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> fltBuildingComponentIfc)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_dtc = dtc;
m_ftc = ftc;
m_dataIfc = dataInterface;
m_session = session;
m_mapGuiInterface = mapIfc;
m_ismGuiIfc = ismGuiIfc;
m_fltBuildingComponentIfc = fltBuildingComponentIfc;
disconnect(m_ui->mountingPointListView);
disconnect(this);
if (!m_ftc->enableInstrumentationAssetModify())
{
ERROR_LOG(m_logger) << "Could not enable FT InstrumentationAssetModify of ISM";
return false;
}
if (!m_ftc->enableInstrumentationAssetModify())
{
ERROR_LOG(m_logger) << "Could not enable FT enableInstrumentationAssetModify of ISM";
return false;
}
if (!m_ftc->enableInstrumentationAssetRemove())
{
ERROR_LOG(m_logger) << "Could not enable FT enableInstrumentationAssetRemove of ISM";
return false;
}
if (!m_ftc->enableInstrumentationAssetUnmount())
{
ERROR_LOG(m_logger) << "Could not enable FT enableInstrumentationAssetUnmount of ISM";
return false;
}
if (!m_ftc->enableMountingPointAssetModify())
{
ERROR_LOG(m_logger) << "Could not enable FT MountingPointAssetModify of ISM";
return false;
}
if (!m_ftc->enableMountingPointAssetRemove())
{
ERROR_LOG(m_logger) << "Could not enable FT MountingPointAssetRemove of ISM";
return false;
}
if (!m_ftc->enableStructureElementModify())
{
ERROR_LOG(m_logger) << "Could not enable FT enableStructureElementModify of ISM";
return false;
}
delete m_sourceModel;
m_sourceModel = new MountingPointListDialogModel(this);
const QSet<MountingPointType> filters = { MountingPointType::BuildingSensorModule,
MountingPointType::OutdoorCamera,
// MountingPointType::BuildingControlUnit,
MountingPointType::IndoorCamera,
MountingPointType::OutdoorIPS,
MountingPointType::IndoorIPS,
MountingPointType::EffectGenerationControlUnit,
#ifndef GUEZ_MODE
MountingPointType::AnnouncementUnit,
MountingPointType::BuildingNetworkSwitch
#endif
};
m_sourceModel->setMntPointFilterTypes(filters);
if (!m_sourceModel->initModel(m_dtc, m_dataIfc))
{
ERROR_LOG(m_logger) << "Could not init model";
delete m_sourceModel;
m_sourceModel = nullptr;
return false;
}
connect(m_sourceModel, &MountingPointListDialogModel::changesMade,
this, &MountingPointListDialog::slotChangesMade); /*[this]
{
slotChangesMade();
});*/
delete m_sortProxyModel;
m_sortProxyModel = new MountingPointListSortModel(this);
m_sortProxyModel->setTypeFilter(filters);
m_sortProxyModel->setSourceModel(m_sourceModel);
delete m_checkboxProxyModel;
m_checkboxProxyModel = new CheckboxProxyModel;
/* OKAY, get this...:
* We need LtsDataView's filtering mechanism. But the CheckBoxProxyModel needs to be the *last* Proxy Model
* because it checks which Checkbox state a leaf's parent and its parent's parents has. If the LtsDataView
* does the filtering, then the CheckboxProxyModel doesn't know what lines were hidden, so the Checkbox
* states don't match.
* If LtsDataView is given an LtsColumnFilterProxyModel instead of an ItemModel, it will not create a
* LtsColumnFilterProxyModel for filtering, but use the given one instead.
* Here's the super hacky solution:
* 1. First we need a barebones LtsColumnFilterProxyModel as the LAST model instance, for the LtsDataView,
* which just sends a signa - when setColumnStringFilter was called - to ...
* 2. the REAL LtsColumnFilterProxyModel, which does the real filtering. It needs to be put BEFORE
* the CheckboxFilterProxy. So the CheckboxFilterProxy will see ALL rows that remain visible.
*/
// Model => Sort => rcfpm => CheckboxProxy => dcfpm => View
m_sortProxyModel->setRecursiveFilteringEnabled(true); // non-leafs don't have a type to filter by, so tell LtsDataView's filter proxy model to ignore these and still show them if at least ONE child (recursive) of a non-leaf is visible
LtsColumnFilterProxyModel *rcfpm = new LtsColumnFilterProxyModel; // the REAL filter, put before CheckboxFilterProxy.
rcfpm->setSourceModel(m_sortProxyModel);
rcfpm->setRecursiveFilteringEnabled(true); // non-leafs don't have a type to filter by, so tell LtsDataView's filter proxy model to ignore these and still show them if at least ONE child (recursive) of a non-leaf is visible
m_checkboxProxyModel->setSourceModel(rcfpm);
DummyLtsColumnFilterProxyModel *dcfpm = new DummyLtsColumnFilterProxyModel; // the fake filter, put as LAST instance. Source model is the CheckboxFilterProxy.
dcfpm->setRecursiveFilteringEnabled(true); // non-leafs don't have a type to filter by, so tell LtsDataView's filter proxy model to ignore these and still show them if at least ONE child (recursive) of a non-leaf is visible
connect(dcfpm, &DummyLtsColumnFilterProxyModel::signalSetColumnDataFilter,
rcfpm, &LtsColumnFilterProxyModel::onSetColumnDataFilter);
dcfpm->setSourceModel(m_checkboxProxyModel);
m_ui->mountingPointListView->setModel(dcfpm);
// Needed as otherwise changes to the model do not affect the visibility of Rooms and Levels.
connect(m_sourceModel, &MountingPointListDialogModel::dataChanged, m_sortProxyModel, &MountingPointListSortModel::invalidateFilter);
if (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::SystemConfiguration))
{
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load, this, &MountingPointListDialog::onUnmountButtonClicked);
m_buttonBox->setIcon(LtsWidgets::DialogButton::Load, QIcon(QLatin1String("icon:fixed_video_announcement.svg")));
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setEnabled(false);
}
// connect signals of TableView/CustomView: (for MapObjectIndicator
connect(m_ui->mountingPointListView, &LtsDataView::LtsDataView::clicked, this, &MountingPointListDialog::onDataViewClicked);
connect(m_ui->mountingPointListView, &LtsDataView::LtsDataView::signalEntered, this, &MountingPointListDialog::onDataViewEntered);
//------------- Filter ----------------
// SWPÄ 2/22 / GUEZE-1478:
// Diese Filter werden ersetzt durch übergeordnete BuildingComponentnFilter (Extras | SituationMap | BuildingComponent)
// subscribe to Filter:
if (m_fltBuildingComponentIfc)
{
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
m_buildingComponentSettings = m_fltBuildingComponentIfc->buildingComponentSettingsForOperator(operatorId, m_session->workspaceId());
if (m_buildingComponentSettings)
m_buildingComponentSettings->addChangedCallback(this); // will call onBuildingComponentSettingsChanged
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " addChangedCallback fltBuildingComponentIfc failed";
#ifdef LTS_DEBUG
Q_ASSERT(false);
#endif // LTS_DEBUG
}
// call on init:
onBuildingComponentSettingsChanged();
}else
{
ERROR_LOG(m_logger) << "No BuildingCOmponentIfc ";
}
// honor visibilityChanged (dialog toogles between foreground/background)
connect(this, &MountingPointListDialog::visibilityChanged, this, &MountingPointListDialog::onVisibilityChanged);
// show first tree level when activating the dialog
m_ui->mountingPointListView->treeView()->expandToDepth(0);
delete m_ddsSelector;
m_ddsSelector = nullptr;
m_ddsSelector = new DdsSelector(dtc, ftc, m_dataIfc, m_requestHelper);
// always select from the map when the dialog is visible
m_ismGuiIfc->setSelector(m_ddsSelector);
// SWPÄ GUEZE-1478 (?)
// Mit Aufschalten des Dialog wird umgeschaltet auf Modus SituationMap::ResourceManagerMode::RMM_PlanDefinitionView
// mit RMM_PlanDefinitionView sollte die Notification disabled werden...
// bis Ende des Dialoges...
m_oldResourceManagerMode = m_mapGuiInterface->resourceManagerMode();
// since switching _to_ RMM_PlanDefinitionView could be timeconsuming:
// (and give the GlobalWaitDialog time being displayed)
QTimer::singleShot(100, this, [this] () {
m_mapGuiInterface->setResourceManagerMode(SituationMap::ResourceManagerMode::RMM_PlanDefinitionView);
});
m_mapGuiInterface->setSkipMapObjectSelectionDialog(true);
m_scheduleId = m_dataIfc->scheduleId();
connect(m_dataIfc.get(), &ForeignDataInterface::scheduleIdChanged,
this, &MountingPointListDialog::onScheduleIdChanged);
m_ui->mountingPointListView->setContextMenuPolicyPerView(LtsDataView::LtsDataView::Page::TABLE, Qt::CustomContextMenu);
connect(m_ui->mountingPointListView->treeView(), &QTreeView::customContextMenuRequested,
this, &MountingPointListDialog::onCustomContextMenu);
m_ui->mountingPointListView->treeView()->setColumnWidth(0, 500);
m_ui->mountingPointListView->treeView()->setColumnWidth(1, 300);
m_ui->mountingPointListView->treeView()->setColumnWidth(2, 300);
m_ui->mountingPointListView->treeView()->header()->setSectionResizeMode(1, QHeaderView::Fixed);
m_ui->mountingPointListView->searchView()->setColumnWidth(0, 500);
m_ui->mountingPointListView->searchView()->setColumnWidth(1, 300);
m_ui->mountingPointListView->searchView()->setColumnWidth(2, 300);
m_ui->mountingPointListView->searchView()->header()->setSectionResizeMode(1, QHeaderView::Fixed);
connect(m_ui->mountingPointListView->searchView()->horizontalScrollBar(), &QScrollBar::rangeChanged,
this, [this]()
{
m_ui->mountingPointListView->slotSetHorizontalRange(0,0);
}, Qt::QueuedConnection);
connect(m_ui->mountingPointListView->treeView()->horizontalScrollBar(), &QScrollBar::rangeChanged,
this, [this]()
{
m_ui->mountingPointListView->slotSetHorizontalRange(0,0);
}, Qt::QueuedConnection);
m_ui->mountingPointListView->treeView()->setItemDelegateForColumn(MountingPointListDialogModel::Columns::NAME, new CheckboxDelegate);
// connect onEscapePressed of Map:
if (m_mapGuiInterface && m_mapGuiInterface->map())
connect(m_mapGuiInterface->map().data(), &SituationMap::Map::escapePressed,
this, &MountingPointListDialog::onEscapePressed, Qt::UniqueConnection);
// InfoMountButton:
connect(m_ui->tbMountMode, &QToolButton::clicked,
this, &MountingPointListDialog::onInfoMountButtonClicked, Qt::UniqueConnection);
onUpdateInfoMountButtonAndBehaviour();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void MountingPointListDialog::getMountingPointPlanData(const QModelIndex &index, std::vector<MountingPointPlan>&modify, const QHash<int, MountingPointPlan> &mppMap)
{
NGLTreeItem *item = m_sourceModel->privateData(index);
if (!item)
return;
if (item->data().canConvert<SimpleMountingPointData>())
{
const SimpleMountingPointData &data = item->data().value<SimpleMountingPointData>();
DEBUG_LOG(m_logger) << "Item: " << m_sourceModel->data(index, Qt::DisplayRole).toString()
<< ", Structure Element Id: " << data.id;
if (mppMap.contains(data.id))
{
if (data.aimState != mppMap[data.id].mountingPointState())
modify.push_back(MountingPointPlan(data.id, data.aimState));
}
else if (data.aimState != MountingPointState_def::Idle)
{
DEBUG_LOG(m_logger) << "Not available in Map. Desired: " << data.aimState;
modify.push_back(MountingPointPlan(data.id, data.aimState));
}
}
for (int i =0 ; i< m_sourceModel->rowCount(index); i++ )
getMountingPointPlanData(m_sourceModel->index(i, 0, index), modify, mppMap);
}
bool MountingPointListDialog::hasMountingPointMountedAsset(const QModelIndex &index)
{
NGLTreeItem *treeItem = m_sourceModel->privateData(mapToSourciest(index));
if (!treeItem)
return false;
QVariant v = treeItem->data();
if (v.canConvert<SimpleMountingPointData>())
{
// MountingPoint:
const SimpleMountingPointData itemData = v.value<SimpleMountingPointData>();
int assetId = m_dtc->getMountedAssetId(itemData.id);
return !(assetId == -1);
}
return false;
}
void MountingPointListDialog::onMountingPointPlanModifyReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void MountingPointListDialog::onInstrumentationAssetModifyReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void MountingPointListDialog::onInstrumentationAssetUnmountReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void MountingPointListDialog::onStructureElementModifyReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void MountingPointListDialog::onMountingPointAssetModifyReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void MountingPointListDialog::onMountingPointAssetRemoveReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void MountingPointListDialog::onBuildingComponentSettingsChanged()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START";
// update view via m_sortProxyModel:
if (!m_buildingComponentSettings)
return;
const FilterManagement::BuildingComponentSettings::BldCmpSettings &bldCmpSettings =
m_buildingComponentSettings->bldCmpSettings();
// 1) setTypeFilter:
{
const QSet<MountingPointType> visibleTypes = FilterManagement::getVisibleTypesOfFilter(bldCmpSettings);
m_sortProxyModel->setTypeFilter(visibleTypes);
}
// 2) floor:
{
// '-10' is floorId of Exterior / Outdoor
// Filter has HIDDEN floorIds
// (good reason: if filter not available (or nothing is checked), show all item on map...)
// so translate here to visibleFloors:
const QSet<int> &hiddenFloorIds = bldCmpSettings.buildingSettings.hiddenFloorIds;
const QSet<int> &availableFloors = m_sourceModel->getAvailableFloors();
QSet<int> visibleFloors;
for (int floor : availableFloors)
if (!hiddenFloorIds.contains(floor))
visibleFloors.insert(floor);
// qCritical() << " hiddenFloorIds" << hiddenFloorIds;
// qCritical() << " availableFloors" << availableFloors;
// qCritical() << " visibleFloors" << visibleFloors;
m_sortProxyModel->setFloorFilter(visibleFloors);
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " END";
}
bool MountingPointListDialog::apply()
{
std::vector<MountingPointPlan> modify;
const QModelIndex root = m_sourceModel->getIndexOfVisibleRootItem();
if (!root.isValid())
return false;
MainSchedule mainSchedule = m_dataIfc->mainSchedule(m_dataIfc->scheduleId());
QHash<int,MountingPointPlan> mppMap;
for(const auto &elem : mainSchedule.elements())
mppMap[elem.structureElementId()] = elem;
getMountingPointPlanData(root, modify, mppMap);
if (modify.empty())
return true;
MountingPointPlanModifyRequest req(m_dataIfc->scheduleId(), modify);
return m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->mountingPointPlanModifyRequest(req, this);
});
}
void MountingPointListDialog::onPrint()
{
MainSchedule ms = m_dtc->mainSchedule(m_dataIfc->scheduleId());
QString header;
header += QStringLiteral("<p>");
header += tr("Instrumentation Plan: %1").arg(QString::fromStdString(ms.name()));
header += QStringLiteral("<br/>");
header += tr("Status: %1").arg(toString(ms.statusId()));
header += QStringLiteral("<br/>");
header += tr("Created: %1").arg(DTG::toStringMSec(ms.timeCreated()));
header += QStringLiteral("<br/>");
if (ms.timeStart().is_set())
header += tr("START: %1").arg(DTG::toStringMSec(ms.timeStart().get()));
else
header += tr("START: %1").arg(tr("[N/A]"));
header += QStringLiteral(" - ");
if (ms.timeEnd().is_set())
header += tr("END: %1").arg(DTG::toStringMSec(ms.timeEnd().get()));
else
header += tr("END: %1").arg(tr("[N/A]"));
header += QStringLiteral("<br/>");
header += QStringLiteral("</p>");
m_ui->mountingPointListView->expandAll();
LtsPrinting::printView(m_session, this, m_ui->mountingPointListView->treeView(), header);
}
void MountingPointListDialog::onScheduleIdChanged(int32_t scheduleId)
{
if (scheduleId == m_scheduleId)
return;
// scheduleId changed, data is maybe invalid -> close dialog:
deleteLater();
}
void MountingPointListDialog::onVisibilityChanged(bool visible)
{
Q_UNUSED(visible);
// maybe dialog is put to background -> leave mount mode:
onUpdateInfoMountButtonAndBehaviour();
}
void MountingPointListDialog::onCustomContextMenu(QPoint pos)
{
QMenu *contextMenu = new QMenu(this);
contextMenu->setAttribute(Qt::WA_DeleteOnClose);
{
QAction *action = new QAction(tr("Expand All"), this);
action->setEnabled(true);
connect(action, &QAction::triggered, this, [this]()
{
m_ui->mountingPointListView->expandAll();
});
contextMenu->addAction(action);
}
{
QAction *action = new QAction(tr("Collapse All"), this);
action->setEnabled(true);
connect(action, &QAction::triggered, this, [this]()
{
m_ui->mountingPointListView->collapseAll();
});
contextMenu->addAction(action);
}
contextMenu->addSeparator();
QModelIndex index = m_ui->mountingPointListView->treeView()->indexAt(pos);
bool hasChildren = m_ui->mountingPointListView->treeView()->model()->rowCount(index) > 0;
{
QAction *action = new QAction(tr("Expand"), this);
action->setEnabled(hasChildren);
connect(action, &QAction::triggered, this, [this, index]()
{
#if QT_VERSION < QT_VERSION_CHECK(5,13,0)
m_ui->mountingPointListView->treeView()->expand(index);
#else
m_ui->mountingPointListView->treeView()->expandRecursively(index);
#endif
});
contextMenu->addAction(action);
}
{
QAction *action = new QAction(tr("Collapse"), this);
action->setEnabled(hasChildren);
connect(action, &QAction::triggered, this, [this, index]()
{
m_ui->mountingPointListView->treeView()->collapse(index);
});
contextMenu->addAction(action);
}
contextMenu->popup(m_ui->mountingPointListView->treeView()->mapToGlobal(pos));
}
void MountingPointListDialog::onDataViewClicked(const QModelIndex &mi)
{
m_clickedObjectStore.reset();
onDataViewEntered(mi);
// suppress Entered for a while:
m_clickedObjectStore.timestampMsec = QDateTime::currentMSecsSinceEpoch();
bool enabled = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::SystemConfiguration);
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setEnabled(hasMountingPointMountedAsset(mi) && enabled);
}
QModelIndex MountingPointListDialog::mapToSourciest(const QModelIndex &index)
{
QModelIndex currentIndex = index;
const QAbstractItemModel *model = index.model();
//qWarning() << "start" << model << currentIndex;
while (true)
{
const QAbstractProxyModel *proxyModel = qobject_cast<const QAbstractProxyModel *>(model);
if (proxyModel == nullptr)
break;
model = proxyModel->sourceModel();
currentIndex = proxyModel->mapToSource(currentIndex);
//qWarning() << "new" << model << currentIndex;
}
//qWarning() << "done" << model << currentIndex;
return currentIndex;
}
void MountingPointListDialog::onDataViewEntered(const QModelIndex & mi)
{
if ( (QDateTime::currentMSecsSinceEpoch() - m_clickedObjectStore.timestampMsec) < 500)
return;
const QModelIndex &theIndex(mapToSourciest(mi));
NGLTreeItem *treeItem = m_sourceModel->privateData(theIndex);
if (!treeItem)
return;
const QVariant v(treeItem->data());
if (v.canConvert<SimpleStructureElementData>())
{
// Building:
const SimpleStructureElementData itemData = v.value<SimpleStructureElementData>();
m_clickedObjectStore.mot = SituationMap::MapObjectType::MOT_Building;
m_clickedObjectStore.entityId = itemData.mseId;
}
else if (v.canConvert<SimpleMountingPointData>())
{
// MountingPoint:
const SimpleMountingPointData itemData = v.value<SimpleMountingPointData>();
m_clickedObjectStore.mot = SituationMap::MapObjectType::MOT_MountingPoint;
m_clickedObjectStore.entityId = itemData.id;
}
else
{
m_clickedObjectStore.reset();
}
if (m_clickedObjectStore.entityId>=0)
{
m_mapGuiInterface->objectIndicatorToMapObject(m_clickedObjectStore.mot, m_clickedObjectStore.entityId, true);
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
m_mapGuiInterface->centerMapToMapObject(m_clickedObjectStore.mot, m_clickedObjectStore.entityId);
}
}
void MountingPointListDialog::onEscapePressed()
{
if (!m_mapGuiInterface)
return;
m_mapGuiInterface->removeObjectIndicator();
}
void MountingPointListDialog::onUnmountButtonClicked()
{
if (m_ui->mountingPointListView->selectionModel()->selectedRows().size() < 1)
return;
NGLTreeItem *treeItem = m_sourceModel->privateData(mapToSourciest(m_ui->mountingPointListView->currentIndex()));
if (!treeItem)
return;
const QVariant v = treeItem->data();
if (v.canConvert<SimpleMountingPointData>())
{
const SimpleMountingPointData itemData = v.value<SimpleMountingPointData>();
LtsWidgets::Button button = LtsWidgets::LtsMessageDialog::showMessage(
this, tr("Do you really want to unmount asset on selected mounting point?"), tr("Unmount Assets"), LtsWidgets::Behaviour::Modal,
{ LtsWidgets::Button::Yes, LtsWidgets::Button::No });
if (button == LtsWidgets::Button::Yes)
{
const int assetId = m_dtc->getMountedAssetId(itemData.id);
if (assetId > 0)
{
InstrumentationAssetUnmountRequest req(assetId);
bool ret = m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->instrumentationAssetUnmountRequest(req, this);
});
if (!ret)
WARNING_LOG(m_logger)<<" couldn't unmount asset on MountingPoinAsset id: "<<req.id();
else
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load,false);
}
else // mounted asset id not found
{
LtsWidgets::LtsMessageDialog::showMessage(
this, tr("No mounted asset found on this mounting point"), tr("Unmount Assets"), LtsWidgets::Behaviour::Modal, LtsWidgets::Button::Ok);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load,false);
}
} // end if allow unmount asset
}
else
{
ERROR_LOG(m_logger)<<" Couldn't convert to SimpleMountingPointData: ";
}
}
void MountingPointListDialog::onInfoMountButtonClicked(bool)
{
// toggle btn and sitMap behaviour, but keep visibility in mind:
switch (m_infoMount) {
case InfoMount::IM_INFO:
m_infoMount = InfoMount::IM_MOUNT;
break;
case InfoMount::IM_MOUNT:
m_infoMount = InfoMount::IM_INFO;
break;
default:
// empty
break;
} // switch
onUpdateInfoMountButtonAndBehaviour();
}
void MountingPointListDialog::onUpdateInfoMountButtonAndBehaviour()
{
// // maybe dialog is put to background and is hidden now -> leave mount mode:
// // in that case switch to 'IM_INFO' tempoary:
InfoMount infoMountTemp = m_infoMount;
const bool bDialogIsVisi = this->isVisible();
if (!bDialogIsVisi)
infoMountTemp = InfoMount::IM_INFO;
switch (infoMountTemp) {
case InfoMount::IM_INFO:
{
QColor backgroundColor = QToolButton().palette().window().color();
QColor textColor = QGuiApplication::palette().color(QPalette::Text);
QString style = QStringLiteral("QToolButton { background-color: rgb(%1,%2,%3); color: rgb(%4,%5,%6) }")
.arg(backgroundColor.red()).arg(backgroundColor.green()).arg(backgroundColor.blue())
.arg(textColor.red()).arg(textColor.green()).arg(textColor.blue());
m_ui->tbMountMode->setText(tr("Info"));
m_ui->tbMountMode->setStyleSheet(style);
m_ui->tbMountMode->setToolTip(tr("Click on map object opens info dialog"));
m_ismGuiIfc->setSelector(nullptr);
m_mapGuiInterface->setSkipMapObjectSelectionDialog(false);
}
break;
case InfoMount::IM_MOUNT:
{
QColor color = QGuiApplication::palette().color(QPalette::Link);
QString style = QStringLiteral("QToolButton { background-color: rgb(%1,%2,%3); color: white }").arg(
QString::number(color.red()), QString::number(color.green()), QString::number(color.blue())
);
m_ui->tbMountMode->setStyleSheet(style);
m_ui->tbMountMode->setText(tr("Map Selection"));
m_ui->tbMountMode->setToolTip(tr("Click on map object toogles aim state"));
m_ismGuiIfc->setSelector(m_ddsSelector);
m_mapGuiInterface->setSkipMapObjectSelectionDialog(true);
}
break;
default:
// empty
break;
} // switch
}
//------------------------------------------------------------------------------
//( class ClickedObjectStore
//------------------------------------------------------------------------------
void MountingPointListDialog::ClickedObjectStore::reset()
{
mot = SituationMap::MapObjectType::MOT_Undefined;
entityId = -1;
timestampMsec = 0;
}
} // namespace InfrastructureManagement
#include "ism_mounting_point_list_dialog.moc"
@@ -0,0 +1,167 @@
/**
* @RDE_HEADER@
* The MountingPointListDialog shows how many assets are needed for a specific schedule, needed elsewhere,
* totally possessed, free, and missing
* Modified version using the checkStateProxyModel to allow setting via the checkboxes of the tree structure hjl 5/19
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#pragma once
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/ism_ftc.h>
#include <InfrastructureManagement/logger.h>
#include <InfrastructureManagement/ism_data_plugin_interface.h>
#include <SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <InfrastructureManagement/Gui/ResourceManagement/MountingPointMapSelection/ism_dds_selector.h>
#include <InfrastructureManagement/Gui/ResourceManagement/MountingPointMapSelection/ism_selector.h>
#include <FilterManagement/flt_building_cmpnt_plugin_interface.h> // honor current filter settings (menue SituationMap)
#include <FilterManagement/flt_building_cmpnt_settings.h> // hold current filter settings (and for addCSubscriberCallback)
#include <LtsWidgets/lts_dialog.h>
#include <LtsDataView/check_state_proxy_model.h>
#include <LtsWidgets/lts_abstract_table_model.h>
#include <QItemDelegate>
class QCheckBox;
namespace Ui
{
class MountingPointListDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace LtsUtils
{
class RequestHelper;
}
namespace SituationMap
{
enum class MapObjectType;
}
namespace InfrastructureManagement
{
class MountingPointListDialogModel;
class MountingPointListSortModel;
class CheckboxProxyModel;
class MountingPointListDialog final
: public LtsWidgets::LtsDialog
, protected Interface::Ftc::MountingPointPlanModifyReplyHandler
, protected Interface::Ftc::InstrumentationAssetUnmountReplyHandler
, protected Interface::Ftc::StructureElementModifyReplyHandler
, protected Interface::Ftc::InstrumentationAssetModifyReplyHandler
, protected Interface::Ftc::MountingPointAssetModifyReplyHandler
, protected Interface::Ftc::MountingPointAssetRemoveReplyHandler
, protected FilterManagement::BuildingComponentSettings::SettingsChangedCallback
{
Q_OBJECT
public:
explicit MountingPointListDialog(const QString &menuGroup, QWidget *parent = nullptr);
~MountingPointListDialog();
bool init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignDataInterface> &dataInterface,
InfrastructureManagement::ForeignResourceManagementGuiInterface *ismGuiIfc,
const std::shared_ptr<SituationMap::ForeignGuiInterface> &mapIfc,
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> fltBuildingComponentIfc
);
void onMountingPointPlanModifyReply(const Core::FunctionReplyObject &replyObject) override final;
void onInstrumentationAssetModifyReply(const Core::FunctionReplyObject &replyObject) override final;
void onInstrumentationAssetUnmountReply(const Core::FunctionReplyObject &replyObject) override final;
void onStructureElementModifyReply(const Core::FunctionReplyObject &replyObject) override final;
void onMountingPointAssetModifyReply(const Core::FunctionReplyObject &replyObject) override final;
void onMountingPointAssetRemoveReply(const Core::FunctionReplyObject &replyObject) override final;
void onBuildingComponentSettingsChanged() override final;
void getMountingPointPlanData(const QModelIndex &index, std::vector<MountingPointPlan> &add, const QHash<int, MountingPointPlan> &mppMap);
bool hasMountingPointMountedAsset(const QModelIndex &index);
friend class MountingPointSelector;
private slots:
void onVisibilityChanged(bool visible);
void onPrint();
void onScheduleIdChanged(int32_t scheduleId);
void onCustomContextMenu(QPoint pos);
void onDataViewClicked(const QModelIndex &mi);
void onDataViewEntered(const QModelIndex &mi);
void onEscapePressed();
void onUnmountButtonClicked();
void onInfoMountButtonClicked(bool);
void onUpdateInfoMountButtonAndBehaviour();
private: // methods
void retranslate() override;
bool apply() override final;
bool isIncludedId(int32_t mountingPointId) const;
QModelIndex mapToSourciest(const QModelIndex &index);
private: // attributes
MountingPointListDialogModel *m_sourceModel{nullptr};
MountingPointListSortModel *m_sortProxyModel{nullptr};
CheckboxProxyModel *m_checkboxProxyModel{nullptr};
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
std::shared_ptr<ForeignDataInterface> m_dataIfc;
LtsUtils::RequestHelper *m_requestHelper{nullptr};
QString m_menuGroup;
LtsSession::LtsSession *m_session{nullptr};
ForeignResourceManagementGuiInterface *m_ismGuiIfc{nullptr};
std::shared_ptr<SituationMap::ForeignGuiInterface> m_mapGuiInterface;
struct ClickedObjectStore
{
SituationMap::MapObjectType mot {SituationMap::MapObjectType::MOT_Undefined};
int entityId {-1};
qint64 timestampMsec {-1};
void reset();
} m_clickedObjectStore;
unsigned int m_typeFilterColumn;
unsigned int m_typeFilterRow;
DdsSelector *m_ddsSelector{nullptr};
int32_t m_scheduleId;
// click leads to a) InfoDialog or b) mounting/changing aimState (Idle, Equipped, Empty)
enum class InfoMount
{
IM_INFO, ///! on Click on MapObject, normal map behaviour: info dialog
IM_MOUNT ///! on Click on MapObject, change aim state
}
m_infoMount{InfoMount::IM_INFO};
SituationMap::ResourceManagerMode m_oldResourceManagerMode{SituationMap::ResourceManagerMode::Undefined};
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> m_fltBuildingComponentIfc;
std::shared_ptr<FilterManagement::BuildingComponentSettings> m_buildingComponentSettings;
Ui::MountingPointListDialog *m_ui{nullptr};
LOGGER_T m_logger;
}; // class MountingPointListDialog
} // namespace InfrastructureManagement
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MountingPointListDialog</class>
<widget class="QWidget" name="MountingPointListDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>833</width>
<height>478</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Asset Stocks</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="1" colspan="2">
<widget class="LtsDataView::LtsDataView" name="mountingPointListView" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="rootIsDecorated" stdset="0">
<bool>true</bool>
</property>
<property name="showColumnCount" stdset="0">
<bool>false</bool>
</property>
<property name="toolButtonsVisible" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>439</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="2">
<widget class="QToolButton" name="tbMountMode">
<property name="minimumSize">
<size>
<width>150</width>
<height>50</height>
</size>
</property>
<property name="text">
<string notr="true">mountMode</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,52 @@
#include "ism_mounting_point_list_dialog_checkbox_delegate.h"
#include "ism_mounting_point_list_dialog_model.h"
#include <QPainter>
namespace InfrastructureManagement
{
CheckboxDelegate::CheckboxDelegate(QObject *parent)
: QItemDelegate(parent)
{}
void CheckboxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QItemDelegate::paint(painter, option, index);
if (index.column() != MountingPointListDialogModel::Columns::NAME)
return;
painter->save();
painter->setClipRect(option.rect);
painter->setClipping(true);
const QVariant value(index.data(Qt::UserRole + 1));
if (value.isValid() && value.canConvert<int>())
{
QPixmap x(QStringLiteral(":/style/checkbox-multi-state.svg"));
switch (value.toInt())
{
case MountingPointState::Equipped:
x = QPixmap(QStringLiteral(":/style/checkbox-true.svg"));
break;
case MountingPointState::Idle:
x = QPixmap(QStringLiteral(":/style/checkbox-empty.svg"));
break;
case MountingPointState::Empty:
x = QPixmap(QStringLiteral(":/style/checkbox-false.svg"));
break;
}
const QStyleOptionViewItem opt = setOptions(index, option);
const QRect checkRect(QItemDelegate::doCheck(opt, opt.rect, /*value*/1));
painter->drawPixmap(checkRect.adjusted(3,0,3,0), x, QRect());
//QItemDelegate::drawCheck(painter, opt, checkRect, Qt::CheckState::Checked); // test
}
painter->restore();
}
} // namespace InfrastructureManagement
@@ -0,0 +1,18 @@
#pragma once
#include "ism_mounting_point_list_dialog_checkbox_delegate.h"
#include <QItemDelegate>
namespace InfrastructureManagement
{
class CheckboxDelegate : public QItemDelegate
{
Q_OBJECT
public:
CheckboxDelegate(QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,168 @@
#include "ism_mounting_point_list_dialog_checkbox_proxy_model.h"
#include "ism_mounting_point_list_dialog_model.h"
namespace InfrastructureManagement
{
Qt::ItemFlags CheckboxProxyModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return sourceModel()->flags(index); // delegate to source model for further processing if necessary
// Sets only the checkbox nodes on user checkable,
// checkbox leaves must be handled in source model.
QModelIndex sourceIndex = mapToSource(index);
Qt::ItemFlags fl = sourceModel()->flags(sourceIndex);
if (index.column() == 0)
return fl | Qt::ItemIsUserCheckable;
return fl;
}
QVariant CheckboxProxyModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return {};
const QModelIndex sourceIndex(mapToSource(index));
// delegate everything except CheckStateRole to source model
if (role != (Qt::UserRole + 1))
return sourceModel()->data(sourceIndex, role);
// delegate a leaf too with CheckStateRole to source model
if (isLeaf(index))
return sourceModel()->data(sourceIndex, role);
// delegate to source model for further processing of further columns if necessary
if (index.column() != MountingPointListDialogModel::Columns::NAME)
return sourceModel()->data(sourceIndex, role);
// sets the node checkboxes and decoration depending on the entries in the tree structure
bool lastMpsSet = false; // std::optional >_>
int lastMps = -2;
int childCount = rowCount(index);
for (int childRow = 0; childRow < childCount; ++childRow)
{
const QModelIndex childIndex(this->index(childRow, 0, index));
const QVariant value(data(childIndex, (Qt::UserRole + 1)));
if (value.isValid() && value.canConvert<int>())
{
int state = value.toInt();
if (!lastMpsSet)
{
lastMpsSet = true;
lastMps = state;
continue;
}
if (lastMps != state) // if at one point there is a different status inside one parent, show the 'partial' checkbox state as there are mixed states
return -2;
}
}
return lastMps;
}
QString mpsToString(const int mps)
{
switch ((int)mps)
{
case -2:
return QStringLiteral("PARTIALLY");
case -1:
return QStringLiteral("EMPTY");
case 0:
return QStringLiteral("IDLE");
case 1:
return QStringLiteral("EQUIPPED");
default:
return QStringLiteral("( !UNKNOWN! )");
}
}
QString mpsToString(const MountingPointState_def::type mps)
{
return mpsToString((int)mps);
}
bool CheckboxProxyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
/* this setData is called if the user clicks on a checkbox
* then this setData calls the sourceModel's setData to finally
* set the underlying checkboxes */
if (!index.isValid())
return false;
const QModelIndex sourceIndex(mapToSource(index));
// delegate to source model for further processing of further columns if necessary
if (index.column() != MountingPointListDialogModel::Columns::NAME)
return sourceModel()->setData(sourceIndex, value, role);
/* Qt calls setData with role == Qt::CheckStateRole if the user clicks on a checkbox.
* We need to know at this point if wither the call to this method was called by Qt,
* or if this method called setData recursively. If this is the first call, the new
* checkbox state has to be determined at this point. To determine if the call to
* setData is a recursive call, we set role to Qt::UserRole+1. Kind of a hack. */
int newMps = value.toInt();
if (role == Qt::CheckStateRole)
{
//newMps = (int)MountingPointState_def::Idle;
int mps = index.data(Qt::UserRole + 1).toInt();
switch (mps)
{
case -2: // SPECIAL CASE, not a real MPS, but the indicator that there are mixed states on the underlying children
newMps = (int)MountingPointState_def::Idle;
break;
case (int)MountingPointState_def::Idle:
newMps = (int)MountingPointState_def::Equipped;
break;
case (int)MountingPointState_def::Equipped:
newMps = (int)MountingPointState_def::Empty;
break;
case (int)MountingPointState_def::Empty:
newMps = (int)MountingPointState_def::Idle;
break;
default:
return false;
}
}
if (isLeaf(index))
{
// delegate a leaf to source model
sourceModel()->setData(sourceIndex, newMps, role);
}
else
{
// update underlying children recursively (Additional nodes with leaves may also exist)
const int childCount = rowCount(index);
for (int childRow = 0; childRow < childCount; ++childRow)
{
const QModelIndex childIndex(this->index(childRow, 0, index));
setData(childIndex, newMps, (Qt::UserRole + 1));
}
}
return true;
}
bool CheckboxProxyModel::isLeaf(const QModelIndex &index) const
{
const QModelIndex sourceIndex(mapToSource(index));
return sourceModel()->flags(sourceIndex).testFlag(Qt::ItemIsUserCheckable);
}
} // namespace InfrastructureManagement
@@ -0,0 +1,19 @@
#pragma once
#include <QIdentityProxyModel>
namespace InfrastructureManagement
{
class CheckboxProxyModel : public QIdentityProxyModel
{
public:
using QIdentityProxyModel::QIdentityProxyModel;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
private:
bool isLeaf(const QModelIndex &index) const;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,120 @@
#include "ism_mounting_point_list_dialog_list_sort_model.h"
#include <Plugins/InfrastructureManagement/Shared/ism_mounting_point.h>
namespace InfrastructureManagement
{
void MountingPointListSortModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<MountingPointListDialogModel*>(sourceModel);
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(m_sourceModel);
}
void MountingPointListSortModel::setTypeFilter(const QSet<MountingPointType> &visibleTypes)
{
if (m_visibleTypes == visibleTypes)
return;
m_visibleTypes = visibleTypes;
invalidateFilter();
}
void MountingPointListSortModel::addToTypeFilter(MountingPointType mpt, bool bAdd)
{
auto visibleTypes = m_visibleTypes;
if (bAdd)
{
if(mpt == MountingPointType::IndoorIPS)
{
visibleTypes.insert(MountingPointType::OutdoorIPS);
}
visibleTypes.insert(mpt);
}
else
{
if(mpt == MountingPointType::IndoorIPS)
{
visibleTypes.remove(MountingPointType::OutdoorIPS);
}
visibleTypes.remove(mpt);
}
setTypeFilter(visibleTypes);
}
void MountingPointListSortModel::setFloorFilter(const QSet<int> &visibleFloors)
{
if (m_visibleFloors == visibleFloors)
return;
m_visibleFloors = visibleFloors;
invalidateFilter();
}
void MountingPointListSortModel::addToFloorFilter(int floor, bool bAdd)
{
auto visibleFloors = m_visibleFloors;
if (bAdd)
visibleFloors.insert(floor);
else
visibleFloors.remove(floor);
setFloorFilter(visibleFloors);
}
bool MountingPointListSortModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (!m_sourceModel)
return true;
bool isRootItem = !source_parent.isValid();
if (isRootItem)
{
Q_ASSERT(source_row == 0);
return true; // root item shall always be visible
}
const QModelIndex childIdx = m_sourceModel->index(source_row, 0, source_parent);
const NGLTreeItem *itemChild = m_sourceModel->privateData(childIdx);
Q_ASSERT(itemChild);
bool isLeaf = itemChild->data().canConvert<SimpleMountingPointData>();
if (isLeaf)
{
const SimpleMountingPointData data = itemChild->data().value<SimpleMountingPointData>();
Q_ASSERT(data.isMountingPoint());
return m_visibleTypes.contains(data.mpType) && m_visibleFloors.contains(data.floor);
}
else
{
if (!itemChild->data().canConvert<SimpleStructureElementData>())
return true;
const SimpleStructureElementData ssed = itemChild->data().value<SimpleStructureElementData>();
if (ssed.floor != -20 && !m_visibleFloors.contains(ssed.floor))
return false;
}
// Qt5.11: setRecursiveFilteringEnabled(true);
for (int i = 0; i < itemChild->childCount(); ++i)
{
if (filterAcceptsRow(i, childIdx))
return true;
}
return false;
}
bool MountingPointListSortModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_sourceModel || source_left.column() != source_right.column())
return BaseClass::lessThan(source_left, source_right);
const NGLTreeItem *itemLeft = m_sourceModel->privateData(source_left);
const NGLTreeItem *itemRight = m_sourceModel->privateData(source_right);
if (!itemLeft || !itemRight)
return BaseClass::lessThan(source_left, source_right);
const SimpleMountingPointData left = itemLeft->data().value<SimpleMountingPointData>();
const SimpleMountingPointData right = itemRight->data().value<SimpleMountingPointData>();
if (left.name != right.name)
return left.name < right.name;
return left.id < right.id;
}
} // namespace InfrastructureManagement
@@ -0,0 +1,38 @@
#pragma once
#include "ism_mounting_point_list_dialog_model.h"
#include <LtsWidgets/lts_column_filter_proxy_model.h>
#include <QSet>
namespace InfrastructureManagement
{
class MountingPointListSortModel final : public LtsWidgets::LtsColumnFilterProxyModel
{
using BaseClass = LtsWidgets::LtsColumnFilterProxyModel;
Q_OBJECT
public:
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
void setSourceModel(QAbstractItemModel *sourceModel) override;
void setTypeFilter(const QSet<MountingPointType> &visibleTypes);
void addToTypeFilter(MountingPointType mpt, bool bAdd);
void setFloorFilter(const QSet<int> &visibleFloors);
void addToFloorFilter(int floor, bool bAdd);
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
using LtsWidgets::LtsColumnFilterProxyModel::invalidateFilter;
private:
MountingPointListDialogModel *m_sourceModel = nullptr;
QSet<MountingPointType> m_visibleTypes;
QSet<int> m_visibleFloors;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,478 @@
/**
* @RDE_HEADER@
* The MountingPointListDialogModel provices data for MountingPointListDialog
* Modified version using the checkStateProxyModel to allow setting via the checkboxes of the tree structure hjl 5/19
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#include "ism_mounting_point_list_dialog_model.h"
#include "ism_mounting_point_list_dialog_list_sort_model.h"
#include <InfrastructureManagement/ism_translation.h>
#include <Plugins/InfrastructureManagement/Shared/ism_mounting_point.h>
#include <QTimer>
// #define BENCHMARK
#ifdef BENCHMARK
# include <QElapsedTimer>
# include <QDebug>
#endif
namespace InfrastructureManagement
{
MountingPointListDialogModel::MountingPointListDialogModel(QObject *parent)
: NGLTreeModel(parent, new NGLTreeItem(QVariant()), { tr("Name"), tr("Type"), tr("Asset"), tr("Aim State") })
, m_visRoot(new NGLTreeItem(tr("Mounting Points")))
, m_dtc(nullptr)
, m_scheduleId(-1)
, m_dataChangedTimer(new QTimer(this))
, m_logger(getLogger("MountingPointListDialogModel"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_dataChangedTimer->setSingleShot(true);
m_dataChangedTimer->setInterval(100);
connect(m_dataChangedTimer, &QTimer::timeout, this, &MountingPointListDialogModel::emitDataChanged);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QVariant MountingPointListDialogModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
NGLTreeItem *item = privateData(index);
const int indexColumn = index.column();
if (role == Qt::DisplayRole)
{
if (indexColumn != NAME && !item->data().canConvert<SimpleMountingPointData>())
return QVariant();
const SimpleMountingPointData itemData = item->data().value<SimpleMountingPointData>();
switch (indexColumn)
{
case NAME:
if (item->data().canConvert<SimpleMountingPointData>())
return item->data().value<SimpleMountingPointData>().name;
if (item->data().canConvert<SimpleStructureElementData>())
return item->data().value<SimpleStructureElementData>().name;
if (item->data().canConvert<SimpleBuildingGroupData>())
return item->data().value<SimpleBuildingGroupData>().name;
return tr("all");
case STATE:
if (itemData.seType == StructureElementType::MountingPoint)
return toString(itemData.aimState);
break;
case ASSET_BARCODE:
if (item->data().canConvert<SimpleMountingPointData>())
return item->data().value<SimpleMountingPointData>().assetBarcode;
break;
case TYPE:
if (itemData.seType == StructureElementType::MountingPoint)
{
if(itemData.mpType == MountingPointType::OutdoorIPS)
return toString(MountingPointType::IndoorIPS);
return toString(itemData.mpType);
}
break;
}
}
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole
&& indexColumn == TYPE)
{
const SimpleMountingPointData itemData = item->data().value<SimpleMountingPointData>();
if (itemData.mpType.underlying() == MountingPointType::Unknown)
{
ERROR_LOG(m_logger) << "unknown!!!";
return QVariant(); // return INVALID QVariant to let LtsDataView's proxy filter model ignore this row while filtering / aka. don't hide it when filtering
}
ERROR_LOG(m_logger) << "mpType = " << itemData.mpType.underlying();
if(itemData.mpType == MountingPointType::OutdoorIPS)
return MountingPointType::IndoorIPS;
return itemData.mpType.underlying();
}
if (role == Qt::CheckStateRole && index.column() == NAME)
return Qt::Unchecked; // dummy
if (role == Qt::UserRole && item->data().canConvert<SimpleMountingPointData>())
return item->data().value<SimpleMountingPointData>().id;
if (role == (Qt::UserRole + 1) && item->data().canConvert<SimpleMountingPointData>())
return item->data().value<SimpleMountingPointData>().aimState.underlying();
return {};
}
bool MountingPointListDialogModel::initModel(const std::shared_ptr<Interface::Dtc> &dtc, const std::shared_ptr<ForeignDataInterface> &dataInterface)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_dtc == dtc)
return true;
if (!(dtc->enableMainStructureElement() &&
dtc->enableMountingPointAsset()))
{
ERROR_LOG(m_logger) << "Could not enable Datatopics";
return false;
}
m_dtc = dtc;
m_dataInterface = dataInterface;
m_scheduleId = m_dataInterface->scheduleId();
connect(m_dataInterface.get(), &ForeignDataInterface::mountingPointChanged,
this, &MountingPointListDialogModel::onMountingPointChanged);
DEBUG_LOG(m_logger) << "initModel successful";
initData();
beginResetModel();
endResetModel();
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
return true;
}
QModelIndex MountingPointListDialogModel::getIndexOfVisibleRootItem() const
{
return indexFromItem(m_visRoot);
}
void MountingPointListDialogModel::initData()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
#ifdef BENCHMARK
QElapsedTimer elapsedTimer1;
elapsedTimer1.start();
#endif // BENCHMARK
NGLTreeModel::resetModel();
m_rootItem->appendChild(m_visRoot);
// const InfrastructureManagement::MainSchedule &currentSchedule = m_dtc->mainSchedule(m_scheduleId);
const QMap<int, InfrastructureManagement::MainStructureElement> &mainStructEles = m_dtc->mainStructureElements();
// cfroebel 2018-11-07:
// The algorithm of building the tree structure assumes that
// the StructureElements are hierarchically ordered, i.e. that the
// MountingPoint comes after its Room, Level and Building.
// Is that guaranteed by the service?
m_mountingPointIndexes.reserve(mainStructEles.size());
m_availableBuildingGroups.reserve(mainStructEles.size());
for (const MainStructureElement &mse : mainStructEles)
{
// only consider buildings
if (mse.structureElementTypeId() != StructureElementType::Building)
continue;
// 1- if a buildingGroup modelIndex for current building dosen't exist
// a new one will be first added and used as parentIndex for the blg_Index.
QModelIndex groupIndex;
const StructureElement bse= setBuildingGroup(mse.groupId());
// Outdoor camera will not be displayed
if (mse.groupId() != BuildingGroup::OutdoorCameras)
{
if (m_availableBuildingGroups.contains(bse.id()) == false)
{
SimpleBuildingGroupData buildingGroup;
buildingGroup.name = QString::fromStdString(bse.displayName());
NGLTreeItem *groupItem = new NGLTreeItem(QVariant::fromValue(buildingGroup));
QModelIndex groupParentIndex;
groupParentIndex = indexFromItem(m_visRoot);
insertRow(rowCount(groupParentIndex), groupParentIndex, groupItem);
groupIndex = index(groupItem->row(), 0, groupParentIndex);
m_mountingPointIndexes.insert(bse.id(), groupIndex);
m_availableBuildingGroups.insert(bse.id());
}
else
{
groupIndex = m_mountingPointIndexes.value(bse.id(), indexFromItem(m_visRoot));
}
}
for (const StructureElement &currentElement : mse.elements())
{
NGLTreeItem *item;
if (currentElement.structureElementTypeId() == StructureElementType::MountingPoint)
{
const MountingPoint &mountingPoint = m_dataInterface->mountingPoint(currentElement.id());
if (!mountingPoint.isValid())
continue;
if (mountingPoint.type() == MountingPointType::Unknown ||
mountingPoint.type() == MountingPointType::BuildingControlUnit ||
mountingPoint.type() == MountingPointType::VirtualIPS ||
mountingPoint.type() == MountingPointType::MeteoDataUnit ||
mountingPoint.type() == MountingPointType::BuildingNetworkSwitch ||
mountingPoint.type() == MountingPointType::OutdoorCamera)
continue;
SimpleMountingPointData mpData;
mpData.seType = currentElement.structureElementTypeId();
mpData.id = mountingPoint.id();
mpData.name = mountingPoint.name();
mpData.aimState = mountingPoint.aimState();
mpData.mpType = mountingPoint.type();
mpData.floor = mountingPoint.floor();
// attention: getMountedAssetId could be expensive
// const int assetId = m_dtc->getMountedAssetId(mountingPoint.data().id());
// use already available mountingPoint instead: :-)
const int assetId = mountingPoint.associatedAssetId();
mpData.assetBarcode = QStringLiteral("-");
if(assetId != -1)
{
mpData.assetBarcode = QString::fromStdString(m_dtc->instrumentationAsset(assetId).barcode());
}
item = new NGLTreeItem(QVariant::fromValue(mpData));
}
else
{
SimpleStructureElementData ssed;
ssed.mseId = mse.id();
if (currentElement.structureElementTypeId() == StructureElementType::Floor)
ssed.floor = QString::fromStdString(currentElement.name()).split(QLatin1Literal("_")).value(1, QLatin1String("-10")).toInt();
else
ssed.floor = -20;
ssed.name = currentElement.displayName().empty() ? QString::fromStdString(currentElement.name()) : QString::fromStdString(currentElement.displayName());
item = new NGLTreeItem(QVariant::fromValue(ssed));
m_availableFloors << ssed.floor;
}
const auto &path = currentElement.path();
QModelIndex parentIndex;
if (path.size() > 1)
{
parentIndex = m_mountingPointIndexes.value(path.at(path.size() - 2), indexFromItem(m_visRoot)); //default sollte nie erreicht werden
if (!parentIndex.isValid())
{
ERROR_LOG(m_logger) << "Did not find parent for structure element with id " << currentElement.id() << " mseid: " << mse.id();
for (const StructureElement &se : mse.elements())
ERROR_LOG(m_logger) << " se: " << se.id() << ", " << se.displayName() << ", " << se.name();
}
}
else
{
// 2- Append building to it section index
if(groupIndex.isValid() == false)
{
parentIndex = indexFromItem(m_visRoot);
}
else
{
parentIndex = groupIndex;
}
}
insertRow(rowCount(parentIndex), parentIndex, item);
m_mountingPointIndexes.insert(currentElement.id(), index(item->row(), 0, parentIndex));
}
}
m_availableFloors << -10;
#ifdef BENCHMARK
qCritical() << " MountingPointListDialogModel::init-BENCHMARK: took " << elapsedTimer1.elapsed() << " [ms]";
#endif // BENCHMARK
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QSet<int> MountingPointListDialogModel::getAvailableFloors() const
{
return m_availableFloors;
}
StructureElement MountingPointListDialogModel::setBuildingGroup(int groupId)
{
StructureElement se{};
InfrastructureManagement::BuildingGroup_def::type buildingGroup = static_cast<InfrastructureManagement::BuildingGroup_def::type>(groupId);
if(buildingGroup == 0)
{
buildingGroup = InfrastructureManagement::BuildingGroup_def::UnknownGroup;
}
se.id() = maxIntValue - static_cast<int>(buildingGroup);
se.name() = InfrastructureManagement::toString(buildingGroup).toStdString();
se.displayName() = InfrastructureManagement::toString(buildingGroup).toStdString();
se.structureElementTypeId() = InfrastructureManagement::StructureElementType::Section;
return se;
}
Qt::ItemFlags MountingPointListDialogModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags fl = NGLTreeModel::flags(index);
if (!index.isValid())
return fl;
NGLTreeItem *item = privateData(index);
bool isLeaf = item->data().canConvert<SimpleMountingPointData>();
if (isLeaf && index.column() == Columns::NAME)
return fl | Qt::ItemIsUserCheckable | Qt::ItemIsUserTristate;
return fl;
}
bool MountingPointListDialogModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
// is called by the CheckboxProxyModel's setData method
if (index.column() != NAME || !index.isValid())
return NGLTreeModel::/**/setData(index, value, role);
auto lambda = [this, &value](const QModelIndex &idx)
{
NGLTreeItem *item = privateData(idx);
if (!item->data().canConvert<SimpleMountingPointData>()) // not a leaf?
{
Q_ASSERT(false); // CheckboxProxyModel never calls this model's setData if the index is not a leaf
/* we don't know what state the parent is, wo don't know how many children there REALLY are.
* all this is hidden behind multiple proxy models. so send a signal to the dialog,
* get the clicked parent's state and set all its (visible!) children.
* at least that's the plan .... */
return;
}
SimpleMountingPointData smpd = item->data().value<SimpleMountingPointData>();
smpd.aimState = (MountingPointState::inner_enum)value.toInt();
item->setData(QVariant::fromValue(smpd));
emit changesMade();
};
if (index.parent().isValid())
{
lambda(index);
}
else
{
for (const QModelIndex &idx : qAsConst(m_mountingPointIndexes))
lambda(idx);
}
m_dataChangedTimer->start(); // ugly hack
return true;
}
QVariant MountingPointListDialogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal
&& role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole
&& section == TYPE)
return m_cbxFilterType;
return BaseClass::headerData(section, orientation, role);
}
void MountingPointListDialogModel::setMntPointFilterTypes(QSet<MountingPointType> types)
{
LtsWidgets::ComboboxFilterContent cfc;
LtsWidgets::ComboboxFilterData cfd;
for (const auto es : qAsConst(types))
{
if (es == MountingPointType::OutdoorIPS)
continue;
cfd.data = es.underlying();
cfd.text = toString(es);
cfc.data.push_back(cfd);
// DEBUG_LOG(m_logger)<<" cfd.text: "<<cfd.text;
}
cfc.sortItems = true;
m_cbxFilterType = cfc.toVariant();
}
void MountingPointListDialogModel::onMountingPointChanged(const MountingPoint &mountingPoint, DataModification modType)
{
if (modType != DataModification::eModified)
return;
QModelIndex index = m_mountingPointIndexes.value(mountingPoint.id());
if (!index.isValid())
return;
NGLTreeItem *item = privateData(index);
if (!(item && item->data().canConvert<SimpleMountingPointData>()))
return;
SimpleMountingPointData mpData = item->data().value<SimpleMountingPointData>();
mpData.name = mountingPoint.name();
mpData.aimState = mountingPoint.aimState();
const int assetId = mountingPoint.associatedAssetId(); // (m_dtc->getMountedAssetId(mountingPoint.data().id());
mpData.assetBarcode = QStringLiteral("-");
mpData.floor = mountingPoint.floor();
if(assetId != -1)
{
mpData.assetBarcode = QString::fromStdString(m_dtc->instrumentationAsset(assetId).barcode());
}
item->setData(QVariant::fromValue(mpData));
m_dataChangedTimer->start();
}
void MountingPointListDialogModel::onScheduleIdChanged(int32_t scheduleId)
{
// is this unreachable code?
if (scheduleId == m_scheduleId)
return;
DEBUG_LOG(m_logger) << "onScheduleIdChanged: " << scheduleId;
m_scheduleId = scheduleId;
// !!! Maybe this is critical !!!
// !!! Maybe this is critical !!!
// !!! Maybe this is critical !!!
// m_dataInterface::setScheduleId will update the MountingPoints (aimState) according schedule!!!
m_dataInterface->setScheduleId(m_scheduleId);
initData();
}
void MountingPointListDialogModel::emitDataChanged()
{
QModelIndex vri = getIndexOfVisibleRootItem();
emit dataChanged(vri, index(rowCount(vri) -1, Columns::STATE, vri), {Qt::DisplayRole, Qt::CheckStateRole});
}
//
// MountingPointListSortModel
//
} // namespace InfrastructureManagement
@@ -0,0 +1,137 @@
/**
* @RDE_HEADER@
* The MountingPointListDialogModel provices data for MountingPointListDialog
* Modified version using the checkStateProxyModel to allow setting via the checkboxes of the tree structure hjl 5/19
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#pragma once
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
#include <QSet>
#include <nglwidgets/ngltreemodel.h>
#include <nglwidgets/ngltreeitem.h>
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <LtsWidgets/lts_column_filter_proxy_model.h>
#include <LtsDataView/check_state_proxy_model.h>
namespace InfrastructureManagement
{
struct SimpleMountingPointData
{
QString name;
int32_t id = 0; // StructureElementId
StructureElementType seType;
MountingPointType mpType;
MountingPointState aimState;
// int assetId; Chance to only reload assetBarcode, if assetId changes...
QString assetBarcode;
int32_t floor;
bool isMountingPoint() const { return seType == StructureElementType::MountingPoint; }
};
struct SimpleStructureElementData
{
int mseId;
QString name;
int floor;
};
struct SimpleBuildingGroupData
{
QString name;
};
class MountingPointListDialogModel final : public NGLTreeModel
{
Q_OBJECT
using BaseClass = NGLTreeModel;
public:
enum Columns
{
NAME,
TYPE,
ASSET_BARCODE,
STATE
};
explicit MountingPointListDialogModel(QObject *parent = nullptr);
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
/**
* Handles the representation of data.
* In case of CheckStateRole only leafs will be handled.
* Nodes are handled in the upstream CheckStateProxyModel class.
* @param[in] index item index to be handled
* @param[in] role role to which the data relates
*
*/
QVariant data(const QModelIndex &index, int role) const override final;
bool initModel(const std::shared_ptr<Interface::Dtc> &dtc, const std::shared_ptr<ForeignDataInterface> &dataInterface);
QModelIndex getIndexOfVisibleRootItem() const;
/**
* Sets only the leafs of the tree view to Qt::ItemIsUserCheckable.
* Nodes are handled in the upstream CheckStateProxyModel class.
* @param[in] index item index to be handled
*
*/
Qt::ItemFlags flags(const QModelIndex &index) const override final;
/**
* Sets the check state data according to their check box in the internal model.
* CheckState data can be set for leafs only.
* Nodes are handled in the upstream CheckStateProxyModel class.
* @param[in] index item index to be handled
* @param[in] value value to be set
* @param[in] role role to which the data relates (here especially Qt::CheckStateRole)
*
*/
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
void setMntPointFilterTypes(QSet<InfrastructureManagement::MountingPointType> types);
QSet<int> getAvailableFloors() const;
StructureElement setBuildingGroup(int groupId);
static const int maxIntValue = std::numeric_limits<int>::max();
signals:
void changesMade();
public slots:
void onMountingPointChanged(const MountingPoint &mountingPoint, DataModification modType);
private slots:
void onScheduleIdChanged(int32_t scheduleId);
void emitDataChanged();
private:
void initData();
friend class MountingPointListSortModel;
NGLTreeItem *m_visRoot;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> m_dataInterface;
int32_t m_scheduleId;
QHash<int, QModelIndex> m_mountingPointIndexes;
QTimer *m_dataChangedTimer{nullptr};
QSet<int> m_availableFloors;
QSet<int> m_availableBuildingGroups;
QVariant m_cbxFilterType;
LOGGER_T m_logger;
}; // class MountingPointListDialogModel
} // namespace InfrastructureManagement
Q_DECLARE_METATYPE(InfrastructureManagement::SimpleMountingPointData)
Q_DECLARE_METATYPE(InfrastructureManagement::SimpleStructureElementData)
Q_DECLARE_METATYPE(InfrastructureManagement::SimpleBuildingGroupData)
@@ -0,0 +1,102 @@
/**
* @RDE_HEADER@
* Class which adds single mounting points to the current schedule by id
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2017-04-06
*/
#include "ism_dds_selector.h"
#include <LtsUtilsCore/dds_vector.h>
#include <Plugins/InfrastructureManagement/Shared/ism_mounting_point.h>
#include <LtsWidgets/lts_message_dialog.h>
#include <QApplication>
using namespace InfrastructureManagement;
DdsSelector::DdsSelector(const std::shared_ptr<Interface::Dtc> &dtc, const std::shared_ptr<Interface::Ftc> &ftc, const std::shared_ptr<ForeignDataInterface> &ismDataIfc, LtsUtils::RequestHelper *requestHelper)
: MountingPointSelector(dtc, ftc, ismDataIfc, requestHelper, getLogger(QStringLiteral("DdsSelector")))
{
}
void DdsSelector::addMountingPoints(const QVector<int32_t> &mountingPointIds, const QMap<int32_t, MountingPointState> &states, QWidget *parentWidget)
{
if (mountingPointIds.isEmpty())
return;
Q_UNUSED(states)
std::vector<MountingPointPlan> modifyVec;
modifyVec.reserve(mountingPointIds.size());
MainSchedule mainSchedule = m_ismDataIfc->mainSchedule(m_ismDataIfc->scheduleId());
MountingPointState mps = m_ismDataIfc->mountingPoint(mountingPointIds.first()).aimState();
bool override = false;
for (int32_t currentMountingPointId : mountingPointIds)
{
MountingPoint mountingPoint = m_ismDataIfc->mountingPoint(currentMountingPointId);
if (!mountingPoint.isValid())
continue;
if (mountingPoint.aimState() == mps)
continue;
LtsWidgets::Button resButton = LtsWidgets::LtsMessageDialog::showMessage(parentWidget,
QApplication::translate("Ism::Selector", "Multiple selected components have different states.\nPlease select desired state"),
QApplication::translate("Ism::Selector", "Inconsistent component state"),
LtsWidgets::Behaviour::Modal,
LtsWidgets::Button::Yes | LtsWidgets::Button::No | LtsWidgets::Button::Discard,
{ {LtsWidgets::Button::Yes, QApplication::translate("Ism::Selector", "Equipped")},
{LtsWidgets::Button::No, QApplication::translate("Ism::Selector", "Empty")},
{LtsWidgets::Button::Discard, QApplication::translate("Ism::Selector", "Idle")}
});
switch(resButton)
{
case LtsWidgets::Button::Yes:
mps = MountingPointState::Equipped;
break;
case LtsWidgets::Button::No:
mps = MountingPointState::Empty;
break;
case LtsWidgets::Button::Discard:
default:
mps = MountingPointState::Idle;
break;
}
override = true;
break;
}
for (int32_t currentMountingPointId : mountingPointIds)
{
MountingPoint mountingPoint = m_ismDataIfc->mountingPoint(currentMountingPointId);
if (!mountingPoint.isValid())
continue;
MountingPointState aimState = override ? mps : mountingPoint.getNextMountingPointState(mountingPoint.aimState());
auto it = std::find_if(mainSchedule.elements().cbegin(), mainSchedule.elements().cend(), [currentMountingPointId](const MountingPointPlan &mpp){ return (mpp.structureElementId() == currentMountingPointId); });
if (it != mainSchedule.elements().cend())
{
if ((*it).mountingPointState() == aimState)
continue;
MountingPointPlan mpp = (*it);
mpp.mountingPointState() = aimState;
modifyVec.push_back(mpp);
}
else if (aimState != MountingPointState::Idle)
modifyVec.push_back(MountingPointPlan(currentMountingPointId,aimState));
}
if (!modifyVec.empty())
startModifyRequest(modifyVec);
}
@@ -0,0 +1,25 @@
/**
* @RDE_HEADER@
* Class which adds single mounting points to the current schedule by id
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2017-04-06
*/
#pragma once
#include "ism_selector.h"
namespace InfrastructureManagement
{
class DdsSelector
: public MountingPointSelector
{
public:
explicit DdsSelector(const std::shared_ptr<Interface::Dtc> &dtc, const std::shared_ptr<Interface::Ftc> &ftc, const std::shared_ptr<ForeignDataInterface> &ismDataIfc, LtsUtils::RequestHelper *requestHelper);
void addMountingPoints(const QVector<int32_t> &mountingPointIds, const QMap<int32_t, MountingPointState> &states, QWidget *parentWidget) override final;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,58 @@
/**
* @RDE_HEADER@
* Abstract class which defines selection behavior when clicking on mounting points on the map
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2017-04-05
*/
#include "ism_selector.h"
#include <LtsUtilsGuiDds/request_helper.h>
namespace InfrastructureManagement
{
MountingPointSelector::MountingPointSelector(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignDataInterface> &ismDataIfc,
LtsUtils::RequestHelper *requestHelper,
LOGGER_T logger)
: m_ismDataIfc(ismDataIfc)
, m_ftc(ftc)
, m_dtc(dtc)
, m_requestHelper(requestHelper)
, m_logger(logger)
{
if (!m_ftc->enableMountingPointPlanModify())
{
ERROR_LOG(m_logger) << "Could not enable FT MountingPointPlanModify of ISM";
}
}
void MountingPointSelector::onMountingPointPlanModifyReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
if (replyObject.error())
ERROR_LOG(m_logger) << "MountingPointPlansRemove error: "
<< replyObject.str();
else
DEBUG_LOG(m_logger) << "MountingPointPlansRemove success";
}
void MountingPointSelector::startModifyRequest(const std::vector<MountingPointPlan> &data)
{
if (data.empty())
return;
MountingPointPlanModifyRequest req(m_ismDataIfc->scheduleId(), data);
m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->mountingPointPlanModifyRequest(req, this);
});
}
}
@@ -0,0 +1,47 @@
/**
* @RDE_HEADER@
* Abstract class which defines selection behavior when clicking on mounting points on the map
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2017-04-05
*/
#pragma once
#include <InfrastructureManagement/ism_ftc.h>
#include <InfrastructureManagement/logger.h>
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <Plugins/InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
namespace LtsUtils
{
class RequestHelper;
}
namespace InfrastructureManagement
{
class MountingPointSelector
: public Interface::Ftc::MountingPointPlanModifyReplyHandler
{
public:
explicit MountingPointSelector(const std::shared_ptr<Interface::Dtc> &dtc, const std::shared_ptr<Interface::Ftc> &ftc, const std::shared_ptr<ForeignDataInterface> &ismDataIfc, LtsUtils::RequestHelper *requestHelper, LOGGER_T logger);
virtual ~MountingPointSelector() = default;
virtual void addMountingPoints(const QVector<int32_t> &mountingPointIds, const QMap<int32_t, MountingPointState> &states, QWidget *parentWidget) = 0;
void onMountingPointPlanModifyReply(const Core::FunctionReplyObject &replyObject) override final;
protected: //methods
void startModifyRequest(const std::vector<MountingPointPlan> &data);
protected: // attributes
std::shared_ptr<ForeignDataInterface> m_ismDataIfc;
std::shared_ptr<Interface::Ftc> m_ftc;
std::shared_ptr<Interface::Dtc> m_dtc;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,233 @@
/**
* @RDE_HEADER@
* The ConflictsDialog shows conflicts between 2 instrumentation plans
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLTE, 2022-11-15
*/
#include "ism_overview_conflicts_dialog.h"
#include "ui_ism_overview_conflicts_dialog.h"
#include "ism_overview_conflicts_model.h"
#include <InfrastructureManagement/ism_translation.h>
#include <LtsPrinting/printing.h>
#include <QMenu>
#include <QAction>
#include <QTreeView>
#include <QHeaderView>
#include <QScrollBar>
using namespace InfrastructureManagement;
ConflictsDialog::ConflictsDialog(const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkCancel)
, m_ui(new Ui::ConflictsDialog)
, m_sourceModel(nullptr)
, m_menuGroup(menuGroup)
, m_logger(getLogger("ConflictsDialog"))
{
m_ui->setupUi(this);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Conflicts"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &ConflictsDialog::onPrint);
}
ConflictsDialog::~ConflictsDialog()
{
if (m_sourceModel)
{
delete m_sourceModel;
m_sourceModel = nullptr;
}
delete m_ui;
}
void ConflictsDialog::retranslate()
{
QString plan1 = QString::fromStdString(m_dtc->mainSchedule(m_scheduleId).name());
QString plan2 = QString::fromStdString(m_dtc->mainSchedule(m_anotherScheduleId).name());
translate(m_ui, tr("Conflicts: %1 - %2").arg(plan1, plan2));
}
bool ConflictsDialog::init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
int scheduleId,
int anotherScheduleId)
{
m_session = session;
m_dtc = dtc;
m_scheduleId = scheduleId;
m_anotherScheduleId = anotherScheduleId;
if (m_scheduleId <= 0)
{
ERROR_LOG(m_logger) << "Invalid id for Instrumentation plan: " << m_scheduleId;
return false;
}
connect(m_dtc.get(), &Interface::Dtc::mainScheduleChanged, this, &ConflictsDialog::dataChanged);
m_sourceModel = new ConflictsDialogModel(this);
if (!m_sourceModel->initModel(m_scheduleId, m_anotherScheduleId, m_dtc))
{
ERROR_LOG(m_logger) << "Could not init ConflictsDialogModel";
delete m_sourceModel;
m_sourceModel = nullptr;
return false;
}
m_ui->dvConflicts->setModel(m_sourceModel);
m_ui->dvConflicts->setContextMenuPolicyPerView(LtsDataView::LtsDataView::Page::TABLE, Qt::CustomContextMenu);
connect(m_ui->dvConflicts->treeView(), &QTreeView::customContextMenuRequested,
this, &ConflictsDialog::onCustomContextMenu);
// show first tree level when activating the dialog
m_ui->dvConflicts->treeView()->expandToDepth(0);
m_ui->dvConflicts->treeView()->setColumnWidth(0, 400);
m_ui->dvConflicts->treeView()->setColumnWidth(1, 200);
m_ui->dvConflicts->treeView()->setColumnWidth(2, 200);
m_ui->dvConflicts->treeView()->setColumnWidth(3, 200);
m_ui->dvConflicts->searchView()->setColumnWidth(0, 400);
m_ui->dvConflicts->searchView()->setColumnWidth(1, 200);
m_ui->dvConflicts->searchView()->setColumnWidth(2, 200);
m_ui->dvConflicts->searchView()->setColumnWidth(3, 200);
connect(m_ui->dvConflicts->searchView()->horizontalScrollBar(), &QScrollBar::rangeChanged,
this, [this]()
{
m_ui->dvConflicts->slotSetHorizontalRange(0,0);
}, Qt::QueuedConnection);
connect(m_ui->dvConflicts->treeView()->horizontalScrollBar(), &QScrollBar::rangeChanged,
this, [this]()
{
m_ui->dvConflicts->slotSetHorizontalRange(0,0);
}, Qt::QueuedConnection);
m_ui->dvConflicts->treeView()->expandAll();
return true;
}
void ConflictsDialog::updateModel()
{
if(m_sourceModel)
{
m_sourceModel->onConflictedDataChanged();
m_ui->dvConflicts->treeView()->expandAll();
}
}
void ConflictsDialog::dataChanged(const InfrastructureManagement::MainSchedule &data, DataModification modType)
{
Q_UNUSED(modType);
if (data.id() == m_scheduleId)
m_sourceModel->initModel(m_scheduleId, m_anotherScheduleId, m_dtc);
}
void ConflictsDialog::tableColumnOrganiserSetting()
{
//LtsColumnOrganiser
m_ui->dvConflicts->setColumnsOrganiserEnabled(identifier(), true);
}
void ConflictsDialog::onPrint()
{
MainSchedule plan1 = m_dtc->mainSchedule(m_scheduleId);
MainSchedule plan2 = m_dtc->mainSchedule(m_anotherScheduleId);
m_ui->dvConflicts->treeView()->expandAll();
QString header;
header += QStringLiteral("<p>");
header += QStringLiteral("<b>") + tr("Overview Conflicts") + QStringLiteral("</b>");
header += QStringLiteral("<hr/>");
header += tr("Current Instrumentation Plan: %1").arg(QString::fromStdString(plan1.name()));
header += QStringLiteral(" - ");
if (plan1.timeStart().is_set())
header += tr("START: %1").arg(DTG::toStringMSec(plan1.timeStart().get()));
else
header += tr("START: %1").arg(tr("[N/A]"));
header += QStringLiteral(" - ");
if (plan1.timeEnd().is_set())
header += tr("END: %1").arg(DTG::toStringMSec(plan1.timeEnd().get()));
else
header += tr("END: %1").arg(tr("[N/A]"));
header += QStringLiteral("<br/>");
header += tr("Compared Instrumentation Plan: %1").arg(QString::fromStdString(plan2.name()));
header += QStringLiteral(" - ");
if (plan2.timeStart().is_set())
header += tr("START: %1").arg(DTG::toStringMSec(plan2.timeStart().get()));
else
header += tr("START: %1").arg(tr("[N/A]"));
header += QStringLiteral(" - ");
if (plan2.timeEnd().is_set())
header += tr("END: %1").arg(DTG::toStringMSec(plan2.timeEnd().get()));
else
header += tr("END: %1").arg(tr("[N/A]"));
header += QStringLiteral("<br/>");
header += QStringLiteral("</p>");
LtsPrinting::printView(m_session, this, m_ui->dvConflicts->treeView(), header);
}
void ConflictsDialog::onCustomContextMenu(QPoint pos)
{
QMenu *contextMenu = new QMenu(this);
contextMenu->setAttribute(Qt::WA_DeleteOnClose);
{
QAction *action = new QAction(tr("Expand All"), this);
action->setEnabled(true);
connect(action, &QAction::triggered, this, [this]()
{
m_ui->dvConflicts->expandAll();
});
contextMenu->addAction(action);
}
{
QAction *action = new QAction(tr("Collapse All"), this);
action->setEnabled(true);
connect(action, &QAction::triggered, this, [this]()
{
m_ui->dvConflicts->collapseAll();
});
contextMenu->addAction(action);
}
contextMenu->addSeparator();
QModelIndex index = m_ui->dvConflicts->treeView()->indexAt(pos);
bool hasChildren = m_ui->dvConflicts->treeView()->model()->rowCount(index) > 0;
{
QAction *action = new QAction(tr("Expand"), this);
action->setEnabled(hasChildren);
connect(action, &QAction::triggered, this, [this, index]()
{
#if QT_VERSION < QT_VERSION_CHECK(5,13,0)
m_ui->dvConflicts->treeView()->expand(index);
#else
m_ui->dvConflicts->treeView()->expandRecursively(index);
#endif
});
contextMenu->addAction(action);
}
{
QAction *action = new QAction(tr("Collapse"), this);
action->setEnabled(hasChildren);
connect(action, &QAction::triggered, this, [this, index]()
{
m_ui->dvConflicts->treeView()->collapse(index);
});
contextMenu->addAction(action);
}
contextMenu->popup(m_ui->dvConflicts->treeView()->mapToGlobal(pos));
}
@@ -0,0 +1,64 @@
/**
* @RDE_HEADER@
* The ConflictsDialog shows differences between 2 instrumentation plans
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLTE, 2022-11-15
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
namespace Ui
{
class ConflictsDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
class ConflictsDialogModel;
class ConflictsDialog final
: public LtsWidgets::LtsDialog
{
Q_OBJECT
public:
explicit ConflictsDialog(const QString &menuGroup, QWidget *parent = nullptr);
~ConflictsDialog();
bool init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
int scheduleId,
int anotherScheduleId);
void updateModel();
private: // methods
void retranslate() override;
void dataChanged(const InfrastructureManagement::MainSchedule &data, DataModification modType);
void tableColumnOrganiserSetting() override;
private slots:
void onPrint();
void onCustomContextMenu(QPoint pos);
private: // attributes
Ui::ConflictsDialog *m_ui{nullptr};
ConflictsDialogModel *m_sourceModel{nullptr};
std::shared_ptr<Interface::Dtc> m_dtc{nullptr};
QString m_menuGroup;
LtsSession::LtsSession *m_session{nullptr};
int m_scheduleId{-1};
int m_anotherScheduleId{-1};
LOGGER_T m_logger;
}; // class ConflictsDialog
} // namespace InfrastructureManagement
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConflictsDialog</class>
<widget class="QWidget" name="ConflictsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1169</width>
<height>517</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Differences</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="LtsDataView::LtsDataView" name="dvConflicts" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="rootIsDecorated" stdset="0">
<bool>true</bool>
</property>
<property name="showColumnCount" stdset="0">
<bool>false</bool>
</property>
<property name="toolButtonsVisible" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,388 @@
/**
* @RDE_HEADER@
* The ConflictsDialog shows differences between 2 instrumentation plans
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLTE, 2022-11-15
*/
#include "ism_overview_conflicts_model.h"
#include <InfrastructureManagement/ism_translation.h>
#include <QDebug>
#include <QElapsedTimer>
// #define BENCHMARK
#ifdef BENCHMARK
# include <QElapsedTimer>
# include <QDebug>
#endif
static const int maxIntValue = std::numeric_limits<int>::max();
namespace InfrastructureManagement
{
ConflictsDialogModel::ConflictsDialogModel(QObject *parent)
: NGLTreeModel(parent, new NGLTreeItem(QVariant()), { tr("Name"), tr("Type"), tr("Aim State"), tr("Conflict State") })
, m_dtc(nullptr)
, m_scheduleId(-1)
, m_anotherScheduleId(-1)
, m_logger(getLogger("OverviewConflictsDialogModel"))
{
}
QVariant ConflictsDialogModel::data(const QModelIndex &index, int role) const
{
if ( !index.isValid() && (role == Qt::DisplayRole || role == Qt::DecorationRole) )
return QVariant();
NGLTreeItem *item = privateData(index);
if (role == Qt::DisplayRole)
{
if (index.column() != NAME && !item->data().canConvert<ConflictMountingPointData>())
return QVariant();
const ConflictMountingPointData itemData = item->data().value<ConflictMountingPointData>();
switch (index.column())
{
case NAME:
if (item->data().canConvert<ConflictMountingPointData>())
return item->data().value<ConflictMountingPointData>().name;
if (item->data().canConvert<ConflictStructureElementData>())
return item->data().value<ConflictStructureElementData>().name;
return tr("all");
case AIM_STATE:
if (itemData.seType == StructureElementType::MountingPoint)
return toString(itemData.aimState);
break;
case CONFLICT_STATE:
if (itemData.seType == StructureElementType::MountingPoint)
return toString(itemData.conflictState);
break;
case TYPE:
if (itemData.seType == StructureElementType::MountingPoint)
{
const MountingPointType mpt = itemData.mpType == MountingPointType::OutdoorIPS ? MountingPointType::IndoorIPS : itemData.mpType;
return toString(mpt);
}
break;
}
}
if (role == Qt::DecorationRole)
{
if (!item->data().canConvert<ConflictMountingPointData>())
return QVariant();
const ConflictMountingPointData itemData = item->data().value<ConflictMountingPointData>();
static const QIcon green(QLatin1String("icon:green_light.svg"));
static const QIcon red(QLatin1String("icon:red_light.svg"));
switch (index.column())
{
case AIM_STATE:
{
return itemData.aimState == MountingPointState_def::Equipped ? green : red;
}
case CONFLICT_STATE:
{
return itemData.conflictState == MountingPointState_def::Equipped ? green : red;
}
default:
return QVariant();
}
}
return QVariant();
}
QVariant ConflictsDialogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
{
QString plan1 = QString::fromStdString(m_dtc->mainSchedule(m_scheduleId).name());
QString plan2 = QString::fromStdString(m_dtc->mainSchedule(m_anotherScheduleId).name());
Columns col = static_cast<Columns>(section);
switch (col)
{
case NAME:
return tr("Name");
case TYPE:
return tr("Type");
case AIM_STATE:
return tr("Aim State (%1)").arg(plan1);
case CONFLICT_STATE:
return tr("Conflict State (%1)").arg(plan2);
}
}
return NGLTreeModel::headerData(section, orientation, role);
}
bool ConflictsDialogModel::initModel(int scheduleId,
int anotherScheduleId,
const std::shared_ptr<Interface::Dtc> &dtc)
{
if (m_dtc == dtc) //already initialized...
return true;
if (!(dtc->enableMainStructureElement() &&
dtc->enableMainSchedule()))
{
ERROR_LOG(m_logger) << "Could not enable Data Topics";
return false;
}
/* Stand 2022.11.16
struct MountingPointType_def {
enum type {
Unknown = 0,
BuildingSensorModule = 1,
BuildingControlUnit = 2,
OutdoorCamera = 3,
IndoorCamera = 4,
OutdoorIPS = 5,
IndoorIPS = 6,
MeteoDataUnit = 7,
AnnouncementUnit = 10,
VirtualIPS = 11,
EffectGenerationControlUnit = 12,
OutdoorControlUnit = 13,
BuildingNetworkSwitch = 14
};
*/
// same as filters in Mounting Points Dialog (ism_mounting_point_list_dialog.cpp:196)?
m_visibleTypes = { MountingPointType_def::BuildingSensorModule,
// MountingPointType_def::OutdoorCamera,
MountingPointType_def::IndoorCamera,
MountingPointType_def::OutdoorIPS,
MountingPointType_def::IndoorIPS,
MountingPointType_def::EffectGenerationControlUnit
};
m_dtc = dtc;
m_scheduleId = scheduleId;
m_anotherScheduleId = anotherScheduleId;
initData();
beginResetModel();
endResetModel();
return true;
}
StructureElement ConflictsDialogModel::setBuildingGroup(int groupId)
{
StructureElement se;
BuildingGroup_def::type buildingGroup = static_cast<BuildingGroup_def::type>(groupId);
se.id() = maxIntValue - static_cast<int>(buildingGroup);
se.name() = InfrastructureManagement::toString(buildingGroup).toStdString();
se.displayName() = InfrastructureManagement::toString(buildingGroup).toStdString();
se.structureElementTypeId() = StructureElementType_def::Section;
return se;
}
void ConflictsDialogModel::onConflictedDataChanged()
{
if(m_rootItem)
initData();
}
void ConflictsDialogModel::initData()
{
NGLTreeModel::resetModel();
m_availableBuildingGroups.clear();
m_mountingPointIndexes.clear();
QHash<int /*<structureElementId>*/, MountingPointPlan> currentMountingPoints;
QHash<int /*<structureElementId>*/, MountingPointPlan> compareMountingPoints;
QHash<int/*<mse.id>*/, InfrastructureManagement::MainStructureElement> conflictedMainStructElements;
QSet<int> conflictedStructElIds;
#ifdef BENCHMARK
QElapsedTimer elapsedTimer1;
QElapsedTimer elapsedTimer2;
elapsedTimer1.start();
elapsedTimer2.start();
#endif // BENCHMARK
// Plan 1
InfrastructureManagement::MainSchedule currentSchedule = m_dtc->mainSchedule(m_scheduleId);
for (const InfrastructureManagement::MountingPointPlan &currentPlan : currentSchedule.elements())
{
StructureElement se;
if (!m_dtc->getStructureElementById(currentPlan.structureElementId(), se))
continue;
if (m_visibleTypes.contains(se.mountingPointTypeId()))
currentMountingPoints.insert(currentPlan.structureElementId(), currentPlan);
}
// Plan 2
InfrastructureManagement::MainSchedule compareSchedule = m_dtc->mainSchedule(m_anotherScheduleId);
for (const InfrastructureManagement::MountingPointPlan &comparePlan : compareSchedule.elements())
{
if (!currentMountingPoints.contains(comparePlan.structureElementId()))
continue;
StructureElement structEl;
if (!m_dtc->getStructureElementById(comparePlan.structureElementId(), structEl))
continue;
if (!m_visibleTypes.contains(structEl.mountingPointTypeId()))
continue;
// calculate final state for this MP, except conflicts
// p1 | p2 | final
// equipped equipped +1
// equipped idle +1
// idle equipped +1
// empty empty 0
// idle idle 0
// empty idle 0
// idle empty 0
// equipped empty - conflict
// empty equipped - conflict
const MountingPointPlan &mp1 = currentMountingPoints[comparePlan.structureElementId()];
if ((mp1.mountingPointState() == MountingPointState::Equipped && comparePlan.mountingPointState() == MountingPointState::Empty) ||
(mp1.mountingPointState() == MountingPointState::Empty && comparePlan.mountingPointState() == MountingPointState::Equipped))
{
compareMountingPoints.insert(comparePlan.structureElementId(), comparePlan);
StructureElement se;
// get mounting point path: (building id, floor id, room id)
if (!m_dtc->getStructureElementById(comparePlan.structureElementId(), se))
continue;
const std::vector<int> &path = se.path();
for(const auto &seId : path)
conflictedStructElIds.insert(seId);
if(conflictedMainStructElements.contains(se.mainStructureElementId()))
continue;
const MainStructureElement &mse = m_dtc->mainStructureElement(se.mainStructureElementId());
conflictedMainStructElements.insert(mse.id(), mse);
}// end if currentMountingPoint contains cmp mounting point plan
}
#ifdef BENCHMARK
qCritical() << " OverviewDialogModel::initData-BENCHMARK: compareSchedule took " << elapsedTimer1.elapsed() << " [ms]";
#endif // BENCHMARK
for (const MainStructureElement &mse : conflictedMainStructElements)
{
// only consider buildings
if (mse.structureElementTypeId() != StructureElementType::Building)
continue;
// 1- if a buildingGroup modelIndex for current building doesn't exist
// a new one will be first added and used as parentIndex for the blg_Index.
QModelIndex groupIndex;
const StructureElement bse = setBuildingGroup(mse.groupId());
if(!m_availableBuildingGroups.contains(bse.id()))
{
ConflictStructureElementData buildingGroup;
buildingGroup.name = QString::fromStdString(bse.displayName());
NGLTreeItem *groupItem = new NGLTreeItem(QVariant::fromValue(buildingGroup));
QModelIndex groupParentIndex;
groupParentIndex = indexFromItem(m_rootItem);
insertRow(rowCount(groupParentIndex), groupParentIndex, groupItem);
groupIndex = index(groupItem->row(), 0, groupParentIndex);
m_mountingPointIndexes.insert(bse.id(), groupIndex);
m_availableBuildingGroups.insert(bse.id());
}
else
{
groupIndex = m_mountingPointIndexes.value(bse.id(), indexFromItem(m_rootItem));
}
for (const StructureElement &currentElement : mse.elements())
{
NGLTreeItem *item = nullptr;
if (!conflictedStructElIds.contains(currentElement.id()))
continue;
if (currentElement.structureElementTypeId() == StructureElementType::MountingPoint)
{
if (!currentMountingPoints.contains(currentElement.id()))
continue;
const MountingPointPlan &mountingPoint = currentMountingPoints[currentElement.id()];
// we don't care about Idle items
if (mountingPoint.mountingPointState() == MountingPointState::Idle)
continue;
auto compareMountingPointState = compareMountingPoints.value(currentElement.id()).mountingPointState();
if (mountingPoint.mountingPointState() == compareMountingPointState)
{
DEBUG_LOG(m_logger) << "No conflict for mounting point id = " << currentElement.id() << " - " << currentElement.name();
continue;
}
ConflictMountingPointData mpData;
mpData.seType = currentElement.structureElementTypeId();
mpData.id = currentElement.id();
mpData.name = currentElement.displayName().empty() ? QString::fromStdString(currentElement.name()) : QString::fromStdString(currentElement.displayName());
mpData.aimState = mountingPoint.mountingPointState();
mpData.conflictState = compareMountingPointState;
mpData.mpType = currentElement.mountingPointTypeId();
DEBUG_LOG(m_logger) << "## MP Id = " << mpData.id;
DEBUG_LOG(m_logger) << "## MP Name = " << mpData.name;
DEBUG_LOG(m_logger) << "## Aim state = " << mpData.aimState;
DEBUG_LOG(m_logger) << "Adding mounting point id = " << mpData.id << " - " << mpData.name;
item = new NGLTreeItem(QVariant::fromValue(mpData));
}
else
{
ConflictStructureElementData ssed;
ssed.name = currentElement.displayName().empty() ? QString::fromStdString(currentElement.name()) : QString::fromStdString(currentElement.displayName());
item = new NGLTreeItem(QVariant::fromValue(ssed));
}
const auto &path = currentElement.path();
QModelIndex parentIndex;
if (path.size() > 1)
{
parentIndex = m_mountingPointIndexes.value(path.at(path.size() - 2), indexFromItem(m_rootItem)); //default sollte nie erreicht werden
if (!parentIndex.isValid())
{
DEBUG_LOG(m_logger) << "Did not find parent for structure element with id " << currentElement.id() << " mseid: " << mse.id();
for (const StructureElement &se : mse.elements())
DEBUG_LOG(m_logger) << " se: " << se.id() << ", " << se.displayName() << ", " << se.name();
}
}
else
{
// Isn't indexFrom RootItem == QModelIndex() ?!?
parentIndex = groupIndex.isValid() ? groupIndex : indexFromItem(m_rootItem);
DEBUG_LOG(m_logger) << "Insert row under root: " << currentElement.displayName();
}
insertRow(rowCount(parentIndex), parentIndex, item);
m_mountingPointIndexes.insert(currentElement.id(), index(item->row(), 0, parentIndex));
}//end for-loop over conflicted structureelements
} //end for-loop over conflicted mainstructureelements
#ifdef BENCHMARK
qCritical() << " OverviewDialogModel::initData-BENCHMARK: initData took " << elapsedTimer2.elapsed() << " [ms]";
#endif // BENCHMARK
}
}// namespace InfrastructureManagement
@@ -0,0 +1,124 @@
/**
* @RDE_HEADER@
* The ConflictsDialog shows differences between 2 instrumentation plans
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLTE, 2022-11-15
*/
#pragma once
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
#include <nglwidgets/ngltreemodel.h>
#include <nglwidgets/ngltreeitem.h>
#include <LtsWidgets/lts_column_filter_proxy_model.h>
#include <QSet>
#include <QList>
#include <QHash>
#include <QTimer>
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
struct ConflictMountingPointData
{
int32_t id = 0; // se_id
QString name; // se_name
StructureElementType seType;
MountingPointType mpType;
MountingPointState aimState; // in Plan1 (m_scheduleId)
MountingPointState conflictState; // in Plan2 (m_anotherScheduleId)
bool isMountingPoint() const { return seType == StructureElementType::MountingPoint; }
};
struct ConflictBuildingGroupData
{
QString name;
};
struct ConflictStructureElementData
{
QString name;
};
class ConflictsDialogModel final : public NGLTreeModel
{
Q_OBJECT
public:
public:
enum Columns
{
NAME,
TYPE,
AIM_STATE,
CONFLICT_STATE
};
explicit ConflictsDialogModel(QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role) const override final;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
bool initModel(int scheduleId, int anotherScheduleId,
const std::shared_ptr<Interface::Dtc> &dtc);
StructureElement setBuildingGroup(int groupId);
public slots:
void onConflictedDataChanged();
private:
void initData();
// friend class ConflictsDialogSortModel;
std::shared_ptr<Interface::Dtc> m_dtc;
int32_t m_scheduleId;
int32_t m_anotherScheduleId;
QHash<int, QModelIndex> m_mountingPointIndexes;
QSet<int> m_availableBuildingGroups;
QList<MountingPointType> m_visibleTypes;
LOGGER_T m_logger;
};
/*
class ConflictsDialogSortModel final : public LtsWidgets::LtsColumnFilterProxyModel
{
using BaseClass = LtsWidgets::LtsColumnFilterProxyModel;
Q_OBJECT
public:
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
void setSourceModel(QAbstractItemModel *sourceModel ) override;
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
//QList<MountingPointType> getVisibleTypes() { return m_visibleTypes ;}
//using LtsWidgets::LtsColumnFilterProxyModel::invalidateFilter;
private:
ConflictsDialogModel *m_sourceModel = nullptr;
QList<MountingPointType> m_visibleTypes;
};
*/
} // namespace InfrastructureManagement
Q_DECLARE_METATYPE(InfrastructureManagement::ConflictMountingPointData)
Q_DECLARE_METATYPE(InfrastructureManagement::ConflictStructureElementData)
Q_DECLARE_METATYPE(InfrastructureManagement::ConflictBuildingGroupData)
@@ -0,0 +1,231 @@
/**
* @RDE_HEADER@
* The OverviewDialog shows how many assets are needed for a specific schedule, needed elsewhere,
* totally possessed, free, and missing
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#include "ism_overview_dialog.h"
#include "ism_overview_conflicts_dialog.h"
#include "ui_ism_overview_dialog.h"
#include "ism_overview_dialog_model.h"
#include "ism_overview_conflicts_dialog.h"
#include <ngltools/ngltools_dtg.h>
#include <InfrastructureManagement/ism_translation.h>
#include <LtsSession/lts_session.h>
#include <LtsPrinting/printing.h>
#include <LtsWidgets/lts_base_layout_widget.h>
#include <QTreeView>
#include <QDateTime>
#include <QComboBox>
#include <QTimer>
namespace InfrastructureManagement
{
OverviewDialog::OverviewDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_session(session)
, m_ui(new Ui::OverviewDialog)
, m_menuGroup(menuGroup)
, m_logger(getLogger("OverviewDialog"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_ui->setupUi(this);
m_timerUpdateView = new QTimer(this);
m_timerUpdateView->setSingleShot(true);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &OverviewDialog::onPrint);
connect(m_ui->cbComparePlan, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &OverviewDialog::onCbComparePlanIndexChanged);
connect(m_ui->cbBasePlan, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &OverviewDialog::onCbBasePlanIndexChanged);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Overview"));
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
OverviewDialog::~OverviewDialog()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_ui;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void OverviewDialog::aboutToClose()
{
DEBUG_LOG(m_logger) << "About to close";
if (m_session->baseLayout()->getWidget(m_menuGroup, QStringLiteral("OverviewConflicts")))
m_session->baseLayout()->getWidget(m_menuGroup, QStringLiteral("OverviewConflicts"))->closeRequest();
}
void OverviewDialog::retranslate()
{
translate(m_ui, m_dtc->mainSchedule(m_scheduleId), tr("Overview"));
}
void OverviewDialog::tableColumnOrganiserSetting()
{
//LtsColumnOrganiser
m_ui->overviewView->setColumnsOrganiserEnabled(identifier(), true);
}
bool OverviewDialog::init(int planId,
const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignDataInterface> &dataInterface)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_scheduleId = planId;
m_dtc = dtc;
m_ftc = ftc;
m_dataIfc = dataInterface;
delete m_model;
setCbComparePlan();
setCbBasePlan();
m_model = new OverviewDialogModel(this);
if (!m_model->initModel(m_scheduleId, m_dtc, 0))
{
delete m_model;
m_model = nullptr;
return false;
}
m_ui->overviewView->setModel(m_model);
connect(m_dataIfc.get(), &ForeignDataInterface::scheduleIdChanged, this, &OverviewDialog::onScheduleIdChanged);
connect(m_dtc.get(), &Interface::Dtc::mainStructureElementChanged, this, &OverviewDialog::onPlansDataChanged);
connect(m_dtc.get(), &Interface::Dtc::instrumentationAssetChanged, this, &OverviewDialog::onPlansDataChanged);
connect(m_dtc.get(), &Interface::Dtc::mainScheduleChanged, this, &OverviewDialog::onPlansDataChanged);
connect(m_timerUpdateView, &QTimer::timeout, this, &OverviewDialog::reloadModel);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void OverviewDialog::setCbBasePlan()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_ui->cbBasePlan->clear();
m_ui->cbBasePlan->addItem(tr("Actual Mountings"), 0);
m_ui->cbBasePlan->insertSeparator(1);
for (auto ms : m_dtc->mainSchedules())
m_ui->cbBasePlan->addItem(QString::fromStdString(ms.name()), ms.id());
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void OverviewDialog::setCbComparePlan()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_ui->cbComparePlan->clear();
m_ui->cbComparePlan->addItem(tr("All active(*) plans"),0);
m_ui->cbComparePlan->insertSeparator(1);
for (auto ms : m_dtc->mainSchedules())
m_ui->cbComparePlan->addItem((ms.statusId() == ScheduleStatus_def::Active ? QLatin1Literal("* ") : QLatin1Literal(" ")) +
QString::fromStdString(ms.name()), ms.id());
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void OverviewDialog::onPrint()
{
MainSchedule ms = m_dtc->mainSchedule(m_scheduleId);
QString header;
header += QStringLiteral("<p>");
header += tr("Instrumentation Plan: %1").arg(QString::fromStdString(ms.name()));
header += QStringLiteral("<br/>");
header += tr("Status: %1").arg(toString(ms.statusId()));
header += QStringLiteral("<br/>");
header += tr("Created: %1").arg(DTG::toStringMSec(ms.timeCreated()));
header += QStringLiteral("<br/>");
if (ms.timeStart().is_set())
header += tr("START: %1").arg(DTG::toStringMSec(ms.timeStart().get()));
else
header += tr("START: %1").arg(tr("[N/A]"));
header += QStringLiteral(" - ");
if (ms.timeEnd().is_set())
header += tr("END: %1").arg(DTG::toStringMSec(ms.timeEnd().get()));
else
header += tr("END: %1").arg(tr("[N/A]"));
header += QStringLiteral("<br/>");
header += QStringLiteral("</p>");
LtsPrinting::printView(m_session, this, m_ui->overviewView->treeView() , header);
}
void OverviewDialog::onScheduleIdChanged(int32_t scheduleId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_scheduleId == scheduleId)
return;
setCbComparePlan();
setCbBasePlan();
m_scheduleId = scheduleId;
updateOverviewData();
// close Dialog OverviewConflicts, if open
if (m_session->baseLayout()->getWidget(m_menuGroup, QStringLiteral("OverviewConflicts")))
m_session->baseLayout()->getWidget(m_menuGroup, QStringLiteral("OverviewConflicts"))->closeRequest();
retranslate();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void OverviewDialog::onCbComparePlanIndexChanged(int index)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
Q_UNUSED(index);
updateOverviewData();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void OverviewDialog::onCbBasePlanIndexChanged(int index)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
Q_UNUSED(index);
updateOverviewData();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void OverviewDialog::onPlansDataChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
updateOverviewData(); //reloadModel();
ConflictsDialog *dialog = static_cast<ConflictsDialog*>(m_session->baseLayout()->getWidget(m_menuGroup, QStringLiteral("OverviewConflicts")));
if (dialog)
{
dialog->updateModel();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void OverviewDialog::updateOverviewData()
{
m_timerUpdateView->start(100);
}
void OverviewDialog::reloadModel()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_model == nullptr)
return;
const int simPlanId = m_ui->cbBasePlan->currentData().toInt();
const int cmpPlanId = m_ui->cbComparePlan->currentData().toInt();
m_model->initModel(m_scheduleId, m_dtc, cmpPlanId, simPlanId);
// close conflict dialog if opened
if (m_session->baseLayout()->getWidget(m_menuGroup, QStringLiteral("OverviewConflicts")))
m_session->baseLayout()->getWidget(m_menuGroup, QStringLiteral("OverviewConflicts"))->closeRequest();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
} // namespace InfrastructureManagement
@@ -0,0 +1,77 @@
/**
* @RDE_HEADER@
* The OverviewDialog shows how many assets are needed for a specific schedule, needed elsewhere,
* totally possessed, free, and missing
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <Plugins/InfrastructureManagement/Data/ism_data_plugin.h>
#include <InfrastructureManagement/logger.h>
#include <Plugins/InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
namespace Ui
{
class OverviewDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
class OverviewDialogModel;
class OverviewDialog
: public LtsWidgets::LtsDialog
{
Q_OBJECT
public:
explicit OverviewDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
~OverviewDialog();
bool init(int planId,
const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignDataInterface> &dataInterface);
void setCbComparePlan();
void setCbBasePlan();
protected:
void aboutToClose() override;
private slots:
void onPrint();
void onScheduleIdChanged(int32_t scheduleId);
void onCbComparePlanIndexChanged(int index);
void onCbBasePlanIndexChanged(int index);
void onPlansDataChanged();
void updateOverviewData();
void reloadModel();
private:
void retranslate() override;
void tableColumnOrganiserSetting() override;
LtsSession::LtsSession *m_session{nullptr};
Ui::OverviewDialog *m_ui{nullptr};
int m_scheduleId{-1};
OverviewDialogModel *m_model{nullptr};
QString m_menuGroup;
std::shared_ptr<Interface::Dtc> m_dtc{nullptr};
std::shared_ptr<Interface::Ftc> m_ftc{nullptr};
std::shared_ptr<ForeignDataInterface> m_dataIfc{nullptr};
ForeignResourceManagementGuiInterface *m_ismGuiIfc{nullptr};
QTimer *m_timerUpdateView{nullptr};
LOGGER_T m_logger;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OverviewDialog</class>
<widget class="QWidget" name="OverviewDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>630</width>
<height>328</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Asset Availability</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="lbxBasePlan">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Base Plan:</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsComboBox" name="cbBasePlan"/>
</item>
<item>
<widget class="QLabel" name="lbxComparePlan">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Plan to compare:</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsComboBox" name="cbComparePlan"/>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="LtsDataView::LtsDataView" name="overviewView" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,466 @@
/**
* @RDE_HEADER@
* The OverviewDialogModel provides data for OverviewDialog
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#include "ism_overview_dialog_model.h"
#include <InfrastructureManagement/Shared/ism_mounting_point.h>
#include <InfrastructureManagement/ism_translation.h>
#include <algorithm>
//#define BENCHMARK
#ifdef BENCHMARK
# include <QElapsedTimer>
# include <QDebug>
#endif
namespace InfrastructureManagement
{
OverviewDialogModel::OverviewDialogModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<RowData>( {tr("Type"),
tr("Base Demand"),
tr("Compare Demand"),
tr("Total Demand"),
tr("Assets"),
tr("Free assets"),
tr("Available")
},
parent)
, m_loadedScheduleId(-1)
, m_comparedScheduleId(0)
, m_dtc(nullptr)
, m_logger(getLogger("OverviewDialogModel"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
//#define TEST
m_vecData = {RowData(MountingPointType::BuildingSensorModule),
RowData(MountingPointType::EffectGenerationControlUnit),
#ifdef TEST
MountingPointType::BuildingControlUnit,
MountingPointType::BuildingNetworkSwitch,
MountingPointType::OutdoorCamera,
MountingPointType::OutdoorControlUnit,
MountingPointType::OutdoorIPS,
MountingPointType::AnnouncementUnit,
#endif
RowData(MountingPointType::IndoorCamera),
RowData(MountingPointType::IndoorIPS)}; //TODO: for Guez add OutdoorIPS, for non-Guez show separate!
m_refMap[MountingPointType_def::BuildingSensorModule] = 0;
m_refMap[MountingPointType_def::EffectGenerationControlUnit] = 1;
m_refMap[MountingPointType_def::IndoorCamera] = 2;
m_refMap[MountingPointType_def::IndoorIPS] = 3;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QVariant OverviewDialogModel::data(const QModelIndex &index, int role) const
{
if (!indexIsValid(index))
return {};
const auto &rowData = m_vecData.at(index.row());
// If we want to display OutdoorIPS (as IndoorIPS) (later), we need to remove this and chnage mpt to IndoorIPS...
if (rowData.mpt == MountingPointType::OutdoorIPS)
return {};
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case TYPE:
return toString(rowData.mpt);
case BASEPLAN_DEMAND:
return rowData.basePlanDemand;
case COMPARED_DEMAND:
return rowData.comparePlanDemand;
case TOTAL_DEMAND:
return rowData.totalDemand;
case ASSETS_OWNED:
return rowData.assetCount;
case ASSETS_FREE:
return rowData.assetsFree;
case ASSETS_AVAILABLE:
return rowData.assetsAvailable;
default:
return {};
}
}
else if (role == Qt::DecorationRole)
{
static const QIcon green(QLatin1String("icon:green_light.svg"));
static const QIcon red(QLatin1String("icon:red_light.svg"));
static const QIcon yellow(QLatin1String("icon:yellow_light.svg"));
switch (index.column())
{
case ASSETS_AVAILABLE:
{
if (rowData.assetsAvailable == 0)
return yellow;
else
return rowData.assetsAvailable < 0 ? red : green;
}
default:
return {};
}
}
return {};
}
bool OverviewDialogModel::initModel(int32_t mainScheduleId,
const std::shared_ptr<Interface::Dtc> &dtc,
int32_t comparedScheduleId, int32_t basePlanId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_dtc = dtc;
m_loadedScheduleId = mainScheduleId;
m_comparedScheduleId = comparedScheduleId;
m_basePlanId = basePlanId;
m_mountingPointAssets = m_dtc->mountingPointAssets();
if (!m_dtc->mainSchedules().contains(m_loadedScheduleId))
{
m_loadedScheduleId = -1;
ERROR_LOG(m_logger) << "Invalid scheduleId = " << mainScheduleId;
return false;
}
DEBUG_LOG(m_logger) << "[INITIAL] loaded: "<<m_loadedScheduleId<<" cmp: "<<m_comparedScheduleId<<" sim: "<<m_basePlanId;
if (!initData())
{
ERROR_LOG(m_logger) << "Could not init data";
return false;
}
DEBUG_LOG(m_logger) << "initModel successful";
// initModel will be executed later -> Qt::UniqueConnection
connect(m_dtc.get(), &Interface::Dtc::mainStructureElementChanged,
this, &OverviewDialogModel::initData, Qt::UniqueConnection);
connect(m_dtc.get(), &Interface::Dtc::mainScheduleChanged,
this, &OverviewDialogModel::initData, Qt::UniqueConnection);
connect(m_dtc.get(), &Interface::Dtc::instrumentationAssetChanged,
this, &OverviewDialogModel::initData, Qt::UniqueConnection);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool OverviewDialogModel::initData()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
#ifdef BENCHMARK
QElapsedTimer elapsedTimer1;
elapsedTimer1.start();
#endif // BENCHMARK
beginResetModel();
// m_neededPerType.clear();
endResetModel();
m_conflictedStructureElementIds.clear();
// if (m_basePlanId != 0)
// setOverviewSimulatedData();
// else
// setOverviewData();
setNewData();
for ( int mppId : qAsConst(m_conflictedStructureElementIds))
DEBUG_LOG(m_logger) << "Conflicted structure element id = " << mppId;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
MountingPointType OverviewDialogModel::getMountingPointTypeId(int structureElementId)
{
if (m_availableMountingPointTypes.contains(structureElementId))
return m_availableMountingPointTypes[structureElementId];
StructureElement se;
if (!m_dtc->getStructureElementById(structureElementId, se))
return MountingPointType_def::get_default();
//OutdoorIPS will be considered as IndoorIPS
const MountingPointType mpType = (se.mountingPointTypeId() == MountingPointType_def::OutdoorIPS) ? MountingPointType_def::IndoorIPS : se.mountingPointTypeId();
m_availableMountingPointTypes.insert(structureElementId, mpType);
return mpType;
}
bool OverviewDialogModel::hasMountedAsset(int seId)
{
for (const InfrastructureManagement::MountingPointAsset &asset : qAsConst(m_mountingPointAssets))
{
if (asset.structureElementId() == seId)
return true;
}
return false;
}
bool OverviewDialogModel::hasConflictedMountingPoints()
{
return !m_conflictedStructureElementIds.isEmpty();
}
/**
* @brief OverviewDialogModel::mergePlans
* @param currPlanId : loaded schedule id
* @param currPlan : current active mounting points
* @param cmpPlanId: plan == 0: no compare plan | plan > 0: plan to compare with
* @return
*/
QHash<int/*sructElId*/, MountingPointPlan> OverviewDialogModel::mergePlans(const QHash<int/*sructElId*/, MountingPointPlan> &currPlan, const int cmpPlanId)
{
DEBUG_LOG(m_logger)<<"[MERGE PLANs] currPlanId: "<<m_loadedScheduleId<<" ; cmpPlanId: "<<cmpPlanId;
QHash<int/*sructElId*/, MountingPointPlan> mergedPlan = currPlan;
// iterate over all active plan
const auto msConst = m_dtc->mainSchedules();
for (const auto &schedule : msConst)
{
if (cmpPlanId == 0 && schedule.statusId() != ScheduleStatus_def::Active)
continue;
if (cmpPlanId != 0 && cmpPlanId != schedule.id())
continue;
for (const MountingPointPlan &currentMpp : schedule.elements())
{
if (m_conflictedStructureElementIds.contains(currentMpp.structureElementId()))
continue;
const MountingPointType mpType = getMountingPointTypeId(currentMpp.structureElementId());
if (!m_refMap.contains(mpType))
continue;
if (currPlan.contains(currentMpp.structureElementId()))
{
const MountingPointPlan &basePlanMpp = currPlan[currentMpp.structureElementId()];
/// 1. conflicted when 1&2: equipped | empty.
/// 2. state of merge is idle when on conflict
if ((basePlanMpp.mountingPointState() == MountingPointState::Equipped && currentMpp.mountingPointState() == MountingPointState::Empty) ||
(basePlanMpp.mountingPointState() == MountingPointState::Empty && currentMpp.mountingPointState() == MountingPointState::Equipped))
{
DEBUG_LOG(m_logger)<<" conflicted name: "<<currentMpp.structureElementId();
mergedPlan[currentMpp.structureElementId()].mountingPointState(MountingPointState::Idle);
m_conflictedStructureElementIds.insert(basePlanMpp.structureElementId());
}
else
{
switch(basePlanMpp.mountingPointState().underlying())
{
case MountingPointState_def::Empty:
mergedPlan[currentMpp.structureElementId()].mountingPointState(MountingPointState::Empty);
break;
case MountingPointState_def::Equipped:
mergedPlan[currentMpp.structureElementId()].mountingPointState(MountingPointState::Equipped);
break;
case MountingPointState_def::Idle:
mergedPlan[currentMpp.structureElementId()].mountingPointState(currentMpp.mountingPointState());
break;
default:
break;
}
}
}
else
{
mergedPlan[currentMpp.structureElementId()] = currentMpp;
}
}//end for-loop over mountingPointPlans
}// end for-loop over schedules
return mergedPlan;
}
void OverviewDialogModel::setNewData()
{
QHash<int /*<structureElementId>*/, MountingPointPlan> baseMountingPointPlans;
// If basePlanId == 0 -> current actual status is used.
DEBUG_LOG(m_logger) << "We compare plan " << m_basePlanId << " with " << m_comparedScheduleId;
baseMountingPointPlans.clear();
m_conflictedStructureElementIds.clear();
// ...on InstrumentationAssetsChanged(); || BasePlanChanged and BasePlanId == 0
for (int id : qAsConst(m_refMap))
{
m_vecData[id] = RowData(m_vecData[id].mpt);
// val.assetCount = 0;
// val.assetsDefect = 0;
// val.assetsFree = 0;
// val.assetsMounted = 0;
// val.basePlanDemand = 0;
// val.basePlanUnmount = 0;
}
const auto iaConst = m_dtc->instrumentationAssets();
for (const InstrumentationAsset &asset : iaConst )
{
//OutdoorIPS will be considered as IndoorIPS
const MountingPointType mpType = (asset.mountingPointTypeId() == MountingPointType::OutdoorIPS) ? MountingPointType::IndoorIPS : asset.mountingPointTypeId();
if (!m_refMap.contains(mpType))
continue;
++m_vecData[m_refMap[mpType]].assetCount;
/// Defekte Komponente
if (asset.assetStateId() == InstrumentationAssetState_def::Defect)
++m_vecData[m_refMap[mpType]].assetsDefect;
if (asset.assetStateId() == InstrumentationAssetState_def::Unmounted)
++m_vecData[m_refMap[mpType]].assetsFree;
if (asset.assetStateId() == InstrumentationAssetState_def::Mounted)
{
++m_vecData[m_refMap[mpType]].assetsMounted;
if (m_basePlanId == 0)
++m_vecData[m_refMap[mpType]].basePlanDemand;
}
}
// onMainSchedule[basePlanId]Changed || basePlanId changed
// for (auto id : m_refMap)
// {
// auto &val = m_vecData[id];
// val.basePlanDemand = 0;
// val.basePlanUnmount = 0;
// }
if (m_basePlanId > 0)
{
MainSchedule baseSchedule = m_dtc->mainSchedules().value(m_basePlanId);
for (const MountingPointPlan &mpp : baseSchedule.elements())
{
const MountingPointType mpType = getMountingPointTypeId(mpp.structureElementId());
if (!m_refMap.contains(mpType))
continue;
baseMountingPointPlans.insert(mpp.structureElementId(), mpp);
if (mpp.mountingPointState() == MountingPointState::Equipped)
++m_vecData[m_refMap[mpType]].basePlanDemand;
}
}
else
{
// Todo: Save this in m_currentMountingPointState and update onMSEChanged(), here: Get a copy into m_mergedMountingPoints
const auto msesConst = m_dtc->mainStructureElements();
for(const auto &mse : msesConst)
for (const auto &se : mse.elements())
if (hasMountedAsset(se.id()))
baseMountingPointPlans.insert(se.id(), MountingPointPlan(se.id(), MountingPointState_def::Equipped));
}
QHash<int/*sructElId*/, MountingPointPlan> comparedMountingPointPlans = mergePlans({}, m_comparedScheduleId);
QHash<int/*sructElId*/, MountingPointPlan> totalMPPs = comparedMountingPointPlans;
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
QHashIterator<int, MountingPointPlan> it(baseMountingPointPlans);
while (it.hasNext())
{
it.next();
totalMPPs.insert(it.key(), it.value());
}
#else
totalMPPs.insert(baseMountingPointPlans);
#endif //
/// Übergreifender Bedarf
for(const auto &bla: totalMPPs)
{
MountingPointPlan compareMpp = comparedMountingPointPlans.value(bla.structureElementId(), MountingPointPlan(bla.structureElementId(), MountingPointState_def::Idle));
MountingPointPlan baseMpp = baseMountingPointPlans.value(bla.structureElementId(), MountingPointPlan(bla.structureElementId(), MountingPointState_def::Idle));
const MountingPointType mpType = getMountingPointTypeId(bla.structureElementId());
if (!m_refMap.contains(mpType))
continue;
switch(baseMpp.mountingPointState().underlying())
{
case MountingPointState_def::Empty:
if (compareMpp.mountingPointState() == MountingPointState_def::Equipped)
++m_vecData[m_refMap[mpType]].totalDemand;
break;
case MountingPointState_def::Equipped:
if (compareMpp.mountingPointState() != MountingPointState_def::Equipped)
--m_vecData[m_refMap[mpType]].totalDemand;
break;
case MountingPointState_def::Idle:
if (compareMpp.mountingPointState() == MountingPointState_def::Equipped)
++m_vecData[m_refMap[mpType]].totalDemand;
break;
default:
break;
}
switch(compareMpp.mountingPointState().underlying())
{
case MountingPointState_def::Equipped:
++m_vecData[m_refMap[mpType]].comparePlanDemand;
break;
case MountingPointState_def::Empty:
++m_vecData[m_refMap[mpType]].comparePlanUnmount;
break;
default:
break;
}
}
/// Verfügbarer Bestand: ASSETS_OWNED - DEFECT_ASSETS - MERGED_MOUNTED_ASSET - NEED_EQUIPPED + MERGE_TO_UNMOUNT_ASSETS
/// Freie Komponente bei simulation: ASSETS_OWNED - MERGED_MOUNTED_ASSET - DEFEKT_ASSETS
for (auto id : qAsConst(m_refMap))
{
auto &rowData = m_vecData[id];
const int availableAssetCount =
rowData.assetCount
- rowData.assetsDefect
- rowData.assetsMounted
- rowData.comparePlanDemand
+ rowData.comparePlanUnmount;
rowData.assetsAvailable = availableAssetCount;
}
}
QString RowData::toString() const
{
return QStringLiteral("MPT ") + InfrastructureManagement::toString(mpt) +
QStringLiteral(", bpDem: ") + QString::number(basePlanDemand) +
QStringLiteral(", pbDiff: ") + QString::number(basePlanDifference) +
QStringLiteral(", cpDem: ") + QString::number(comparePlanDemand) +
QStringLiteral(", cpUmnt: ") + QString::number(comparePlanUnmount) +
QStringLiteral(", toDem: ") + QString::number(totalDemand) +
QStringLiteral(", asCnt: ") + QString::number(assetCount) +
QStringLiteral(", asFre: ") + QString::number(assetsFree) +
QStringLiteral(", AsAv: ") + QString::number(assetsAvailable) +
QStringLiteral(", AsMt: ") + QString::number(assetsMounted) +
QStringLiteral(", AsDef: ") + QString::number(assetsDefect);
}
} // namespace InfrastructureManagement
@@ -0,0 +1,108 @@
/**
* @RDE_HEADER@
* The OverviewDialogModel provides data for OverviewDialog
* $Id$
* $HeadURL$
* $Author$
* Created by Hannes Baeuerle, SLSE, 2016-11-03
*/
#pragma once
#include <LtsWidgets/lts_abstract_table_model.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
namespace InfrastructureManagement
{
struct RowData
{
MountingPointType mpt;
int basePlanDemand{0}; // "PlanBedarf" (Basisplan)
int basePlanDifference{0}; // Differenzbedarf (zum aktuellen Anbaustatus)
int comparePlanDemand{0}; // "Planbedarf" (VGL Einrüstplan) (= Differenz zu Basisplan)
int comparePlanUnmount{0}; // Im Vergleichsplan zu als demontiert markierte Assets.
int totalDemand{0}; // "Übergreifender Bedarf"
int assetCount{0}; // "Komponentenbestand" // All asset states
int assetsFree{0}; // "Freie Komponenten" // AssetState: Unmounted
int assetsAvailable{0}; // "Verfügbarer Bestand"
int assetsMounted{0}; // Aktuell gemountete Assets // AssetState: Mounted
int assetsDefect{0}; // Aktuell als defekt deklarierte Assets // AssetState: Defect
explicit RowData(MountingPointType _mpt)
: mpt(_mpt){}
QString toString() const;
};
class OverviewDialogModel : public LtsWidgets::LtsAbstractTableModel<RowData>
{
Q_OBJECT
public:
explicit OverviewDialogModel(QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role) const override final;
bool initModel(int32_t mainScheduleId,
const std::shared_ptr<Interface::Dtc> &dtc,
int32_t comparedScheduleId = 0,
int32_t basePlanId = 0);
bool initData();
// void setOverviewData();
// void setOverviewSimulatedData();
void setNewData();
bool hasConflictedMountingPoints();
QMap<MountingPointType, int> getOtherActiveNeeded(const int &currPlanId);
private: // methods
QHash<int, MountingPointPlan> mergePlans(const QHash<int, MountingPointPlan> &currPlan, const int cmpPlanId);
void setTotalCmpActiveNeed(const QMap<int, MountingPointPlan> &mergedPlan);
MountingPointType getMountingPointTypeId(int structureElementId);
bool hasMountedAsset(int seId);
private: // other
enum Columns
{
TYPE =0,
BASEPLAN_DEMAND , // needed in current plan
COMPARED_DEMAND , // needed in compared plan
TOTAL_DEMAND , // needed current plan + needed in compared plan
ASSETS_OWNED , // TOTAL components in system
ASSETS_FREE , // total unmounted assets
ASSETS_AVAILABLE , // OWNED - mounted + to_unmount (FREE + assets_to_unmount, maximal TOTAL owned)
COLUMNs_COUNT // not displayed in view
};
private: // attributes
// QMap<MountingPointType, QVector<int>> m_neededPerType;
QHash<int/*seId*/, MountingPointType> m_availableMountingPointTypes;
int32_t m_loadedScheduleId{-1}; // loaded plan
int32_t m_basePlanId{0}; // simulated plan
int32_t m_comparedScheduleId{0}; // plan to compare with
std::shared_ptr<Interface::Dtc> m_dtc;
/**
* @brief m_includedMountingPoints
* contains all mpt from : loaded plan + (active plan or cmp plan). conflicted mntp are not included
*/
QSet<int /*<structureElementId>*/> m_conflictedStructureElementIds;
QMap<qint32, InfrastructureManagement::MountingPointAsset> m_mountingPointAssets;
QMap<MountingPointType, int> m_refMap;
LOGGER_T m_logger;
}; // class OverviewDialogModel
} // namespace InfrastructureManagement
@@ -0,0 +1,520 @@
/**
* @RDE_HEADER@
* tbc
* $Id$
* $HeadURL$
* $Author$
* Created by
*/
#include "ism_overview_mounting_point_list_dialog.h"
#include "ui_ism_overview_mounting_point_list_dialog.h"
#include <QTreeView>
#include <QListWidget>
#include <QMenu>
#include <qlabel.h>
#include <InfrastructureManagement/ism_translation.h>
#include <InfrastructureManagement/Shared/ism_mounting_point.h>
#include <LtsPrinting/printing.h>
#include <ngltools/ngltools_dtg.h>
#include <QMessageBox>
#include <QHeaderView>
#include <qscrollbar.h>
using namespace InfrastructureManagement;
/*!
* \brief OverviewMountingPointListDialog::OverviewMountingPointListDialog
* \param menuGroup
* \param parent
*/
OverviewMountingPointListDialog::OverviewMountingPointListDialog(const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_menuGroup(menuGroup)
, m_ui(new Ui::OverViewMountingPointListDialog)
, m_logger(getLogger("OverviewMountingPointListDialog"))
, m_actionMenu(new QMenu(this))
, m_printMountingAction(new QAction(tr("To Mount"), this))
, m_printUnmountingAction(new QAction(tr("To Unmount"), this))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
setAttribute(Qt::WA_DeleteOnClose);
m_ui->setupUi(this);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Completness_Check"));
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Print, true);
m_actionMenu->addAction(m_printMountingAction);
m_actionMenu->addAction(m_printUnmountingAction);
connect(m_actionMenu, &QMenu::triggered, this, &OverviewMountingPointListDialog::onPrint);
m_buttonBox->setMenu(LtsWidgets::DialogButton::Print, m_actionMenu);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
OverviewMountingPointListDialog::~OverviewMountingPointListDialog()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_ui;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
/*!
* \brief OverviewMountingPointListDialog::init
* \param session
* \param dtc
* \param ftc
* \param dataInterface
* \return
*/
bool OverviewMountingPointListDialog::init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignDataInterface> &dataInterface,
int32_t scheduleId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, scheduleId=" << scheduleId;
m_dtc = dtc;
m_dataIfc = dataInterface;
m_session = session;
m_ftc = ftc;
m_scheduleId = scheduleId;
// disconnect(m_ui->mountingPointListView);
// disconnect(this);
if (!m_ftc->enableInstrumentationAssetModify())
{
ERROR_LOG(m_logger) << "Could not enable FT InstrumentationAssetModify of ISM";
return false;
}
if (!m_ftc->enableMountingPointPlanModify())
{
ERROR_LOG(m_logger) << "Could not enable FT enableMountingPointPlansModify of ISM";
return false;
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " new ViewMountingPointListModel...";
delete m_sourceModel;
m_sourceModel = new ViewMountingPointListModel(this);
if (!m_sourceModel->initModel(m_dtc, m_dataIfc, m_scheduleId))
{
ERROR_LOG(m_logger) << "Could not init model";
delete m_sourceModel;
m_sourceModel = nullptr;
return false;
}
/// current state is equipped -> to unmount
DEBUG_LOG(m_logger) << LOGFUNCTION << " new m_mountedPointSortProxyModel ...";
delete m_mountedPointSortProxyModel;
m_mountedPointSortProxyModel = new ViewMountingPointListSortModel(this);
m_mountedPointSortProxyModel->setVisibleState(MountingPointState::Equipped);
m_mountedPointSortProxyModel->setSourceModel(m_sourceModel);
m_mountedPointSortProxyModel->sort(0, Qt::AscendingOrder);
connect(m_sourceModel, &ViewMountingPointListModel::dataChanged, m_mountedPointSortProxyModel, &ViewMountingPointListSortModel::invalidateFilter);
m_ui->mountingPointListView->setModel(m_mountedPointSortProxyModel);
m_ui->mountingPointListView->setSortingEnabled(true);
/// current state is empty -> to mount
DEBUG_LOG(m_logger) << LOGFUNCTION << " new m_unmountedPointSortProxyModel ...";
delete m_unmountedPointSortProxyModel;
m_unmountedPointSortProxyModel = new ViewMountingPointListSortModel(this);
m_unmountedPointSortProxyModel->setVisibleState(MountingPointState::Empty);
m_unmountedPointSortProxyModel->setSourceModel(m_sourceModel);
m_unmountedPointSortProxyModel->sort(0, Qt::AscendingOrder);
connect(m_sourceModel, &ViewMountingPointListModel::dataChanged, m_unmountedPointSortProxyModel, &ViewMountingPointListSortModel::invalidateFilter);
m_ui->unmountingPointListView->setModel(m_unmountedPointSortProxyModel);
m_ui->unmountingPointListView->setSortingEnabled(true);
m_ui->mountingPointListView->treeView()->setColumnWidth(0, 315);
m_ui->mountingPointListView->treeView()->setColumnWidth(1, 160);
// m_ui->mountingPointListView->treeView()->header()->setSectionResizeMode(1, QHeaderView::Fixed);
// m_ui->mountingPointListView->treeView()->header()->setSectionResizeMode(0, QHeaderView::Fixed);
m_ui->mountingPointListView->searchView()->setColumnWidth(0, 315);
m_ui->mountingPointListView->searchView()->setColumnWidth(1, 160);
// m_ui->mountingPointListView->searchView()->header()->setSectionResizeMode(1, QHeaderView::Fixed);
// m_ui->mountingPointListView->searchView()->header()->setSectionResizeMode(0, QHeaderView::Fixed);
m_ui->unmountingPointListView->treeView()->setColumnWidth(0, 315);
m_ui->unmountingPointListView->treeView()->setColumnWidth(1, 160);
// m_ui->unmountingPointListView->treeView()->header()->setSectionResizeMode(1, QHeaderView::Fixed);
// m_ui->unmountingPointListView->treeView()->header()->setSectionResizeMode(0, QHeaderView::Fixed);
m_ui->unmountingPointListView->searchView()->setColumnWidth(0, 315);
m_ui->unmountingPointListView->searchView()->setColumnWidth(1, 160);
// m_ui->unmountingPointListView->searchView()->header()->setSectionResizeMode(1, QHeaderView::Fixed);
// m_ui->unmountingPointListView->searchView()->header()->setSectionResizeMode(0, QHeaderView::Fixed);
//------------- Filter ----------------
DEBUG_LOG(m_logger) << LOGFUNCTION << " filter... ...";
const auto filters = { MountingPointType::BuildingSensorModule,
// MountingPointType::OutdoorCamera,
// MountingPointType::BuildingControlUnit,
MountingPointType::IndoorCamera,
//MountingPointType::OutdoorIPS, //TODO: Remove OutdoorIPS from Enum in EnterpriseArchitect
MountingPointType::IndoorIPS,
// MountingPointType::AnnouncementUnit,
MountingPointType::EffectGenerationControlUnit
// MountingPointType::BuildingNetworkSwitch
};
m_ui->lwMountingPointType->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
connect(m_ui->lwMountingPointType, &QListWidget::itemSelectionChanged,
this, [this]()
{
QVector<MountingPointType> types;
types << MountingPointType::Unknown;
for (const QListWidgetItem *lwi : m_ui->lwMountingPointType->findItems(QLatin1String(""), Qt::MatchContains))
{
MountingPointType mpt = static_cast<MountingPointType::inner_enum>(lwi->data(Qt::UserRole).toInt());
if (lwi->isSelected())
types << mpt;
m_mountedPointSortProxyModel->addToTypeFilter(mpt, lwi->isSelected());
m_unmountedPointSortProxyModel->addToTypeFilter(mpt, lwi->isSelected());
m_ui->mountingPointListView->treeView()->expandAll();
m_ui->unmountingPointListView->treeView()->expandAll();
}
});
for (const MountingPointType currentFilter : filters)
addMountingPointTypeFilter(currentFilter);
// connect is used to to enable Accept/Ok Buttons
connect(m_sourceModel, &ViewMountingPointListModel::dataChanged, this, &OverviewMountingPointListDialog::onDataChanged);
// mounted view
connect(m_ui->mountingPointListView->searchView()->horizontalScrollBar(), &QScrollBar::rangeChanged,
this, [this]()
{
m_ui->mountingPointListView->slotSetHorizontalRange(0,0);
}, Qt::QueuedConnection);
connect(m_ui->mountingPointListView->treeView()->horizontalScrollBar(), &QScrollBar::rangeChanged,
this, [this]()
{
m_ui->mountingPointListView->slotSetHorizontalRange(0,0);
}, Qt::QueuedConnection);
// unmounted view
connect(m_ui->unmountingPointListView->searchView()->horizontalScrollBar(), &QScrollBar::rangeChanged,
this, [this]()
{
m_ui->unmountingPointListView->slotSetHorizontalRange(0,0);
}, Qt::QueuedConnection);
connect(m_ui->unmountingPointListView->treeView()->horizontalScrollBar(), &QScrollBar::rangeChanged,
this, [this]()
{
m_ui->unmountingPointListView->slotSetHorizontalRange(0,0);
}, Qt::QueuedConnection);
connect(m_dataIfc.get(), &ForeignDataInterface::scheduleIdChanged,
this, &OverviewMountingPointListDialog::onScheduleIdChanged);
m_ui->mountingPointListView->treeView()->expandAll();
m_ui->unmountingPointListView->treeView()->expandAll();
// context menu expand / collapse treeview
m_ui->mountingPointListView->setContextMenuPolicyPerView(LtsDataView::LtsDataView::Page::TABLE, Qt::CustomContextMenu);
connect(m_ui->mountingPointListView->treeView(), &QTreeView::customContextMenuRequested,
this, &OverviewMountingPointListDialog::onMountedCustomContextMenu);
m_ui->unmountingPointListView->setContextMenuPolicyPerView(LtsDataView::LtsDataView::Page::TABLE, Qt::CustomContextMenu);
connect(m_ui->unmountingPointListView->treeView(), &QTreeView::customContextMenuRequested,
this, &OverviewMountingPointListDialog::onUnMountedCustomContextMenu);
// update title:
retranslate();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
/*!
* \brief OverviewMountingPointListDialog::retranslate
*/
void OverviewMountingPointListDialog::retranslate()
{
if (m_dtc)
{
MainSchedule ms = m_dtc->mainSchedule(m_scheduleId);
const QString msName = QString::fromStdString(ms.name());
translate(m_ui, tr("Completeness Check '%1'").arg(msName));
}
else
translate(m_ui, tr("Completeness Check"));
}
/*!
* \brief OverviewMountingPointListDialog::addMountingPointTypeFilter
* \param mpt
*/
void OverviewMountingPointListDialog::addMountingPointTypeFilter(MountingPointType mpt)
{
QListWidgetItem *lwi = new QListWidgetItem(m_ui->lwMountingPointType);
bool isInitChecked = true;
m_mountedPointSortProxyModel->addToTypeFilter(mpt, isInitChecked);
m_unmountedPointSortProxyModel->addToTypeFilter(mpt, isInitChecked);
lwi->setData(Qt::UserRole, mpt.underlying());
const QString text = toString(mpt);
lwi->setText(text);
lwi->setSelected(isInitChecked);
}
/*!
* \brief OverviewMountingPointListDialog::onDataChanged
* \param topLeft
* \param bottomRight
* \param roles
*/
void OverviewMountingPointListDialog::onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
Q_UNUSED(topLeft);
Q_UNUSED(bottomRight);
Q_UNUSED(roles);
slotChangesMade();
m_ui->mountingPointListView->treeView()->expandAll();
m_ui->unmountingPointListView->treeView()->expandAll();
}
/*!
* \brief OverviewMountingPointListDialog::onPrint
* \param action
*/
void OverviewMountingPointListDialog::onPrint(QAction *action)
{
MainSchedule ms = m_dtc->mainSchedule(m_dataIfc->scheduleId());
QString header;
header += QStringLiteral("<p>");
header += tr("Instrumentation Plan: %1").arg(QString::fromStdString(ms.name()));
header += QStringLiteral("<br/>");
header += tr("Created: %1").arg(DTG::toStringMSec(ms.timeCreated()));
header += QStringLiteral("<br/>");
if (ms.timeStart().is_set())
header += tr("START: %1").arg(DTG::toStringMSec(ms.timeStart().get()));
else
header += tr("START: %1").arg(tr("[N/A]"));
header += QStringLiteral(" - ");
if (ms.timeEnd().is_set())
header += tr("END: %1").arg(DTG::toStringMSec(ms.timeEnd().get()));
else
header += tr("END: %1").arg(tr("[N/A]"));
header += QStringLiteral("<br/>");
QString filterTypes;
if(!getUsedFilterTypes().isEmpty())
{
QStringList filterList = getUsedFilterTypes();
header += QStringLiteral("<br/>");
filterTypes = tr("<b>Active filter:</b>");
filterTypes += QStringLiteral("<ul>");
for (int i=0; i<filterList.count(); i++ ) {
filterTypes += QStringLiteral("<li>%1</li>").arg(filterList.at(i));
}
filterTypes += QStringLiteral("</ul><br/>");
header += filterTypes;
}
if (action->text() == m_printMountingAction->text())
{
//
header += tr("The following items have to be mounted:");
header += QStringLiteral("<br/>");
header += QStringLiteral("</p>");
m_ui->mountingPointListView->expandAll();
if(itemsHaveNoChildren(m_ui->mountingPointListView->treeView()) == false)
LtsPrinting::printView(m_session, this, m_ui->mountingPointListView->treeView(), header );
else
{
QMessageBox::warning(this, tr("Completeness Check"), tr("There is No Entry to Print"), QMessageBox::Ok);
}
}
else if (action->text() == m_printUnmountingAction->text())
{
header += tr("The following items have to be unmounted:");
header += QStringLiteral("<br/>");
header += QStringLiteral("</p>");
m_ui->unmountingPointListView->expandAll();
if(itemsHaveNoChildren(m_ui->unmountingPointListView->treeView()) == false)
LtsPrinting::printView(m_session, this, m_ui->unmountingPointListView->treeView(), header );
else
{
QMessageBox::warning(this, tr("Completeness Check"), tr("There is No Entry to Print"), QMessageBox::Ok);
}
}
}
/*!
* \brief OverviewMountingPointListDialog::itemsHaveNoChildren
* \param view
* \return
*/
bool OverviewMountingPointListDialog::itemsHaveNoChildren(const QTreeView *view)
{
const QAbstractItemModel *itemModel = view->model();
int rowCount = itemModel->rowCount();
for (int row = 0; row < rowCount; ++row)
{
if (itemModel->hasChildren(itemModel->index(row, 0)))
return false;
}
return true;
}
void OverviewMountingPointListDialog::tableColumnOrganiserSetting()
{
//LtsColumnOrganiser
m_ui->mountingPointListView->setColumnsOrganiserEnabled(identifier(), true);
}
/*!
* \brief OverviewMountingPointListDialog::getUsedFilterTypes
* get the list of the selected filter
* \return QStringList
*/
QStringList OverviewMountingPointListDialog::getUsedFilterTypes()
{
QStringList filterList;
for (const QListWidgetItem *lwi : m_ui->lwMountingPointType->findItems(QLatin1String(""), Qt::MatchContains))
{
MountingPointType mpt = static_cast<MountingPointType::inner_enum>(lwi->data(Qt::UserRole).toInt());
if (lwi->isSelected())
filterList<<toString(mpt);
}
return filterList;
}
/*!
* \brief OverviewMountingPointListDialog::onScheduleIdChanged
* \param scheduleId
*/
void OverviewMountingPointListDialog::onScheduleIdChanged(int32_t scheduleId)
{
if (scheduleId == m_scheduleId)
return;
// scheduleId changed, data is maybe invalid -> close dialog:
this->close(); // Since Qt::WA_DeleteOnClose the dtor will be called :-)
}
void OverviewMountingPointListDialog::onMountedCustomContextMenu(QPoint pos)
{
QMenu *contextMenu = new QMenu(this);
contextMenu->setAttribute(Qt::WA_DeleteOnClose);
{
QAction *action = new QAction(tr("Expand All"), this);
action->setEnabled(true);
connect(action, &QAction::triggered, this, [this]()
{
m_ui->mountingPointListView->expandAll();
});
contextMenu->addAction(action);
}
{
QAction *action = new QAction(tr("Collapse All"), this);
action->setEnabled(true);
connect(action, &QAction::triggered, this, [this]()
{
m_ui->mountingPointListView->collapseAll();
});
contextMenu->addAction(action);
}
contextMenu->addSeparator();
QModelIndex index = m_ui->mountingPointListView->treeView()->indexAt(pos);
bool hasChildren = m_ui->mountingPointListView->treeView()->model()->rowCount(index) > 0;
{
QAction *action = new QAction(tr("Expand"), this);
action->setEnabled(hasChildren);
connect(action, &QAction::triggered, this, [this, index]()
{
#if QT_VERSION < QT_VERSION_CHECK(5,13,0)
m_ui->dvConflicts->treeView()->expand(index);
#else
m_ui->mountingPointListView->treeView()->expandRecursively(index);
#endif
});
contextMenu->addAction(action);
}
{
QAction *action = new QAction(tr("Collapse"), this);
action->setEnabled(hasChildren);
connect(action, &QAction::triggered, this, [this, index]()
{
m_ui->mountingPointListView->treeView()->collapse(index);
});
contextMenu->addAction(action);
}
contextMenu->popup(m_ui->mountingPointListView->treeView()->mapToGlobal(pos));
}
void OverviewMountingPointListDialog::onUnMountedCustomContextMenu(QPoint pos)
{
QMenu *contextMenu = new QMenu(this);
contextMenu->setAttribute(Qt::WA_DeleteOnClose);
{
QAction *action = new QAction(tr("Expand All"), this);
action->setEnabled(true);
connect(action, &QAction::triggered, this, [this]()
{
m_ui->unmountingPointListView->expandAll();
});
contextMenu->addAction(action);
}
{
QAction *action = new QAction(tr("Collapse All"), this);
action->setEnabled(true);
connect(action, &QAction::triggered, this, [this]()
{
m_ui->unmountingPointListView->collapseAll();
});
contextMenu->addAction(action);
}
contextMenu->addSeparator();
QModelIndex index = m_ui->unmountingPointListView->treeView()->indexAt(pos);
bool hasChildren = m_ui->unmountingPointListView->treeView()->model()->rowCount(index) > 0;
{
QAction *action = new QAction(tr("Expand"), this);
action->setEnabled(hasChildren);
connect(action, &QAction::triggered, this, [this, index]()
{
#if QT_VERSION < QT_VERSION_CHECK(5,13,0)
m_ui->dvConflicts->treeView()->expand(index);
#else
m_ui->unmountingPointListView->treeView()->expandRecursively(index);
#endif
});
contextMenu->addAction(action);
}
{
QAction *action = new QAction(tr("Collapse"), this);
action->setEnabled(hasChildren);
connect(action, &QAction::triggered, this, [this, index]()
{
m_ui->unmountingPointListView->treeView()->collapse(index);
});
contextMenu->addAction(action);
}
contextMenu->popup(m_ui->unmountingPointListView->treeView()->mapToGlobal(pos));
}
/*!
* \brief OverviewMountingPointListDialog::apply
* \return
*/
bool OverviewMountingPointListDialog::apply()
{
return true;
}
@@ -0,0 +1,99 @@
/**
* @RDE_HEADER@
* tbc
* $Id$
* $HeadURL$
* $Author$
* Created by
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <InfrastructureManagement/logger.h>
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <Plugins/InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <LtsDataView/check_state_proxy_model.h>
#include <InfrastructureManagement/Gui/ResourceManagement/MountingPointMapSelection/ism_dds_selector.h>
#include <InfrastructureManagement/Gui/ResourceManagement/MountingPointMapSelection/ism_selector.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/ism_ftc.h>
#include <LtsWidgets/lts_abstract_table_model.h>
#include <qtreeview.h>
#include "ism_overview_mounting_point_list_model.h"
namespace Ui {
class OverViewMountingPointListDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
class ViewMountingPointListModel;
class ViewMountingPointListSortModel;
class OverviewMountingPointListDialog : public LtsWidgets::LtsDialog
{
Q_OBJECT
public: explicit OverviewMountingPointListDialog(const QString &menuGroup, QWidget *parent = nullptr);
~OverviewMountingPointListDialog();
bool init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignDataInterface> &dataInterface,
int32_t scheduleId);
void onDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) ;
private slots:
void onPrint(QAction *action);
void onScheduleIdChanged(int32_t scheduleId);
void onMountedCustomContextMenu(QPoint pos);
void onUnMountedCustomContextMenu(QPoint pos);
private: // methods
void retranslate() override;
void addMountingPointTypeFilter(MountingPointType mpt);
void addFloorFilter(int floor);
bool apply() override final;
bool isIncludedId(int32_t mountingPointId) const;
bool itemsHaveNoChildren(const QTreeView *view);
void tableColumnOrganiserSetting() override;
QStringList getUsedFilterTypes();
private:
QString m_menuGroup;
Ui::OverViewMountingPointListDialog *m_ui;
int32_t m_scheduleId;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
std::shared_ptr<ForeignDataInterface> m_dataIfc;
ViewMountingPointListModel *m_sourceModel{nullptr};
ViewMountingPointListSortModel *m_mountedPointSortProxyModel{nullptr};
ViewMountingPointListSortModel *m_unmountedPointSortProxyModel{nullptr};
LtsSession::LtsSession *m_session{nullptr};
LOGGER_T m_logger;
QMenu *m_actionMenu;
QAction *m_printMountingAction;
QAction *m_printUnmountingAction;
}; // class OverViewMountingPointListDialog
} // namespace InfrastructureManagement
@@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OverViewMountingPointListDialog</class>
<widget class="QWidget" name="OverViewMountingPointListDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>868</width>
<height>490</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QGroupBox" name="grpTypeFilters">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>221</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Type filter</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QListWidget" name="lwMountingPointType">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="2">
<widget class="QLabel" name="umntLbl">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To Unmount</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="LtsDataView::LtsDataView" name="mountingPointListView" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="rootIsDecorated" stdset="0">
<bool>true</bool>
</property>
<property name="showColumnCount" stdset="0">
<bool>false</bool>
</property>
<property name="toolButtonsVisible" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="mntLbl">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>To Mount</string>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="LtsDataView::LtsDataView" name="unmountingPointListView" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="rootIsDecorated" stdset="0">
<bool>true</bool>
</property>
<property name="showColumnCount" stdset="0">
<bool>false</bool>
</property>
<property name="toolButtonsVisible" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>566</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,542 @@
/**
* @RDE_HEADER@
* tbc
* $Id$
* $HeadURL$
* $Author$
* Created by
*/
#include "ism_overview_mounting_point_list_model.h"
#include <InfrastructureManagement/ism_translation.h>
#include <Plugins/InfrastructureManagement/Shared/ism_mounting_point.h>
#include <QDebug>
#include <QTimer>
// #define BENCHMARK
#ifdef BENCHMARK
# include <QElapsedTimer>
# include <QDebug>
#endif
namespace InfrastructureManagement
{
static const int maxIntValue = std::numeric_limits<int>::max();
ViewMountingPointListModel::ViewMountingPointListModel(QObject *parent)
: NGLTreeModel(parent, new NGLTreeItem(QVariant()), { tr("Name"), tr("Type"), tr("Aim State") })
, m_visRoot(new NGLTreeItem(tr("Mounting Points")))
, m_dtc(nullptr)
, m_logger(getLogger("ViewMountingPointListModel"))
, m_dataChangedTimer(new QTimer(this))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_dataChangedTimer->setSingleShot(true);
m_dataChangedTimer->setInterval(100);
connect(m_dataChangedTimer, &QTimer::timeout, this, &ViewMountingPointListModel::emitDataChanged);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QVariant ViewMountingPointListModel::data(const QModelIndex &index, int role) const
{
if (!(index.isValid() && (role == Qt::DisplayRole || role == Qt::UserRole || role == (Qt::UserRole + 1) || role == Qt::CheckStateRole)))
return QVariant();
NGLTreeItem *item = privateData(index);
if (role == Qt::DisplayRole)
{
if (index.column() != NAME && !item->data().canConvert<OverviewSimpleMountingPointData>())
return QVariant();
const OverviewSimpleMountingPointData itemData = item->data().value<OverviewSimpleMountingPointData>();
switch (index.column())
{
case NAME:
if (item->data().canConvert<OverviewSimpleMountingPointData>())
return item->data().value<OverviewSimpleMountingPointData>().name;
if (item->data().canConvert<OverviewSimpleStructureElementData>())
return item->data().value<OverviewSimpleStructureElementData>().name;
if (item->data().canConvert<OverviewSimpleBuildingGroupData>())
return item->data().value<OverviewSimpleBuildingGroupData>().name;
return tr("all");
case STATE:
if (itemData.seType == StructureElementType::MountingPoint)
return toString(itemData.aimState);
break;
case TYPE:
if (itemData.seType == StructureElementType::MountingPoint)
{
const MountingPointType mpType = (itemData.mpType == MountingPointType_def::OutdoorIPS) ? MountingPointType_def::IndoorIPS : itemData.mpType;
return toString(mpType);
}
break;
}
}
// else if (role == Qt::CheckStateRole)
// {
// if (index.column() != NAME)
// return QVariant();
// bool isLeaf = item->data().canConvert<OverviewSimpleMountingPointData>();
// if (isLeaf)
// {
// auto cs = item->data().value<OverviewSimpleMountingPointData>().aimState.underlying();
// switch (cs)
// {
// case MountingPointState::Equipped:
// return Qt::Checked;
// case MountingPointState::Idle:
// return Qt::PartiallyChecked;
// case MountingPointState::Empty:
// return Qt::Unchecked;
// }
// }
// }
else if (role == Qt::UserRole && item->data().canConvert<OverviewSimpleMountingPointData>())
return item->data().value<OverviewSimpleMountingPointData>().id;
else if (role == (Qt::UserRole + 1) && item->data().canConvert<OverviewSimpleMountingPointData>())
return item->data().value<OverviewSimpleMountingPointData>().aimState.underlying();
return QVariant();
}
bool ViewMountingPointListModel::initModel(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<ForeignDataInterface> &dataInterface,
int32_t requestedScheduleId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, scheduleId=" << requestedScheduleId;
if (m_dtc == dtc)
return true;
if (!(dtc->enableMainStructureElement() &&
dtc->enableMountingPointAsset()))
{
ERROR_LOG(m_logger) << "Could not enable Datatopics";
return false;
}
m_dtc = dtc;
m_dataInterface = dataInterface;
m_scheduleId = requestedScheduleId;
// !!! Maybe this is critical !!!
// !!! Maybe this is critical !!!
// !!! Maybe this is critical !!!
// m_dataInterface::setScheduleId will update the MountingPoints (aimState) according schedule!!!
// // m_dataInterface->setScheduleId(m_scheduleId);
// connect(m_dataInterface.get(), &ForeignDataInterface::scheduleIdChanged,
// this, &MountingPointListDialogModel::onScheduleIdChanged);
connect(m_dataInterface.get(), &ForeignDataInterface::mountingPointChanged,
this, &ViewMountingPointListModel::onMountingPointChanged);
DEBUG_LOG(m_logger) << "initModel successful";
initData();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
QModelIndex ViewMountingPointListModel::getIndexOfVisableRootItem() const
{
return indexFromItem(m_visRoot);
}
/**
* @brief setBuildingGroup: create fake structure element of building group
* @param groupId
* @return
*/
inline StructureElement setBuildingGroup(int groupId)
{
StructureElement se;
InfrastructureManagement::BuildingGroup_def::type buildingGroup = static_cast<InfrastructureManagement::BuildingGroup_def::type>(groupId);
if(buildingGroup == 0)
{
buildingGroup = InfrastructureManagement::BuildingGroup_def::UnknownGroup;
}
se.id() = maxIntValue - static_cast<int>(buildingGroup);
se.name() = InfrastructureManagement::toString(buildingGroup).toStdString();
se.displayName() = InfrastructureManagement::toString(buildingGroup).toStdString();
se.structureElementTypeId() = InfrastructureManagement::StructureElementType::Section;
return se;
}
/**
* @brief getFakeBuildingGroupId: idi will only be use for treeview
* @param seId
* @return
*/
inline int getFakeBuildingGroupId(int seId)
{
InfrastructureManagement::BuildingGroup_def::type buildingGroup = static_cast<InfrastructureManagement::BuildingGroup_def::type>(seId);
if(buildingGroup == 0)
{
buildingGroup = InfrastructureManagement::BuildingGroup_def::UnknownGroup;
}
return (maxIntValue - static_cast<int>(buildingGroup));
}
void ViewMountingPointListModel::initData()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, m_scheduleId=" << m_scheduleId;
// #define BENCHMARK
#ifdef BENCHMARK
QElapsedTimer elapsedTimer1;
elapsedTimer1.start();
#endif // BENCHMARK
const int32_t loadedScheduleId = m_dataInterface->scheduleId();
m_bIsRequestedScheduleId_EqualTo_LoadedScheduleId = (m_scheduleId == loadedScheduleId);
// scenario: load plan 1, open checkDialog (OverviewMountingPointListDialog)
// (m_bIsRequestedScheduleId_EqualTo_LoadedScheduleId==true)
// load another plan.... --> dialog should be closed
NGLTreeModel::resetModel();
m_rootItem->appendChild(m_visRoot);
const QMap<int, InfrastructureManagement::MainStructureElement> &mainStructEles = m_dtc->mainStructureElements();
// how do we get the aimState?
// via m_dataInterface->mountingPoint() (loaded schedule)
// or via schedule?
QHash<int32_t, MountingPointPlan> mountingPointPlanCont;
if (!m_bIsRequestedScheduleId_EqualTo_LoadedScheduleId)
{
// prepare MountingPointPlan of schedule to speed up access:
const InfrastructureManagement::MainSchedule &currentSchedule = m_dtc->mainSchedule(m_scheduleId);
for (const MountingPointPlan &mpp : qAsConst(currentSchedule.elements()))
mountingPointPlanCont.insert(mpp.structureElementId(), mpp);
}
// QSet<int> includedMountingPointIds;
// includedMountingPointIds.reserve(currentSchedule.elements().size());
// for (const InfrastructureManagement::MountingPointPlan &currentPlan : currentSchedule.elements())
// includedMountingPointIds.insert(currentPlan.structureElementId());
// qCritical() << " includedMountingPointIds " << includedMountingPointIds.size();
// cfroebel 2018-11-07:
// The algorithm of building the tree structure assumes that
// the StructureElements are hierarchically ordered, i.e. that the
// MountingPoint comes after its Room, Level and Building.
// Is that guaranteed by the service?
for (const MainStructureElement &mse : mainStructEles)
{
// only consider buildings
if (mse.structureElementTypeId() != StructureElementType::Building)
continue;
// 1- if a buildingGroup modelIndex for current building dosen't exist
// a new one will be first added and used as parentIndex for the blg_Index.
QModelIndex groupIndex;
const StructureElement bse= setBuildingGroup(mse.groupId());
if (m_availableBuildingGroups.contains(bse.id()) == false)
{
OverviewSimpleBuildingGroupData buildingGroup;
buildingGroup.name = QString::fromStdString(bse.displayName());
buildingGroup.id = bse.id();
NGLTreeItem *groupItem = new NGLTreeItem(QVariant::fromValue(buildingGroup));
QModelIndex groupParentIndex;
groupParentIndex = indexFromItem(m_visRoot);
insertRow(rowCount(groupParentIndex), groupParentIndex, groupItem);
groupIndex = index(groupItem->row(), 0, groupParentIndex);
m_mountingPointIndexes.insert(bse.id(), groupIndex);
m_availableBuildingGroups.insert(bse.id());
}
else
{
groupIndex = m_mountingPointIndexes.value(bse.id(), indexFromItem(m_visRoot));
}
for (const StructureElement &currentElement : mse.elements())
{
NGLTreeItem *item = nullptr;
if (currentElement.structureElementTypeId() == StructureElementType::MountingPoint)
{
MountingPoint mountingPoint = m_dataInterface->mountingPoint(currentElement.id());
if (!mountingPoint.isValid())
continue;
if (mountingPoint.type() == MountingPointType::Unknown ||
mountingPoint.type() == MountingPointType::BuildingControlUnit ||
mountingPoint.type() == MountingPointType::VirtualIPS ||
mountingPoint.type() == MountingPointType::MeteoDataUnit)
continue;
OverviewSimpleMountingPointData mpData;
mpData.seType = currentElement.structureElementTypeId();
mpData.id = mountingPoint.id();
mpData.name = mountingPoint.name();
mpData.mpType = mountingPoint.type();
mpData.hasAsset = mountingPoint.hasAssociatedAsset();
if (m_bIsRequestedScheduleId_EqualTo_LoadedScheduleId)
{
mpData.aimState = mountingPoint.aimState(); // mountingPoint.aimState was set according the loaded schedule!!!
} else {
// neu:
const int32_t mpId_StructEleId = mountingPoint.id();
if (mountingPointPlanCont.contains(mpId_StructEleId))
{
const MountingPointPlan &mpp = mountingPointPlanCont.value(mpId_StructEleId);
mpData.aimState = mpp.mountingPointState();
} else {
mpData.aimState = MountingPointState_def::Idle;
}
}
item = new NGLTreeItem(QVariant::fromValue(mpData));
}
else
{
OverviewSimpleStructureElementData ssed;
if (currentElement.structureElementTypeId() == StructureElementType::Floor)
ssed.floor = QString::fromStdString(currentElement.name()).split(QLatin1Literal("_")).value(1, QLatin1String("-10")).toInt();
else
ssed.floor = -20;
ssed.name = currentElement.displayName().empty() ? QString::fromStdString(currentElement.name()) : QString::fromStdString(currentElement.displayName());
item = new NGLTreeItem(QVariant::fromValue(ssed));
}
const auto &path = currentElement.path();
QModelIndex parentIndex;
if (path.size() > 1)
{
parentIndex = m_mountingPointIndexes.value(path.at(path.size() - 2), indexFromItem(m_visRoot)); //default sollte nie erreicht werden
if (!parentIndex.isValid())
{
ERROR_LOG(m_logger) << "Did not find parent for structure element with id " << currentElement.id() << " mseid: " << mse.id();
for (const StructureElement &se : mse.elements())
ERROR_LOG(m_logger) << " se: " << se.id() << ", " << se.displayName() << ", " << se.name();
}
}
else
{
if (groupIndex.isValid())
{
parentIndex = groupIndex;
}
else
{
parentIndex = indexFromItem(m_visRoot);
}
}
insertRow(rowCount(parentIndex), parentIndex, item);
m_mountingPointIndexes.insert(currentElement.id(), index(item->row(), 0, parentIndex));
}
}
m_availableFloors << -10;
#ifdef BENCHMARK
const InfrastructureManagement::MainSchedule &currentSchedule = m_dtc->mainSchedule(m_scheduleId);
qCritical() << " ViewMountingPointListModel::initData-BENCHMARK: m_scheduleId=" << currentSchedule.id();
qCritical() << " ViewMountingPointListModel::initData-BENCHMARK: m_scheduleId=" << currentSchedule.name().c_str();
qCritical() << " ViewMountingPointListModel::initData-BENCHMARK: m_scheduleId=" << m_scheduleId << " took " << elapsedTimer1.elapsed() << " [ms]";
#endif // BENCHMARK
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool ViewMountingPointListModel::mountingPointHasAssetMounted(int32_t mountingPointId, const QMap<qint32, MountingPointAsset> &mountingPointAssetMap)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
for (const MountingPointAsset &mpa : mountingPointAssetMap)
{
if (mpa.structureElementId() == mountingPointId)
return true;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return false;
}
Qt::ItemFlags ViewMountingPointListModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags fl = NGLTreeModel::flags(index);
if (!index.isValid())
return fl;
NGLTreeItem *item = privateData(index);
bool isLeaf = item->data().canConvert<OverviewSimpleMountingPointData>();
if (isLeaf && index.column() == Columns::NAME)
return fl | Qt::ItemIsUserCheckable | Qt::ItemIsUserTristate;
return fl;
}
void ViewMountingPointListModel::onMountingPointChanged(const MountingPoint &mountingPoint, DataModification modType)
{
if (modType != DataModification::eModified)
return;
QModelIndex index = m_mountingPointIndexes.value(mountingPoint.id());
if (!index.isValid())
return;
NGLTreeItem *item = privateData(index);
if (!(item && item->data().canConvert<OverviewSimpleMountingPointData>()))
return;
OverviewSimpleMountingPointData mpData = item->data().value<OverviewSimpleMountingPointData>();
mpData.name = mountingPoint.name();
if (m_bIsRequestedScheduleId_EqualTo_LoadedScheduleId)
mpData.aimState = mountingPoint.aimState();
item->setData(QVariant::fromValue(mpData));
m_dataChangedTimer->start();
}
void ViewMountingPointListModel::emitDataChanged()
{
QModelIndex vri = getIndexOfVisableRootItem();
emit dataChanged(vri, index(rowCount(vri) -1, Columns::STATE, vri), {Qt::DisplayRole, Qt::CheckStateRole});
}
void ViewMountingPointListSortModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<ViewMountingPointListModel*>(sourceModel);
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(sourceModel);
}
void ViewMountingPointListSortModel::setTypeFilter(const QSet<MountingPointType> &visibleTypes)
{
if (m_visibleTypes == visibleTypes)
return;
m_visibleTypes = visibleTypes;
invalidateFilter();
}
void ViewMountingPointListSortModel::addToTypeFilter(MountingPointType mpt, bool bAdd)
{
auto visibleTypes = m_visibleTypes;
if (bAdd)
{
// TODO: outdoor / indoor ips should be unified
if(mpt == MountingPointType::IndoorIPS)
{
visibleTypes.insert(MountingPointType::OutdoorIPS);
}
visibleTypes.insert(mpt);
}
else
{
if(mpt == MountingPointType::IndoorIPS)
{
visibleTypes.remove(MountingPointType::OutdoorIPS);
}
visibleTypes.remove(mpt);
}
setTypeFilter(visibleTypes);
}
bool ViewMountingPointListSortModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (!m_sourceModel)
return true;
bool isRootItem = !source_parent.isValid();
if (isRootItem)
{
Q_ASSERT(source_row == 0);
return true; // root item shall always be visible
}
const QModelIndex childIdx = m_sourceModel->index(source_row, 0, source_parent);
const NGLTreeItem *itemChild = m_sourceModel->privateData(childIdx);
Q_ASSERT(itemChild);
bool isLeaf = itemChild->data().canConvert<OverviewSimpleMountingPointData>();
if (isLeaf)
{
const OverviewSimpleMountingPointData data = itemChild->data().value<OverviewSimpleMountingPointData>();
Q_ASSERT(data.isMountingPoint());
bool visible = false;
if (data.aimState == m_mnpState && m_mnpState == MountingPointState::Equipped)
{
if (!data.hasAsset)
visible = true;
}
else if (data.aimState == m_mnpState && m_mnpState == MountingPointState::Empty)
{
if (data.hasAsset)
visible = true;
}
return m_visibleTypes.contains(data.mpType) && visible;//(data.aimState == m_mnpState);
}
else
{
if (!itemChild->data().canConvert<OverviewSimpleStructureElementData>() &&
!itemChild->data().canConvert<OverviewSimpleBuildingGroupData>())
return true;
}
// Qt5.11: setRecursiveFilteringEnabled(true);
for (int i = 0; i < itemChild->childCount(); ++i)
{
if (filterAcceptsRow(i, childIdx))
return true;
}
return false;
}
bool ViewMountingPointListSortModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_sourceModel || source_left.column() != source_right.column())
return BaseClass::lessThan(source_left, source_right);
const NGLTreeItem *itemLeft = m_sourceModel->privateData(source_left);
const NGLTreeItem *itemRight = m_sourceModel->privateData(source_right);
if (!itemLeft || !itemRight)
return BaseClass::lessThan(source_left, source_right);
if (itemLeft->data().canConvert<OverviewSimpleBuildingGroupData>())
{
const OverviewSimpleBuildingGroupData left = itemLeft->data().value<OverviewSimpleBuildingGroupData>();
const OverviewSimpleBuildingGroupData right = itemRight->data().value<OverviewSimpleBuildingGroupData>();
if (left.name != right.name)
return left.name < right.name;
}
else if (itemLeft->data().canConvert<OverviewSimpleStructureElementData>())
{
const OverviewSimpleStructureElementData left = itemLeft->data().value<OverviewSimpleStructureElementData>();
const OverviewSimpleStructureElementData right = itemRight->data().value<OverviewSimpleStructureElementData>();
if (left.name != right.name)
return left.name < right.name;
}
const OverviewSimpleMountingPointData left = itemLeft->data().value<OverviewSimpleMountingPointData>();
const OverviewSimpleMountingPointData right = itemRight->data().value<OverviewSimpleMountingPointData>();
if (left.name != right.name)
return left.name < right.name;
return left.id < right.id;
}
}// namespace InfrastructureManagement
@@ -0,0 +1,184 @@
/**
* @RDE_HEADER@
* tbc
* $Id$
* $HeadURL$
* $Author$
* Created by
*/
#pragma once
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
#include <QSet>
#include <nglwidgets/ngltreemodel.h>
#include <nglwidgets/ngltreeitem.h>
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <LtsWidgets/lts_column_filter_proxy_model.h>
#include <LtsDataView/check_state_proxy_model.h>
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
struct OverviewSimpleMountingPointData
{
QString name;
int32_t id = 0; // StructureElementId
StructureElementType seType;
MountingPointType mpType;
MountingPointState aimState;
bool hasAsset = false;
bool isMountingPoint() const { return seType == StructureElementType::MountingPoint; }
};
struct OverviewSimpleBuildingGroupData
{
QString name;
int id;
};
struct OverviewSimpleStructureElementData
{
QString name;
int floor;
};
class ViewMountingPointListModel final : public NGLTreeModel
{
Q_OBJECT
public:
public:
enum Columns
{
NAME,
TYPE,
STATE
};
explicit ViewMountingPointListModel(QObject *parent = nullptr);
/**
* Handles the representation of data.
* In case of CheckStateRole only leafs will be handled.
* Nodes are handled in the upstream CheckStateProxyModel class.
* @param[in] index item index to be handled
* @param[in] role role to which the data relates
*
*/
QVariant data(const QModelIndex &index, int role) const override final;
bool initModel(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<ForeignDataInterface> &dataInterface,
int32_t requestedScheduleId);
QModelIndex getIndexOfVisableRootItem() const;
/**
* Sets only the leafs of the tree view to Qt::ItemIsUserCheckable.
* Nodes are handled in the upstream CheckStateProxyModel class.
* @param[in] index item index to be handled
*
*/
Qt::ItemFlags flags(const QModelIndex &index) const override final;
/**
* Sets the check state data according to their check box in the internal model.
* CheckState data can be set for leafs only.
* Nodes are handled in the upstream CheckStateProxyModel class.
* @param[in] index item index to be handled
* @param[in] value value to be set
* @param[in] role role to which the data relates (here especially Qt::CheckStateRole)
*
*/
//bool setData(const QModelIndex &index, const QVariant &value, int role) override;
bool mountingPointHasAssetMounted(int32_t mountingPointId, const QMap<qint32, MountingPointAsset> &mountingPointAssetMap);
static const int maxIntValue = std::numeric_limits<int>::max();
public Q_SLOTS:
void onMountingPointChanged(const MountingPoint &mountingPoint, DataModification modType);
private Q_SLOTS:
// void onScheduleIdChanged(int32_t scheduleId);
void emitDataChanged();
private:
void initData();
void initMountedData();
void initUnmountedData();
friend class ViewMountingPointListSortModel;
QSet<int> m_availableBuildingGroups;
NGLTreeItem *m_visRoot;
NGLTreeItem *m_mountedParent;
NGLTreeItem *m_unmountedParent;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> m_dataInterface;
int32_t m_scheduleId{-1};
bool m_bIsRequestedScheduleId_EqualTo_LoadedScheduleId{false};
QHash<int, QModelIndex> m_mountingPointIndexes;
QHash<int, QModelIndex> m_mountedPointIndexes;
QHash<int, QModelIndex> m_unmountedPointIndexes;
QHash<int32_t, bool> m_mountingPointHasAssetMounted;
QSet<int> m_availableFloors;
LOGGER_T m_logger;
QTimer *m_dataChangedTimer{nullptr};
}; // class OverViewDialogMountingPointListModel
//class ViewMountingPointListCheckStateModel final : public LtsDataView::CheckStateProxyModel
//{
// Q_OBJECT
//public:
// bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
//};
class ViewMountingPointListSortModel final : public LtsWidgets::LtsColumnFilterProxyModel
{
using BaseClass = LtsWidgets::LtsColumnFilterProxyModel;
Q_OBJECT
public:
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
void setSourceModel(QAbstractItemModel *sourceModel ) override;
void setTypeFilter(const QSet<MountingPointType> &visibleTypes);
void addToTypeFilter(MountingPointType mpt, bool bAdd);
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
using LtsWidgets::LtsColumnFilterProxyModel::invalidateFilter;
void setVisibleState(MountingPointState visibleState){m_mnpState = visibleState;}
private:
ViewMountingPointListModel *m_sourceModel = nullptr;
QSet<MountingPointType> m_visibleTypes;
QSet<int> m_visibleFloors;
MountingPointState m_mnpState;
};
} // namespace InfrastructureManagement
Q_DECLARE_METATYPE(InfrastructureManagement::OverviewSimpleMountingPointData)
Q_DECLARE_METATYPE(InfrastructureManagement::OverviewSimpleStructureElementData)
Q_DECLARE_METATYPE(InfrastructureManagement::OverviewSimpleBuildingGroupData)
@@ -0,0 +1,68 @@
/**
* @RDE_HEADER@
* PlanChooser - New Plan Dialog - Asks for Plan name
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2017-04-20
*/
#include "new_plan_dialog.h"
#include "ui_new_plan_dialog.h"
#include <LtsSession/lts_session.h>
#include <QDateTime>
namespace InfrastructureManagement
{
NewPlanDialog::NewPlanDialog(LtsSession::LtsSession *session, QWidget *parent)
: QDialog(parent)
, m_ui(new Ui::NewPlanDialog)
, m_session(session)
, m_logger(getLogger("NewPlanDialog"))
{
setWindowTitle(tr("Create New Plan"));
m_ui->setupUi(this);
connect(m_ui->pbCreate, &QPushButton::clicked, this, &NewPlanDialog::accept);
connect(m_ui->pbCancel, &QPushButton::clicked, this, &NewPlanDialog::reject);
Qt::WindowFlags wf = Qt::FramelessWindowHint; // make frameless, shadow replaces the border / frame
//setModal(true);
wf |= Qt::Dialog;
wf |= Qt::WindowStaysOnTopHint;
setWindowFlags(wf);
m_ui->dteBegin->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
m_ui->dteEnd->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
//m_ui->dteBegin->setMsecsSinceEpoch(QDateTime::currentMSecsSinceEpoch());
//m_ui->dteEnd->setMsecsSinceEpoch(QDateTime::currentMSecsSinceEpoch());
}
NewPlanDialog::~NewPlanDialog()
{
delete m_ui;
}
void NewPlanDialog::init(const std::shared_ptr<ForeignGuiComboboxInterface> &ismCbx)
{
ismCbx->fillScheduleStatusComboBox(m_ui->cbStatus);
m_ui->cbStatus->setCurrentIndex(m_ui->cbStatus->findData(ScheduleStatus::Inactive));
}
bool NewPlanDialog::getData(QString &name, qint64 &begin, qint64 &end, int &status)
{
if (exec() != QDialog::Accepted)
return false;
name = m_ui->lePlanName->text();
begin = m_ui->dteBegin->msecsSinceEpoch();
end = m_ui->dteEnd->msecsSinceEpoch();
status = static_cast<ScheduleStatus::type>(m_ui->cbStatus->currentData().toInt());
return true;
}
} // namespace InfrastructureManagement
@@ -0,0 +1,45 @@
/**
* @RDE_HEADER@
* PlanChooser - New Plan Dialog - Asks for Plan name
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2017-04-20
*/
#pragma once
#include <InfrastructureManagement/logger.h>
#include <InfrastructureManagement/ism_combobox_gui_plugin_interface.h>
#include <Plugins/InfrastructureManagement/Data/ism_data_plugin.h>
#include <Plugins/InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <QDialog>
namespace Ui
{
class NewPlanDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
class NewPlanDialog : public QDialog
{
Q_OBJECT
public:
explicit NewPlanDialog(LtsSession::LtsSession *session, QWidget *parent = nullptr);
~NewPlanDialog();
void init( const std::shared_ptr<ForeignGuiComboboxInterface> &ismCbx);
bool getData(QString &name, qint64 &begin, qint64 &end, int &status);
private:
Ui::NewPlanDialog* m_ui;
std::shared_ptr<ForeignGuiComboboxInterface> m_ismGuiCbx{nullptr};
LtsSession::LtsSession *m_session{nullptr};
LOGGER_T m_logger;
};
}
@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewPlanDialog</class>
<widget class="QDialog" name="NewPlanDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>304</width>
<height>238</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>RME EXCON - Exercise Chooser</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0,0,0,0,0,0">
<item>
<widget class="QLabel" name="lblName">
<property name="text">
<string>Name for new Plan:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lePlanName"/>
</item>
<item>
<widget class="QLabel" name="lblStatus">
<property name="text">
<string>Status:</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsComboBox" name="cbStatus"/>
</item>
<item>
<widget class="QLabel" name="lblBegin">
<property name="text">
<string>Begin</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsDateTimeEdit" name="dteBegin" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblEnd">
<property name="text">
<string>End</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsDateTimeEdit" name="dteEnd" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pbCreate">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbCancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsDateTimeEdit</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_date_time_edit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,143 @@
/**
* @RDE_HEADER@
* PlanChooser Payload UI
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, SLSE, 2016-08-12
*/
#include "plan_chooser.h"
#include "ui_plan_chooser.h"
#include "ism_plan_dialog_model.h"
#include "CustomViews/ism_schedule.h"
#include <LtsSession/lts_session_manager.h>
#include <LtsSession/lts_session.h>
#include <ConnectDialog/connect_dialog_nt.h>
#include <LtsWidgets/lts_global_wait_dialog.h>
#include <QCloseEvent>
#include <QPushButton>
#define DEVEL
namespace InfrastructureManagement
{
PlanChooser::PlanChooser(const std::shared_ptr<Interface::Dtc> &dtc, QWidget *parent)
: QDialog(parent)
, m_ui(new Ui::PlanChooser)
, m_model(nullptr)
, m_dtc(dtc)
, m_selected(false)
, m_logger(getLogger("PlanChooser"))
{
LtsWidgets::LtsGlobalWaitDialog::getInstance()->setVisible(false);
m_ui->setupUi(this);
setWindowTitle(tr("Select Instrumentation Plan"));
setWindowFlags(windowFlags() | /*Qt::WindowStaysOnTopHint | */Qt::FramelessWindowHint); // hints..
m_ui->widget->seamless();
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
this, &PlanChooser::enaDisa, Qt::QueuedConnection);
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked,
this, &PlanChooser::slotPlanSelected, Qt::QueuedConnection);
connect(m_ui->pbNewPlan, &QPushButton::clicked,
this, &PlanChooser::signalNewPlan); //[this]() { emit signalNewPlan(); });
connect(m_ui->pbSelect, &QPushButton::clicked,
this, &PlanChooser::slotPlanSelected, Qt::QueuedConnection);
connect(m_ui->pbCancel, &QPushButton::clicked,
this, &PlanChooser::signalQuit, Qt::QueuedConnection);
connect(m_ui->pbCancel, &QPushButton::clicked,
this, [this]()
{
LtsWidgets::LtsGlobalWaitDialog::getInstance()->setVisible(true);
m_close = true;
close();
});
new LtsUtils::ConnectingDialogNT([this](int timeWait) { return m_dtc->waitForHistoricalDataMainSchedule(timeWait); }, tr("Infrastructure Management"), tr("Global"), parent);
}
bool PlanChooser::init(LtsSession::LtsSession *session)
{
m_session = session;
delete m_model;
m_model = new PlanDialogModel(this);
m_model->initModel(m_dtc);
m_ui->widget->selectCustomView();
m_ui->widget->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
m_ui->widget->setModel(m_model, [this]() { return new CustomViewSchedule(this); });
for (int i = 0; i < m_model->columnCount(); ++i)
m_ui->widget->hideColumn(i);
m_ui->widget->showColumn(PlanDialogModel::NAME);
return true;
}
PlanChooser::~PlanChooser()
{
LtsWidgets::LtsGlobalWaitDialog::getInstance()->setVisible(true);
delete m_ui;
}
void PlanChooser::reject()
{
if (!m_selected)
emit signalQuit();
QDialog::reject();
}
void PlanChooser::enaDisa()
{
//const QModelIndex idx = m_ui->widget->currentIndex();
//const MainSchedule ms = m_model->getRowData(idx.row());
m_ui->pbSelect->setEnabled(m_ui->widget->selectedRows().size() == 1);
}
void PlanChooser::closeEvent(QCloseEvent *event) // TODO: override reject()
{
if (!m_close)
event->ignore();
}
void PlanChooser::slotPlanSelected()
{
const QModelIndex idx = m_ui->widget->currentIndex();
const MainSchedule ms = m_model->getRowData(idx.row());
int id = ms.id();
if (id <= 0)
return;
m_selected = true;
emit signalSelectPlan(id);
m_close = true;
close();
}
void PlanChooser::selectPlan(int planId)
{
m_selected = true;
emit signalSelectPlan(planId);
m_close = true;
close();
}
} // namespace InfrastructureManagement
@@ -0,0 +1,65 @@
/**
* @RDE_HEADER@
* PlanChooser Payload UI
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2016-11-02
*/
#pragma once
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
#include <InfrastructureManagement/logger.h>
#include <QDialog>
namespace Ui
{
class PlanChooser;
}
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
class PlanDialogModel;
class PlanChooser : public QDialog // TODO: move me directly to Gui ?
{
Q_OBJECT
public:
explicit PlanChooser(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &dtc, QWidget *parent = nullptr);
~PlanChooser();
bool init(LtsSession::LtsSession *session);
void selectPlan(int planId);
private:
Ui::PlanChooser *m_ui{nullptr};
PlanDialogModel *m_model{nullptr};
LtsSession::LtsSession *m_session{nullptr};
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_dtc{nullptr};
bool m_close{false};
bool m_selected{false};
LOGGER_T m_logger;
protected:
void closeEvent(QCloseEvent *event) override;
private Q_SLOTS:
void slotPlanSelected();
void enaDisa();
void reject() override;
Q_SIGNALS:
void signalNewPlan();
void signalSelectPlan(int planId);
void signalQuit();
};
}
@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PlanChooser</class>
<widget class="QDialog" name="PlanChooser">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>758</width>
<height>521</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>RME EXCON - Plan Chooser</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Login to Plan:</string>
</property>
</widget>
</item>
<item>
<widget class="LtsDataView::LtsDataView" name="widget">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>600</width>
<height>300</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pbCancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pbNewPlan">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Add new Plan</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbSelect">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Select</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,111 @@
/**
* @RDE_HEADER@
* The ScheduleDifferencesListDialog shows differences for an incomplete instrumentation plan (schedule)
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLTE, 2021-08-24
*/
#include "ism_schedule_differences_list_dialog.h"
#include "ui_ism_schedule_differences_list_dialog.h"
#include "ism_schedule_differences_list_model.h"
#include <InfrastructureManagement/ism_translation.h>
#include <LtsPrinting/printing.h>
#include <ngltools/ngltools_dtg.h>
#include <QTreeView>
using namespace InfrastructureManagement;
ScheduleDifferencesListDialog::ScheduleDifferencesListDialog(const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkCancel)
, m_ui(new Ui::ScheduleDifferencesListDialog)
, m_sourceModel(nullptr)
, m_menuGroup(menuGroup)
, m_logger(getLogger("ScheduleDifferencesListDialog"))
{
m_ui->setupUi(this);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Completeness_Check"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &ScheduleDifferencesListDialog::onPrint);
}
ScheduleDifferencesListDialog::~ScheduleDifferencesListDialog()
{
if (m_sourceModel)
{
delete m_sourceModel;
m_sourceModel = nullptr;
}
delete m_ui;
}
void ScheduleDifferencesListDialog::retranslate()
{
translate(m_ui, tr("Completeness Check: %1").arg(QString::fromStdString(m_dtc->mainSchedule(m_scheduleId).name())));
}
bool ScheduleDifferencesListDialog::init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
int scheduleId)
{
m_dtc = dtc;
m_session = session;
m_scheduleId = scheduleId;
if (m_scheduleId <= 0)
{
ERROR_LOG(m_logger) << "Invalid id for Instrumentation plan: " << m_scheduleId;
return false;
}
connect(m_dtc.get(), &Interface::Dtc::mainScheduleChanged, this, &ScheduleDifferencesListDialog::dataChanged);
m_sourceModel = new ScheduleDifferencesListDialogModel(this);
if (!m_sourceModel->initModel(m_scheduleId, m_dtc))
{
ERROR_LOG(m_logger) << "Could not init ScheduleDifferencesListDialogModel";
delete m_sourceModel;
m_sourceModel = nullptr;
return false;
}
m_ui->mpDifferencesListView->setModel(m_sourceModel);
return true;
}
void ScheduleDifferencesListDialog::dataChanged(const InfrastructureManagement::MainSchedule &data, DataModification modType)
{
Q_UNUSED(modType);
if (data.id() == m_scheduleId)
m_sourceModel->initModel(m_scheduleId, m_dtc);
}
void ScheduleDifferencesListDialog::onPrint()
{
MainSchedule ms = m_dtc->mainSchedule(m_scheduleId);
QString header;
header += QStringLiteral("<p>");
header += QStringLiteral("<b>") + tr("Differences List - Plan incomplete") + QStringLiteral("</b>");
header += QStringLiteral("<hr/>");
header += tr("Instrumentation Plan: %1").arg(QString::fromStdString(ms.name()));
header += QStringLiteral("<br/>");
header += tr("Status: %1").arg(toString(ms.statusId()));
header += QStringLiteral("<br/>");
header += tr("Created: %1").arg(DTG::toStringMSec(ms.timeCreated()));
header += QStringLiteral("<br/>");
if (ms.timeStart().is_set())
header += tr("START: %1").arg(DTG::toStringMSec(ms.timeStart().get()));
else
header += tr("START: %1").arg(tr("[N/A]"));
header += QStringLiteral(" - ");
if (ms.timeEnd().is_set())
header += tr("END: %1").arg(DTG::toStringMSec(ms.timeEnd().get()));
else
header += tr("END: %1").arg(tr("[N/A]"));
header += QStringLiteral("<br/>");
header += QStringLiteral("</p>");
LtsPrinting::printView(m_session, this, m_ui->mpDifferencesListView->treeView(), header);
}
@@ -0,0 +1,59 @@
/**
* @RDE_HEADER@
* The ScheduleDifferencesListDialog shows differences for an incomplete instrumentation plan (schedule)
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLTE, 2021-08-24
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
namespace Ui
{
class ScheduleDifferencesListDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
class ScheduleDifferencesListDialogModel;
class ScheduleDifferencesListDialog final
: public LtsWidgets::LtsDialog
{
Q_OBJECT
public:
explicit ScheduleDifferencesListDialog(const QString &menuGroup, QWidget *parent = nullptr);
~ScheduleDifferencesListDialog();
bool init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
int scheduleId);
private: // methods
void retranslate() override;
void dataChanged(const InfrastructureManagement::MainSchedule &data, DataModification modType);
private slots:
void onPrint();
private: // attributes
Ui::ScheduleDifferencesListDialog *m_ui{nullptr};
ScheduleDifferencesListDialogModel *m_sourceModel{nullptr};
std::shared_ptr<Interface::Dtc> m_dtc{nullptr};
QString m_menuGroup;
LtsSession::LtsSession *m_session{nullptr};
int m_scheduleId{-1};
LOGGER_T m_logger;
}; // class ScheduleDifferencesListDialog
} // namespace InfrastructureManagement
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ScheduleDifferencesListDialog</class>
<widget class="QWidget" name="ScheduleDifferencesListDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1169</width>
<height>517</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Differences</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="LtsDataView::LtsDataView" name="mpDifferencesListView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="rootIsDecorated">
<bool>true</bool>
</property>
<property name="showColumnCount" stdset="0">
<bool>false</bool>
</property>
<property name="toolButtonsVisible">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,112 @@
/**
* @RDE_HEADER@
* The ScheduleDifferencesListDialogModel provices data for ScheduleDifferencesListDialog
* Modified version using the checkStateProxyModel to allow setting via the checkboxes of the tree structure hjl 5/19
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLTE, 2021-08-24
*/
#include "ism_schedule_differences_list_model.h"
#include <InfrastructureManagement/ism_translation.h>
#include <InfrastructureManagement/Shared/ism_mounting_point.h>
#include <LtsCoordTrans/lts_coord_trans.h>
namespace InfrastructureManagement
{
ScheduleDifferencesListDialogModel::ScheduleDifferencesListDialogModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<MountingPointPlan>({tr("Id"),
tr("Name"),
tr("Type"),
tr("Building"),
tr("Position"),
tr("Aim State"),
tr("Current State"),
tr("Asset Id"),
tr("Asset Name")},
parent)
, m_logger(getLogger("ScheduleDifferencesListDialogModel"))
{
}
QVariant ScheduleDifferencesListDialogModel::data(const QModelIndex &index, int role) const
{
if (!(index.isValid() && role == Qt::DisplayRole))
return QVariant();
MountingPointPlan item = m_vecData.at(index.row());
InfrastructureManagement::StructureElement se;
m_dtc->getStructureElementById(item.structureElementId(), se);
int assetId = m_dtc->getMountedAssetId(item.structureElementId());
switch (index.column())
{
case SE_ID:
return item.structureElementId();
case SE_TYPE:
return InfrastructureManagement::toString(se.mountingPointTypeId());
case SE_NAME:
return QString::fromStdString(se.displayName().size() > 0 ? se.displayName() : se.name());
case MSE_NAME:
return m_dtc->getBuildingDisplayName(se.mainStructureElementId());
case SE_POS:
return LtsCoordTrans::mgrsFromGeographic(se.geoPosition().lon(), se.geoPosition().lat());
case MP_AIM_STATE:
return InfrastructureManagement::toString(item.mountingPointState());
case MP_CURRENT_STATE: // opposite as desired
if (item.mountingPointState() == MountingPointState::Equipped)
return InfrastructureManagement::toString(MountingPointState::Empty);
if (item.mountingPointState() == MountingPointState::Empty)
return InfrastructureManagement::toString(MountingPointState::Equipped);
return {};
case ASSET_ID:
if (assetId > 0)
return assetId;
return {};
case ASSET_NAME:
if (assetId > 0)
return QString::fromStdString(m_dtc->instrumentationAsset(assetId).name());
}
return QVariant();
}
bool ScheduleDifferencesListDialogModel::initModel(int scheduleId,
const std::shared_ptr<Interface::Dtc> &dtc)
{
clear();
m_dtc = dtc;
m_scheduleId = scheduleId;
if (m_scheduleId <= 0)
{
ERROR_LOG(m_logger) << "Invalid scheduleId = " << m_scheduleId;
return false;
}
QList<MountingPointPlan> diff;
bool isComplete = m_dtc->getScheduleDifferences(m_scheduleId, diff);
DEBUG_LOG(m_logger) << "Plan id = " << m_scheduleId << ", Differences = " << diff.size();
if (isComplete)
{
WARNING_LOG(m_logger) << "Instrumentation plan is complete. No differences to show.";
return false;
}
for (const MountingPointPlan &mpp : qAsConst(diff))
{
DEBUG_LOG(m_logger) << "Adding to model MPP = " << mpp.id();
insertRow(mpp);
}
DEBUG_LOG(m_logger) << "initModel successful";
return true;
}
} // namespace InfrastructureManagement
@@ -0,0 +1,47 @@
/**
* @RDE_HEADER@
* The ScheduleDifferencesListDialogModel provices data for ScheduleDifferencesListDialog
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLTE, 2021-08-24
*/
#pragma once
#include <InfrastructureManagement/logger.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <LtsWidgets/lts_abstract_table_model.h>
namespace InfrastructureManagement
{
class ScheduleDifferencesListDialogModel : public LtsWidgets::LtsAbstractTableModel<MountingPointPlan>
{
Q_OBJECT
public:
enum Columns
{
SE_ID,
SE_NAME,
SE_TYPE,
MSE_NAME,
SE_POS,
MP_AIM_STATE,
MP_CURRENT_STATE,
ASSET_ID,
ASSET_NAME
};
explicit ScheduleDifferencesListDialogModel(QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role) const override;
bool initModel(int scheduleId, const std::shared_ptr<Interface::Dtc> &dtc);
private:
int m_scheduleId{-1};
std::shared_ptr<Interface::Dtc> m_dtc{nullptr};
LOGGER_T m_logger;
}; // class ScheduleDifferencesListDialogModel
} // namespace InfrastructureManagement
@@ -0,0 +1,38 @@
#include "ism_plan_tln_delegate.h"
#include <LtsTimeline/timeline_header_view.h>
#include <QGuiApplication>
#include <QModelIndex>
#include <QPainter>
#include <QStyleOptionViewItem>
namespace InfrastructureManagement
{
PlanTimelineDelegate::PlanTimelineDelegate(LtsTimeline::TimelineView *view)
: LtsTimeline::ItemDelegate(view)
{}
void PlanTimelineDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
LtsTimeline::ItemDelegate::paint(painter, option, index);
if (index.column() == LtsTimeline::Section::eActuator)
{
painter->save();
painter->setPen(QPen(QGuiApplication::palette().color(QPalette::Text), 2));
painter->drawLine(option.rect.topRight(), option.rect.bottomRight());
painter->restore();
return;
}
painter->save();
painter->setPen(Qt::black);
painter->setBrush(QBrush(Qt::transparent));
painter->drawLine(option.rect.left(), option.rect.bottom(), option.rect.right(), option.rect.bottom());
painter->restore();
}
} // namespace InfrastructureManagement
@@ -0,0 +1,21 @@
#pragma once
#include <LtsTimeline/item_delegate.h>
namespace InfrastructureManagement
{
class PlanTimelineDelegate : public LtsTimeline::ItemDelegate
{
Q_OBJECT
public:
explicit PlanTimelineDelegate(LtsTimeline::TimelineView *view = nullptr);
private:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,360 @@
/**
* @RDE_HEADER@
* Plans Overview Timeline Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Steve Kemayou, SLTE, 2021-07-26
*/
#include "ism_plan_tln_dialog.h"
#include "ui_ism_plan_tln_dialog.h"
#include "ism_plan_dialog.h"
#include "ism_plan_tln_delegate.h"
#include <InfrastructureManagement/logger.h>
#include <LtsSession/lts_session.h>
#include <LtsWidgets/lts_base_layout_widget.h>
#include <InfrastructureManagement/ism_ftc.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/ism_enums.hpp>
#include <InfrastructureManagement/settings.h>
#include <QScrollBar>
namespace InfrastructureManagement
{
static LtsTimeline::Zoom::Factor s_zoomFactor = LtsTimeline::Zoom::OneDay;
PlanTimeLineDialog::PlanTimeLineDialog(LtsSession::LtsSession *session, const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_session(session)
, m_menuGroup(menuGroup)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_ui(new Ui::PlanTimeLineDialog)
, m_logger(getLogger(QStringLiteral("PlanTimeLineDialog")))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " ";
m_ui->setupUi(this);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load, this, &PlanTimeLineDialog::onLoad);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Save, this, &PlanTimeLineDialog::onApply);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &PlanTimeLineDialog::onRemove);
m_buttonBox->getButton(LtsWidgets::DialogButton::Save)->setText(tr("Apply"));
//default disabled
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, false);
s_zoomFactor = LtsTimeline::Zoom::OneDay;
setOnlineHelpFilename(QStringLiteral("Ressourcen-Timeline"));
}
PlanTimeLineDialog::~PlanTimeLineDialog()
{
delete m_ui;
}
bool PlanTimeLineDialog::init(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &dtc, const std::shared_ptr<Interface::Ftc> &ftc, const std::shared_ptr<ForeignDataInterface> &dataInterface, InfrastructureManagement::ForeignResourceManagementGuiInterface *ismGuiIfc)
{
DEBUG_LOG(m_logger) << "Start init FileManagementDialogWidget...";
m_dtc = dtc;
m_ftc = ftc;
m_dataIfc = dataInterface;
m_ismGuiIfc = ismGuiIfc;
bool bRet = true;
bRet &= m_dtc->enableMainSchedule();
bRet &= m_dtc->enableMainStructureElement();
bRet &= m_ftc->enableInstrumentationAssetModify();
bRet &= m_ftc->enableMainScheduleRemove();
if (!bRet)
{
ERROR_LOG(m_logger) << "Could not enable DTC/FTC from ISM";
return false;
}
m_scheduleId = m_dataIfc->scheduleId();
connect(m_dataIfc.get(), &ForeignDataInterface::scheduleIdChanged,
this, &PlanTimeLineDialog::onScheduleIdChanged);
connect(m_dtc.get(), &Interface::Dtc::mainScheduleChanged,
this, &PlanTimeLineDialog::onMainScheduleChanged);
// timeline model initialization
if (m_model != nullptr)
delete m_model;
m_model = new PlanTimelineModel(m_ui->timeline->view(), this);
if (!m_model->initModel(m_dtc, m_dataIfc))
{
ERROR_LOG(m_logger) << "Could not init model";
delete m_model;
m_model = nullptr;
return false;
}
m_ui->timeline->setModel(m_model);
#ifdef LTS_DEBUG
m_ui->timeline->showDebugWidget();
#endif
m_ui->timeline->header()->setLimitsVisible(true);
m_ui->timeline->setMinimumZoomFactor(LtsTimeline::Zoom::ceil(LtsTimeline::Zoom::OneDay));
m_ui->timeline->setZoomFactor(s_zoomFactor);
m_ui->timeline->view()->setItemDelegate(new PlanTimelineDelegate(m_ui->timeline->view()));
resizeView();
m_ui->timeline->show();
connect(m_ui->timeline->view(), &LtsTimeline::TimelineView::selectedItemsChanged,
this, &PlanTimeLineDialog::onItemsSelected);
connect(m_ui->timeline->view(), &LtsTimeline::TimelineView::currentItemTimeChanged,
this, &PlanTimeLineDialog::onCurrentItemChanged);
connect(m_ui->timeline->view(), &LtsTimeline::TimelineView::zoomChanged,
this, &PlanTimeLineDialog::onZoomChanged);
connect(m_ui->timeline->slider(), &QScrollBar::valueChanged,
this, &PlanTimeLineDialog::onSliderValueChanged);
setScheduleId(m_scheduleId);
m_ui->timeline->view()->setDragEnabled(false);
m_ui->timeline->timelineModel()->setEditable(true);
m_ui->timeline->view()->setDragDropMode(LtsTimeline::TimelineView::NoDragDrop);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, false);
return true;
}
void PlanTimeLineDialog::setScheduleId(const int scheduleId)
{
m_scheduleId = scheduleId;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismIfc;
if (!m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(ismIfc))
{
new LtsWidgets::LtsMessageDialogNew(this, tr("Infrastructure Management Interface is not available!"), tr("Cannot set Instrumentation Plan Id"));
return;
}
DEBUG_LOG(m_logger) << "ism_plan_tln_dialog: setScheduleId = " << m_scheduleId;
ismIfc->setScheduleId(m_scheduleId);
// set name to "title":
MainSchedule ms = ismIfc->mainSchedule(m_scheduleId);
QString msName = QString::fromStdString(ms.name());
if (m_session && m_session->baseLayout())
m_session->baseLayout()->setCustomText(tr("Instrumentation Plan: '%1'").arg(msName));
}
void PlanTimeLineDialog::retranslate()
{
//translate(m_ui, tr("Instrumentation Plan Timeline"));
translate(m_ui, m_dtc->mainSchedule(m_scheduleId), tr("Instrumentation Plan Timeline"));
}
void PlanTimeLineDialog::onLoad()
{
// get schedule id of selected item
int scheduleId = m_model->getScheduleIdOfItem(m_selectedItem);
if (scheduleId == -1)
{
ERROR_LOG(m_logger) << "onLoad failed: Could not find model for selected item:" << m_selectedItem;
return;
}
emit m_dataIfc.get()->scheduleIdChanged(scheduleId);
}
void PlanTimeLineDialog::onRemove()
{
if (m_scheduleId == -1)
return;
int scheduleId = m_model->getScheduleIdOfItem(m_selectedItem);
MainSchedule item = m_dtc->mainSchedule(scheduleId);
if (item.id() == m_scheduleId)
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot remove current Instrumentation Plan"));
return;
}
InstrumentationAssetModifyRequest req;
InstrumentationAsset asset;
for (const auto &element : qAsConst(item.elements()))
{
QMap<qint32, MountingPointAsset> mntPntAssets = m_dtc->mountingPointAssets();
for (const auto &mntPntAsset : qAsConst(mntPntAssets))
{
if (mntPntAsset.structureElementId() == element.structureElementId())
{
asset = m_dtc->instrumentationAsset(mntPntAsset.assetId());
req = InstrumentationAssetModifyRequest(
1,
asset.name(),
asset.mountingPointTypeId(),
asset.barcode(),
asset.hostname(),
asset.properties(),
InstrumentationAssetState_def::Unmounted, // <- unmount
asset.lastUpdated(),
asset.availableInExercise()
);
m_requestHelper->addRequest([req, this](){
return m_ftc->instrumentationAssetModifyRequest(req, this);
});
} // if
} // for
} // for
if (m_requestHelper->hasRequests())
m_requestHelper->startRequests();
// remove MainSchedule
Core::RemoveElementRequest rmReq{item.id()};
m_requestHelper->startSingleRequest([rmReq, this]()
{
return m_ftc->mainScheduleRemoveRequest(rmReq, this);
});
}
void PlanTimeLineDialog::onApply()
{
if (!m_model)
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Invalid model!"));
return;
}
QVector<int> itemIds = m_ui->timeline->timelineModel()->itemIds();
for (auto itemId : qAsConst(itemIds))
{
int seId = m_model->getScheduleIdOfItem(itemId);
if (seId == -1)
{
WARNING_LOG(m_logger) << "Could not find schedule for item id:" << itemId;
continue;
}
InfrastructureManagement::MainSchedule mse = m_dtc->mainSchedule(seId);
InfrastructureManagement::MainScheduleModifyRequest data;
qint64 timeStart = m_ui->timeline->timelineModel()->item(itemId).startTime();
qint64 timeEnd = timeStart + m_ui->timeline->timelineModel()->item(itemId).duration();
data.id(mse.id());
data.name(mse.name());
data.statusId(mse.statusId());
data.exerciseId(mse.exerciseId());
data.timeCreated(mse.timeCreated());
data.timeStart(timeStart);
data.timeEnd(timeEnd);
data.description(mse.description());
m_requestHelper->addRequest([data, this](){
return m_ftc->mainScheduleModifyRequest(data, this);
});
}
if (m_requestHelper->hasRequests())
m_requestHelper->startRequests();
}
void PlanTimeLineDialog::onItemsSelected(const QVector<int> &itemIds)
{
if (itemIds.isEmpty())
{
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
}
else
{
m_ui->timeline->setCurrentTime(m_model->getStartTime() - 10'000);
m_selectedItem = itemIds.first();
int32_t seId = m_model->getScheduleIdOfItem(m_selectedItem);
if (m_scheduleId != seId && seId != -1)
{
MainSchedule mse = m_dtc->mainSchedule(seId);
if (mse.timeStart().is_set())
m_ui->timeline->setCurrentTime(mse.timeStart().get());
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, true);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, true);
}
else
{
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
}
}
}
void PlanTimeLineDialog::onScheduleIdChanged(int32_t id)
{
if (id == m_scheduleId)
return;
m_scheduleId = id;
setScheduleId(m_scheduleId);
m_ismGuiIfc->setPlanId(m_scheduleId);
updateTimeLine();
}
void PlanTimeLineDialog::onMainScheduleChanged(const MainSchedule &data, DataModification modType)
{
updateTimeLine();
Q_UNUSED(data);
Q_UNUSED(modType);
}
void PlanTimeLineDialog::updateTimeLine()
{
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, false);
if (m_scheduleId == -1)
{
ERROR_LOG(m_logger) << "Invalid schedule id: timeline update aborted!";
return;
}
if (m_model!= nullptr && !m_model->updateModel())
{
ERROR_LOG(m_logger) << "Invalid model!";
return;
}
resizeView();
}
void PlanTimeLineDialog::onCurrentItemChanged()
{
if (!m_buttonBox->getButton(LtsWidgets::DialogButton::Save)->isEnabled())
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, true);
}
void PlanTimeLineDialog::onZoomChanged(LtsTimeline::ZoomFactor zoom)
{
s_zoomFactor = zoom;
m_sliderCurrentTime = qint64(m_ui->timeline->slider()->value()) * 1000;
}
void PlanTimeLineDialog::resizeView()
{
if (m_model == nullptr)
return;
qint64 startTime = m_model->getStartTime() - (2 * 60 * 60 * 1000);
m_ui->timeline->setStartTime(startTime);
qint64 duration = m_model->getDuration() + (4 * 60 * 60 * 1000);
m_sliderCurrentTime = m_model->getStartTime();
m_ui->timeline->setCurrentTime(m_model->getStartTime());
m_ui->timeline->setDuration(duration);
}
void PlanTimeLineDialog::onSliderValueChanged(int value)
{
m_sliderCurrentTime = qint64(value) *1000;
}
} // namespace InfrastructureManagement
@@ -0,0 +1,119 @@
/**
* @RDE_HEADER@
* Plans Overview Timeline Dialog
* $Id$
* $HeadURL$
*$Autor: kemayou_s $
* Created by Steve Kemayou, SLTE, 2021-07-26
*/
#pragma once
#include "Timeline/ism_plan_tln_model.h"
#include "ui_ism_plan_tln_dialog.h"
#include <LtsTimeline/timeline_utils.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsWidgets/lts_dialog.h>
#include <InfrastructureManagement/logger.h>
#include <LtsTimeline/item_delegate.h>
#include <Plugins/InfrastructureManagement/Data/ism_data_plugin.h>
#include <Plugins/InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <QDateTime>
namespace Ui
{
class PlanTimeLineDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace LtsPluginManager
{
class LtsPluginManager;
}
namespace InfrastructureManagement
{
class PlanTimelineModel;
class PlanTimeLineDialog
: public LtsWidgets::LtsDialog
, protected Interface::Ftc::MainScheduleRemoveReplyHandler
, protected Interface::Ftc::MainScheduleModifyReplyHandler
, protected Interface::Ftc::InstrumentationAssetModifyReplyHandler
{
Q_OBJECT
public:
explicit PlanTimeLineDialog(LtsSession::LtsSession *session, const QString &menuGroup, QWidget *parent = nullptr);
~PlanTimeLineDialog();
bool init(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignDataInterface> &dataInterface,
ForeignResourceManagementGuiInterface *ismGuiIfc);
void retranslate() override;
void setScheduleId(const int scheduleId);
int getSelectedItem(){ return m_selectedItem;}
protected:
void onMainScheduleRemoveReply(const Core::FunctionReplyObject &replyObject) override final
{
m_requestHelper->requestReply(replyObject);
}
void onInstrumentationAssetModifyReply(const Core::FunctionReplyObject &replyObject) override final
{
m_requestHelper->requestReply(replyObject);
}
void onMainScheduleModifyReply(const Core::FunctionReplyObject &replyObject) override final
{
m_requestHelper->requestReply(replyObject);
}
private slots:
void onLoad();
void onRemove();
void onApply();
void onItemsSelected(const QVector<int> &itemIds);
void onScheduleIdChanged(int32_t id);
void onMainScheduleChanged(const MainSchedule &data, DataModification modType);
void updateTimeLine();
void onCurrentItemChanged();
void onZoomChanged(LtsTimeline::ZoomFactor zoom);
void resizeView();
void onSliderValueChanged(int value);
private:
LtsSession::LtsSession *m_session { nullptr };
QString m_menuGroup;
qint64 m_sliderCurrentTime{0};
int m_scheduleId{-1};
int m_selectedItem{-1};
PlanTimelineModel *m_model { nullptr };
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc{nullptr};
std::shared_ptr<ForeignDataInterface> m_dataIfc;
ForeignResourceManagementGuiInterface *m_ismGuiIfc{nullptr};
LtsUtils::RequestHelper *m_requestHelper{nullptr};
TimelineViewResizeHandler *m_resizeHandler { nullptr };
QPoint m_cursorPosition;
Ui::PlanTimeLineDialog *m_ui{nullptr};
LOGGER_T &m_logger;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PlanTimeLineDialog</class>
<widget class="QWidget" name="PlanTimeLineDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="LtsTimeline::TimelineWidget" name="timeline" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsTimeline::TimelineWidget</class>
<extends>QWidget</extends>
<header>LtsTimeline/timeline_widget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,213 @@
/**
* @RDE_HEADER@
* Plans Overview Timeline Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Steve Kemayou, SLTE, 2021-07-26
*/
#include "ism_plan_tln_model.h"
#include <LtsWidgets/lts_message_dialog.h>
#include <QDateTime>
//using namespace LtsTimelineClassic;
using namespace LtsTimeline;
namespace InfrastructureManagement
{
PlanTimelineModel::PlanTimelineModel(TimelineView *tlv, QObject *parent)
: LtsTimeline::TimelineModel(tlv, parent)
, m_session(nullptr)
, m_startTime(QDateTime::currentMSecsSinceEpoch())
, m_endTime(m_startTime + (LtsTimeline::ZoomFactor::OneDay))
, m_scheduleId(-1)
, m_tlv(tlv)
, m_logger(getLogger("PlanTimeLineModel"))
{
}
bool PlanTimelineModel::initModel(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &dtc, const std::shared_ptr<ForeignDataInterface> &dataInterface)
{
DEBUG_LOG(m_logger) << "Start init FileManagement timeline model...";
if (m_dtc == dtc)
return true;
m_dtc = dtc;
bool bRet = true;
bRet &= m_dtc->enableMainSchedule();
bRet &= m_dtc->enableMainStructureElement();
m_dataInterface = dataInterface;
m_scheduleId = m_dataInterface->scheduleId();
connect(m_dataInterface.get(), &ForeignDataInterface::scheduleIdChanged,
this, &PlanTimelineModel::onScheduleIdChanged);
if (!bRet)
{
ERROR_LOG(m_logger) << "Could not enable ISM DTC Main schedule or Structure elements";
return false;
}
if (!setModel())
{
ERROR_LOG(m_logger) << "Could not set timeline model";
return false;
}
INFO_LOG(m_logger) << "initModel successful";
return true;
}
bool PlanTimelineModel::setModel()
{
if (m_scheduleId == -1)
{
WARNING_LOG(m_logger) << "Invalid scheduleId " << m_scheduleId;
return false;
}
QVector <int> scheduleIds{};
scheduleIds = m_dtc->getIntersectedMainSchedulesIds(m_scheduleId);
int itemIndex = 0, itemId = 0;
m_startTime = QDateTime::currentMSecsSinceEpoch();
m_endTime = QDateTime::currentMSecsSinceEpoch() + (LtsTimeline::ZoomFactor::OneDay);
m_duration = m_endTime - m_startTime;
for (auto scheduleId : qAsConst(scheduleIds))
{
MainSchedule mse = m_dtc->mainSchedule(scheduleId);
if (scheduleId == m_scheduleId)
{
if (!mse.timeStart().is_set() || !mse.timeEnd().is_set())
{
LtsWidgets::LtsMessageDialog::showMessage(m_tlv, tr("Invalid Begin/End time for Instrumentation Plan with Id = %1").arg(m_scheduleId));
return true;
}
if (mse.timeStart().is_set())
m_startTime = mse.timeStart().get();
if (mse.timeEnd().is_set())
m_endTime = mse.timeEnd().get();
m_duration = m_endTime - m_startTime;
}
QColor color = (mse.id() == m_scheduleId) ? QColor(2,47,102) : getColor(mse.id());
if (mse.timeStart().is_set() && mse.timeEnd().is_set())
{
try
{
this->addTrack<LtsTimeline::Track>(0, LtsTimeline::Track(QString::fromStdString(mse.name())));
itemId = this->addItem<LtsTimeline::Item>(++itemIndex, LtsTimeline::Item(mse.timeStart().get(), (mse.timeEnd().get() - mse.timeStart().get()), color));
m_itemIntersection.push_back({scheduleId,itemId});
}
catch (const std::exception &e)
{
ERROR_LOG(m_logger) << "## Unable to add item or track to model. Exception: " << e.what();
return false;
}
}
else
WARNING_LOG(m_logger) << "Time start/end not set for schedule id " << mse.id();
}
return true;
}
bool PlanTimelineModel::updateModel()
{
this->clear();
m_itemIntersection.clear();
setModel();
return true;
}
qint64 PlanTimelineModel::getDuration() const
{
return m_duration;
}
qint64 PlanTimelineModel::getStartTime() const
{
return m_startTime;
}
qint64 PlanTimelineModel::getCurrentTime() const
{
return m_startTime;
}
QVector<PlanTimelineModel::ItemIntersection> PlanTimelineModel::getIntersectedPlan() const
{
return m_itemIntersection;
}
int32_t PlanTimelineModel::getScheduleIdOfItem(int itemId)
{
int32_t scheduleId = -1;
for (auto item : qAsConst(m_itemIntersection))
{
if (item.itemId == itemId)
{
scheduleId = item.scheduleId;
break;
}
}
return scheduleId;
}
void PlanTimelineModel::onScheduleIdChanged(int32_t scheduleId)
{
if (scheduleId == m_scheduleId)
return;
m_scheduleId = scheduleId;
}
//QVariant PlanTimelineModel::data(const QModelIndex &index, int role) const
//{
//// if (isCurrentlyUpdating())
//// return {};
// if (role != Qt::DisplayRole || !index.isValid() || index.column() != 0)
// return {};
// // actuators column (0)
// QString text;
// try
// {
// const Track &t = track(index.internalId());
// text = QStringLiteral("%1").arg(t.text());
// }
// catch(...)
// {
// Q_ASSERT(false);
// return QStringLiteral("[?????]");
// }
// if (text.isEmpty())
// text = tr("[unknown]");
// return text;
//}
QColor PlanTimelineModel::getColor(int planId)
{
MainSchedule ms = m_dtc->mainSchedule(planId);
switch (ms.statusId().underlying())
{
case ScheduleStatus::Active:
return QColor(Qt::darkGreen);
case ScheduleStatus::Inactive:
return QColor(Qt::red);
default:
return QColor(Qt::lightGray);
}
}
} // namespace InfrastructureManagement
@@ -0,0 +1,80 @@
/**
* @RDE_HEADER@
* Plans Overview Timeline Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Steve Kemayou, SLTE, 2021-07-26
*/
#pragma once
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <InfrastructureManagement/logger.h>
#include <Plugins/InfrastructureManagement/Data/ism_data_plugin.h>
#include <Plugins/Timeline/tln_data_plugin_interface.h>
#include <Plugins/InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
//#include <LtsEventTimeline/AbstractTimelineModel.h>
#include <LtsTimeline/item.h>
#include <LtsTimeline/timeline_model.h>
#include <LtsTimeline/timeline_utils.h>
#include <LtsTimeline/timeline_view.h>
namespace LtsSession { class LtsSession; }
namespace LtsPluginManager { class LtsPluginManager; }
namespace LtsTimeline { class TimelineView; }
using namespace LtsTimeline;
namespace InfrastructureManagement
{
class PlanTimelineModel: public LtsTimeline::TimelineModel
{
Q_OBJECT
public:
explicit PlanTimelineModel(TimelineView *tlv, QObject *parent);
bool initModel(const std::shared_ptr<InfrastructureManagement::Interface::Dtc> &dtc, const std::shared_ptr<ForeignDataInterface> &dataInterface);
struct ItemIntersection
{
int scheduleId;
int itemId;
};
bool updateModel();
qint64 getDuration() const;
qint64 getStartTime() const;
qint64 getCurrentTime() const;
//QVariant data(const QModelIndex &index, int role) const override;
QVector<PlanTimelineModel::ItemIntersection> getIntersectedPlan() const;
int32_t getScheduleIdOfItem(int itemId);
private Q_SLOTS:
void onScheduleIdChanged(int32_t scheduleId);
private:
bool setModel();
QColor getColor(int planId);
LtsSession::LtsSession *m_session;
qint64 m_startTime{0};
qint64 m_currentTime{0};
qint64 m_endTime{0};
qint64 m_duration{0};
QVector<ItemIntersection> m_itemIntersection{};
std::shared_ptr<InfrastructureManagement::Interface::Dtc> m_dtc;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> m_dataInterface;
int32_t m_scheduleId{-1};
TimelineView *m_tlv;
LOGGER_T &m_logger;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,532 @@
/**
* @RDE_HEADER@
* Show all main structure elements including their structure elements
* totally possessed, free, and missing
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-12-06
*/
#include "ism_building_mount_point_dialog.h"
#include "ism_building_mount_point_model.h"
#include "ui_ism_building_mount_point_dialog.h"
#include <InfrastructureManagement/ism_translation.h>
#include <InfrastructureManagement/ism_operator_rights.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <LtsSession/lts_session_data.h>
#include <QFileDialog>
#include <QMenu>
#include <QTextStream>
using namespace InfrastructureManagement;
BuildingMountPointDialog::BuildingMountPointDialog(QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_ui(new Ui::BuildingMountPointDialog)
, m_model(new BuildingMountPointModel(this))
, m_proxyModel(new BuildingMountPointSortModel(this))
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_ismGuiIfc(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("BuildingMountPointDialog"))
, m_importedModelIndex()
{
m_ui->setupUi(this);
m_proxyModel->setSourceModel(m_model);
m_ui->tvBuildings->setModel(m_proxyModel);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Export,
this,
&BuildingMountPointDialog::onExportClicked);
if (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::SystemConfiguration))
{
m_buttonBox->connectButton(LtsWidgets::DialogButton::Import,
this,
&BuildingMountPointDialog::onImportClicked);
}
m_buttonBox->setText(LtsWidgets::DialogButton::No, tr("Reset"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::No,
this,
&BuildingMountPointDialog::onResetClicked);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Building_List"));
}
BuildingMountPointDialog::~BuildingMountPointDialog()
{
delete m_ui;
}
void BuildingMountPointDialog::retranslate()
{
translate(m_ui, tr("Building List"));
}
bool BuildingMountPointDialog::init(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
InfrastructureManagement::ForeignResourceManagementGuiInterface *ismGuiIfc)
{
m_dtc = dtc;
m_ftc = ftc;
m_ismGuiIfc = ismGuiIfc;
if (!m_model->initModel(m_dtc))
{
ERROR_LOG(m_logger) << "Could not init model";
return false;
}
#ifndef LTS_DEBUG
m_ui->tvBuildings->hideColumn(BuildingMountPointModel::ColId);
m_ui->tvBuildings->hideColumn(BuildingMountPointModel::ColType);
m_ui->tvBuildings->hideColumn(BuildingMountPointModel::ColProperties);
#endif
m_ui->tvBuildings->hideColumn(BuildingMountPointModel::ColBarcodeNew);
m_ui->tvBuildings->sortByColumn(BuildingMountPointModel::ColName, Qt::AscendingOrder);
m_ui->tvBuildings->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::No, false); // used as 'Reset-Button'
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Export, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Import, false);
connect(m_ui->tvBuildings->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &BuildingMountPointDialog::onSelectionChanged);
connect(m_ui->tvBuildings, &QTreeView::customContextMenuRequested, this,
&BuildingMountPointDialog::showContextMenu);
if (!m_ftc->enableMainStructureElementModify())
{
ERROR_LOG(m_logger) << "Could not enable FT MainStructureElementModify of ISM";
return false;
}
//
connect(m_ui->tvBuildings, &QTreeView::doubleClicked, this,
&BuildingMountPointDialog::onShowMntPointInfo);
return true;
}
void BuildingMountPointDialog::onSelectionChanged()
{
bool enable = false;
const auto mil = m_ui->tvBuildings->selectionModel()->selectedRows();
if (mil.size() == 1)
{
const QModelIndex &index = mil.at(0);
if (index.isValid())
enable = (index.parent().isValid() && !m_importedModelIndex.isValid());
}
enable = enable && LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::SystemConfiguration);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Import, enable);
// allow export of multiple items:
enable = !mil.isEmpty();
for (const auto index : mil)
{
if (index.isValid())
enable = enable && (index.parent().isValid());
} //
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Export, enable);
}
bool BuildingMountPointDialog::exportData(const std::vector<StructureElement> &structureElements, const QString &fileName)
{
if (structureElements.empty())
return false;
QFile file(fileName);
if (!file.open(QFile::WriteOnly))
{
LtsWidgets::LtsMessageDialog::showMessage(this,
tr("Cannot save file '%1': %2").arg(file.fileName(),
file.errorString()));
return false;
}
QTextStream out(&file);
out.setLocale(QLocale::c());
QHash<int, QString> names;
names.reserve(structureElements.size());
for (const StructureElement &se : structureElements)
names.insert(se.id(), QString::fromStdString(se.name()));
static const QStringList headerNames = { QStringLiteral("Data Matrix Code"),
QStringLiteral("Anbringungspunkt Id"),
QStringLiteral("Gebäude"),
QStringLiteral("Ebene und Raum"),
QStringLiteral("RelPos X"),
QStringLiteral("RelPos Y"),
QStringLiteral("RelPos Z"),
QStringLiteral("Anbringungpunkttyp"),
QStringLiteral("Ref. Gebäude-Anbaupositions-Tags-Plan")};
const QString header = headerNames.join(QLatin1Char(';'));
out << header << "\n";
QString bldgName = m_model->getMainStructureElementName(structureElements.at(0).mainStructureElementId());
if (bldgName.startsWith(QLatin1String("bldg_")))
bldgName = bldgName.mid(QLatin1String("bldg_").size());
bldgName = bldgName.left(11);
QStringList sl;
QStringList name;
sl.reserve(8);
for (const StructureElement &se : structureElements)
{
if (se.structureElementTypeId() != StructureElementType::MountingPoint)
continue;
sl.clear();
const QString mountingPointType = (se.mountingPointTypeId() == MountingPointType::Unknown) ? QString() : toString(se.mountingPointTypeId());
// 1. DataMatrix (barcode)
sl << QString::fromStdString(se.barcode());
// 2. MountingpointId
sl << QString::number(se.mountingPointId());
// 3. always the building Name
sl << bldgName;
// 4. Floor and Room
name.clear();
for (const int pathId : se.path())
{
static const QString room = QStringLiteral("SW_room_");
static const QString floor = QStringLiteral("floor_");
const QString str = names.value(pathId);
if (str.startsWith(room))
name << str.mid(room.size());
if (str.startsWith(floor))
name << str.mid(floor.size());
}
const QString strName = name.join(QLatin1Char('/'));
sl << strName;
// 5 - 7 relativ Position
sl << QString::number(se.relPosition().offsetX());
sl << QString::number(se.relPosition().offsetY());
sl << QString::number(se.relPosition().offsetZ());
// 8. MountingpointTypeId
sl << mountingPointType;
// 9. Ref. Gebäude-Anbaupositions-Tags-Plan (always existent in the ICD) - do nothing
const QString str = sl.join(QLatin1Char(';'));
out << str << "\n";
}
file.close();
return true;
}
void BuildingMountPointDialog::onExportClicked()
{
DEBUG_LOG(m_logger) << "**** onExportClicked() ";
const QModelIndexList indexList = m_ui->tvBuildings->selectionModel()->selectedRows();
if (indexList.isEmpty())
return;
if (indexList.size() == 1)
{
const QModelIndex &idx = m_proxyModel->mapToSource(indexList.first());
const auto structureElements = m_model->getChildren(idx, false);
const QString bldgName = QString::fromStdString(m_model->getMainStructureElement(idx).name());
const QString fileName = QFileDialog::getSaveFileName(this, tr("Export"),
bldgName + QStringLiteral("_structure") + QStringLiteral(".csv"),
tr("CSV-Files (*.csv)"));
if (fileName.isEmpty())
return;
if (!exportData(structureElements, fileName))
return;
LtsWidgets::LtsMessageDialog::showMessage(this,
tr("Successfully saved data to %1").arg(fileName));
return;
}
// More then one item selected:
// get TEMPLATE for files to be exported:
const QLatin1String placeholder("@bldg@");
QString fileNameTemplate = QFileDialog::getSaveFileName(this, tr("Export"),
placeholder + QStringLiteral("_structure") + QStringLiteral(".csv"),
tr("CSV-Files (*.csv)"));
if (!fileNameTemplate.contains(placeholder))
{
ERROR_LOG(m_logger) << " no placeholder '" << placeholder << "'";
LtsWidgets::LtsMessageDialog::showMessage(this, tr("The name must have a placeholder (%1). Please try again.").arg(placeholder));
return;
}
const QString &dir = QFileInfo(fileNameTemplate).absolutePath();
fileNameTemplate.replace(placeholder, QStringLiteral("%1"));
DEBUG_LOG(m_logger) << " fileNameTemplate after '" << fileNameTemplate << "'";
for (auto idxItem : indexList)
{
const QModelIndex &idx = m_proxyModel->mapToSource(idxItem);
const auto structureElements = m_model->getChildren(idx, false);
const QString bldgName = QString::fromStdString(m_model->getMainStructureElement(idx).name());
if (bldgName.isEmpty())
{
ERROR_LOG(m_logger) << " bldgName is empty";
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Name is empty").arg(dir));
return;
}
const QString &fileName = QString(fileNameTemplate).arg(bldgName);
DEBUG_LOG(m_logger) << " fileName '" << fileName << "'";
if (!exportData(structureElements, fileName))
ERROR_LOG(m_logger) << " exportData failed bldgName " << bldgName;
} // for
LtsWidgets::LtsMessageDialog::showMessage(this,
tr("Successfully saved data to %1").arg(dir));
}
void BuildingMountPointDialog::onExportAllClicked()
{
const QModelIndexList indexList = m_ui->tvBuildings->selectionModel()->selectedRows();
if (indexList.isEmpty())
return;
const QString dirName = QFileDialog::getExistingDirectory(this, tr("Select directory to export"), QString(), QFileDialog::ShowDirsOnly);
if (dirName.isEmpty())
return;
for (const QModelIndex &idx : indexList)
{
const QModelIndex &sourceIdx = m_proxyModel->mapToSource(idx);
const auto structureElements =
m_model->getChildren(sourceIdx, false);
if (structureElements.empty())
continue;
const QString bldgName = QString::fromStdString(m_model->getMainStructureElement(sourceIdx).name());
const QString fileName = dirName + QLatin1Char('/') + bldgName + QStringLiteral(".csv");
if (!exportData(structureElements, fileName))
return;
}
LtsWidgets::LtsMessageDialog::showMessage(this,
tr("Successfully saved data to %1").arg(dirName));
}
void BuildingMountPointDialog::onImportClicked()
{
DEBUG_LOG(m_logger) << "**** onImportClicked() ";
QModelIndexList indexList = m_ui->tvBuildings->selectionModel()->selectedRows();
if (indexList.isEmpty() || indexList.size() > 1)
return;
QString fileName = QFileDialog::getOpenFileName(this, tr("Import Barcodes"), QString(),
tr("CSV-Files (*.csv)"));
if (fileName.isEmpty())
return;
QFile file(fileName);
if (!file.open(QFile::ReadOnly))
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot open file '%1': %2").arg(file.fileName(), file.errorString()));
return;
}
QTextStream in(&file);
in.setLocale(QLocale::c());
// first get the header data
in.readLine();
// the Data Matrix Code (Barcode) information is always column(0) and
// MountingPointId column(1)
int colBarcode = 0;
int colMountingPointId = 1;
DEBUG_LOG(m_logger) << "colBarcode: " << colBarcode
<< ", colMountingPointId: " << colMountingPointId;
m_importedModelIndex = m_proxyModel->mapToSource(indexList.at(0));
QHash<int, QString> barcodes;
QHash<int, QVector<QString>> additionalBarcodes;
int prevMountingPointId = -1;
QString line;
while (in.readLineInto(&line))
{
const QVector<QStringRef> values = line.splitRef(QLatin1Char(';'));
if (colMountingPointId >= values.size() ||
colBarcode >= values.size())
{
WARNING_LOG(m_logger) << "skipping line - to few data: '" << line << "'";
continue;
}
QString newBarCode = values.at(colBarcode).toString();
if (newBarCode.size() > 1 && newBarCode.startsWith(QLatin1Char('"')) && newBarCode.endsWith(QLatin1Char('"')))
newBarCode = newBarCode.mid(1, newBarCode.size() - 2);
if (newBarCode.isEmpty())
continue;
const int curMountingPointId = values.at(colMountingPointId).toInt();
if (curMountingPointId == 0)
{
additionalBarcodes[prevMountingPointId].push_back(newBarCode);
}
else
{
barcodes.insert(curMountingPointId, newBarCode);
prevMountingPointId = curMountingPointId;
}
DEBUG_LOG(m_logger) << "mountingPoint: " << curMountingPointId
<< ", new barcode: " << newBarCode;
}
file.close();
m_ui->tvBuildings->showColumn(BuildingMountPointModel::ColBarcodeNew);
m_model->updateBarcodes(m_importedModelIndex, barcodes, additionalBarcodes);
if (barcodes.size())
{
QStringList ids;
ids.reserve(barcodes.size());
for (auto it = barcodes.begin(); it != barcodes.end(); ++it)
ids += QString::number(it.key());
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot find mounting point:\n\n%1").arg(ids.join(QLatin1Char('\n'))));
}
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::No, true);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Export, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Import, false);
slotChangesMade();
}
bool BuildingMountPointDialog::apply()
{
MainStructureElement mainStructureElement = m_model->getMainStructureElement(m_importedModelIndex);
MainStructureElementModifyRequest request;
request.name(mainStructureElement.name());
request.description(mainStructureElement.description());
request.geoPosition(mainStructureElement.geoPosition());
request.angle(mainStructureElement.angle());
request.externalWlsId(mainStructureElement.externalWlsId());
request.elements(mainStructureElement.elements());
request.structureElementId(mainStructureElement.structureElementId());
request.structureElementTypeId(mainStructureElement.structureElementTypeId());
request.id(mainStructureElement.id());
request.properties(mainStructureElement.properties());
request.modelId(mainStructureElement.modelId());
request.groupId(mainStructureElement.groupId());
m_requestHelper->startSingleRequest([this, request]() {
return m_ftc->mainStructureElementModifyRequest(request, this);
});
m_ui->tvBuildings->hideColumn(BuildingMountPointModel::ColBarcodeNew);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::No, false);
m_model->resetNewBarcodes(m_importedModelIndex);
m_importedModelIndex = QModelIndex();
return true;
}
void BuildingMountPointDialog::onResetClicked()
{
DEBUG_LOG(m_logger) << "**** onResetClicked() ";
m_model->resetNewItems(m_importedModelIndex);
m_model->resetNewBarcodes(m_importedModelIndex);
m_ui->tvBuildings->hideColumn(BuildingMountPointModel::ColBarcodeNew);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::No, false);
m_importedModelIndex = QModelIndex();
__unchange__();
onSelectionChanged();
}
void BuildingMountPointDialog::showContextMenu(const QPoint &position)
{
QModelIndexList mil = m_ui->tvBuildings->selectionModel()->selectedRows();
for (int i = mil.size() - 1; i >= 0; --i)
{
const QModelIndex &idx = mil.at(i);
// remove all non-toplevel indexes
if (!idx.isValid() || idx.parent().isValid())
mil.removeAt(i);
}
if (mil.isEmpty())
return;
QMenu menu;
if (!m_importedModelIndex.isValid())
{
if (mil.size() == 1)
{
menu.addAction(tr("Import Barcodes"), this, &BuildingMountPointDialog::onImportClicked);
menu.addAction(tr("Export Buildings structure"), this, &BuildingMountPointDialog::onExportClicked);
}
menu.addAction(tr("Export selected"), this, &BuildingMountPointDialog::onExportAllClicked);
}
if (!mil.isEmpty())
{
menu.addAction(tr("Clear selected"), m_ui->tvBuildings->selectionModel(), &QItemSelectionModel::clearSelection);
menu.addAction(tr("Expand selected"), this, &BuildingMountPointDialog::expandSelected);
menu.addAction(tr("Collapse selected"), this, &BuildingMountPointDialog::collapseSelected);
}
if (menu.actions().isEmpty())
return;
menu.exec(m_ui->tvBuildings->viewport()->mapToGlobal(position));
}
void BuildingMountPointDialog::expandSelected()
{
const auto mil = m_ui->tvBuildings->selectionModel()->selectedRows();
for (const QModelIndex &idx : mil)
expandCollapseRecursivly(idx, true);
}
void BuildingMountPointDialog::collapseSelected()
{
const auto mil = m_ui->tvBuildings->selectionModel()->selectedRows();
for (const QModelIndex &idx : mil)
expandCollapseRecursivly(idx, false);
}
void BuildingMountPointDialog::onShowMntPointInfo(const QModelIndex &index)
{
if (!m_ismGuiIfc)
return;
const QModelIndex &idx = m_proxyModel->mapToSource(index);
const auto structureElements = m_model->getChildren(idx, false);
//show only one mounting point. avoid displaying mntp on parent click
if(structureElements.empty() || structureElements.size() > 1)
{
return;
}
m_ismGuiIfc->showMountingPointInfoWindows(QVector<int>() << structureElements.at(0).id());
m_ui->tvBuildings->selectionModel()->clear();
}
void BuildingMountPointDialog::expandCollapseRecursivly(const QModelIndex &idx, bool bExpand)
{
if (bExpand)
m_ui->tvBuildings->expand(idx);
else
m_ui->tvBuildings->collapse(idx);
const int childCount = m_proxyModel->rowCount(idx);
for (int row = 0; row < childCount; ++row)
expandCollapseRecursivly(m_proxyModel->index(row, 0, idx), bExpand);
}
@@ -0,0 +1,76 @@
/**
* @RDE_HEADER@
* Show all main structure elements including their structure elements
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-12-06
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/ism_ftc.h>
#include <InfrastructureManagement/logger.h>
#include <InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <QModelIndex>
namespace Ui
{
class BuildingMountPointDialog;
}
namespace InfrastructureManagement
{
class BuildingMountPointModel;
class BuildingMountPointSortModel;
class BuildingMountPointDialog final : public LtsWidgets::LtsDialog
, protected Interface::Ftc::MainStructureElementModifyReplyHandler
{
Q_OBJECT
public:
explicit BuildingMountPointDialog(QWidget *parent = nullptr);
~BuildingMountPointDialog();
bool init(const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc, ForeignResourceManagementGuiInterface *ismGuiIfc);
void onMainStructureElementModifyReply(const Core::FunctionReplyObject &replyObject) override final
{
m_requestHelper->requestReply(replyObject);
}
void retranslate() override;
private slots:
void onSelectionChanged();
void onExportClicked();
void onExportAllClicked();
void onImportClicked();
void onResetClicked();
void showContextMenu(const QPoint &position);
void expandSelected();
void collapseSelected();
void onShowMntPointInfo(const QModelIndex &index);
bool apply() override;
private:
bool exportData(const std::vector<StructureElement> &structureElements, const QString &fileName);
void expandCollapseRecursivly(const QModelIndex &idx, bool bExpand);
private: // attributes
Ui::BuildingMountPointDialog *m_ui{nullptr};
BuildingMountPointModel *m_model{nullptr};
BuildingMountPointSortModel *m_proxyModel{nullptr};
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
ForeignResourceManagementGuiInterface *m_ismGuiIfc{nullptr};
LtsUtils::RequestHelper *m_requestHelper{nullptr};
LOGGER_T m_logger;
QModelIndex m_importedModelIndex;
}; // class BuildingMountPointDialog
} // namespace InfrastructureManagement
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BuildingMountPointDialog</class>
<widget class="QWidget" name="BuildingMountPointDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>268</width>
<height>204</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QTreeView" name="tvBuildings">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,789 @@
/**
* @RDE_HEADER@
* Show (all) buildings including mounting points
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-12-06
*/
#include "ism_building_mount_point_model.h"
#include <QDataStream>
#include <QVector>
#include <nglwidgets/ngltreeitem.h>
#include <InfrastructureManagement/ism_translation.h>
#include <InfrastructureManagement/Shared/ism_mounting_point.h>
#include <LtsWidgets/lts_abstract_table_model.h>
namespace InfrastructureManagement
{
BuildingMountPointModel::BuildingMountPointModel(QObject *parent)
: NGLTreeModel(parent, new NGLTreeItem(QVariant()), {
tr("Name"),
tr("Id"),
tr("Internal Name"),
tr("RelPos X"),
tr("RelPos Y"),
tr("RelPos Z"),
tr("MountingPoint Type"),
tr("MountingPoint Id"),
tr("Structure Type"),
tr("Barcode"),
tr("Barcode (new)"),
tr("Mounted Asset"),
tr("Properties")})
, m_logger(getLogger("BuildingMountPointModel"))
{
}
Qt::ItemFlags BuildingMountPointModel::flags(const QModelIndex &index) const
{
/// allowing row selection only for Building types
Qt::ItemFlags ret = NGLTreeModel::flags(index);
if (index.parent().isValid())
{
NGLTreeItem *item = privateData(index);
if (!item)
{
ret.setFlag(Qt::ItemIsSelectable, false);
}
else
{
const StructureElementTreeItem *sitem = static_cast<StructureElementTreeItem*>(item);
if(!sitem)
{
ret.setFlag(Qt::ItemIsSelectable, false);
}
else if(sitem->data.structureElementTypeId() == InfrastructureManagement::StructureElementType::Building)
{
ret.setFlag(Qt::ItemIsSelectable, true);
}
else
{
ret.setFlag(Qt::ItemIsSelectable, false);
}
};
}
else
{
ret.setFlag(Qt::ItemIsSelectable, false);
}
return ret;
}
QVariant BuildingMountPointModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return NGLTreeModel::data(index, role);
if (role != Qt::DisplayRole && role != Qt::BackgroundRole)
return NGLTreeModel::data(index, role);
const StructureElementTreeItem *item = static_cast<StructureElementTreeItem*>(privateData(index));
if (item)
{
if (role == Qt::BackgroundRole)
{
if (item->data.id() < 0)
return QColor(Qt::red);
if (item->newBarcode != QString::fromStdString(item->data.barcode()))
return QColor(Qt::darkYellow);
return NGLTreeModel::data(index, role);
}
switch (index.column())
{
case ColName:
return item->displayName();
case ColId:
return item->data.id();
case ColInternalName:
return QString::fromStdString(item->data.name());
case ColRelPosX:
return QString::number(item->data.relPosition().offsetX());
case ColRelPosY:
return QString::number(item->data.relPosition().offsetY());
case ColRelPosZ:
return QString::number(item->data.relPosition().offsetZ());
case ColMountingPointTypeId:
if (item->data.mountingPointTypeId() != MountingPointType::Unknown)
return toString(item->data.mountingPointTypeId());
return QString();
case ColMountingPointId:
return item->data.mountingPointId();
case ColMountedAsset:
{
if(item->data.mountingPointTypeId() != MountingPointType::Unknown)
{
const int assetId = m_dtc->getMountedAssetId(item->data.id());
if(assetId != -1)
{
return QString::fromStdString(m_dtc->instrumentationAsset(assetId).barcode());
}
else
{
return QString(QStringLiteral("-"));
}
}
return QString();
}
case ColType:
return toString(item->data.structureElementTypeId());
case ColBarcode:
return QString::fromStdString(item->data.barcode());
case ColBarcodeNew:
return item->newBarcode;
case ColProperties:
return QString::fromStdString(item->data.properties());
}
}
return NGLTreeModel::data(index, role);
}
bool BuildingMountPointModel::initModel(const std::shared_ptr<Interface::Dtc> &dtc)
{
m_dtc = dtc;
connect(m_dtc.get(), &Interface::Dtc::mainStructureElementChanged,
this, &BuildingMountPointModel::onMainStructureElementChanged);
auto cb = [this](const MainStructureElement & mse)
{
if (mse.structureElementTypeId() == InfrastructureManagement::StructureElementType::Building)
addBuilding(mse);
};
resetModel();
connect(m_dtc.get(), &Interface::Dtc::mountingPointAssetChanged, this, &BuildingMountPointModel::onMountingPointAssetChanged);
m_dtc->mainStructureElements(cb);
return true;
}
void BuildingMountPointModel::onMountingPointAssetChanged(const InfrastructureManagement::MountingPointAsset &mpa, DataModification modType)
{
Q_UNUSED(modType)
InfrastructureManagement::StructureElement newSe;
m_dtc->getStructureElementById(mpa.structureElementId(), newSe);
StructureElementTreeItem *seItem = findItemByStructureElementId(newSe.id(), m_rootItem);
if(seItem == nullptr)
{
return;
}
if (seItem->data != newSe)
{
std::swap(seItem->data, newSe);
const QModelIndex idx = indexFromItem(seItem);
emit dataChanged(idx, idx);
}
}
StructureElementTreeItem* BuildingMountPointModel::findItemByStructureElementId(int id, NGLTreeItem *parent)
{
if(!parent)
{
return nullptr;
}
StructureElementTreeItem *item = static_cast<StructureElementTreeItem*>(parent);
if(item && item->data.structureElementTypeId() == InfrastructureManagement::StructureElementType::MountingPoint)
{
return item;
}
auto rows = parent->childCount();
for(int i=0; i<rows; ++i)
{
StructureElementTreeItem *seItem = findItemByStructureElementId(id, parent->child(i));
if(seItem && seItem->data.id() == id)
{
//DEBUG_LOG(m_logger)<<"modifed item found: itemId: "<<id;
return seItem;
}
}
return nullptr;
}
StructureElement BuildingMountPointModel::setBuildingGroup(int groupId)
{
StructureElement se;
InfrastructureManagement::BuildingGroup_def::type buildingGroup = static_cast<InfrastructureManagement::BuildingGroup_def::type>(groupId);
if(buildingGroup == 0)
{
buildingGroup = InfrastructureManagement::BuildingGroup_def::UnknownGroup;
}
se.id() = maxIntValue - static_cast<int>(buildingGroup);
se.name() = toString(buildingGroup).toStdString();
se.displayName() = toString(buildingGroup).toStdString();
se.structureElementTypeId() = InfrastructureManagement::StructureElementType::Section;
return se;
}
int BuildingMountPointModel::getSectionId(int groupId)
{
InfrastructureManagement::BuildingGroup_def::type buildingGroup = static_cast<InfrastructureManagement::BuildingGroup_def::type>(groupId);
if(buildingGroup == 0)
{
buildingGroup = InfrastructureManagement::BuildingGroup_def::UnknownGroup;
}
return (maxIntValue - static_cast<int>(buildingGroup));
}
StructureElementTreeItem *BuildingMountPointModel::getStructureTreeItemById(int id, NGLTreeItem *parent)
{
if (!parent)
return nullptr;
for(int i =0; i<parent->childCount(); ++i)
{
StructureElementTreeItem *item = static_cast<StructureElementTreeItem*>(parent->child(i));
if (item != nullptr && item->data.id() == id)
{
return item;
}
}
return nullptr;
}
StructureElementTreeItem *BuildingMountPointModel::getStructureTreeItemByMSEId(int id, NGLTreeItem *parent)
{
if (!parent)
return nullptr;
for(int i =0; i<parent->childCount(); ++i)
{
StructureElementTreeItem *item = static_cast<StructureElementTreeItem*>(parent->child(i));
if (item != nullptr && item->data.mainStructureElementId() == id)
{
return item;
}
}
return nullptr;
}
static inline int getParent(const std::vector<int32_t> &path)
{
// path also contains ourself
if (path.size() <= 1)
return 0;
return path.at(path.size() - 2);
}
void BuildingMountPointModel::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType)
{
if (modType == DataModification::eAdded)
return addBuilding(data);
if (modType == DataModification::eModified)
return modifyBuilding(data);
if (modType == DataModification::eRemoved)
return removeBuildingByGroupId(data);
}
void BuildingMountPointModel::addBuilding(const MainStructureElement &mse)
{
if (mse.structureElementTypeId() != InfrastructureManagement::StructureElementType::Building)
return;
m_mainStructureElements[mse.id()] = mse;
QHash<int, StructureElement> structureElements;
QHash<int, QVector<int>> parentId2id;
int gParentId =0;
QModelIndex gParentIndex = QModelIndex();
// we need to get the section('group_id') given current mainstructureElement:
// All buildings for the current mainStructur element will be assigned as children to this section
const StructureElement gse = setBuildingGroup(mse.groupId());
if (m_availableBuildingGroups.contains(gse.id()) == false)
{
m_availableBuildingGroups.insert(gse.id());
structureElements[gse.id()] = gse;
parentId2id[0].push_back(gse.id());
}
else
{
gParentId = gse.id();
}
for (const StructureElement &se : mse.elements())
{
if (se.mountingPointTypeId() == InfrastructureManagement::MountingPointType_def::BuildingControlUnit)
continue;
int parentId = getParent(se.path());
if(parentId == 0)
{
parentId = gse.id();
}
structureElements[se.id()] = se;
parentId2id[parentId].push_back(se.id());
}//end for-loop over structur elements children
// get parent index of groupIndex because gParentId != 0 (gParentId is equal mse.groupId)
if(gParentId != 0)
{
StructureElementTreeItem *item = getStructureTreeItemById(gParentId,m_rootItem);// static_cast<StructureElementTreeItem*>(m_rootItem->child(i));
if (item != nullptr && item->data.id() == gParentId)
{
gParentIndex = indexFromItem(item);
}
}
insertChildren(gParentId, gParentIndex, parentId2id, structureElements);
}
void BuildingMountPointModel::modifyBuilding(const MainStructureElement &mse)
{
auto it = m_mainStructureElements.find(mse.id());
if (it == m_mainStructureElements.end())
{
return addBuilding(mse);
}
// search building in section indexes
const StructureElement gse = setBuildingGroup(mse.groupId());
int gParentId = gse.id();
StructureElementTreeItem *building = nullptr;
// if section exist get the building data
// 1- get corresponding section
// 2- get corresponding building structure
// 3- update building data
StructureElementTreeItem *gItem = getStructureTreeItemById(gParentId, m_rootItem); // get Section
if (gItem != nullptr)
{
StructureElementTreeItem *bItem = getStructureTreeItemByMSEId(mse.id(), gItem);
if (bItem != nullptr)
{
building = bItem;
}//end if-statement: building found
}//end if-statement: section found
// not found -> add
if (!building)
{
// check if availaible in other sections before add it.
WARNING_LOG(m_logger)<<">>> not found section: "<<gse.id()<<" not exist. new one will be added ";
findAndRemoveBuilding(mse);
return addBuilding(mse);
}
// update mse data
*it = mse;
// upadte elements
int buildingSeId = 0;
QHash<int, StructureElement> structureElements;
QHash<int, QVector<int>> parentId2id;
for (const StructureElement &se : mse.elements())
{
if (se.structureElementTypeId() == StructureElementType::Building)
buildingSeId = se.id();
int parentId = getParent(se.path());
if(parentId == 0) // if parent = 0 structurEl. is a bulding | paste building as child of it defined section 'groupId'. see: m_buildingIndexes
{
parentId = gParentId;
}
structureElements[se.id()] = se;
parentId2id[parentId].push_back(se.id());
}
if (!buildingSeId)
{
ERROR_LOG(m_logger) << "Found no structure element with type 'Building' in content: " << mse;
return;
}
StructureElement newSe = structureElements.value(buildingSeId);
if (building->data != newSe)
{
std::swap(building->data, newSe);
const QModelIndex idx = indexFromItem(building);
emit dataChanged(idx, idx);
}
updateChildren(buildingSeId, building, parentId2id, structureElements);
}
void BuildingMountPointModel::updateChildren(int parentId,
NGLTreeItem *parent,
QHash<int, QVector<int> > &parentId2id,
const QHash<int, StructureElement> &structureElements)
{
if (!parent)
return;
QVector<int> childIds = parentId2id.value(parentId);
for (int i = parent->childCount() - 1; i >= 0; --i)
{
StructureElementTreeItem *child = static_cast<StructureElementTreeItem*>(parent->child(i));
// no longer available - remove
bool bFound = false;
for (int j = 0; j < childIds.size(); ++j)
{
if (childIds.at(j) == child->data.id())
{
bFound = true;
childIds.remove(j);
break;
}
}
if (!bFound)
{
const QModelIndex parentIdx = indexFromItem(parent);
beginRemoveRows(parentIdx, i, i);
parent->removeChild(child);
endRemoveRows();
continue;
}
// update element
StructureElement newSe = structureElements.value(child->data.id());
if (child->data != newSe)
{
std::swap(child->data, newSe);
const QModelIndex idx = indexFromItem(child);
emit dataChanged(idx, idx);
}
// update children
updateChildren(child->data.id(), child, parentId2id, structureElements);
}
// now parentId2id[id] only contains the items to add
parentId2id[parentId] = childIds;
if (childIds.isEmpty())
return;
// add the new children
insertChildren(parentId, indexFromItem(parent), parentId2id, structureElements);
}
void BuildingMountPointModel::removeBuildingByGroupId(const MainStructureElement &mse)
{
m_mainStructureElements.remove(mse.id());
int section = getSectionId(mse.groupId());
bool bfound = false;
StructureElementTreeItem *gItem = getStructureTreeItemById(section, m_rootItem);
if (gItem != nullptr)
{
for (int i = 0; i < gItem->childCount(); ++i)
{
StructureElementTreeItem *item = static_cast<StructureElementTreeItem*>(gItem->child(i));
if (item->data.mainStructureElementId() == mse.id())
{
const QModelIndex parentIdx = indexFromItem(gItem);
beginRemoveRows(parentIdx, i, i);
gItem->removeChild(i);
endRemoveRows();
bfound = true;
break;
}//end if-statement: remove found building
}//end for-loop: iterate over section children
}//end if statement: section found
if (bfound == false)
{
ERROR_LOG(m_logger)<<"No mse with Id: ( "<<mse.id()<<" ) | groupId: "<<mse.groupId()<<" | sectionId: "<<section<<" found!";
}
}
/*!
* \brief BuildingMountPointModel::findAndRemoveBuilding
* \param mse
* This method check and remove current building in a section
* The Intend is prevent existing of a builiding in more than on section
* \see modifyBuilding
*/
void BuildingMountPointModel::findAndRemoveBuilding(const MainStructureElement &mse)
{
bool bfound = false;
for(int rcIndex=0; rcIndex<= m_rootItem->childCount(); ++rcIndex)
{
NGLTreeItem *groupItem = m_rootItem->child(rcIndex);
if (groupItem != nullptr)
{
for (int gcIndex = 0; gcIndex < groupItem->childCount(); ++gcIndex)
{
StructureElementTreeItem *item = static_cast<StructureElementTreeItem*>(groupItem->child(gcIndex));
if (item->data.mainStructureElementId() == mse.id())
{
const QModelIndex parentIdx = indexFromItem(groupItem);
beginRemoveRows(parentIdx, gcIndex, gcIndex);
groupItem->removeChild(gcIndex);
endRemoveRows();
bfound = true;
break;
}
}//end if-statement: building found
if(bfound)
{
break;
}
}
}
}
void BuildingMountPointModel::insertChildren(int parentId,
const QModelIndex &parentIdx,
const QHash<int, QVector<int>> &parentId2id,
const QHash<int, StructureElement> &structureElements)
{
const QVector<int> childIds = parentId2id.value(parentId);
for (int childId : childIds)
{
auto it = structureElements.constFind(childId);
if (it == structureElements.constEnd())
{
ERROR_LOG(m_logger) << "Can not find structure element with id " << childId << " - ignoring";
continue;
}
const StructureElement &data = it.value();
int insertPos = 0;
const NGLTreeItem *treeItemParent = privateData(parentIdx);
if (treeItemParent)
insertPos = treeItemParent->childCount();
StructureElementTreeItem *childItem = static_cast<StructureElementTreeItem*>(createItem(QVariant(), QIcon()));
childItem->data = data;
insertRow(insertPos, parentIdx, childItem);
const QModelIndex childIdx = index(insertPos, 0, parentIdx);
insertChildren(data.id(), childIdx, parentId2id, structureElements);
}
}
std::vector<StructureElement> BuildingMountPointModel::getChildren(const QModelIndex &index, bool bUseNewBarcode) const
{
return getChildren(privateData(index), bUseNewBarcode);
}
std::vector<StructureElement> BuildingMountPointModel::getChildren(NGLTreeItem *item, bool bUseNewBarcode) const
{
std::vector<StructureElement> ret;
if (!item)
return ret;
// check for children of this item
for (int i = 0; i < item->childCount(); i++)
{
const auto val(getChildren(item->child(i), bUseNewBarcode));
ret.insert(ret.end(), val.begin(), val.end());
}
const StructureElementTreeItem *sitem = static_cast<StructureElementTreeItem*>(item);
StructureElement structureElement = sitem->data;
if (bUseNewBarcode)
structureElement.barcode(sitem->newBarcode.toStdString());
ret.push_back(std::move(structureElement));
return ret;
}
MainStructureElement BuildingMountPointModel::getMainStructureElement(const QModelIndex &index) const
{
MainStructureElement ret;
NGLTreeItem *item = privateData(index);
if (!item)
return ret;
const StructureElementTreeItem *sitem = static_cast<StructureElementTreeItem*>(item);
auto it = m_mainStructureElements.find(sitem->data.mainStructureElementId());
if (it == m_mainStructureElements.end())
return ret;
ret = it.value();
MainStructureElement mseFromDtc = m_dtc->mainStructureElement(ret.id());
auto children = getChildren(item, true);
auto comp = [](const StructureElement &a, const StructureElement &b)
{
const int idA = std::abs(a.id());
const int idB = std::abs(b.id());
if (idA != idB)
return idA < idB;
return QString::fromStdString(a.name()) < QString::fromStdString(b.name());
};
std::sort(children.begin(), children.end(), comp);
bool hasNewMountingPoints = false;
QHash<MountingPointType, int> maxIds;
QSet<int> setIds;
for (const StructureElement &se : qAsConst(children))
{
setIds.insert(se.id());
auto &ref = maxIds[se.mountingPointTypeId()];
ref = std::max(ref, se.mountingPointId());
if (se.id() <= 0)
hasNewMountingPoints = true;
}
if (hasNewMountingPoints)
{
for (StructureElement &se : children)
{
if (se.id() > 0 || se.mountingPointId() > 0)
continue;
auto &ref = maxIds[se.mountingPointTypeId()];
se.mountingPointId(++ref);
}
}
for (const auto& obj : mseFromDtc.elements())
{
if(setIds.contains(obj.id()))
continue;
if(obj.mountingPointTypeId() == MountingPointType::BuildingControlUnit)
{
children.insert(children.begin() + 1 , obj);
setIds.insert(obj.id());
}
}
ret.elements(children);
return ret;
}
QString BuildingMountPointModel::getMainStructureElementName(qint32 mainStructureElementId) const
{
return QString::fromStdString(m_mainStructureElements.value(mainStructureElementId).name());
}
void BuildingMountPointModel::updateBarcodes(const QModelIndex &idx,
QHash<int, QString> &barcodes,
QHash<int, QVector<QString>> &additionalBarcodes)
{
updateBarcodes(privateData(idx), barcodes, additionalBarcodes);
}
void BuildingMountPointModel::updateBarcodes(NGLTreeItem *item,
QHash<int, QString> &barcodes,
QHash<int, QVector<QString>> &additionalBarcodes)
{
if (!item)
return;
StructureElementTreeItem *sitem = static_cast<StructureElementTreeItem*>(item);
if (sitem->data.mountingPointTypeId() != MountingPointType::Unknown)
{
auto it = barcodes.find(sitem->data.mountingPointId());
if (it != barcodes.end())
{
sitem->newBarcode = it.value();
barcodes.erase(it);
auto itNewBc = additionalBarcodes.find(sitem->data.mountingPointId());
if (itNewBc != additionalBarcodes.end())
{
const QString name = QString::fromStdString(sitem->data.name());
const QString displayName = sitem->displayName();
const QVector<QString> newBarcodes = itNewBc.value();
StructureElement newSe(sitem->data);
newSe.mountingPointId(0);
const int itemRow = item->row();
for (int i = 0; i < newBarcodes.size(); ++i)
{
const int rowToInsert = itemRow + i + 1;
newSe.barcode() = std::string();
newSe.id(-sitem->data.id());
newSe.name(QString(name + QLatin1Char('_') + QString::number(i + 1)).toStdString());
newSe.displayName(QString(displayName + QLatin1Char('_') + QString::number(i + 1)).toStdString());
StructureElementTreeItem *childItem = static_cast<StructureElementTreeItem*>(createItem(QVariant(), QIcon()));
childItem->newBarcode = newBarcodes.at(i);
childItem->data = newSe;
insertRow(rowToInsert, indexFromItem(item->parent()), childItem);
}
additionalBarcodes.erase(itNewBc);
}
}
else
{
if (sitem->data.id() > 0)
sitem->newBarcode.clear();
}
}
else
{
barcodes.remove(sitem->data.mountingPointId());
additionalBarcodes.remove(sitem->data.mountingPointId());
}
for (int i = 0; i < item->childCount(); ++i)
updateBarcodes(item->child(i), barcodes, additionalBarcodes);
}
void BuildingMountPointModel::resetNewItems(const QModelIndex &idx)
{
StructureElementTreeItem *sitem = static_cast<StructureElementTreeItem*>(privateData(idx));
if (!sitem)
return;
if (sitem->data.id() < 0 && sitem->parent())
{
beginRemoveRows(idx.parent(), idx.row(), idx.row());
sitem->parent()->removeChild(sitem);
endRemoveRows();
return;
}
for (int i = sitem->childCount() - 1; i >= 0; --i)
resetNewItems(index(i, 0, idx));
}
void BuildingMountPointModel::resetNewBarcodes(const QModelIndex &idx)
{
resetNewBarcodes(privateData(idx));
}
void BuildingMountPointModel::resetNewBarcodes(NGLTreeItem *parent)
{
if (!parent)
return;
StructureElementTreeItem *sitem = static_cast<StructureElementTreeItem*>(parent);
sitem->newBarcode = QString::fromStdString(sitem->data.barcode());
for (int i = 0; i < parent->childCount(); ++i)
resetNewBarcodes(parent->child(i));
}
//
// BuildingMountPointSortModel
//
void BuildingMountPointSortModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<BuildingMountPointModel*>(sourceModel);
QSortFilterProxyModel::setSourceModel(sourceModel);
}
bool BuildingMountPointSortModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_sourceModel || source_left.column() != source_right.column())
return QSortFilterProxyModel::lessThan(source_left, source_right);
const StructureElementTreeItem *itemLeft = static_cast<StructureElementTreeItem*>(m_sourceModel->privateData(source_left));
const StructureElementTreeItem *itemRight = static_cast<StructureElementTreeItem*>(m_sourceModel->privateData(source_right));
if (!itemLeft || !itemRight)
return QSortFilterProxyModel::lessThan(source_left, source_right);
if (itemLeft->displayName() != itemRight->displayName())
return itemLeft->displayName() < itemRight->displayName();
const int idLeft = qAbs(itemLeft->data.id());
const int idRight = qAbs(itemLeft->data.id());
return idLeft < idRight;
}
}
@@ -0,0 +1,129 @@
/**
* @RDE_HEADER@
* Show (all) buildings including mounting points
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-12-06
*/
#pragma once
#include <nglwidgets/ngltreemodel.h>
#include <nglwidgets/ngltreeitem.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
#include <QSortFilterProxyModel>
#include <QSet>
namespace InfrastructureManagement
{
struct StructureElementTreeItem : public NGLTreeItem
{
using NGLTreeItem::NGLTreeItem;
StructureElement data;
QString newBarcode;
QString displayName() const
{
if (m_dispName.isNull())
m_dispName = QString::fromStdString(data.displayName());
return m_dispName;
}
private:
mutable QString m_dispName;
};
class BuildingMountPointModel final : public NGLTreeModel
{
Q_OBJECT
public:
enum Columns
{
ColName,
ColId,
ColInternalName,
ColRelPosX,
ColRelPosY,
ColRelPosZ,
ColMountingPointTypeId,
ColMountingPointId,
ColType,
ColBarcode,
ColBarcodeNew,
ColMountedAsset,
ColProperties
};
explicit BuildingMountPointModel(QObject *parent = nullptr);
bool initModel(const std::shared_ptr<Interface::Dtc> &dtc);
Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant data(const QModelIndex &index, int role) const override;
std::vector<StructureElement> getChildren(const QModelIndex &index, bool bUseNewBarcode) const;
MainStructureElement getMainStructureElement(const QModelIndex &index) const;
QString getMainStructureElementName(qint32 mainStructureElementId) const;
// idx - index to building knot
// barcodes - map<subId,barcode> with new barcodes
// errorString - out -> error msg if failed
void updateBarcodes(const QModelIndex &idx,
QHash<int, QString> &barcodes,
QHash<int, QVector<QString>> &additionalBarcodes);
void resetNewItems(const QModelIndex &idx);
void resetNewBarcodes(const QModelIndex &idx);
protected:
NGLTreeItem *createItem(const QVariant &data, const QIcon &icon) const override
{
return new StructureElementTreeItem(data, icon);
}
private:
std::vector<StructureElement> getChildren(NGLTreeItem *item, bool bUseNewBarcode) const;
void updateBarcodes(NGLTreeItem *item,
QHash<int, QString> &barcodes,
QHash<int, QVector<QString>> &additionalBarcodes);
void resetNewItems(NGLTreeItem *parent);
void resetNewBarcodes(NGLTreeItem *parent);
void updateChildren(int parentId,
NGLTreeItem *parent,
QHash<int, QVector<int> > &parentId2id,
const QHash<int, StructureElement> &structureElements);
void onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data, DataModification modType);
void addBuilding(const MainStructureElement &mse);
void modifyBuilding(const MainStructureElement &mse);
void removeBuildingByGroupId(const MainStructureElement &mse);
void findAndRemoveBuilding(const MainStructureElement &mse);
void insertChildren(int parentId,
const QModelIndex &parentIdx,
const QHash<int, QVector<int> > &parentId2id,
const QHash<int, StructureElement> &structureElements);
void onMountingPointAssetChanged(const InfrastructureManagement::MountingPointAsset &mpa, DataModification modType);
StructureElementTreeItem *findItemByStructureElementId(int id, NGLTreeItem *parent);
StructureElement setBuildingGroup(int groupId);
int getSectionId(int groupId); /// we have to fake the id and get a new because of the treeView | max_int - groupId
StructureElementTreeItem *getStructureTreeItemById(int id, NGLTreeItem *parent);
StructureElementTreeItem *getStructureTreeItemByMSEId(int id, NGLTreeItem *parent);
private:
QHash<int, QModelIndex> m_buildingsIndexes;
const int maxIntValue = std::numeric_limits<int>::max();
QMap<int, MainStructureElement> m_mainStructureElements;
NGL::INGLLogger &m_logger;
std::shared_ptr<Interface::Dtc> m_dtc{nullptr};
QSet<int> m_availableBuildingGroups;
};
class BuildingMountPointSortModel final : public QSortFilterProxyModel
{
Q_OBJECT
public:
using QSortFilterProxyModel::QSortFilterProxyModel;
void setSourceModel(QAbstractItemModel *sourceModel) override;
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
private:
BuildingMountPointModel *m_sourceModel = nullptr;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,377 @@
/**
* @RDE_HEADER@
* ResourceManangement - Plan Dialog
* $Id$
* $HeadURL$
* $Author$
*/
#include "ism_plan_dialog.h"
#include "ui_ism_plan_dialog.h"
#include "ism_plan_dialog_model.h"
#include "ism_plan_edit_dialog.h"
#include <InfrastructureManagement/ism_operator_rights.h>
#include "Overview/ism_overview_mounting_point_list_dialog.h"
#include <InfrastructureManagement/logger.h>
#include <InfrastructureManagement/ism_data_plugin_interface.h>
#include <InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <LtsWidgets/lts_base_layout_widget.h>
#include <LtsPrinting/printing.h>
#include <QTreeView>
namespace InfrastructureManagement
{
PlanDialog::PlanDialog(const QString &menuGroup, LtsSession::LtsSession * session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_session(session)
, m_menuGroup(menuGroup)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_ui(new Ui::PlanDialog)
, m_logger(getLogger(QStringLiteral("PlanDialog")))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_ui->setupUi(this);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print, this, &PlanDialog::onPrint);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &PlanDialog::onRemove);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load, this, &PlanDialog::onLoad);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &PlanDialog::onEdit);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &PlanDialog::onAdd);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Show, this, &PlanDialog::onCopy);
m_buttonBox->getButton(LtsWidgets::DialogButton::Show)->setText(tr("Copy"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Save, this, &PlanDialog::onCheck);
m_buttonBox->getButton(LtsWidgets::DialogButton::Save)->setText(tr("Completeness Check"));
connect(m_ui->planView, &LtsDataView::LtsDataView::signalSelectionChanged, this, &PlanDialog::enaDisa);
connect(m_ui->planView, &LtsDataView::LtsDataView::doubleClicked, this, &PlanDialog::onEdit);
setOnlineHelpFilename(QStringLiteral("Ressourcen-Plans"));
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
PlanDialog::~PlanDialog()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_ui;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void PlanDialog::retranslate()
{
translate(m_ui, tr("Instrumentation Plans"));
}
void PlanDialog::tableColumnOrganiserSetting()
{
//LtsColumnOrganiser
m_ui->planView->setColumnsOrganiserEnabled(identifier(), true);
}
bool PlanDialog::init(int scheduleId, const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignGuiComboboxInterface> &ismGuiCbx,
const std::shared_ptr<ForeignDataInterface> &dataInterface,
ForeignResourceManagementGuiInterface *ismGuiIfc)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_scheduleId = scheduleId;
m_dtc = dtc;
m_ftc = ftc;
m_ismGuiCbx = ismGuiCbx;
m_ismGuiIfc = ismGuiIfc;
m_dataIfc = dataInterface;
bool bRet = true;
bRet &= m_dtc->enableInstrumentationAsset();
bRet &= m_dtc->enableMountingPointAsset();
bRet &= m_dtc->enableMainSchedule();
bRet &= m_dtc->enableMainStructureElement();
bRet &= m_ftc->enableMainScheduleModify();
bRet &= m_ftc->enableMainScheduleCopy();
bRet &= m_ftc->enableMainScheduleRemove();
bRet &= m_ftc->enableInstrumentationAssetModify();
if (!bRet)
{
ERROR_LOG(m_logger) << "Could not enable DTC or FTC from ISM";
return false;
}
delete m_model;
m_model = new PlanDialogModel(this);
m_model->initModel(m_dtc);
m_ui->planView->setModel(m_model);
#ifndef LTS_DEBUG
m_ui->planView->hideColumn(PlanDialogModel::Columns::CREATED);
#endif
connect(m_dataIfc.get(), &ForeignDataInterface::scheduleIdChanged, this, &PlanDialog::onScheduleIdchanged);
m_ui->planView->setToolTip(tr("Current Instrumentation Plan Id = %1").arg(m_scheduleId));
DEBUG_LOG(m_logger) << "m_scheduleId = " << m_scheduleId;
setScheduleId(m_scheduleId);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void PlanDialog::setScheduleId(const int scheduleId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_scheduleId = scheduleId;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismIfc;
if (!m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(ismIfc))
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot set Instrumentation Plan Id"));
return;
}
DEBUG_LOG(m_logger) << "setScheduleId = " << m_scheduleId;
ismIfc->setScheduleId(m_scheduleId);
// set name to "title":
MainSchedule ms = ismIfc->mainSchedule(m_scheduleId);
QString msName = QString::fromStdString(ms.name());
if (m_session && m_session->baseLayout())
m_session->baseLayout()->setCustomText(tr("Instrumentation Plan: '%1'").arg(msName));
m_ui->planView->setToolTip(tr("Current Instrumentation Plan Id = %1").arg(m_scheduleId));
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void PlanDialog::onPrint()
{
LtsPrinting::printView(m_session, this, m_ui->planView->treeView() );
}
void PlanDialog::onMainScheduleChanged(const MainSchedule &data, DataModification modType)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_scheduleId = data.id();
enaDisa();
Q_UNUSED(modType);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void PlanDialog::onScheduleIdchanged(int32_t id)
{
m_scheduleId = id;
enaDisa();
}
void PlanDialog::onLoad()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
QModelIndexList indexList = m_ui->planView->selectedRows();
if (indexList.size() == 0)
return;
MainSchedule item{m_model->getRowData(indexList.front().row())};
if (item.id() == m_scheduleId)
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("This instrumentation plan is already loaded"));
return;
}
m_scheduleId = item.id();
setScheduleId(m_scheduleId);
m_ismGuiIfc->setPlanId(m_scheduleId);
enaDisa();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void PlanDialog::onRemove()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
QModelIndexList indexList = m_ui->planView->selectedRows();
if (indexList.size() == 0)
return;
MainSchedule item{m_model->getRowData(indexList.front().row())};
if (item.id() == m_scheduleId)
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot remove current instrumentation plan"));
return;
}
// unmount MountingPoints
InstrumentationAssetModifyRequest req;
InstrumentationAsset asset;
for (const auto &element : qAsConst(item.elements()))
{
QMap<qint32, MountingPointAsset> mntPntAssets = m_dtc->mountingPointAssets();
for (const auto &mntPntAsset : qAsConst(mntPntAssets))
{
if (mntPntAsset.structureElementId() == element.structureElementId())
{
asset = m_dtc->instrumentationAsset(mntPntAsset.assetId());
req = InstrumentationAssetModifyRequest(
1,
asset.name(),
asset.mountingPointTypeId(),
asset.barcode(),
asset.hostname(),
asset.properties(),
InstrumentationAssetState_def::Unmounted, // <- unmount
asset.lastUpdated(),
asset.availableInExercise()
);
// m_requestHelper->addRequest([req, this](){
// return m_ftc->instrumentationAssetModifyRequest(req, this);
// });
} // if
} // for
} // for
if (m_requestHelper->hasRequests())
m_requestHelper->startRequests();
// remove MainSchedule
Core::RemoveElementRequest rmReq{item.id()};
m_requestHelper->startSingleRequest([rmReq, this]()
{
return m_ftc->mainScheduleRemoveRequest(rmReq, this);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void PlanDialog::enaDisa()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Add, true);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Print, true);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Show, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, false);
QModelIndexList indexList = m_ui->planView->selectedRows();
if (indexList.size() == 0)
return;
MainSchedule item{m_model->getRowData(indexList.front().row())};
bool isComplete = m_dtc->checkSchedule(item.id());
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, !(item.id() == m_scheduleId || item.statusId() == ScheduleStatus::Active) );
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, !(item.id() == m_scheduleId) );
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, (indexList.size() == 1) );
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Show, (indexList.size() == 1) );
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, (indexList.size() == 1 && !isComplete) );
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void PlanDialog::onEdit()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
QModelIndexList indexList = m_ui->planView->selectedRows();
if (indexList.size() == 0)
return;
MainSchedule item{m_model->getRowData(indexList.front().row())};
if (item.id() < 0 )
return;
DEBUG_LOG(m_logger) << "onEdit schedule with id = " << item.id();
PlanEditDialog *dialog = new PlanEditDialog(this);
if (!dialog->init(m_session, item.id(), m_dtc, m_ftc, m_ismGuiCbx))
{
delete dialog;
return;
}
addDialog(dialog, m_menuGroup, QStringLiteral("EditSchedule%1").arg(item.id()), LtsWidgets::LayoutArea::eDialogTab);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void PlanDialog::onAdd()
{
DEBUG_LOG(m_logger) << "onAdd";
PlanEditDialog *dialog = new PlanEditDialog(this);
if (!dialog->init(m_session, 0, m_dtc, m_ftc, m_ismGuiCbx))
{
delete dialog;
return;
}
addDialog(dialog, m_menuGroup, QStringLiteral("AddSchedule"), LtsWidgets::LayoutArea::eDialogTab);
}
void PlanDialog::onCheck()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
QModelIndexList indexList = m_ui->planView->selectedRows();
if (indexList.size() == 0)
return;
MainSchedule item{m_model->getRowData(indexList.front().row())};
if (item.id() < 0 )
return;
DEBUG_LOG(m_logger) << "show Differences schedule with id = " << item.id();
// replace old dialog (created by Iuliana Ojog):
// ScheduleDifferencesListDialog *dialog = new ScheduleDifferencesListDialog(m_menuGroup, this);
// if (!dialog->init(m_session, m_dtc, item.id()))
// {
// delete dialog;
// return;
// }
OverviewMountingPointListDialog *dialog = new OverviewMountingPointListDialog(m_menuGroup, this);
const int32_t scheduleId = item.id();
if (!dialog->init(m_session, m_dtc, m_ftc, m_dataIfc, scheduleId))
{
delete dialog;
return;
}
addDialog(dialog, m_menuGroup, QStringLiteral("ShowDifferences%1").arg(item.id()), LtsWidgets::LayoutArea::eDialogTab);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void PlanDialog::onCopy()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
QModelIndexList indexList = m_ui->planView->selectedRows();
if (indexList.size() == 0)
return;
MainSchedule item{m_model->getRowData(indexList.front().row())};
if (item.id() < 0 )
return;
DEBUG_LOG(m_logger) << "onCopy schedule with id = " << item.id();
MainScheduleCopyRequest req;
req.id(item.id());
m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->mainScheduleCopyRequest(req, this);
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
} // namespace InfrastructureManagement
@@ -0,0 +1,109 @@
/**
* @RDE_HEADER@
* ResourceManangement - Plan Dialog
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/ism_ftc.h>
#include <InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
#include <InfrastructureManagement/ism_combobox_gui_plugin_interface.h>
#include <Plugins/InfrastructureManagement/Data/ism_data_plugin.h>
namespace Ui
{
class PlanDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace NGL
{
class INGLLogger;
}
namespace InfrastructureManagement
{
class ForeignResourceManagementGuiInterface;
class PlanDialogModel;
class PlanDialog
: public LtsWidgets::LtsDialog
, protected Interface::Ftc::MainScheduleRemoveReplyHandler
, protected Interface::Ftc::MainScheduleModifyReplyHandler
, protected Interface::Ftc::MainScheduleCopyReplyHandler
, protected Interface::Ftc::InstrumentationAssetModifyReplyHandler
{
Q_OBJECT
public:
explicit PlanDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
~PlanDialog();
bool init(int scheduleId, const std::shared_ptr<Interface::Dtc> &dtc, const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignGuiComboboxInterface> &ismGuiCbx,
const std::shared_ptr<ForeignDataInterface> &dataInterface,
ForeignResourceManagementGuiInterface *ismGuiIfc);
void setScheduleId(const int scheduleId);
protected:
void onMainScheduleRemoveReply(const Core::FunctionReplyObject &replyObject) override final
{
m_requestHelper->requestReply(replyObject);
}
void onMainScheduleModifyReply(const Core::FunctionReplyObject &replyObject) override final
{
m_requestHelper->requestReply(replyObject);
}
void onMainScheduleCopyReply(const Core::FunctionReplyObject &replyObject) override final
{
m_requestHelper->requestReply(replyObject);
}
void onInstrumentationAssetModifyReply(const Core::FunctionReplyObject &replyObject) override final
{
m_requestHelper->requestReply(replyObject);
}
private slots:
void onPrint();
/**
* @brief onRemove removes all selected plans from the database.
*/
void onRemove();
void onLoad();
void enaDisa();
void onEdit();
void onAdd();
void onCopy();
void onCheck();
void onMainScheduleChanged(const MainSchedule &data, DataModification modType);
void onScheduleIdchanged(int32_t id);
private:
void retranslate() override;
void tableColumnOrganiserSetting() override;
LtsSession::LtsSession *m_session{nullptr};
PlanDialogModel *m_model{nullptr};
QString m_menuGroup;
std::shared_ptr<Interface::Dtc> m_dtc{nullptr};
std::shared_ptr<Interface::Ftc> m_ftc{nullptr};
std::shared_ptr<ForeignGuiComboboxInterface> m_ismGuiCbx{nullptr};
ForeignResourceManagementGuiInterface *m_ismGuiIfc{nullptr};
std::shared_ptr<ForeignDataInterface> m_dataIfc{nullptr};
LtsUtils::RequestHelper *m_requestHelper{nullptr};
int m_scheduleId{-1};
Ui::PlanDialog *m_ui{nullptr};
NGL::INGLLogger &m_logger;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PlanDialog</class>
<widget class="QWidget" name="PlanDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>618</width>
<height>538</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="LtsDataView::LtsDataView" name="planView"/>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,112 @@
/**
* @RDE_HEADER@
* Plans Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2016-11-02
*/
#include <InfrastructureManagement/ism_translation.h>
#include <ngltools/ngltools_dtg.h>
#include "ism_plan_dialog_model.h"
namespace InfrastructureManagement
{
PlanDialogModel::PlanDialogModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<MainSchedule>({tr("Plan Id"),
tr("Name"),
tr("Status"),
tr("Created"),
tr("Begin"),
tr("End"),
tr("Complete")},
parent)
, m_dtc(nullptr)
, m_logger(getLogger("PlanDialogModel"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
PlanDialogModel::~PlanDialogModel()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool PlanDialogModel::initModel(const std::shared_ptr<Interface::Dtc> &dtc)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_dtc = dtc;
connect(m_dtc.get(), &Interface::Dtc::mainScheduleChanged, this, &PlanDialogModel::onDataChanged);
m_dtc->mainSchedules([this](const MainSchedule &ms){ onDataChanged(ms, DataModification::eAdded); });
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
QVariant PlanDialogModel::data(const QModelIndex &index, int role) const
{
if (!indexIsValid(index)) //role != Qt::DisplayRole ||
return QVariant();
const MainSchedule &ms = m_vecData.at(index.row());
if (role == Qt::DecorationRole)
{
static const QIcon green(QLatin1String("icon:green_light.svg"));
static const QIcon red(QLatin1String("icon:red_light.svg"));
if (index.column() == PlanDialogModel::Columns::COMPLETE)
{
// since checkSchedule could be timeconsuming, perform only if needed:
bool isComplete = m_dtc->checkSchedule(ms.id());
return (isComplete ? green : red);
}
}
else if (role == Qt::TextColorRole)
{
if (index.column() == PlanDialogModel::Columns::STATUS)
{
switch (ms.statusId().underlying())
{
case ScheduleStatus::Active:
return QColor(Qt::darkGreen);
case ScheduleStatus::Inactive:
return QColor(Qt::red);
}
}
}
else if (role == Qt::DisplayRole)
{
switch (index.column())
{
case ID:
return ms.id();
case NAME:
return QString::fromStdString(ms.name());
case STATUS:
return toString(ms.statusId());
case CREATED:
return DTG::toStringMSec(ms.timeCreated());
case START:
return (ms.timeStart().is_set() ? DTG::toStringMSec(ms.timeStart().get()) : QVariant()) ;
case END:
return (ms.timeEnd().is_set() ? DTG::toStringMSec(ms.timeEnd().get()) : QVariant());
case COMPLETE:
{
// since checkSchedule could be timeconsuming, perform only if needed:
bool isComplete = m_dtc->checkSchedule(ms.id());
return (isComplete ? tr("Yes") : tr("No"));
}
}
}
return QVariant();
}
}
@@ -0,0 +1,48 @@
/**
* @RDE_HEADER@
* ResourceManangement - Plan Dialog
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <LtsWidgets/lts_abstract_table_model.h>
#include <InfrastructureManagement/ism_dtc.h>
#include <InfrastructureManagement/logger.h>
namespace InfrastructureManagement
{
class PlanDialogModel : public LtsWidgets::LtsAbstractTableModel<MainSchedule>
{
Q_OBJECT
public:
explicit PlanDialogModel(QObject *parent = nullptr);
~PlanDialogModel();
QVariant data(const QModelIndex &index, int role) const override final;
bool initModel(const std::shared_ptr<Interface::Dtc> &dtc);
enum Columns
{
ID,
NAME,
STATUS,
CREATED,
START,
END,
COMPLETE
};
private:
std::shared_ptr<Interface::Dtc> m_dtc;
LOGGER_T m_logger;
};
} // namespace InfrastructureManagement
@@ -0,0 +1,191 @@
/**
* @RDE_HEADER@
* ResourceManangement - Plan Edit Dialog
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2017-04-21
*/
#include "ism_plan_edit_dialog.h"
#include "ui_ism_plan_edit_dialog.h"
#include "ism_plan_dialog_model.h"
#include <Services/InfrastructureManagement/ism_dtc.h>
#include <Services/InfrastructureManagement/ism_ftc.h>
#include <LtsUtilsGuiDds/request_helper.h>
namespace InfrastructureManagement
{
PlanEditDialog::PlanEditDialog(QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_session(nullptr)
, m_ui(new Ui::PlanEditDialog)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("PlanEditDialog"))
{
m_ui->setupUi(this);
m_uiRequirements->addRequirement( { m_ui->lblName, [this]()
{
return (!m_ui->leName->text().isEmpty()); }
});
setOnlineHelpFilename(QStringLiteral("Ressourcen-Plans"));
}
PlanEditDialog::~PlanEditDialog()
{
delete m_ui;
}
bool PlanEditDialog::init(LtsSession::LtsSession *session,
const int scheduleId,
const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignGuiComboboxInterface> &ismCbx)
{
m_scheduleId = scheduleId;
m_dtc = dtc;
m_ftc = ftc;
m_ismGuiCbxIfc = ismCbx;
m_session = session;
m_ui->dteBegin->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
m_ui->dteEnd->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
m_ismGuiCbxIfc->fillScheduleStatusComboBox(m_ui->cbStatus);
if (m_scheduleId > 0) // edit plan
{
MainSchedule data = dtc->mainSchedule(m_scheduleId);
m_currentState = data.statusId();
m_ui->cbStatus->setCurrentIndex(m_ui->cbStatus->findData(data.statusId().underlying()));
m_ui->leName->setText(QString::fromStdString(data.name()));
if (data.timeStart().is_set())
m_ui->dteBegin->setMsecsSinceEpoch(data.timeStart().get());
if (data.timeEnd().is_set())
m_ui->dteEnd->setMsecsSinceEpoch(data.timeEnd().get());
}
else // add plan
{
m_currentState = ScheduleStatus::Active;
m_ui->cbStatus->setCurrentIndex(m_ui->cbStatus->findData(ScheduleStatus::Inactive));
m_ui->cbStatus->setEnabled(true);
}
enaDisa();
return true;
}
bool PlanEditDialog::apply()
{
if (!m_ui->dteBegin->isEmpty() && !m_ui->dteEnd->isEmpty() && m_ui->dteBegin->msecsSinceEpoch() > m_ui->dteEnd->msecsSinceEpoch())
{
QString msg = tr("Begin time must be before end time.");
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot save instrumentation plan '%1':\n%2").arg(m_ui->leName->text(), msg));
return false;
}
for(auto schedule : m_dtc->mainSchedules())
{
if(schedule.name() == m_ui->leName->text().toStdString())
{
if(m_scheduleId <= 0)
{
QString msg = tr("The name is already in use.");
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot save instrumentation plan '%1':\n%2").arg(m_ui->leName->text(), msg));
return false;
}
else
{
if(m_scheduleId != schedule.id() && schedule.name() == m_ui->leName->text().toStdString())
{
QString msg = tr("The name is already in use.");
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot save instrumentation plan '%1':\n%2").arg(m_ui->leName->text(), msg));
return false;
}
}
}
}
MainScheduleModifyRequest data;
data.name((m_ui->leName->text().toStdString()));
ScheduleStatus newStatus = static_cast<ScheduleStatus::type>(m_ui->cbStatus->currentData().toInt());
if (newStatus != m_currentState)
{
switch (newStatus.underlying())
{
case ScheduleStatus::Active:
//m_ui->dteBegin->setMsecsSinceEpoch(QDateTime::currentMSecsSinceEpoch());
// data.statusId(ScheduleStatus::Active);
break;
case ScheduleStatus::Inactive:
//m_ui->dteEnd->setMsecsSinceEpoch(QDateTime::currentMSecsSinceEpoch());
// data.statusId(ScheduleStatus::Inactive);
break;
default:
break;
}
}
if (m_scheduleId > 0) // edit schedule
{
MainSchedule ms = m_dtc->mainSchedule(m_scheduleId);
data.id(ms.id());
data.exerciseId(ms.exerciseId()); //not used
data.description(ms.description()); // not used
data.timeCreated(ms.timeCreated());
}
else // add schedule
{
data.id(0);
data.timeCreated(QDateTime::currentMSecsSinceEpoch());
}
if (!m_ui->dteBegin->isEmpty() && m_ui->dteBegin->isValidDate())
data.timeStart(m_ui->dteBegin->msecsSinceEpoch());
else
data.timeStart();
if (!m_ui->dteEnd->isEmpty() && m_ui->dteEnd->isValidDate())
data.timeEnd(m_ui->dteEnd->msecsSinceEpoch());
else
data.timeEnd();
data.statusId(static_cast<ScheduleStatus::type>(m_ui->cbStatus->currentData().toInt()));
m_requestHelper->addRequest([data,this](){
return m_ftc->mainScheduleModifyRequest(data, this);
});
return m_requestHelper->startRequests();
}
void PlanEditDialog::enaDisa()
{
m_ui->dteBegin->setEnabled(true);
m_ui->dteEnd->setEnabled(true);
}
void PlanEditDialog::retranslate()
{
translate(m_ui, m_dtc->mainSchedule(m_scheduleId), tr("Instrumentation Plan"));
}
} // namespace InfrastructureManagement
@@ -0,0 +1,75 @@
/**
* @RDE_HEADER@
* ResourceManangement - Plan Edit Dialog
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2017-04-21
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <LtsSession/lts_session.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <InfrastructureManagement/ism_combobox_gui_plugin_interface.h>
#include <InfrastructureManagement/logger.h>
#include <Plugins/InfrastructureManagement/Data/ism_data_plugin.h>
#include <Plugins/InfrastructureManagement/ism_resource_management_gui_plugin_interface.h>
namespace Ui
{
class PlanEditDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace InfrastructureManagement
{
namespace Interface
{
class Dtc;
class Ftc;
}
class PlanDialogModel;
class PlanEditDialog : public LtsWidgets::LtsDialog
, protected Interface::Ftc::MainScheduleModifyReplyHandler
{
Q_OBJECT
public:
explicit PlanEditDialog(QWidget *parent = nullptr);
bool init(LtsSession::LtsSession *session, const int scheduleId,
const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ForeignGuiComboboxInterface> &ismCbx);
~PlanEditDialog();
protected:
void onMainScheduleModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void enaDisa();
private:
void retranslate() override;
bool apply() override final;
LtsSession::LtsSession *m_session{nullptr};
Ui::PlanEditDialog *m_ui;
int m_scheduleId;
ScheduleStatus m_currentState;
std::shared_ptr<Interface::Dtc> m_dtc;
std::shared_ptr<Interface::Ftc> m_ftc;
std::shared_ptr<ForeignGuiComboboxInterface> m_ismGuiCbxIfc;
LtsUtils::RequestHelper *m_requestHelper;
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PlanEditDialog</class>
<widget class="QWidget" name="PlanEditDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>656</width>
<height>309</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="3">
<widget class="QLabel" name="lblEnd">
<property name="text">
<string>End</string>
</property>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="3" colspan="2">
<widget class="LtsWidgets::LtsDateTimeEdit" name="dteEnd" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="LtsWidgets::LtsComboBox" name="cbStatus"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="LtsWidgets::LtsDateTimeEdit" name="dteBegin" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblBegin">
<property name="text">
<string>Begin</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLineEdit" name="leName"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblName">
<property name="text">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="lblStatus">
<property name="text">
<string>Status</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsComboBox</class>
<extends>QComboBox</extends>
<header>LtsWidgets/lts_combo_box.h</header>
</customwidget>
<customwidget>
<class>LtsWidgets::LtsDateTimeEdit</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_date_time_edit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,793 @@
/**
* @RDE_HEADER@
* GUI Plugin for ResourceManangement
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2016-11-02
*/
#include "ism_resource_gui_plugin.h"
#include "ism_plan_dialog.h"
#include "ism_building_mount_point_dialog.h"
#include "Overview/ism_overview_dialog.h"
#include "AssetList/ism_asset_list_dialog.h"
#include "MountingPointInfo/ism_mounting_point_info_dialog.h"
#include "MountingPointList/ism_mounting_point_list_dialog.h"
#include "PlanChooser/plan_chooser.h"
#include "PlanChooser/new_plan_dialog.h"
#include "ApproachingPoints/ism_approaching_point_list_dialog.h"
//#include "Timeline/ism_plan_tln_dialog.h"
#include "ism_plan_edit_dialog.h"
#include "Overview/ism_overview_mounting_point_list_dialog.h"
#include "ExerciseAssignment/ism_exercise_assignment_dialog.h"
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <LtsWidgets/lts_background_widget.h>
#include <LtsWidgets/lts_base_layout_widget.h>
#include <LtsWidgets/lts_global_wait_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <MountingPointMapSelection/ism_selector.h>
#include <InfrastructureManagement/ism_operator_rights.h>
#include <InfrastructureManagement/logger.h>
#include <LtsUtilsSettings/settings.h>
#include <LtsNotification/lts_notification.h>
#include <Viewer/SituationMap/Map/map.h>
namespace InfrastructureManagement
{
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
{
return std::make_shared<InterfaceImpl>(session);
}
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
: GuiPluginBase::Interface(session, getLogger("ResourceManagement"))
// , m_dtc(nullptr)
// , m_ftc(nullptr)
//, m_ismIfc(nullptr)
, m_avmIfc(nullptr)
, m_sitmapGuiIfc(nullptr)
, m_planId(-1)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_mountingPointSelector(nullptr)
{
connect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession,
this, &InterfaceImpl::slotOnSessionReady);
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
if (ps->value(QStringLiteral("ism"), QStringLiteral("enableResPlanDialog")).toBool())
{
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Add Instrumentation Plan");
plData.identifier = QLatin1String("IsmResPlanAddDialog");
plData.menuIcon = QIcon(QLatin1String("icon:plan_new.svg"));
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.operatorRight = OperatorRights::InfrastructurePlansEdit;
plData.createWidgetFunc = [this](QWidget *parent)
{
return slotAddPlanDialog(parent);
};
ret.append(plData);
}
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Instrumentation Plans");
plData.identifier = QLatin1String("IsmResPlanDialog");
plData.menuIcon = QIcon(QLatin1String("icon:plans.svg"));
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.operatorRight = OperatorRights::InfrastructurePlansShow;
plData.createWidgetFunc = [this](QWidget *parent)
{
return slotShowPlanDialog(parent);
};
ret.append(plData);
}
/*
{
// Append Time Line view dialog
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Timeline");
plData.identifier = QLatin1String("IsmTimelineView");
plData.menuIcon = QIcon(QLatin1String("icon:timeline.svg"));
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.operatorRight = OperatorRights::InfrastructurePlansShow;
plData.createWidgetFunc = [this](QWidget *parent)
{
return slotShowPlanTimeLineDialog(parent);
};
ret.append(plData);
}
*/
}
if (ps->value(QStringLiteral("ism"), QStringLiteral("enableOverviewDialog")).toBool())
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Overview");
plData.identifier = QLatin1String("IsmOverviewDialog");
plData.menuIcon = QIcon(QLatin1String("icon:evaluate.svg"));
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.operatorRight = OperatorRights::InfrastructurePlansShow;
plData.createWidgetFunc = [this](QWidget *parent)
{
return slotShowOverviewDialog(parent);
};
ret.append(plData);
}
if (ps->value(QStringLiteral("ism"), QStringLiteral("enableAssetListDialog")).toBool())
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Asset List");
plData.identifier = QLatin1String("IsmAssetListDialog");
plData.menuIcon = QIcon(QLatin1String("icon:choose_audio_video_menu.svg"));
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.operatorRight = OperatorRights::InfrastructurePlansShow;
plData.createWidgetFunc = [this](QWidget *parent)
{
return slotShowAssetListDialog(parent);
};
ret.append(plData);
}
if (ps->value(QStringLiteral("ism"), QStringLiteral("enableMpListDialog")).toBool())
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Mounting Point List");
plData.identifier = QLatin1String("IsmMpListDialog");
plData.menuIcon = QIcon(QLatin1String("icon:fixed_video_announcement.svg"));
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.operatorRight = OperatorRights::InfrastructurePlansShow;
plData.createWidgetFunc = [this](QWidget *parent)
{
return slotShowMountingPointListDialog(parent);
};
ret.append(plData);
}
if (ps->value(QStringLiteral("ism"), QStringLiteral("enableBuildingListDialog")).toBool())
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Building List");
plData.identifier = QLatin1String("IsmBuildingListDialog");
plData.menuIcon = QIcon(QLatin1String("icon:show_building_configuration.svg"));
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.operatorRight = OperatorRights::InfrastructurePlansShow;
plData.createWidgetFunc = [this](QWidget *parent) -> LtsWidgets::LtsDialog *
{
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc)
|| !m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc))
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open Building List"));
return nullptr;
}
return LtsWidgets::initDialog(new BuildingMountPointDialog(parent),
ismDtc, ismFtc, this);
};
ret.append(plData);
}
if (ps->value(QStringLiteral("ism"), QStringLiteral("enableApproachingPointsDialog")).toBool())
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Approaching Points");
plData.identifier = QLatin1String("IsmApproachingPointsDialog");
plData.menuIcon = QIcon(QLatin1String("icon:karte.svg"));
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.operatorRight = OperatorRights::InfrastructurePlansShow;
plData.createWidgetFunc = [this](QWidget *parent)
{
return slotShowApproachingPointsDialog(parent);
};
ret.append(plData);
}
if (ps->value(QStringLiteral("ism"), QStringLiteral("enableOverviewMountedPointDialog")).toBool())
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Completeness Check");
plData.identifier = QLatin1String("IsmOverviewMountedPointDialog");
plData.menuIcon = QIcon(QLatin1String("icon:completeness_check_enabled.svg"));
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.operatorRight = OperatorRights::InfrastructurePlansShow;
plData.createWidgetFunc = [this](QWidget *parent)
{
return slotShowMntpCompletenessCheckDialog(parent);
};
ret.append(plData);
}
LtsWidgets::PluginData plData;
plData.menuGroup = tr("Exercise Assignment");
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.menuText = tr("Exercise Assignment");
plData.identifier = QLatin1String("IsmAvcExerciseAssignmentDialog");
plData.menuIcon = QIcon(QLatin1String("icon:set_exercise_process.svg"));
plData.createWidgetFunc = [this](QWidget *) -> LtsWidgets::LtsDialog *
{
try {
return new ExerciseAssignmentDialog(m_session);
}catch(...){return nullptr;}
};
ret.append(plData);
if (m_session->app() == LtsAppDescriptor::App::ResourceManager)
{
// Toggle Planungsansicht/KomponentenÜberwachung
// Toggle PlanView/Component Monitor
LtsWidgets::PluginData plData;
plData.identifier = QStringLiteral("PlanView/Componentmonitor");
plData.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction;
plData.directFunc = [this](const LtsWidgets::PluginData &)
{
if (!m_sitmapGuiIfc)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no sitmapGuiIfc";
return;
}
m_notiResourceManagerMode = m_session->createNotification(QStringLiteral("PlanView/ComponentMonitor"));
m_notiResourceManagerMode->setIcon(QIcon(QStringLiteral("icon:plans.svg")));
m_notiResourceManagerMode->setEnabled(false);
// "icon:status_infrastructure.svg" <> "icon:plans.svg"
m_notiResourceManagerMode->setAction([this]()
{
m_notiResourceManagerMode->setBackground(-1, -1, -1); // Set back to default
if (!m_sitmapGuiIfc || !m_sitmapGuiIfc->isMapReady())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " sitmapGuiIfc no ready yet";
return;
}
const SituationMap::ResourceManagerMode rmm = m_sitmapGuiIfc->resourceManagerMode();
// toogle between RMM_PlanActivityView and RMM_ComponentMonitor:
// not towards RMM_PlanDefinitionView!!
switch (rmm) {
case SituationMap::ResourceManagerMode::Undefined:
// empty
break;
case SituationMap::ResourceManagerMode::RMM_PlanActivityView:
m_notiResourceManagerMode->setBackground(60, 209, 54); //Timeline green
m_sitmapGuiIfc->setResourceManagerMode(SituationMap::ResourceManagerMode::RMM_ComponentMonitor);
break;
case SituationMap::ResourceManagerMode::RMM_PlanDefinitionView:
// RMM_PlanDefinitionView is only available by open "MountingPointListDialog" / "Anbringungspunkte"
// do nothing:
// // m_sitmapGuiIfc->setResourceManagerMode(SituationMap::ResourceManagerMode::RMM_PlanActivityView);
break;
case SituationMap::ResourceManagerMode::RMM_ComponentMonitor:
m_sitmapGuiIfc->setResourceManagerMode(SituationMap::ResourceManagerMode::RMM_PlanActivityView);
break;
default:
//empty
break;
} //switch
});
};
ret.append(plData);
}
return ret;
}
void InterfaceImpl::slotOnSessionReady()
{
DEBUG_LOG(m_logger) << LOGFUNCTION;
disconnect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession,
this, &InterfaceImpl::slotOnSessionReady);
if (m_sitmapGuiIfc->isMapReady())
{
slotOnMapReady();
} else {
auto onMapIsReadyFn = [this]() {
slotOnMapReady();
};
if (!m_sitmapGuiIfc->setMapReadyCallback(this, onMapIsReadyFn))
ERROR_LOG(m_logger) << LOGFUNCTION << ", setMapReadyCallback failed";
}
}
void InterfaceImpl::slotOnMapReady()
{
INFO_LOG(m_logger) << LOGFUNCTION << "START";
//
// update icon and tooltip according current ResourceManagerMode:
// 'connect' via callback :
//
auto onChanged = [this]() {
INFO_LOG(m_logger) << LOGFUNCTION << " update... onResourceManagerModeChanged";
const SituationMap::ResourceManagerMode rmm = m_sitmapGuiIfc->resourceManagerMode();
this->onResourceManagerModeChanged(rmm);
};
m_sitmapGuiIfc->setResourceManagerModeChangedCallback(this, onChanged);
// : 'connect' via callback
const SituationMap::ResourceManagerMode rmm = m_sitmapGuiIfc->resourceManagerMode();
this->onResourceManagerModeChanged(rmm);
}
void InterfaceImpl::onResourceManagerModeChanged(SituationMap::ResourceManagerMode newMode)
{
INFO_LOG(m_logger) << " new ResourceManagerMode: newMode = " << (int)newMode;
// update icon etc. of m_notiResourceManagerMode:
if (!m_notiResourceManagerMode)
return;
if (!m_sitmapGuiIfc)
return;
switch (newMode) {
case SituationMap::ResourceManagerMode::Undefined:
m_notiResourceManagerMode->setEnabled(false);
// disable...
break;
case SituationMap::ResourceManagerMode::RMM_PlanActivityView:
m_notiResourceManagerMode->setBackground(-1, -1, -1); // Set back to default
m_notiResourceManagerMode->setIcon(QIcon(QStringLiteral("icon:completeness_check_enabled.svg"))); // maybe icon:about.svg or icon:arrow_front_back.svg
m_notiResourceManagerMode->setToolTip(tr("Plan Activity View"));
m_notiResourceManagerMode->setEnabled(true);
break;
case SituationMap::ResourceManagerMode::RMM_PlanDefinitionView:
m_notiResourceManagerMode->setBackground(-1, -1, -1); // Set back to default
m_notiResourceManagerMode->setIcon(QIcon(QStringLiteral("icon:plan_new.svg")));
m_notiResourceManagerMode->setToolTip(tr("Plan Definition View"));
m_notiResourceManagerMode->setEnabled(false);
break;
case SituationMap::ResourceManagerMode::RMM_ComponentMonitor:
m_notiResourceManagerMode->setBackground(60, 209, 54); //Timeline green
m_notiResourceManagerMode->setIcon(QIcon(QStringLiteral("icon:status_infrastructure.svg")));
m_notiResourceManagerMode->setToolTip(tr("Component View"));
m_notiResourceManagerMode->setEnabled(true);
break;
default:
// empty
break;
}
}
bool InterfaceImpl::fetchInterfaces()
{
if (/*!m_session->getDtc<InfrastructureManagement::DataInterface>(m_dtc) ||
!m_session->getFtc<InfrastructureManagement::DataInterface>(m_ftc) ||
!m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(m_ismIfc) ||*/
!m_session->getForeignDataInterface_NEW<AudioVideoManagement::ForeignDataInterface>(m_avmIfc) ||
!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitmapGuiIfc))
return false;
return true;
}
void InterfaceImpl::clearInterfaces()
{
m_sitmapGuiIfc = nullptr;
// m_ismIfc = nullptr;
m_avmIfc = nullptr;
// m_ftc = nullptr;
// m_dtc = nullptr;
}
LtsWidgets::LtsDialog *InterfaceImpl::slotShowPlanDialog(QWidget *parent)
{
DEBUG_LOG(m_logger) << "slotShowPlanDialog: m_planId = " << m_planId;
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
std::shared_ptr<InfrastructureManagement::ForeignGuiComboboxInterface> ismCbx;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismIfc;
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc)
|| !m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc)
|| !m_session->getForeignGuiInterface<InfrastructureManagement::ForeignGuiComboboxInterface>(ismCbx)
|| !m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(ismIfc))
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open Plan Dialog"));
return nullptr;
}
return LtsWidgets::initDialog(new PlanDialog(menuGroup(), m_session, parent),
m_planId, ismDtc, ismFtc, ismCbx, ismIfc, this);
}
LtsWidgets::LtsDialog *InterfaceImpl::slotShowOverviewDialog(QWidget *parent)
{
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismIfc;
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc)
|| !m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc)
|| !m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(ismIfc))
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open Plan Dialog"));
return nullptr;
}
return LtsWidgets::initDialog(new OverviewDialog(menuGroup(), m_session, parent),
m_planId, ismDtc,ismFtc, ismIfc);
}
LtsWidgets::LtsDialog *InterfaceImpl::slotShowAssetListDialog(QWidget *parent)
{
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
std::shared_ptr<ComponentMonitor::Interface::Dtc> cmoDtc; // CMO ComponentMonitor
std::shared_ptr<ComponentMonitor::Interface::Ftc> cmoFtc; // CMO ComponentMonitor
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc)
|| !m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc)
|| !m_session->getDtc<ComponentMonitor::DataInterface>(cmoDtc)
|| !m_session->getFtc<ComponentMonitor::DataInterface>(cmoFtc)
)
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open Plan Dialog"));
return nullptr;
}
return LtsWidgets::initDialog(new AssetListDialog(menuGroup(), m_session, parent),
ismDtc, ismFtc, cmoDtc, cmoFtc);
}
LtsWidgets::LtsDialog *InterfaceImpl::slotShowMountingPointListDialog(QWidget *parent)
{
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismIfc;
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> fltBuildingComponentIfc;
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc)
|| !m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc)
|| !m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(ismIfc)
// Nachtrag zu GUEZE-1769: since fltBuildingComponentIfc is optional:
// for this dialog fltBuildingComponentIfc is not optional, is required, so get it (NT, 09.08.2023)
|| !m_session->getForeignGuiInterface<FilterManagement::ForeignFltBuildingComponentGuiInterface>(fltBuildingComponentIfc)
)
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open Mounting Point List"));
return nullptr;
}
// Maybe there is a lot of data to load:
LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(tr("Open Mounting Point List ..."));
MountingPointListDialog *dlg = LtsWidgets::initDialog(new MountingPointListDialog(menuGroup(), parent),
m_session, ismDtc, ismFtc, ismIfc, this, m_sitmapGuiIfc, fltBuildingComponentIfc);
LtsWidgets::LtsGlobalWaitDialog::getInstance()->done();
return dlg;
}
LtsWidgets::LtsDialog *InterfaceImpl::slotShowApproachingPointsDialog(QWidget *parent)
{
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc)
|| !m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc))
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open Approaching Points Dialog"));
return nullptr;
}
return LtsWidgets::initDialog(new ApproachingPointsDialog(menuGroup(), m_session, parent),
ismDtc, ismFtc, m_sitmapGuiIfc);
}
/*
LtsWidgets::LtsDialog *InterfaceImpl::slotShowPlanTimeLineDialog(QWidget *parent)
{
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismDataIfc;
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc)
|| !m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc)
|| !m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(ismDataIfc))
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open Plan timeline Dialog"));
return nullptr;
}
return LtsWidgets::initDialog(new PlanTimeLineDialog(m_session, menuGroup(), parent),
ismDtc,ismFtc, ismDataIfc, this);
}
*/
void InterfaceImpl::onMainScheduleModifyReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void InterfaceImpl::showMountingPointInfoWindows(const QVector<int32_t> &entityIds, bool /*force*/)
{
std::shared_ptr<InfrastructureManagement::Interface::Dtc> dtc;
std::shared_ptr<ForeignDataInterface> ismDataIfc;
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(dtc)
|| !m_session->getForeignDataInterface<DataInterface>(ismDataIfc))
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open Mounting Point Info"));
return;
}
// int len = entityIds.length();
// if (len > 10 && !force)
// {
// auto x = new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(),
// tr("Are you sure that you want to open more than 10 (%1) Mounting Point Info dialogs?").arg(len),
// tr("Mounting Point Info"),
// LtsWidgets::Behaviour::Modal, LtsWidgets::Button::Yes | LtsWidgets::Button::Cancel);
// connect(x, &LtsWidgets::LtsMessageDialogNew::yes,
// this, [this, entityIds]()
// {
// showMountingPointInfoWindows(entityIds, true); // force if user really wants to open more than 10 windows
// });
// return;
// }
for (int32_t entityId : entityIds)
{
MountingPointInfoDialog *dialog = new MountingPointInfoDialog(entityId, m_planId, menuGroup());
dialog->init(dtc, ismDataIfc, m_avmIfc);
m_session->addWidget(dialog, menuGroup(), QStringLiteral("MP info %1").arg(entityId), LtsWidgets::LayoutArea::eInfoTab);
}
}
void InterfaceImpl::slotNewPlan()
{
std::shared_ptr<InfrastructureManagement::ForeignGuiComboboxInterface> ismCbx;
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
if (!m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc)
|| !m_session->getForeignGuiInterface<InfrastructureManagement::ForeignGuiComboboxInterface>(ismCbx))
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open New Plan"));
return;
}
// enable mainScheduleModifyRequest
if (!ismFtc->enableMainScheduleModify())
{
ERROR_LOG(m_logger) << "Could not enable FT MainScheduleModify of ISM";
return;
}
PlanChooser *planChooser = qobject_cast<PlanChooser *>(sender());
if (!planChooser)
{
WARNING_LOG(m_logger) << "cannot create new plan, plan chooser payload dialog not found!";
return;
}
std::unique_ptr<NewPlanDialog> npd(new NewPlanDialog(m_session, planChooser));
npd->init(ismCbx);
if (!LtsSessionData::LtsSessionData::getInstance()->isTablet())
npd->setModal(true);
int status = 0;
QString name;
qint64 tbegin = 0;
qint64 tend = 0;
if (!npd->getData(name, tbegin, tend, status))
return; // user rejected the dialog, do nothing
if (name.length() < 3)
{
LtsWidgets::LtsMessageDialog::showMessage(planChooser,
tr("The name for a new plan must have 3 characters or more. Please try again."),
tr("Error creating new plan"));
return;
}
MainScheduleModifyRequest req;
req.name(name.toStdString());
//req.description(tr("No description").toStdString());
//req.exerciseId(); // not used
req.id(0);
req.statusId(static_cast<ScheduleStatus::inner_enum>(status));
req.timeCreated(QDateTime::currentDateTime().toMSecsSinceEpoch());
if(tbegin > 0)
req.timeStart(tbegin);
req.timeEnd(tend);
if (m_requestHelper->startSingleRequest([req, ismFtc, this]()
{
return ismFtc->mainScheduleModifyRequest(req, this);
}))
{
m_planId = m_requestHelper->getRepliedId();
ERROR_LOG(m_logger) << "New Instrumentation Plan with id " << m_planId << " created!";
planChooser->selectPlan(m_planId);
}
else
{
WARNING_LOG(m_logger) << "Creating new Instrumentation Plan failed!";
}
}
LtsWidgets::LtsDialog *InterfaceImpl::slotAddPlanDialog(QWidget *parent)
{
DEBUG_LOG(m_logger) << "slotAddPlanDialog";
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
std::shared_ptr<InfrastructureManagement::ForeignGuiComboboxInterface> ismCbx;
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc) ||
!m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc) ||
!m_session->getForeignGuiInterface<InfrastructureManagement::ForeignGuiComboboxInterface>(ismCbx))
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open Plan Dialog"));
return nullptr;
}
// enable mainScheduleModifyRequest
if (!ismFtc->enableMainScheduleModify())
{
ERROR_LOG(m_logger) << "Could not enable FT MainScheduleModify of ISM";
return nullptr;
}
return LtsWidgets::initDialog(new PlanEditDialog(parent),
m_session, 0, ismDtc, ismFtc, ismCbx);
}
LtsWidgets::LtsDialog *InterfaceImpl::slotShowMntpCompletenessCheckDialog(QWidget *parent)
{
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
std::shared_ptr<InfrastructureManagement::Interface::Ftc> ismFtc;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismDataIfc;
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc)
|| !m_session->getFtc<InfrastructureManagement::DataInterface>(ismFtc)
|| !m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(ismDataIfc)
)
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot open Mounting Point Completeness check Dialog"));
return nullptr;
}
const int32_t scheduleId = ismDataIfc->scheduleId();
return LtsWidgets::initDialog(new OverviewMountingPointListDialog(menuGroup(), parent),
m_session, ismDtc, ismFtc, ismDataIfc, scheduleId);
}
void InterfaceImpl::setPlanId(const int planId)
{
m_planId = planId;
m_session->setBaseLayoutVisible();
DEBUG_LOG(m_logger) << "setPlanId = " << planId;
std::shared_ptr<InfrastructureManagement::ForeignDataInterface> ismIfc;
if (!m_session->getForeignDataInterface<InfrastructureManagement::DataInterface>(ismIfc))
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot set Plan Id"));
return;
}
ismIfc->setScheduleId(m_planId);
// set name to "title":
MainSchedule ms = ismIfc->mainSchedule(m_planId);
QString msName = QString::fromStdString(ms.name());
connect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession,
this, [this, msName] ()
{
disconnect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession,
this, nullptr);
if (m_session && m_session->baseLayout())
m_session->baseLayout()->setCustomText(tr("Instrumentation Plan: '%1'").arg(msName));
});
}
int InterfaceImpl::getPlanId() const
{
return m_planId;
}
bool InterfaceImpl::isInSelectionMode() const
{
return m_mountingPointSelector;
}
void InterfaceImpl::setSelector(MountingPointSelector *selector)
{
m_mountingPointSelector = selector;
}
void InterfaceImpl::addToSelection(int32_t mountingPointId)
{
addToSelection(QVector<int32_t>() << mountingPointId);
}
void InterfaceImpl::addToSelection(const QVector<int32_t> &simIds)
{
//TODO
if (m_mountingPointSelector)
m_mountingPointSelector->addMountingPoints(simIds, QMap<int32_t, MountingPointState>(), m_session->baseLayoutWidget());
}
void InterfaceImpl::executePayload(LtsWidgets::LtsBackgroundWidget *mainBackground) // TODO: doc: as few d-/ftc passes as possible, better make a signal/slot to the underlying class (like here)
{
DEBUG_LOG(m_logger) << "executePayload";
connect(this, &InterfaceImpl::signalSuccess,
m_session, &LtsSession::LtsSession::slotExecuteNextPayload, Qt::QueuedConnection);
std::shared_ptr<InfrastructureManagement::Interface::Dtc> ismDtc;
if (!m_session->getDtc<InfrastructureManagement::DataInterface>(ismDtc))
{
auto x = new LtsWidgets::LtsMessageDialogNew(m_session->baseLayoutWidget(), tr("The Infrastructure Management is not available!"), tr("Cannot start Application Payload"));
connect(x, &LtsWidgets::LtsMessageDialogNew::destroyed,
this, [this]()
{
emit signalSuccess();
});
return;
}
PlanChooser *planChooser = new PlanChooser(ismDtc, mainBackground);
planChooser->init(m_session);
planChooser->setAttribute(Qt::WA_DeleteOnClose);
connect(planChooser, &PlanChooser::signalSelectPlan,
this, &InterfaceImpl::slotSelectPlan, Qt::QueuedConnection); // queue!!
connect(planChooser, &PlanChooser::signalNewPlan,
this, &InterfaceImpl::slotNewPlan, Qt::QueuedConnection); // queue!!
connect(planChooser, &PlanChooser::signalQuit,
m_session, &LtsSession::LtsSession::signalQuit);
// TODO: connect to deleteLater?
// no presets
if (!LtsSessionData::LtsSessionData::getInstance()->isTablet())
planChooser->setModal(true);
planChooser->show();
}
void InterfaceImpl::slotSelectPlan(int planId)
{
DEBUG_LOG(m_logger) << "Instrumentation Plan id = " << planId;
setPlanId(planId);
emit signalSuccess();
}
} // namespace InfrastructureManagement
Loaded 100 of 16245 files, more files were not shown because too many files have changed in this diff. Show more