Files
qt5-legatus-legacy/Lts/Plugins/Buildings/Gui/BuildingInfo/bld_info_dialog.cpp
T
2026-08-13 18:33:10 +02:00

1140 lines
41 KiB
C++
Executable File

/**
*@RDE_HEADER@
* GUI Plugin for Building - Info
* $Id$
* $HeadURL$
* $Author$
* Created by hjl, SLSE, 2017-04-05
*/
//#define PP_TEST
#include "bld_info_dialog.h"
#include "ui_bld_info_dialog.h"
#include "bld_history_dialog.h"
#include "egcu_info_dialog.h"
#include <ServiceMonitor/smo_operator_rights.h>
// Translations
#include <ParticipantManagement/ppm_translation.h>
#include <ProjectDataManagement/pdm_translation.h>
// DDS
#include <CentralEffectSimulation/ces_data_plugin_interface.h>
#include <AreaEffectSimulation/aes_data_plugin_interface.h>
#include <ParticipantManagement/ppm_data_plugin_interface.h>
#include <ProjectDataManagement/pdm_data_plugin_interface.h>
#include <InfrastructureManagement/ism_data_plugin_interface.h>
#include <Buildings/bld_data_plugin_interface.h>
// Lts
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <LtsAppManager/lts_app_manager.h>
#include <LtsUtilsSettings/settings.h>
// Qt
#include <QPainter>
#include <QPainterPath>
#include <QTimer>
#include <QTextDocument>
#include <QStyledItemDelegate>
#ifdef PP_TEST
#include <QMenu>
#include <QDebug>
#endif
// Std
#include <algorithm>
using namespace InfrastructureManagement;
using namespace ParticipantManagement;
class HtmlDelegate : public QStyledItemDelegate
{
public:
HtmlDelegate(QObject *parent = nullptr)
: QStyledItemDelegate(parent)
{}
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
//qWarning() << "col" << index.column() << "rect" << option.rect;
painter->save();
QTextDocument doc;
doc.setHtml(index.data().toString());
doc.setTextWidth(-1); // prevents wordwrap
painter->translate(option.rect.topLeft());
painter->setClipRect(0, 0, option.rect.width(), option.rect.height());
doc.drawContents(painter);
painter->restore();
}
// QSize sizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& index) const override
// {
// QTextDocument doc;
// doc.setHtml(index.data().toString());
// doc.setTextWidth(-1); // prevents wordwrap
// return QSize(doc.idealWidth(), doc.size().height());
// }
};
namespace Buildings
{
BldInfoDialog::BldInfoDialog(int bldEntityId, const QString &menuGroup, QWidget *parent)
: InfoDialogBase(bldEntityId, menuGroup, QStringLiteral("BldInfoDialog"), LtsWidgets::ButtonCombination::CloseOnly, parent)
, m_ui(new Ui::BldInfoDialog)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START" << ", bldEntityId=" << bldEntityId;
m_ui->setupUi(this);
#ifndef LTS_DEBUG
m_ui->lblAssetId->hide();
m_ui->lbAssetId->hide();
m_ui->lblBldId->hide();
m_ui->lbBldId->hide();
m_ui->lblOrganisatorParticipantId->hide();
m_ui->lbOrganisatorParticipantId->hide();
m_ui->lblStructElementId->hide();
m_ui->lbStructElementId->hide();
m_ui->lbDamagePercentOld->hide();
m_ui->lblDamagePercentOld->hide();
#endif
m_ui->lbStatus->hide();
m_ui->lblStatus->hide();
m_ui->pbFindOnMap->setToolTip(tr("Locate building on map"));
m_ui->pbHistory->setToolTip(tr("Show building history"));
m_ui->pbDetails->setToolTip(tr("Set building status"));
m_ui->pbBuildingViewer->setToolTip(tr("Show building in BuildingViewer"));
m_ui->pbMonitor->setToolTip(tr("Show EGCU monitor"));
connect(m_ui->pbHistory, &QToolButton::clicked, this, &BldInfoDialog::onOpenHistory);
connect(m_ui->pbFindOnMap, &QToolButton::clicked, this, &BldInfoDialog::onFindOnMap);
connect(m_ui->pbDetails, &QToolButton::clicked, this, &BldInfoDialog::onShowDetails);
connect(m_ui->pbBuildingViewer, &QToolButton::clicked, this, &BldInfoDialog::onShowBuildingViewer);
connect(m_ui->pbMonitor, &QToolButton::clicked, this, &BldInfoDialog::onShowEgcuMonitor);
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Building_Viewer"));
DEBUG_LOG(m_logger) << LOGFUNCTION << " END" << ", bldEntityId=" << bldEntityId;
} // end of ctor()
//-----------------------------------------------------------------------------
BldInfoDialog::~BldInfoDialog()
{
delete m_ui;
} // end of dtor()
//-----------------------------------------------------------------------------
void BldInfoDialog::retranslate()
{
constexpr int resolution = ICON_RESOLUTION;
const QVector<QPointF> polyHouse =
{
QPointF(resolution / 4, resolution),
QPointF(resolution / 4 * 3, resolution),
QPointF(resolution / 4 * 3, resolution / 4 * 2),
QPointF(resolution / 4 * 3.5, resolution / 4 * 2),
QPointF(resolution / 4 * 2, resolution / 4 * 0.5),
QPointF(resolution / 4 * 0.5, resolution / 4 * 2),
QPointF(resolution / 4, resolution / 4 * 2),
QPointF(resolution / 4, resolution)
}; // return to start point
QPainterPath pPath;
pPath.addPolygon(polyHouse);
// TODO: get party color!
// TODO2: move icon to tab title!
// Buildings::BuildingState bldState = m_dtc->buildingState(m_bldEntityId);
// CentralEffectSimulation::BuildingOwnership ownership = m_cesDtc->buildingOwnership(bldState.id());
// ERROR_LOG(m_logger) << "OWNERSHIP SIZE->" << ownership.ownerships().size();
// for(const CentralEffectSimulation::Ownership &os : qAsConst(ownership.ownerships()))
// {
// ERROR_LOG(m_logger) << "OWNERSHIP PARTY ID->" << os.partyId();
// }
// QColor partyColor = partyColor(partyId);
QColor partyColor = Qt::red;
const auto dpr = devicePixelRatioF();
QPixmap preIcon(QSize(ICON_RESOLUTION, ICON_RESOLUTION) * dpr);
preIcon.fill(Qt::transparent);
preIcon.setDevicePixelRatio(dpr);
m_ui->lblIcon->setPixmap(preIcon);
QImage img = m_ui->lblIcon->pixmap()->toImage();
QPainter painter(&img);
painter.setPen(QPen(Qt::black, 3, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin));
painter.setBrush(Qt::transparent);
painter.drawPath(pPath);
painter.fillPath(pPath, partyColor);
painter.end();
m_ui->lblIcon->setPixmap(QPixmap::fromImage(img));
translate(m_ui, tr("Building: %1").arg(m_ismDtc->getBuildingDisplayName(m_mse)));
}
bool BldInfoDialog::init(LtsSession::LtsSession *session)
{
if (!InfoDialogBase::init(session))
return false;
connect(m_dtc.get(), &Buildings::Interface::Dtc::buildingStateChanged,
this, &BldInfoDialog::onBuildingStateChanged);
if (!m_session->getDtc<CentralEffectSimulation::DataInterface>(m_cesDtc))
return false;
connect(m_cesDtc.get(), &CentralEffectSimulation::Interface::Dtc::buildingOwnershipChanged,
this, &BldInfoDialog::onBuildingOwnershipChanged);
m_session->getDtc<AreaEffectSimulation::DataInterface>(m_aesDtc);
m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc);
m_session->getDtc<ProjectDataManagement::DataInterface>(m_pdmDtc);
const bool isBridge = m_mse.structureElementTypeId() == InfrastructureManagement::StructureElementType::Bridge;
const bool isResourceManagerApp = m_session->app() == LtsAppDescriptor::App::ResourceManager;
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_mse" << m_mse
<< ", isBridge=" << isBridge;
// Main Structure Elements
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mainStructureElementChanged,
this, &BldInfoDialog::onMainStructureElementChanged);
m_mse = m_ismDtc->mainStructureElement(m_mseId);
// (lbOrganisatorParticipantId, lblOrganisatorParticipantId just visible if LTS_DEBUG)
m_ui->lbDamagePercent->setVisible(m_session->partitionType() != IDL::PartitionType::Global);
m_ui->lblDamagePercent->setVisible(m_session->partitionType() != IDL::PartitionType::Global);
showBuildingInfos();
auto predicate = [](const InfrastructureManagement::InstrumentationAsset & a)
{
return (!a.isDeleted() && (a.mountingPointTypeId() == InfrastructureManagement::MountingPointType::EffectGenerationControlUnit));
};
QMap<int, QVector<InfrastructureManagement::InstrumentationAsset>> assetsMapBuilding;
m_ismDtc->waitForHistoricalDataInstrumentationAsset(500); // to create 'm_dtcInstrumentationAsset' and avoid coredump at getAllAssetsPerBuilding
m_ismDtc->getAllAssetsPerBuilding(predicate, assetsMapBuilding);
QVBoxLayout *l = new QVBoxLayout(m_ui->gbSegments);
m_ui->gbSegments->setLayout(l);
if (assetsMapBuilding.contains(m_mseId))
{
const QVector<InfrastructureManagement::InstrumentationAsset> &instrumentationAssets = assetsMapBuilding[m_mseId];
const QMap<qint32, InfrastructureManagement::MountingPointAsset> &mountingPointAssets = m_ismDtc->mountingPointAssets();
for (const auto &instrumentationAsset : qAsConst(instrumentationAssets))
{
InfrastructureManagement::MountingPointAsset mpa;
for (const auto &mpax : qAsConst(mountingPointAssets))
{
if (mpax.assetId() == instrumentationAsset.id())
{
mpa = mpax;
break;
}
}
if (mpa.assetId() != instrumentationAsset.id())
continue;
std::string name = mpa.name().empty() ? instrumentationAsset.name() : mpa.name();
int assetId = mpa.assetId();
QPushButton *w = new QPushButton(QString::fromStdString(name), this);
w->setProperty("assetId", assetId);
w->setProperty("assetName", QString::fromStdString(instrumentationAsset.name()));
l->addWidget(w);
connect(w, &QPushButton::clicked, this, &BldInfoDialog::onEgcuInfoDialogRequested);
}
}
m_ui->gbSegments->setVisible(egcuVisibility());
bool editable = true; // LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::EgcuMonitorShow);
m_ui->pbMonitor->setVisible(editable && egcuVisibility());
if ((m_session->app() == LtsAppDescriptor::App::OC) || isResourceManagerApp)
{
m_ui->pbDetails->hide();
m_ui->pbHistory->hide();
m_ui->pbBuildingViewer->hide();
}
if (m_session->isReplayPartition()) // is replay?
m_ui->pbDetails->hide();
m_ui->pbBuildingViewer->hide();
if (LtsAppManager::LtsAppManager::getInstance()->hasApp(LtsAppDescriptor::App::BuildingViewer))
m_ui->pbBuildingViewer->setVisible(m_bdvGuiIfc != nullptr && LtsAppManager::LtsAppManager::getInstance()->hasApp(LtsAppDescriptor::App::BuildingViewer));
m_ui->lblIcon->setVisible(true);
m_ui->lblIcon->setFixedSize(ICON_RESOLUTION, ICON_RESOLUTION);
m_ui->lblBldName->setText(buildingDisplayName());
const bool ownershipFunc = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("Buildings"),
QStringLiteral("Ownership"));
const bool bShowBuildingOwnership = ownershipFunc && !isResourceManagerApp && !isBridge;
m_ui->lbOwnership->setVisible(bShowBuildingOwnership);
m_ui->twOwnership->setVisible(bShowBuildingOwnership);
connect(m_ismDtc.get(), &InfrastructureManagement::Interface::Dtc::mountingPointAssetChanged,
this, &BldInfoDialog::onMountingPointAssetChanged);
// FloorParticipantCount stuff:
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableFloorParticipantCount = ps->value(QStringLiteral("bld"), QStringLiteral("enableFloorParticipantCount")).toBool();
if (enableFloorParticipantCount)
{
m_ui->twFloorParticipantCount->setItemDelegate(new HtmlDelegate);
#ifdef PP_TEST
#warning PP_TEST ACTIVE!
static int pid = 1;
struct PPData
{
int roomId;
int partyId;
int dataMod;
int participantId = pid++;
QString changeDesc = {};
};
const auto ppDatas = QVector<PPData>() << PPData{190, 1, 0} << PPData{190, 2, 0} << PPData{190, 3, 0} << PPData{190, 3, 0} << PPData{234, 1, 0} << PPData{234, 1, 0} << PPData{234, 3, 0};
auto fn = [this](const PPData & ppData)
{
ParticipantPosition pp;
pp.roomId(ppData.roomId);
pp.participantId(ppData.participantId);
pp.partyId(ppData.partyId);
pp.buildingId(m_mse.id());
if (!ppData.changeDesc.isEmpty())
{
m_ui->lbFloorParticipantCount->setText(QStringLiteral("%1: %2").arg(ppData.participantId).arg(ppData.changeDesc));
onPositionChanged(pp, ppData.dataMod == 0 ? DataModification::eAdded : DataModification::eModified);
return;
}
qWarning() << "id" << ppData.participantId;
addParticipantPosition(pp, ppData.dataMod == 0 ? DataModification::eAdded : DataModification::eModified);
};
for (const PPData &ppData : ppDatas)
fn(ppData);
updateFloorParticipantTable();
m_ui->twFloorParticipantCount->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_ui->twFloorParticipantCount, &QWidget::customContextMenuRequested,
this, [this, fn](const QPoint & p)
{
QMenu *m = new QMenu(this);
m->setAttribute(Qt::WA_DeleteOnClose);
m->addAction(QStringLiteral("[next test]"), this, [fn]()
{
static int step = 0;
static auto ppDatas = QVector<PPData>()
// floor, party, [mod], participant
<< PPData{190, 1, 1, 1, QStringLiteral("something changed, but nothing relevant")}
<< PPData{234, 2, 1, 2, QStringLiteral("changed from floor_1 to floor_2")}
<< PPData{190, 2, 1, 3, QStringLiteral("changed party to 2")}
<< PPData{234, 2, 1, 4, QStringLiteral("changed party to 2 AND to floor_2")}
<< PPData{190, 3, 1, 1, QStringLiteral("change party to 3")}
<< PPData{277, 3, 1, 5, QStringLiteral("change party to (new) floor_3")}
;
if (step >= ppDatas.count())
return;
fn(ppDatas.at(step++));
});
m->popup(m_ui->twFloorParticipantCount->mapToGlobal(p));
});
#else
// m_ppmDtc->enableParticipantPosition(); // will be enabled implicit
const QMap<qint32, ParticipantManagement::ParticipantPosition> &participantPosition =
m_ppmDtc->participantPositions();
for (const ParticipantPosition &pp : qAsConst(participantPosition))
addParticipantPosition(pp, DataModification::eAdded);
updateFloorParticipantTable();
#endif
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::participantPositionChanged, // ... update on position changed
this, &BldInfoDialog::onPositionChanged);
}
else
{
m_ui->lbFloorParticipantCount->hide();
m_ui->twFloorParticipantCount->hide();
}
return true;
} // end of init()
//-----------------------------------------------------------------------------
QString BldInfoDialog::buildingDisplayName() const
{
return m_ismDtc->getBuildingDisplayName(m_mse);
}
bool BldInfoDialog::egcuVisibility()
{
if (!m_ui || !m_ui->gbSegments)
return false;
QVBoxLayout *l = qobject_cast<QVBoxLayout *>(m_ui->gbSegments->layout());
if (!l)
return false;
return (l->count() > 0) &&
!m_session->isReplayPartition() &&
!((m_session->app() == LtsAppDescriptor::App::OC) || (m_session->app() == LtsAppDescriptor::App::ResourceManager));
}
//-----------------------------------------------------------------------------
void BldInfoDialog::showBuildingInfos()
{
showBuildingInfos(m_dtc->buildingState(m_mseId));
}
//-----------------------------------------------------------------------------
void BldInfoDialog::onPositionChanged(const ParticipantManagement::ParticipantPosition &data, DataModification modType)
{
addParticipantPosition(data, modType);
updateFloorParticipantTable();
}
//-----------------------------------------------------------------------------
QString BldInfoDialog::getFloorName(int floorSeId)
{
auto it = m_floorNames.find(floorSeId);
if (it != m_floorNames.end())
return *it;
InfrastructureManagement::StructureElement floorSe;
if (!getRoom(floorSeId, floorSe))
return QStringLiteral("<unknown floor>");
return QString::fromStdString(floorSe.displayName());
}
//-----------------------------------------------------------------------------
bool BldInfoDialog::getRoom(int roomSeId, InfrastructureManagement::StructureElement &roomSe)
{
auto it = m_roomStructureElementCache.find(roomSeId);
if (it != m_roomStructureElementCache.end())
{
//qWarning() << "getRoom: cache hit!";
roomSe = *it;
return true;
}
if (m_ismDtc->getStructureElementById(roomSeId, roomSe))
{
//qWarning() << "getRoom: cache miss - adding to cache";
m_roomStructureElementCache.insert(roomSeId, roomSe);
return true;
}
return false; // not found :((((
}
//-----------------------------------------------------------------------------
int BldInfoDialog::findFloorIdByRoomId(int roomId) noexcept(false)
{
// get the floor by getting the parent of the room
auto roomToFloorCache = m_roomToFloorCache.constFind(roomId); // try to find the floor in the cache first
if (roomToFloorCache != m_roomToFloorCache.constEnd())
{
//qWarning() << ":) cache hit for room" << roomId;
return roomToFloorCache.value();
}
//qWarning() << ":( cache miss for room" << roomId;
StructureElement roomSe;
if (!m_ismDtc->getStructureElementById(roomId, roomSe))
{
ERROR_LOG(m_logger) << "getStructureElementById roomId=" << roomId << " not found";
return -1;
}
const std::vector<int32_t> path = roomSe.path();
for (const int parentSeId : path)
{
StructureElement parentSe;
if (!getRoom(parentSeId, parentSe))
continue;
//qWarning() << "seId" << seId << "type" << structureElement2.structureElementTypeId().underlying();
if (parentSe.structureElementTypeId().underlying() != StructureElementType_def::Floor)
continue;
// there can only be one floor per room (duh), so we can break after that and finally know the se id for the floor the participant is in
m_floorNames.insert(parentSeId, QString::fromStdString(parentSe.displayName())); // also add the name of the floor for filling the table later (does nothing if already exists, so no need to check)
m_roomToFloorCache.insert(roomId, parentSeId);
return parentSeId;
}
throw QStringLiteral("findFloorId: floor id for room %1 not found").arg(roomSe.id());
}
//-----------------------------------------------------------------------------
void BldInfoDialog::addParticipantPosition(const ParticipantManagement::ParticipantPosition &data, DataModification /*modType*/)
{
if (data.buildingId() != m_mse.id())
{
//qWarning() << "building irrelevant";
return;
}
const int roomId = data.roomId();
const int participantId = data.participantId();
const int participantPartyId = data.partyId();
int participantFloorId;
participantFloorId = findFloorIdByRoomId(roomId);
if (participantFloorId < 0 )
{
ERROR_LOG(m_logger) << "addParticipantPosition: cannot find floor id roomId=" << roomId;
return;
}
m_rawParticipantCount.insert(participantId, QPair<int, int>(participantFloorId, participantPartyId));
// code that works PER CHANGE:
// if (!m_floorToPartyMapping.contains(participantFloorId))
// {
// m_floorToPartyMapping.insert(participantFloorId, QVector<int>()); // insert empty vector for the new floor
// qWarning() << "added new, empty floor-to-party mapping (without parties) to floor" << getFloorName(participantFloorId);
// }
// if (!m_floorNames.contains(participantFloorId))
// m_floorNames.insert(participantFloorId, floorDisplayName); // also add the name of the floor for filling the table later (does nothing if already exists, so no need to check)
// if (!m_roomToFloorCache.contains(roomId))
// m_roomToFloorCache.insert(roomId, QPair<int,QString>(participantFloorId, floorDisplayName));
// if (modType == DataModification::eModified) // check if floor and/or party for participant changed - if yes: remove old m_participantToPartyMapping, remove old m_participantToFloorMapping and finally remove m_floorPartyParticipantCount, then (re)add
// {
// // check if floor and/or party for participant changed
// int oldPartyId = m_participantToPartyMapping.value(participantId, -1);
// int oldFloorId = m_participantToFloorMapping.value(participantId, -1);
// if (oldPartyId != participantPartyId ||
// oldFloorId != participantFloorId)
// {
// qWarning() << "floor & party don't match for" << participantId << "anymore. Floor was" << getFloorName(oldFloorId) << "is" << getFloorName(participantFloorId) << "- Party was" << oldPartyId << "is" << participantPartyId;
// // party for participant changed - remove count from m_floorPartyParticipantCount (using old partyId)
// int &val = m_floorPartyParticipantCount.find(QPair<int,int>(oldFloorId, oldPartyId)).value();
// if (val == 1) // about to remove the last participant from the floor + party? then remove the key
// {
// m_floorPartyParticipantCount.remove(QPair<int,int>(oldFloorId, oldPartyId));
// qWarning() << "last participant removed from for floor" << getFloorName(oldFloorId) << "and party" << oldPartyId;
// auto it = m_floorToPartyMapping.find(oldFloorId);
// if (it != m_floorToPartyMapping.end())
// {
// it.value().removeAll(oldPartyId);
// qWarning() << "removed old party" << oldPartyId << "from old floor" << getFloorName(oldFloorId) << "because it was the last participant in that floor-to-party";
// }
// else
// {
// qWarning() << "FLOOR TO PARTY MAPPING FOR OLD FLOOR" << getFloorName(oldFloorId) << "NOT FOUND!";
// }
// }
// else // otherwise (more than 1), remove one participant
// {
// val--;
// qWarning() << "decreased count for floor" << getFloorName(oldFloorId) << "and party" << oldPartyId;
// }
// // also, m_floorToPartyMapping needs to get the party from the floor removed (using old party id)
// if (oldFloorId != participantFloorId)
// {
// auto it = m_floorToPartyMapping.find(oldFloorId);
// if (it != m_floorToPartyMapping.end())
// {
// it.value().removeAll(oldPartyId);
// qWarning() << "removed old party" << oldPartyId << "from old floor" << getFloorName(oldFloorId) << "because the floor changed";
// }
// else
// {
// qWarning() << "FLOOR TO PARTY MAPPING FOR OLD FLOOR" << getFloorName(oldFloorId) << "NOT FOUND!";
// }
// }
// }
// else
// {
// qWarning() << "neither floor ("<<getFloorName(participantFloorId)<<") or party ("<<participantPartyId<<") changed for participant" << participantId << "- doing nothing";
// return; // nothing changed, no need to do anything
// }
// }
// m_participantToPartyMapping.insert(participantId, participantPartyId); // change to new partyId (no-op if same value)
// m_participantToFloorMapping.insert(participantId, participantFloorId); // change to new floorId (no-op if same value)
// QVector<int> &parties = m_floorToPartyMapping.find(participantFloorId).value();
// if (!parties.contains(participantPartyId))
// {
// parties += participantPartyId; // insert new party id (is either a new list (floor seen first time), or has the old party removed from it (if modified and party or floor changed))
// qWarning() << "added new party" << participantPartyId << "to floor" << getFloorName(participantFloorId);
// }
// auto it = m_floorPartyParticipantCount.find(QPair<int, int>(participantFloorId, participantPartyId));
// if (it == m_floorPartyParticipantCount.end())
// {
// m_floorPartyParticipantCount.insert(QPair<int, int>(participantFloorId, participantPartyId), 1); // first instance of floor + party in map, add THIS (1) participant
// qWarning() << "added new floor-to-party count for party" << participantPartyId << "and floor" << getFloorName(participantFloorId);
// }
// else
// {
// it.value()++; // floor + party already in map, add THIS (1) participant
// qWarning() << "added participant to floor-to-party count for party" << participantPartyId << "and floor" << getFloorName(participantFloorId) << "- is now" << it.value();
// }
// qWarning() << "normal exit";
}
//-----------------------------------------------------------------------------
void BldInfoDialog::updateFloorParticipantTable()
{
// now fill the table
const QMap<qint32, ParticipantManagement::Party> parties(m_ppmDtc->partys());
m_ui->twFloorParticipantCount->setUpdatesEnabled(false);
m_ui->twFloorParticipantCount->clearContents();
m_ui->twFloorParticipantCount->setRowCount(0);
int row = 0;
// gather unique floors
QVector<int> floors;
{
QMapIterator<int /* participant */, QPair<int /* floor */, int /* party */> > it(m_rawParticipantCount);
while (it.hasNext())
{
it.next();
//const int participant = it.key();
const QPair<int, int> &data = it.value();
const int floor = data.first;
if (!floors.contains(floor))
floors += floor;
}
}
// now count how many partypeople :D per floor ... in a map-map :)
QMap<int /* floor */, QMap<int /* party */, int /* count */>> floorPartyPeople;
for (const int floor : qAsConst(floors))
{
QMapIterator<int /* participant */, QPair<int /* floor */, int /* party */> > it(m_rawParticipantCount);
while (it.hasNext())
{
it.next();
const QPair<int /* floor */, int /* party */> &pair = it.value();
const int rawFloor = pair.first;
if (floor != rawFloor)
continue;
const int party = pair.second;
auto it1 = floorPartyPeople.find(floor);
if (it1 == floorPartyPeople.end())
{
QMap<int /* party */, int /* count */> partyPeople;
partyPeople.insert(party, 1);
floorPartyPeople.insert(floor, partyPeople);
}
else
{
QMap<int /* party */, int /* count */> &partyPeopleRef = it1.value();
auto it2 = partyPeopleRef.find(party);
if (it2 == partyPeopleRef.end())
partyPeopleRef.insert(party, 1);
else
it2.value()++;
}
}
}
// finally, create the rows ... (PER FLOOR)
QMapIterator<int /* floor */, QMap<int /* party */, int /* count */>> it1(floorPartyPeople);
while (it1.hasNext())
{
it1.next();
const int floor = it1.key();
int column = 0;
m_ui->twFloorParticipantCount->insertRow(row);
QTableWidgetItem *pItem = new QTableWidgetItem(m_floorNames.value(floor, tr("<unknown>")));
m_ui->twFloorParticipantCount->setItem(row, column++, pItem);
// one column, all parties (participant count)
const QMap<int /* party */, int /* count */> &partyPeople = it1.value();
QStringList floorPartyParticipantCountStrings;
QMapIterator<int /* party */, int /* count */> it2(partyPeople);
while (it2.hasNext())
{
it2.next();
const int party = it2.key();
const int count = it2.value();
floorPartyParticipantCountStrings += QStringLiteral("<font color='#%1'>%2</font>").arg(QString::number((unsigned int)parties.value(party).color(), 16)).arg(count);
//qWarning() << "floor:" << floor << "party:" << party << "count:" << count;
}
//qWarning() << "final html" << floorPartyParticipantCountStrings;
pItem = new QTableWidgetItem(floorPartyParticipantCountStrings.join(QStringLiteral(" ")));
m_ui->twFloorParticipantCount->setItem(row, column, pItem);
row++;
}
// code that works PER CHANGE:
// QMapIterator<int /* floor */, QVector<int> /* parties */> it(m_floorToPartyMapping); // this map doesn't have floor as exclusive key, so we need to look for ALL keys that have the current floor id
// while (it.hasNext())
// {
// it.next();
// const int floorId = it.key();
// int column = 0;
// m_ui->twFloorParticipantCount->insertRow(row);
// QTableWidgetItem *pItem = new QTableWidgetItem(m_floorNames.value(floorId, tr("<unknown>")));
// m_ui->twFloorParticipantCount->setItem(row, column++, pItem);
// // one column, all parties (participant count)
// QVector<int> partyIds = it.value();
// std::sort(partyIds.begin(), partyIds.end()); // guarantee always the same order in view
// QStringList floorPartyParticipantCountStrings;
// for (const int partyId : partyIds)
// {
// const int floorPartyParticipantCount = m_floorPartyParticipantCount.value(QPair<int,int>(floorId, partyId), -1);
// if (floorPartyParticipantCount == -1)
// {
// qWarning() << "WHOOPS!!" << floorId << partyId;
// }
// floorPartyParticipantCountStrings += QStringLiteral("<font color='#%1'>%2</font>").arg(QString::number((unsigned int)parties.value(partyId).color(), 16)).arg(floorPartyParticipantCount);
// qWarning() << "floor:" << floorId << "party:" << partyId << "count:" << floorPartyParticipantCount;
// }
// //qWarning() << "final html" << floorPartyParticipantCountStrings;
// pItem = new QTableWidgetItem(floorPartyParticipantCountStrings.join(QStringLiteral(" ")));
// m_ui->twFloorParticipantCount->setItem(row, column, pItem);
// row++;
// }
m_ui->twFloorParticipantCount->setUpdatesEnabled(true);
}
//-----------------------------------------------------------------------------
void BldInfoDialog::showBuildingInfos(const Buildings::BuildingState &bldState)
{
if (bldState.id() <= 0)
{
m_ui->lblBldId->clear();
m_ui->lblStructElementId->clear();
m_ui->lblAssetId->clear();
m_ui->lblOrganisatorParticipantId->clear();
m_ui->lblDamagePercent->clear();
m_ui->lblDamagePercentOld->clear();
m_ui->lblStatus->clear();
m_ui->lblContamination->clear();
fillOwnership({});
return;
}
m_ui->lblBldId->setText(QString::number(bldState.id()));
m_ui->lblStructElementId->setText(QString::number(bldState.structureElementId()));
m_ui->lblAssetId->setText(QString::number(bldState.assetId()));
m_ui->lblOrganisatorParticipantId->clear();
if (bldState.originatorParticipantId())
{
if (m_ppmDtc)
{
ParticipantManagement::Participant player = m_ppmDtc->participant(bldState.originatorParticipantId());
if (player.equipmentNumber().is_set())
m_ui->lblOrganisatorParticipantId->setText(QString::number(player.equipmentNumber().get()));
}
}
else if (bldState.aesId())
{
if (m_aesDtc)
{
AreaEffectSimulation::AesItem aesItem;
m_aesDtc->aesItemFromId(bldState.aesId(), aesItem);
m_ui->lblOrganisatorParticipantId->setText(QString::fromStdString(aesItem.name()));
}
}
else
m_ui->lblOrganisatorParticipantId->setText(tr("EXCON"));
m_ui->lblDamagePercent->setText(QString::number(bldState.damagePercent()));
m_ui->lblDamagePercentOld->setText(QString::number(bldState.damagePercentOld()));
QStringList contaminationList;
for (const auto &cs : bldState.contaminationStates())
{
AreaEffectSimulation::AesItem item;
m_aesDtc->aesItemFromId(cs.aesId(), item);
const ProjectDataManagement::GearClass &gc = m_pdmDtc->gearClassFromChargeTypeId(item.chargeStruct().chargeTypeId());
if (gc == ProjectDataManagement::GearClass::Unknown)
continue;
QString gearClassName = ProjectDataManagement::toString(gc).trimmed();
gearClassName.chop(gearClassName.size() - 1); // get only the First letter: Nuclear -> 'N'
if (!contaminationList.contains(gearClassName))
contaminationList.append(gearClassName);
}
m_ui->lbContamination->setHidden(contaminationList.isEmpty());
m_ui->lblContamination->setHidden(contaminationList.isEmpty());
m_ui->lblContamination->setText(contaminationList.join(QStringLiteral("+")));
ProjectDataManagement::VulnerabilityState st = bldState.vulnerabilityState();
m_ui->lblStatus->setText(toString(st));
m_ui->twFloorParticipantCount->hideColumn(2);
DEBUG_LOG(m_logger) << "fillOwnership";
fillOwnership(bldState.id());
DEBUG_LOG(m_logger) << "Vor fillContaminationTable";
fillContaminationTable(bldState);
DEBUG_LOG(m_logger) << "Nach fillContaminationTable";
} // end of showBuildingInfos()
void BldInfoDialog::fillContaminationTable(const Buildings::BuildingState &bldState)
{
clearColumn(2);
bool showContaminationCol = false;
DEBUG_LOG(m_logger) << "fillContaminationTable bldState.contaminationStates().size()=" << bldState.contaminationStates().size();
for (const auto &cs : bldState.contaminationStates())
{
DEBUG_LOG(m_logger) << "cs.rooms().size()=" << cs.rooms().size();
/////////////////////////////////////////////
// Set Contamination State to ownership-Table
/////////////////////////////////////////////
for (unsigned int i = 0; i < cs.rooms().size(); i++)
{
int floorIdContamination = findFloorIdByRoomId(cs.rooms()[i]);
DEBUG_LOG(m_logger) << "floorIdContamination=" << floorIdContamination;
if ( floorIdContamination == -1)
{
DEBUG_LOG(m_logger) << "floorIdContamination=" << floorIdContamination << "continue";
continue;
}
QString floorNameConatmaniation = getFloorName(floorIdContamination);
DEBUG_LOG(m_logger) << "Floor:" << floorNameConatmaniation
<< " id=" << floorIdContamination
<< " m_rowToFloorId=" << floorIdContamination ;
if (!m_floorIdToRow.contains(floorIdContamination))
{
DEBUG_LOG(m_logger) << "!m_floorIdToRow.contains(" << floorIdContamination << ")";
continue;
}
int row = m_floorIdToRow.value(floorIdContamination);
int column = 2;
DEBUG_LOG(m_logger) << "floorIdContamination=" << floorIdContamination
<< " row=" << row;
QTableWidgetItem *pItem = m_ui->twOwnership->item(row, column);
if (pItem == nullptr)
{
DEBUG_LOG(m_logger) << "pItem == nullptr";
pItem = new QTableWidgetItem();
}
const QColor color = Qt::yellow;
pItem->setData(Qt::BackgroundRole,
color);
m_ui->twOwnership->setItem(row, column, pItem);
showContaminationCol = true;
}
}
if (showContaminationCol)
m_ui->twOwnership->showColumn(2);
else
m_ui->twOwnership->hideColumn(2);
}
//-----------------------------------------------------------------------------
void BldInfoDialog::fillOwnership(int buildingId)
{
CentralEffectSimulation::BuildingOwnership ownership = m_cesDtc->buildingOwnership(buildingId);
if (ownership.buildingId() == buildingId)
fillOwnership(ownership);
}
void BldInfoDialog::clearColumn(int column)
{
int rowCount = m_ui->twOwnership->rowCount();
for (int row = 0; row < rowCount; row++)
{
QTableWidgetItem *item = m_ui->twOwnership->item(row, column);
if (item != nullptr)
{
const QColor color = Qt::white;
item->setData(Qt::BackgroundRole,
color);
item->setData(Qt::DisplayRole, QString());
//m_ui->twOwnership->setItem(row, column, item);
}
}
}
//-----------------------------------------------------------------------------
void BldInfoDialog::fillOwnership(const CentralEffectSimulation::BuildingOwnership &ownership)
{
m_ui->twOwnership->setUpdatesEnabled(false);
// m_ui->twOwnership->clearContents();
clearColumn(1);
m_ui->twOwnership->setRowCount(ownership.ownerships().size());
int row = m_ui->twOwnership->rowCount();
for (const auto &data : ownership.ownerships())
{
--row;
int column = 0;
QTableWidgetItem *pItem = nullptr;
// column (floor)
for (const InfrastructureManagement::StructureElement &elem : m_mse.elements())
{
if (elem.id() == data.floorId())
{
QString name = QString::fromStdString(elem.displayName());
if (name.isEmpty())
name = QString::fromStdString(elem.name());
pItem = new QTableWidgetItem(name);
break;
}
}
if (!pItem) // no ism, no data?
pItem = new QTableWidgetItem(QString::number(data.floorId()));
m_rowToFloorId.insert(row, data.floorId());
m_floorIdToRow.insert(data.floorId(), row);
DEBUG_LOG(m_logger) << "m_rowToFloorId.insert"
<< " row=" << row
<< " column=" << column
<< " data.floorId()=" << data.floorId();
m_ui->twOwnership->setItem(row, column++, pItem);
// column (ownwership)
pItem = new QTableWidgetItem();
if (m_ppmDtc && data.partyId() > 0)
{
const auto &party = m_ppmDtc->party(data.partyId());
pItem->setData(Qt::BackgroundRole,
QColor::fromRgb(QRgb(party.color())));
pItem->setData(Qt::DisplayRole, ParticipantManagement::trPartyName(party.name()));
}
m_ui->twOwnership->setItem(row, column++, pItem);
} // for
m_ui->twOwnership->setUpdatesEnabled(true);
}// end of fillOwnership()
//-----------------------------------------------------------------------------
void BldInfoDialog::onBuildingStateChanged(const Buildings::BuildingState &data, const DataModification &modType)
{
if (modType == DataModification::eRemoved)
return;
DEBUG_LOG(m_logger) << LOGFUNCTION << " id:" << data.id();
if (data.id() != m_mseId)
return;
showBuildingInfos(data);
} // end of onBuildingStateChanged()
//-----------------------------------------------------------------------------
void BldInfoDialog::onBuildingOwnershipChanged(
const CentralEffectSimulation::BuildingOwnership &data, const DataModification &modType)
{
if (modType == DataModification::eRemoved)
return;
DEBUG_LOG(m_logger) << LOGFUNCTION << " id:" << data.buildingId();
if (data.buildingId() != m_mseId)
return;
fillOwnership(data);
} // end of onBuildingOwnershipChanged()
void BldInfoDialog::onMainStructureElementChanged(const InfrastructureManagement::MainStructureElement &data,
const DataModification &modType)
{
if (modType == DataModification::eRemoved)
return;
DEBUG_LOG(m_logger) << LOGFUNCTION << " id:" << data.id();
if (data.id() != m_mseId)
return;
m_mse = data;
m_ui->lblBldName->setText(buildingDisplayName());
showBuildingInfos();
}
void BldInfoDialog::onMountingPointAssetChanged(const InfrastructureManagement::MountingPointAsset &data, const DataModification &modType)
{
InfrastructureManagement::StructureElement se;
m_ismDtc->getStructureElementById(data.structureElementId(), se);
if (se.mainStructureElementId() != m_mseId)
return;
if (modType == DataModification::eAdded)
{
auto instrumentationAsset = m_ismDtc->instrumentationAsset(data.assetId());
if (instrumentationAsset.mountingPointTypeId() != InfrastructureManagement::MountingPointType::EffectGenerationControlUnit)
return;
QString name = QString::fromStdString(data.name());
if (name.isNull())
name = QString::fromStdString(instrumentationAsset.hostname());
QVBoxLayout *l = qobject_cast<QVBoxLayout *>(m_ui->gbSegments->layout());
QPushButton *w = new QPushButton(name, this);
w->setProperty("assetId", data.assetId());
l->addWidget(w);
connect(w, &QPushButton::clicked, this, &BldInfoDialog::onEgcuInfoDialogRequested);
m_ui->gbSegments->setVisible(egcuVisibility());
bool editable = true; // LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::EgcuMonitorShow);
m_ui->pbMonitor->setVisible(editable && egcuVisibility());
}
else if (modType == DataModification::eRemoved)
{
const QList<QPushButton *> &list = m_ui->gbSegments->findChildren<QPushButton *>();
for (QPushButton *pb : qAsConst(list))
{
if (pb->property("assetId").toInt() == data.assetId())
{
// Letztes Element?
if (m_ui->gbSegments->layout()->count() == 1)
{
m_ui->gbSegments->setVisible(false);
m_ui->pbMonitor->hide();
}
pb->deleteLater();
break;
}
}
}
else if (modType == DataModification::eModified)
{
const QList<QPushButton *> &list = m_ui->gbSegments->findChildren<QPushButton *>();
for (QPushButton *pb : qAsConst(list))
{
if (pb->property("assetId").toInt() == data.assetId())
pb->setText(data.name().empty() ? pb->property("assetName").toString() : QString::fromStdString(data.name()));
}
}
}
//-----------------------------------------------------------------------------
void BldInfoDialog::onOpenHistory()
{
BuildingHistoryDialog *diag = new BuildingHistoryDialog(buildingDisplayName(), this);
if (diag->init(m_mseId, m_session))
addDialog(diag, m_menuGroup, QStringLiteral("BuildingHistory") + QString::number(m_mseId), LtsWidgets::LayoutArea::eDialogTab);
else
delete diag;
}
void BldInfoDialog::onEgcuInfoDialogRequested()
{
QPushButton *sender = qobject_cast<QPushButton *>(QObject::sender());
if (!sender)
return;
QVariant temp = sender->property("assetId");
if (temp.isNull())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " missing property , return";
return;
}
const int assetId = temp.toInt();
temp = sender->property("assetName");
if (temp.isNull())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " missing property, return";
return;
}
const QString name = temp.toString();
if (assetId < 0 || name.isEmpty())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " missing properties, return";
return;
}
EgcuInfoDialog *dialog = new EgcuInfoDialog(assetId, menuGroup());
if (!dialog->init(m_session))
{
delete dialog;
return;
}
m_session->addWidget(dialog, menuGroup(), name, LtsWidgets::LayoutArea::eInfoTab);
}
} // namespace Bridges