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,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>