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