/** *@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 // Translations #include #include // DDS #include #include #include #include #include #include // Lts #include #include #include #include // Qt #include #include #include #include #include #ifdef PP_TEST #include #include #endif // Std #include 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 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(m_cesDtc)) return false; connect(m_cesDtc.get(), &CentralEffectSimulation::Interface::Dtc::buildingOwnershipChanged, this, &BldInfoDialog::onBuildingOwnershipChanged); m_session->getDtc(m_aesDtc); m_session->getDtc(m_ppmDtc); m_session->getDtc(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> 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 &instrumentationAssets = assetsMapBuilding[m_mseId]; const QMap &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{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() // 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 &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(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(""); 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 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(participantFloorId, participantPartyId)); // code that works PER CHANGE: // if (!m_floorToPartyMapping.contains(participantFloorId)) // { // m_floorToPartyMapping.insert(participantFloorId, QVector()); // 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(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(oldFloorId, oldPartyId)).value(); // if (val == 1) // about to remove the last participant from the floor + party? then remove the key // { // m_floorPartyParticipantCount.remove(QPair(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 ("< &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(participantFloorId, participantPartyId)); // if (it == m_floorPartyParticipantCount.end()) // { // m_floorPartyParticipantCount.insert(QPair(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 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 floors; { QMapIterator > it(m_rawParticipantCount); while (it.hasNext()) { it.next(); //const int participant = it.key(); const QPair &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> floorPartyPeople; for (const int floor : qAsConst(floors)) { QMapIterator > it(m_rawParticipantCount); while (it.hasNext()) { it.next(); const QPair &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 partyPeople; partyPeople.insert(party, 1); floorPartyPeople.insert(floor, partyPeople); } else { QMap &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> 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(""))); m_ui->twFloorParticipantCount->setItem(row, column++, pItem); // one column, all parties (participant count) const QMap &partyPeople = it1.value(); QStringList floorPartyParticipantCountStrings; QMapIterator it2(partyPeople); while (it2.hasNext()) { it2.next(); const int party = it2.key(); const int count = it2.value(); floorPartyParticipantCountStrings += QStringLiteral("%2").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 /* 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(""))); // m_ui->twFloorParticipantCount->setItem(row, column++, pItem); // // one column, all parties (participant count) // QVector 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(floorId, partyId), -1); // if (floorPartyParticipantCount == -1) // { // qWarning() << "WHOOPS!!" << floorId << partyId; // } // floorPartyParticipantCountStrings += QStringLiteral("%2").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(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 &list = m_ui->gbSegments->findChildren(); 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 &list = m_ui->gbSegments->findChildren(); 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(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