Files
qt5-legatus-legacy/Lts/Plugins/ParticipantManagement/Gui/ParticipantInfo/participant_info_dialog.cpp
T
torstenandCopilot 3028302f7b Qt6 Migration: Merge latest Qt5 devel content and apply migration fixes
- Merged 292 changed files from dlbo snapshot
- Fixed IDL enum collisions (PortType, PdmEventType)
- Fixed Grantlee template for C++11 scoped enums
- Fixed CMake VERSION_GREATER syntax
- Added missing directories (THP, LtsRestClient, etc.)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-15 18:20:51 +00:00

1767 lines
63 KiB
C++
Executable File

/**
* @RDE_HEADER@
* ParticipantManagement - ParticipantInfoDialog
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwat, SLSE, 2016-06-01
*/
#include "participant_info_dialog.h"
#include "ui_participant_info_dialog.h"
#include "participant_info_helper.h"
#include <ProjectDataManagement/pdm_to_string.h>
#include <ParticipantManagement/ppm_translation.h>
#include <InfrastructureManagement/ism_data_plugin_interface.h>
#include <AreaEffectSimulation/aes_data_plugin_interface.h>
#include <TargetManagement/tgt_data_plugin_interface.h>
#include <TargetManagement/tgt_translation.h>
#include "participant_config_dialog.h"
#include "participant_bite_dialog.h"
#include "participant_history_dialog.h"
#include "participant_set_injury_dialog.h"
#include "participant_set_sanitation_dialog.h"
#include "participants_mounted_table_dialog.h"
#include "participant_gear_restock.h"
#include "participant_target_config_dialog.h"
#include "participant_info_ltd_gear_component.h"
#include <LtsCoordTrans/lts_coord_trans.h>
#include <ngltools/ngltools_dtg.h>
#include <LtsSession/lts_session_data.h>
#include <LtsUtilsCore/outdated_position.h>
#include <LtsUtilsSettings/settings.h>
#include <LtsPluginManager/lts_plugin_loader.h>
#include <Services/AreaEffectSimulation/Utils/polygons.h>
#include <ParticipantManagement/participant_info_gui_element_interface.h>
#include <QJsonDocument>
#include <QTableWidgetItem>
#include <QToolButton>
#include <QTransform>
#include <QMenu>
#include <QColor>
#include <QLabel>
namespace ParticipantManagement
{
ParticipantInfoDialog::ParticipantInfoDialog(int participantId, const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_uasId(0)
, m_lastPositionMSec(0)
, m_typeClass(TypeClass::Unknown)
, m_roomId(0)
, m_menuGroup(menuGroup)
, m_session(nullptr)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_pdmDtc(nullptr)
, m_tgtDtc(nullptr)
, m_tgtFtc(nullptr)
, m_aesDtc(nullptr)
, m_sitMapGuiIfc(nullptr)
, m_ppmGuiIfc(nullptr)
, m_symbolWatcher(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_ui(new Ui::ParticipantInfoDialog)
, m_isTarget(false)
, m_logger(getLogger("ParticipantInfoDialog"))
{
m_ui->setupUi(this);
m_oldSpacerSize.first = m_ui->vsBottom->maximumSize().width();
m_oldSpacerSize.second = m_ui->vsBottom->maximumSize().height();
m_participant.id(participantId);
m_participant.partyId(-1);
m_ui->pbUnlockUas->setIcon(QIcon(QStringLiteral("icon:drone_remote_connection.svg")));
setUnchangeable();
connect(m_ui->pbSetStatus, &QToolButton::clicked, this, &ParticipantInfoDialog::onOpenSetStatusDialog);
connect(m_ui->pbSetInjury, &QToolButton::clicked, this, &ParticipantInfoDialog::onOpenSetInjuryDialog);
connect(m_ui->pbSetSanitation, &QToolButton::clicked, this, &ParticipantInfoDialog::onOpenSetSanitationDialog);
connect(m_ui->pbHistory, &QToolButton::clicked, this, &ParticipantInfoDialog::onOpenHistory);
connect(m_ui->pbBite, &QToolButton::clicked, this, &ParticipantInfoDialog::onOpenBite);
connect(m_ui->pbMessage, &QToolButton::clicked, this, &ParticipantInfoDialog::onOpenMessage);
connect(m_ui->pbFindOnMap, &QToolButton::clicked, this, &ParticipantInfoDialog::onFindOnMap);
connect(m_ui->pbGearRanges, &QToolButton::clicked, this, &ParticipantInfoDialog::onGearRanges);
m_ui->twGear->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_ui->twGear, &QTableWidget::customContextMenuRequested, this, &ParticipantInfoDialog::onContextMenuRequested);
m_ui->pbMovementTrack->setCheckable(true);
connect(m_ui->pbMovementTrack, &QToolButton::clicked, this, &ParticipantInfoDialog::onMovementTrack);
connect(m_ui->pbUnlockUas, &QToolButton::clicked, this, &ParticipantInfoDialog::onUnlockUAS);
//hide first:
m_ui->twGear->hide();
m_ui->lblInfo->hide();
m_ui->lblInfoText->hide();
m_ui->lblInBuildingInfo->hide();
m_ui->pbMounted->hide();
m_ui->lbSpecialSensorState->hide();
m_ui->gbSanitation->hide();
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
const bool enableMassages = ps->value(QStringLiteral("msg"),
QStringLiteral("enableMessages")).toBool();
if (!enableMassages)
m_ui->pbMessage->hide();
m_showPvSan = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("ParticipantInformation"),
QStringLiteral("HasPvSan"));
m_showVulnerabilityKindProject = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("ParticipantInformation"),
QStringLiteral("ShowVulnerabilityKind"));
m_symbolWatcher = new AdvancedSymbology::SymbolResultWatcherLabel(m_ui->lblIcon);
}
ParticipantInfoDialog::~ParticipantInfoDialog()
{
if (m_ui->pbGearRanges->isChecked())
if (m_sitMapGuiIfc)
m_sitMapGuiIfc->enableGearRanges(m_participant.id(), false);
if (m_symbolAppearanceSettings)
m_symbolAppearanceSettings->removeChangedCallback(this);
delete m_ui;
}
void ParticipantInfoDialog::retranslate()
{
QString id;
dds::core::optional<int32_t> eqId = m_participant.equipmentNumber();
if (eqId.is_set())
id = QString::number(eqId.get());
translate(m_ui, id, false, tr("Participant"));
}
bool ParticipantInfoDialog::init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<ProjectDataManagement::Interface::Dtc> &pdmDtc,
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMapGuiIfc,
const std::shared_ptr<AdvancedSymbology::ForeignDataInterface> &asbInterface,
const std::shared_ptr<ForeignParticipantInfoGuiInterface> &ppmGuiIfc)
{
DEBUG_LOG(m_logger)<< "ParticipantInfoDialog::init";
m_session = session;
m_dtc = dtc;
m_ftc = ftc;
m_pdmDtc = pdmDtc;
m_sitMapGuiIfc = sitMapGuiIfc;
m_asbiIfc = asbInterface;
m_ppmGuiIfc = ppmGuiIfc;
if (m_ltdGearComponent)
delete m_ltdGearComponent;
m_ltdGearComponent = new ParticipantInfoLtdGearComponent(m_ui->twGear);
m_session->getDtc<InfrastructureManagement::DataInterface>(m_ismDtc);
if (!m_session->getDtc<AreaEffectSimulation::DataInterface>(m_aesDtc))
m_ui->pbHistory->setEnabled(false);
connect(m_dtc.get(), &Interface::Dtc::partyChanged,
this, &ParticipantInfoDialog::updateCurrentIcon, Qt::UniqueConnection);
// to handle race condition between DynamicParticipantData and DusMineState:
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::dusMineStateChanged,
this, &ParticipantInfoDialog::updateCurrentIcon, Qt::UniqueConnection);
connect(m_ui->twGear, &QTableWidget::cellDoubleClicked, this, [this](int row, int column){
Q_UNUSED(column);
int gearId = m_ui->twGear->item(row, 0)->data(Qt::UserRole).toInt();
int gTypeId = 0;
auto gears = m_dtc->dynamicParticipantData(m_participant.id()).gear();
if (gears.size() < 1)
return;
for(auto gear : gears)
{
if (gear.gearId() == gearId)
gTypeId = gear.gearTypeId();
}
if(m_pdmDtc->canRestock(gTypeId))
{
onRestockNow(gearId, gTypeId);
}
});
DEBUG_LOG(m_logger)<< "Vor setUiValues";
return setUiValues();
}
// private
bool ParticipantInfoDialog::setUiValues()
{
/* NOTE: This is a hide-all-you-don't-need concept. Everything is shown,
* so everything you don't want to show up must be hidden.
* Plus, once hidden, widgets must not be shown again. */
DEBUG_LOG(m_logger) << "------------------setUiValues-----------------";
if (!m_dtc || !m_ftc || m_participant.id() < 0)
return false;
// m_showPvSan = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("ParticipantInformation"),
// QStringLiteral("HasPvSan"));
m_ui->pbTarget->setVisible(false);
m_ui->lblVitality->setVisible(false);
m_ui->pbSetInjury->setVisible(false);
m_ui->pbSetSanitation->setVisible(false);
//hide findOnMap if no interface available
m_ui->pbFindOnMap->setVisible(m_sitMapGuiIfc != nullptr);
m_ui->pbMovementTrack->setVisible(m_sitMapGuiIfc != nullptr);
m_ui->tbNbc->setVisible(false); //show only if visible
// m_participant.id() was given within ctor
const Participant participantData = m_dtc->participant(m_participant.id());
const Type type = m_dtc->type(participantData.typeId());
m_typeClass = type.typeClass();
// uas stuff
const bool isUas = m_dtc->isTypeUas(participantData.typeId());
DEBUG_LOG(m_logger) << "------------------UAS-----------------"
<< " isTypeUas" << isUas
<< " participantId=" <<participantData.id()
<< " typeId=" << participantData.typeId();
if (isUas)
{
connect(m_dtc.get(), &Interface::Dtc::uASChanged, this, &ParticipantInfoDialog::onUasChanged, Qt::UniqueConnection);
m_dtc->waitForHistoricalDataUAS(3000);
const UAS uas = m_dtc->getUasByParticipantId(participantData.id(), m_session->exerciseId());
m_uasId = uas.id();
if (!m_ftc->isModifyUasStateEnabled())
{
m_ftc->enableModifyUasState();
}
// participant might not even be linked to a uas (which isn't even obvious for the operator), so in that case default texts would be shown
m_ui->lblBatteryStatus->setText(QStringLiteral("-"));
m_ui->lblOperatingMode->setText(QStringLiteral("-"));
onUasChanged(uas);
// hide all widgets (and labels) that are not available for uas:
m_ui->pbBite->setVisible(false);
m_ui->pbMessage->setVisible(false);
// these are not supported yet, therefore hidden:
m_ui->lblBatteryStatus->setVisible(false);
m_ui->lbBatteryStatus->setVisible(false);
}
else // not a uas
{
// hide all uas specific widgets (and labels):
m_ui->lblBatteryStatus->setVisible(false);
m_ui->lbBatteryStatus->setVisible(false);
m_ui->lblOperatingMode->setVisible(false);
m_ui->lbOperatingMode->setVisible(false);
m_ui->pbUnlockUas->setVisible(false);
}
if (m_typeClass != TypeClass::Human)
m_ui->lbKind->setText(tr("Damage Type:")); // translates "Beschaedigungs" for non-Humans.
else
m_ui->lbKind->setText(tr("Kind:")); // translates "Verwundung" for Humans.
bool bUpdateDynamicParticipantData = true;
switch (m_typeClass.underlying())
{
case TypeClass::Human:
{
m_ui->lblVitality->setVisible(m_showPvSan);
m_ui->pbSetInjury->setVisible(m_showPvSan);
m_ui->pbSetSanitation->setVisible(m_showPvSan);
Q_FALLTHROUGH();
}
case TypeClass::GroundVehicle:
case TypeClass::VehicleWithGear:
case TypeClass::WeaponSystem:
case TypeClass::Aircraft:
case TypeClass::SupportEntity:
{
onParticipantChanged(participantData);
connect(m_dtc.get(), &Interface::Dtc::participantChanged,
this, &ParticipantInfoDialog::onParticipantChanged, Qt::UniqueConnection);
connect(m_dtc.get(), &Interface::Dtc::participantPositionChanged,
this, &ParticipantInfoDialog::onPositionChanged, Qt::UniqueConnection);
onPositionChanged(m_dtc->participantPosition(m_participant.id()));
onPartitionTimeChanged(m_session->partitionTime());
if (m_sitMapGuiIfc)
{
const int32_t participantId = m_participant.id();
m_ui->pbMovementTrack->setChecked(m_sitMapGuiIfc->isMovementTrackEnabled(participantId));
// set MovementTrackCallback:
std::function<void(const QVector<int32_t> &activeSimIds)> onMovementTrackChangedFunc = [this, participantId](const QVector<int32_t> &activeSimIds)
{
bool checkedNew = activeSimIds.contains(participantId);
if (m_ui->pbMovementTrack->isChecked() != checkedNew)
m_ui->pbMovementTrack->setChecked(checkedNew);
};
m_sitMapGuiIfc->setMovementTrackCallback(this, onMovementTrackChangedFunc);
}
break;
}
case TypeClass::Unit:
case TypeClass::SupportUnit:
{
if (!m_fltParticipantIfc)
m_session->getForeignGuiInterface<FilterManagement::ForeignFltParticipantGuiInterface>(m_fltParticipantIfc);
if (m_fltParticipantIfc)
{
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
m_symbolAppearanceSettings = m_fltParticipantIfc->symbolAppearanceForOperator(operatorId, m_session->workspaceId());
if (m_symbolAppearanceSettings)
m_symbolAppearanceSettings->addChangedCallback(this);
}
//a unit never has a history
m_ui->pbHistory->hide();
m_ui->lblEquipNr->hide();
m_ui->lbEquipNr->hide();
m_ui->pbBite->hide();
m_ui->pbMessage->hide();
m_ui->pbMovementTrack->hide();
m_ui->pbSetInjury->hide();
m_ui->pbSetSanitation->hide();
m_ui->lbContamination->hide();
m_ui->lblContamination->hide();
onParticipantChanged(participantData);
connect(m_dtc.get(), &Interface::Dtc::participantChanged,
this, &ParticipantInfoDialog::onParticipantChanged, Qt::UniqueConnection);
connect(m_dtc.get(), &Interface::Dtc::unitPositionChanged,
this, &ParticipantInfoDialog::onUnitPositionChanged, Qt::UniqueConnection);
onUnitPositionChanged(m_dtc->unitPosition(m_participant.id()));
break;
}
case TypeClass::Vessel:
case TypeClass::Unknown:
ERROR_LOG(m_logger) << LOGFUNCTION << m_typeClass;
return false;
}
if (bUpdateDynamicParticipantData)
{
const auto dpd = m_dtc->dynamicParticipantData(m_participant.id());
if (dpd.participantId() || m_participant.id())
onDynamicParticipantDataChanged(dpd);
else
{
const Party party = m_dtc->party(m_participant.partyId());
const QColor color = QColor::fromRgb(QRgb(party.color()));
updateIcon(color, QString::fromStdString(m_participant.symbol()));
}
}
setKindVisible(m_typeClass != TypeClass::SupportEntity &&
m_typeClass != TypeClass::Unit &&
m_typeClass != TypeClass::SupportUnit);
setStatusVisible(m_typeClass != TypeClass::SupportEntity &&
m_typeClass != TypeClass::Unit &&
m_typeClass != TypeClass::SupportUnit);
setHistoryVisible(m_typeClass != TypeClass::SupportEntity &&
m_typeClass != TypeClass::Unit &&
m_typeClass != TypeClass::SupportUnit);
//other connects
connect(m_dtc.get(), &Interface::Dtc::typeChanged,
this, &ParticipantInfoDialog::onTypeChanged, Qt::UniqueConnection);
connect(m_dtc.get(), &Interface::Dtc::dynamicParticipantDataChanged,
this, &ParticipantInfoDialog::onDynamicParticipantDataChanged, Qt::UniqueConnection);
connect(m_session, &LtsSession::LtsSession::partitionTimeChanged,
this, &ParticipantInfoDialog::onPartitionTimeChanged, Qt::UniqueConnection);
if (m_session->app() == LtsAppDescriptor::App::OC) // is the plugin loaded by the OC-App?
{
// hide several unused Buttons
m_ui->pbBite->hide();
m_ui->pbHistory->hide();
m_ui->pbMessage->hide();
m_ui->pbSetStatus->hide();
m_ui->pbSetInjury->hide();
m_ui->pbSetSanitation->hide();
}
if (m_session->isReplayPartition()) // is replay?
{
m_ui->pbSetStatus->hide();
m_ui->pbMessage->hide();
m_ui->pbBite->hide();
m_ui->pbSetInjury->hide();
m_ui->pbSetSanitation->hide();
}
if (!m_participant.equipmentNumber().is_set())
{
setEquipNrVisible(false);
setBiteVisible(false);
setStatusVisible(false);
setHistoryVisible(false);
setKindVisible(false);
setMessageVisible(false);
initTargetConfig(false);
initTargetConfigL400(false);
}
else
{
const EquipmentType eqType = m_dtc->equipmentType(type.equipmentTypeId());
m_isTarget = (eqType.wmsTypeClass() == WmsTypeClass::TargetHuman ||
eqType.wmsTypeClass() == WmsTypeClass::TargetVehicle);
// m_isTarget = 1;
// initTargetConfigL400(/*m_isTarget*/ true);
initTargetConfig(m_isTarget);
m_ui->twGear->setColumnHidden(0, m_isTarget);
m_ui->twGear->setColumnHidden(1, m_isTarget);
}
switch (m_typeClass.underlying())
{
case TypeClass::SupportEntity:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Support_Entity"));
break;
case TypeClass::Unit:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Unit"));
break;
case TypeClass::Human:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Human"));
break;
case TypeClass::GroundVehicle:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Ground_Vehicle"));
break;
case TypeClass::VehicleWithGear:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Ground_Vehicle_With_Gear"));
break;
case TypeClass::Aircraft:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Aircraft"));
break;
case TypeClass::Vessel:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Vessel"));
break;
case TypeClass::WeaponSystem:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Weapon_System"));
break;
case TypeClass::SupportUnit:
setOnlineHelpFilename(QStringLiteral("Info_Dialog-Unit"));
break;
case TypeClass::Unknown:
ERROR_LOG(m_logger) << LOGFUNCTION << m_typeClass;
}
#if LTS_DEBUG
//-- start Test Gui Elment plugin
auto cb = [this](const LtsPluginManager::PluginInstance &pi) { return loadGuiElementPLugin(pi);};
LtsPluginManager::LtsPluginLoader::getInstance()->loadPlugins(LtsPluginManager::PluginType::GUI_ELEMENT,
cb,
QStringList());
//-- end Test Gui Element plugin
#endif
return true;
}
bool ParticipantInfoDialog::loadGuiElementPLugin(const LtsPluginManager::PluginInstance &pi)
{
WARNING_LOG(m_logger)<<">>>> GUI Element pluginName: "<<pi.fileName;
GuiElementInterface *guiElement = qobject_cast<GuiElementInterface *>(pi.plugin);
if (guiElement->pluginName() == QStringLiteral("KeyValueGuiElement_XY"))
{
if (!guiElement->init(m_session, m_participant.id()))
return false;
m_ui->gridLayout_2->addWidget(guiElement->createGuiElement(this));
return true;
}
return false;
}
//SLOTS
void ParticipantInfoDialog::onDynamicParticipantDataChanged(const DynamicParticipantData &data, DataModification modType)
{
if (data.participantId() != m_participant.id() && data.participantId() != 0)
return;
// Do not continue on modType == DataModification::eRemove
// otherwise for example the icon would look bad (clover with black on black...)
if (modType == DataModification::eRemoved)
{
if (m_ui->lblIcon != nullptr)
m_ui->lblIcon->setEnabled(false);
return;
}
if (m_ui->lblIcon != nullptr)
m_ui->lblIcon->setEnabled(true);
//Current State
qWarning() << "stateHistory count" << data.stateHistory().size();
bool contaminationListIsEmpty = true;
if (!data.stateHistory().empty())
{
const ProjectDataManagement::VulnerabilityClass vc = m_typeClass == TypeClass::Human ?
ProjectDataManagement::VulnerabilityClass_def::SoldierInjuries :
ProjectDataManagement::VulnerabilityClass_def::VehicleDamages;
//#define FAKE_HISTORY
#ifdef FAKE_HISTORY
// fake history, where all sis have the same stateTime
std::vector<ParticipantManagement::StateInformation> history;
if (!data.stateHistory().empty())
{
auto firstTime = data.stateHistory().front().stateTime();
for (const auto &si : data.stateHistory())
{
auto fakeSi = si;
fakeSi.stateTime(firstTime);
history.push_back(fakeSi);
}
}
#else
const auto &history = data.stateHistory();
#endif
//LasState is the last "real" state, that has a VBG <=8 (Castastrophic)
//It's not the last state received, as there can be other state changes like Sanitation, or NearMiss
StateInformation lastState = m_dtc->youngestStateInformation(history/*, true*/ /* debug */);;
StateInformation youngestState;
youngestState.stateTime(0);
for (const StateInformation &si : history)
{
DEBUG_LOG(m_logger) << "StateInformation "
<< " time=" << si.stateTime()
<< " vulnerabilityBits=" << si.vulnerabilityBits()
<< " vulnerabilityKindId=" << si.vulnerabilityKindId();
if ( youngestState.stateTime() < si.stateTime())
youngestState = si;
}
// const bool showPvSan = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("ParticipantInformation"),
// QStringLiteral("HasPvSan"));
m_ui->lblStatus->setText(ProjectDataManagement::toString(lastState.vulnerabilityState(), vc));
//vitality
DEBUG_LOG(m_logger)<<" >>> last state: "<<lastState.vitality() << "last kind: " <<lastState.vulnerabilityKindId();
m_ui->lblVitality->setText(QString::number(lastState.vitality()) + QStringLiteral("%"));
// Set Contamination
const int NCONTAMINATION = 0x4000;
const int BCONTAMINATION = 0x8000;
const int CCONTAMINATION = 0x10000;
QStringList contaminationList;
DEBUG_LOG(m_logger) << "Set Contamination"
<< " time=" << youngestState.stateTime()
<< " vulnerabilityKindId=" << youngestState.vulnerabilityKindId()
<< " vulnerabilityBits=" << youngestState.vulnerabilityBits()
<< " vulnerabilityBits hex=0x" << std::hex << youngestState.vulnerabilityBits();
if ( youngestState.vulnerabilityBits() & NCONTAMINATION)
{
DEBUG_LOG(m_logger) << "append N";
const ProjectDataManagement::VulnerabilityState vs(static_cast<ProjectDataManagement::VulnerabilityState_def::type>(14));
QString fullName = ProjectDataManagement::toString(vs);
QString shortName;
shortName.append(fullName[0]);
contaminationList.append( shortName);
contaminationListIsEmpty = false;
}
if ( youngestState.vulnerabilityBits() & BCONTAMINATION)
{
DEBUG_LOG(m_logger) << "append B";
const ProjectDataManagement::VulnerabilityState vs(static_cast<ProjectDataManagement::VulnerabilityState_def::type>(15));
QString fullName = ProjectDataManagement::toString(vs);
QString shortName;
shortName.append(fullName[0]);
contaminationList.append( shortName);
contaminationListIsEmpty = false;
}
if ( youngestState.vulnerabilityBits() & CCONTAMINATION)
{
DEBUG_LOG(m_logger) << "append C";
const ProjectDataManagement::VulnerabilityState vs(static_cast<ProjectDataManagement::VulnerabilityState_def::type>(16));
QString fullName = ProjectDataManagement::toString(vs);
QString shortName;
shortName.append(fullName[0]);
contaminationList.append( shortName);
contaminationListIsEmpty = false;
}
m_ui->lblContamination->setText(contaminationList.join(QStringLiteral("+")));
// VBA
//AG 40 HACK!
if (lastState.vulnerabilityKindId() == 459286 && !((lastState.vulnerabilityBits() >> 7) & 1)) // VBG7 NOT set in history bits, but kind id still implying that VBG7 is still active
m_ui->lblKind->setText(QLatin1String("-"));
else
m_ui->lblKind->setText(m_pdmDtc->trVulnerabilityKindName(lastState.vulnerabilityKindId(), vc));
if (m_showPvSan && vc == ProjectDataManagement::VulnerabilityClass_def::SoldierInjuries )
{
if (lastState.vulnerabilityState() == ProjectDataManagement::VulnerabilityState::CombatReady ) //Maybe there is some side effect to this like
//if (data.stateHistory().size() == 1 && lastState.vulnerabilityState() == ProjectDataManagement::VulnerabilityState::CombatReady)
{
QPalette pal = QApplication::palette(m_ui->lbKind);
m_ui->lblKind->setPalette(pal);
// m_ui->lblVitality->setText(QString::number(100) + QStringLiteral("%")); fixed in PPM-Service
}
else
{
setSanitationLabelColor(/*m_dtc->proceduresDone(data.stateHistory())*/data.stateHistory().at(data.stateHistory().size()-1).sanitationResult());
}
}
}
else
{
QPalette pal = QApplication::palette(m_ui->lbKind);
m_ui->lblStatus->setText(QStringLiteral("-"));
m_ui->lblVitality->setText(QStringLiteral("-"));
m_ui->lblKind->setText(QStringLiteral("-"));
m_ui->lblKind->setPalette(pal);
}
m_ui->lbContamination->setHidden(contaminationListIsEmpty);
m_ui->lblContamination->setHidden(contaminationListIsEmpty);
DEBUG_LOG(m_logger)<< "setBackgroundColor ="<< data.manipulation().size();
setBackgroundColor(m_ui->lblEquipNr, Qt::red, data.manipulation().size());
// Special Sensor State
if (!data.specialSensorDataState())
{
m_ui->stackSpecialSensor->hide();
m_ui->lbSpecialSensorState->hide();
}
else
{
if (m_typeClass == TypeClass_def::Aircraft)
{
/*
CTC_Apache_Sensor_DiffCorrections = 0x01, // Has GPS Differential Corrections
CTC_Apache_Sensor_RadarJammer = 0x02, // APR 39
CTC_Apache_Sensor_IRJammer = 0x04, // ALQ 144
CTC_Apache_Sensor_RadarDetector = 0x08, // ALQ 136
CTC_Apache_Sensor_LaserSensor = 0x10 // AVR2A
*/
m_ui->stackSpecialSensor->setCurrentWidget(m_ui->stackPageAircraft);
m_ui->ledRadarJammer->setStatus(data.specialSensorDataState() & 0x02);
m_ui->ledIrJammer->setStatus(data.specialSensorDataState() & 0x04);
m_ui->ledRadarDetector->setStatus(data.specialSensorDataState() & 0x08);
m_ui->ledLaserSensor->setStatus(data.specialSensorDataState() & 0x10);
}
else
{
m_ui->stackSpecialSensor->setCurrentWidget(m_ui->stackPageCommon);
showSpecialSensorData(data.specialSensorDataState());
}
m_ui->lbSpecialSensorState->show();
m_ui->stackSpecialSensor->show();
}
// Gear Tabelle für Steilfeuer allgemein verstecken //[GUEZE-2871]
bool showForArtillery = true;
/*
#ifndef LTS_DEBUG
const Participant participantData = m_dtc->participant(m_participant.id());
const Type type = m_dtc->type(participantData.typeId());
const QString jsData = QString::fromStdString(type.properties()).trimmed();
DEBUG_LOG(m_logger)<<">>> >>> properties: "<<jsData<<" /// typeId: "<<type.id();
if(!jsData.isEmpty())
{
const QJsonObject &typObj = QJsonDocument::fromJson(QByteArray::fromStdString(jsData.toStdString())).object();
if (!typObj.isEmpty() && typObj[QStringLiteral("isArtillery")].toBool(false))
{
showForArtillery = false;
}
}
#endif
*/
//Gear
if (data.gear().size() == 0 )
{
m_gearList.clear();
m_ui->twGear->clearContents();
m_ui->twGear->clearSpans();
m_ui->twGear->hide();
m_ui->pbGearRanges->hide();
if (m_ltdGearComponent)
m_ltdGearComponent->clear();
}
else if (data.gear() != m_gearList)
{
m_gearList = data.gear();
std::vector<GearInformation> tmpGearList = m_gearList;
std::sort(tmpGearList.begin(), tmpGearList.end(), &compareGear); //sort
m_ui->twGear->show();
m_ui->pbGearRanges->show();
m_ui->twGear->clearSpans();
m_ui->twGear->clearContents();
int row = 0;
int rowCount = tmpGearList.size();
m_ui->twGear->setRowCount(rowCount);
m_ui->twGear->setSortingEnabled(false);
constexpr int unknownTasId = 0x80000000;
for (const GearInformation &gearInfo : tmpGearList)
{
QTableWidgetItem *item = nullptr;
if (gearInfo.chargeTypeId() == 0) //chargTypeId 0 is near miss code
{
rowCount--;
continue;
}
const int gearTypeId = gearInfo.gearTypeId();
if ((gearTypeId & unknownTasId) == unknownTasId)
item = new QTableWidgetItem(tr("Unknown gear id %1").arg(gearTypeId & ~unknownTasId));
else if (gearTypeId == 0)
{
// Hack for old systems which neither send gearTasCode/gearType nor gearSerialNumber/gearId
// 1 = Wanne, 2 = Turm
switch (gearInfo.gearId())
{
case 1:
item = new QTableWidgetItem(tr("Tank", "Gear Type"));
break;
case 2:
item = new QTableWidgetItem(tr("Turret", "Gear Type"));
break;
default:
item = new QTableWidgetItem(tr("N/A", "Gear Type"));
break;
}
}
else
item = new QTableWidgetItem(m_pdmDtc->trGearTypeName(gearTypeId));
item->setData(Qt::UserRole, gearInfo.gearId());
if(m_pdmDtc->canRestock(gearInfo.gearTypeId()))
{
item->setIcon(QIcon(QLatin1String("icon:service.svg")));
}
// If it's the same gearId, don't set the item, but make a row span to the one(s) before.
int rowStart = row - 1;
while (rowStart >= 0)
{
QTableWidgetItem *oldItem = m_ui->twGear->item(rowStart, 0); //Item above
if (oldItem == nullptr)// not set due to rowSpan...
break;
if (oldItem->data(Qt::UserRole).toInt() != gearInfo.gearId() || // Different gearId
oldItem->text() != item->text()) // Different Text (if gearId not set...)
break;
--rowStart;
}
if (rowStart + 1 < row)
{
m_ui->twGear->setItem(row, 0, item); //Need to be set, because of the check above
m_ui->twGear->setSpan(rowStart + 1, 0, row - rowStart, 1);
}
else
m_ui->twGear->setItem(row, 0, item);
if (gearInfo.chargeTypeId() != 0 && gearInfo.chargeTypeId() != -1) // hat Charge (and ignore only chargecounts)
{
int chargeTypeId = gearInfo.chargeTypeId();
if ((chargeTypeId & unknownTasId) == unknownTasId)
item = new QTableWidgetItem(tr("Unknown charge id %1").arg(chargeTypeId & ~unknownTasId));
else if (chargeTypeId == 0)
item = new QTableWidgetItem(tr("N/A", "Charge Type"));
else
{
item = new QTableWidgetItem(m_pdmDtc->trChargeTypeShortName(chargeTypeId, true));
item->setToolTip(m_pdmDtc->trChargeTypeName(chargeTypeId, true));
}
m_ui->twGear->setItem(row, 1, item);
//ressourceCount
//: Blank in this case refers to blank ammunition used for training
// Chris didn't wanted the chargeCounting Flag like: If they don't make it right why should we do it?
// presevred old mode so just in case..
//UAE wepaons don't send needed telegrams.. so let's hack again..
// in order to avoid the faulty SALTs let's hope they never send remaining ammunition below 100...
#ifdef GUEZ_MODE
item = new QTableWidgetItem((gearInfo.remain() < 0) ? tr("N/A", "Blank Ammunition") : QString::number(gearInfo.remain()));
#else
if ( PROJECTBUILD == "ahtc")
{
if ((gearInfo.chargeTypeId() > 54 && gearInfo.chargeTypeId() < 58) || gearInfo.remain() < 0 || gearInfo.remain() > 1000)
item = new QTableWidgetItem(tr("N/A", "Blank Ammunition"));
else
item = new QTableWidgetItem( QString::number(gearInfo.remain()));
}else
{
item = new QTableWidgetItem((gearInfo.remain() < 0) ? tr("N/A", "Blank Ammunition") : QString::number(gearInfo.remain()));
}
#endif
m_ui->twGear->setItem(row, 2, item);
}
if (gearInfo.gearTypeId() == ParticipantInfoLtdGearComponent::LTD_ID && m_ltdGearComponent)
m_ltdGearComponent->addGear(gearInfo.gearId(), row);
row++;
}
m_ui->twGear->setRowCount(rowCount);
m_ui->twGear->resizeColumnsToContents();
// Avoid shrinking last column (2): It'll auto-stretch afterwards
m_ui->twGear->horizontalHeader()->resizeSection(2, 42);
m_ui->twGear->setColumnHidden(0, m_isTarget);
m_ui->twGear->setColumnHidden(1, m_isTarget);
} //end Gear
if (!showForArtillery)
{
m_ui->twGear->hide();
}
DEBUG_LOG(m_logger) << "### m_sanMatStock: " << m_sanMatStock.size();
DEBUG_LOG(m_logger) << "### data.sanitationMaterialStock(): " << data.sanitationMaterialStock().size();
DEBUG_LOG(m_logger) << "### data.participantId(): " << data.participantId();
DEBUG_LOG(m_logger) << "### data.sampleTime(): " << data.sampleTime();
//sanMat
if (data.sanitationMaterialStock().size() == 0)
{
m_sanMatStock.clear();
m_ui->twSanMat->clearContents();
m_ui->gbSanitation->hide();
}
else if (data.sanitationMaterialStock() != m_sanMatStock)
{
DEBUG_LOG(m_logger) << "### data.qualification(): " << data.qualification();
DEBUG_LOG(m_logger) << "### data.sanitationUniqueId(): " << data.sanitationUniqueId();
m_ui->gbSanitation->show();
m_ui->lblSanAssignState->setText(ParticipantManagement::toString(data.qualification().underlying()));
m_ui->lblSanUniqueID->setText(QString::number(data.sanitationUniqueId(),16));
m_ui->lblSanOriginatorEquipNo->setText(QString::number(data.sanitationOriginatorEquipNo()));
m_sanMatStock = data.sanitationMaterialStock();
std::vector<SanitationMaterial> tmpSanMatStock = m_sanMatStock;
std::sort(tmpSanMatStock.begin(), tmpSanMatStock.end(), &compareSanMat); //sort
m_ui->twSanMat->clearContents();
int row = 0;
m_ui->twSanMat->setRowCount(tmpSanMatStock.size());
m_ui->twSanMat->setColumnCount(2);
m_ui->twSanMat->setSortingEnabled(false);
for (const SanitationMaterial &sanMat : tmpSanMatStock)
{
QTableWidgetItem *item = new QTableWidgetItem(QString::number(sanMat.materialCount()));
m_ui->twSanMat->setItem(row, 0, item);
item = new QTableWidgetItem(ProjectDataManagement::trSanitationMaterialName(m_pdmDtc->sanitationMaterial(sanMat.materialId()).name()));
m_ui->twSanMat->setItem(row, 1, item);
row++;
}
m_ui->twSanMat->resizeColumnsToContents();
m_ui->twSanMat->horizontalHeader()->setStretchLastSection(true);
m_ui->twSanMat->horizontalHeader()->resizeSection(1, 42);
}
m_ui->tbNbc->setVisible(data.hasNbcProtectionConfigured() && data.hasNbcProtectionActive());
if(data.sanitationMaterialStock().size() > 0 || (data.gear().size() > 0 && showForArtillery))
setBottomSpacerVisibility(true);
else
setBottomSpacerVisibility(false);
updateIcon(m_participant);
if (m_ltdGearComponent)
m_ltdGearComponent->updateData(data.designations());
}
void ParticipantInfoDialog::showSpecialSensorData(int specialSensorData)
{
const int specialSensorDataState = specialSensorData & 0xFF;
QString strSpecialSensorData;
switch (specialSensorDataState)
{
case SpecialSensorStatus_def::ChemicalDetectionFunction_NotOperational:
strSpecialSensorData = toString(SpecialSensorStatus_def::ChemicalDetectionFunction_NotOperational);
break;
case SpecialSensorStatus_def::ChemicalDetectionFunction_Detecting:
strSpecialSensorData = toString(SpecialSensorStatus_def::ChemicalDetectionFunction_Detecting);
break;
case SpecialSensorStatus_def::NBCDetectionAccessory_NotOperational:
strSpecialSensorData = toString(SpecialSensorStatus_def::NBCDetectionAccessory_NotOperational);
break;
case SpecialSensorStatus_def::NBCDetectionAccessory_Test:
strSpecialSensorData = toString(SpecialSensorStatus_def::NBCDetectionAccessory_Test);
break;
case SpecialSensorStatus_def::NBCDetectionAccessory_DetectingAir:
strSpecialSensorData = toString(SpecialSensorStatus_def::NBCDetectionAccessory_DetectingAir);
break;
case SpecialSensorStatus_def::AVLB_Mounted:
strSpecialSensorData = toString(SpecialSensorStatus_def::AVLB_Mounted);
break;
case SpecialSensorStatus_def::AVLB_Deployed:
strSpecialSensorData = toString(SpecialSensorStatus_def::AVLB_Deployed);
break;
case SpecialSensorStatus_def::AVLB_Mounting:
strSpecialSensorData = toString(SpecialSensorStatus_def::AVLB_Mounting);
break;
case SpecialSensorStatus_def::AVLB_Deploying:
strSpecialSensorData = toString(SpecialSensorStatus_def::AVLB_Deploying);
break;
case SpecialSensorStatus_def::MineLayer_Operational:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineLayer_Operational);
break;
case SpecialSensorStatus_def::MineLayer_Laying:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineLayer_Laying);
break;
case SpecialSensorStatus_def::MineClearingFunction_March:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineClearingFunction_March);
break;
case SpecialSensorStatus_def::MineClearingFunction_ReadyToClear:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineClearingFunction_ReadyToClear);
break;
case SpecialSensorStatus_def::MineClearingFunction_Clearing:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineClearingFunction_Clearing);
break;
case SpecialSensorStatus_def::MineTrowingFunction_NotOperational:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineTrowingFunction_NotOperational);
break;
case SpecialSensorStatus_def::MineTrowingFunction_ParameterInput:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineTrowingFunction_ParameterInput);
break;
case SpecialSensorStatus_def::MineTrowingFunction_ReadyToDeploy:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineTrowingFunction_ReadyToDeploy);
break;
case SpecialSensorStatus_def::MineTrowingFunction_Deploying:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineTrowingFunction_Deploying);
break;
case SpecialSensorStatus_def::MineTrowingFunction_Resupply:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineTrowingFunction_Resupply);
break;
case SpecialSensorStatus_def::MineTrowingFunction_FinishDeploying:
strSpecialSensorData = toString(SpecialSensorStatus_def::MineTrowingFunction_FinishDeploying);
break;
case SpecialSensorStatus_def::ADLER_Operational:
strSpecialSensorData = toString(SpecialSensorStatus_def::ADLER_Operational);
break;
case SpecialSensorStatus_def::ADLER_ConditionallyOperational:
strSpecialSensorData = toString(SpecialSensorStatus_def::ADLER_ConditionallyOperational);
break;
case SpecialSensorStatus_def::ADLER_NotOperational:
strSpecialSensorData = toString(SpecialSensorStatus_def::ADLER_NotOperational);
break;
default:
strSpecialSensorData = tr("Unknown (%1)").arg(specialSensorDataState);
break;
}
if ((specialSensorData & (1 << 8)) != 0)
strSpecialSensorData += QStringLiteral(" L");
if ((specialSensorData & (1 << 9)) != 0)
strSpecialSensorData += QStringLiteral(" R");
if ((specialSensorData & (1 << 10)) != 0)
strSpecialSensorData += QStringLiteral(" P");
if ((specialSensorData & (1 << 11)) != 0)
strSpecialSensorData += QStringLiteral(" F");
if (specialSensorDataState == 66) // CSF Spürbetrieb
{
const int type = (specialSensorData >> 12) & 0x0F;
strSpecialSensorData += QLatin1Char(' ');
switch (type)
{
case 1:
case 2:
strSpecialSensorData += tr("FIR");
break;
case 3:
strSpecialSensorData += tr("ZABC");
break;
case 4:
strSpecialSensorData += tr("CSF");
break;
case 5:
strSpecialSensorData += tr("PzBr");
break;
case 6:
strSpecialSensorData += tr("MV");
break;
case 7:
strSpecialSensorData += tr("MRF");
break;
case 8:
strSpecialSensorData += tr("WMV");
break;
case 0:
default:
break;
}
if (type == 4) // CSF
{
const int nbcType = (specialSensorData >> 16) & 0x03;
strSpecialSensorData += QLatin1Char(' ');
switch (nbcType)
{
case 0:
strSpecialSensorData += tr("No C-Agent");
break;
case 1:
strSpecialSensorData += tr("Sarin");
break;
case 2:
strSpecialSensorData += tr("VX");
break;
case 3:
strSpecialSensorData += tr("S-Lost");
break;
}
}
}
m_ui->lblSpecialSensorState->setText(strSpecialSensorData);
}
void ParticipantInfoDialog::onPositionChanged(const ParticipantPosition &position)
{
bool isOpsBuildingSource = false;
if (position.participantId() != m_participant.id() && position.participantId() != 0)
return;
if ( position.reportingSource() == Core::PositionReportingSource::OpsBuilding )
isOpsBuildingSource = true;
DEBUG_LOG(m_logger) << "reportingSource = OpsBuilding true" ;
setBackgroundColor(m_ui->lblPositionData, Qt::lightGray, isOpsBuildingSource );
onUpdatePosition(position.participantId(), position.pos(), position.sampleTime());
if (m_ismDtc && m_roomId != position.roomId())
{
if (position.roomId() > 0)
{
const auto mse = m_ismDtc->mainStructureElement(position.buildingId());
QString roomName;
for (const auto &room : mse.elements())
{
if (room.id() == position.roomId())
{
// In the case of external OPS transmitters, the building name was output twice
if ( room.structureElementTypeId() != InfrastructureManagement::StructureElementType_def::Room )
continue;
roomName = QString::fromStdString(room.displayName());
break;
}
}
QString buildingName = m_ismDtc->getBuildingDisplayName(mse);
m_ui->lblInBuildingInfo->setText(buildingName + QLatin1Char(' ') + roomName);
}
m_ui->lblInBuildingInfo->setVisible(position.roomId() > 0);
m_roomId = position.roomId();
}
if (position.mountedOn().is_set())
{
const auto mountedOnParticipant = m_dtc->participant(position.mountedOn().get());
if (mountedOnParticipant.equipmentNumber().is_set())
m_ui->pbMounted->setText(QString::number(mountedOnParticipant.equipmentNumber().get()));
else
m_ui->pbMounted->setText(QString(QLatin1Char('0')));
m_ui->pbMounted->show();
disconnect(m_ui->pbMounted, nullptr, nullptr, nullptr);
connect(m_ui->pbMounted, &QToolButton::clicked, this, &ParticipantInfoDialog::onParticipantMountedOn);
}
if (position.mountedParticipants().is_set())
{
m_ui->pbMounted->setText(QString::number(position.mountedParticipants().get().size()));
m_ui->pbMounted->show();
disconnect(m_ui->pbMounted, nullptr, nullptr, nullptr);
connect(m_ui->pbMounted, &QToolButton::clicked, this, &ParticipantInfoDialog::onMountedParticipants);
}
// hide button when both are not set
if (!position.mountedOn().is_set() && !position.mountedParticipants().is_set())
m_ui->pbMounted->hide();
}
void ParticipantInfoDialog::onUnitPositionChanged(const UnitPosition &position)
{
if (position.participantId() != m_participant.id() && position.participantId() != 0)
return;
const bool bCenter = m_symbolAppearanceSettings &&
(m_symbolAppearanceSettings->settings().symbolSettings.unitSymbolPosition == FilterManagement::SymbolAppearanceSettings::UnitSymbolPosition::Center);
onUpdatePosition(position.participantId(),
bCenter ? position.positionCenter() : position.positionLeader(),
bCenter ? position.sampleTimeCenter() : position.sampleTimeLeader());
m_ui->lblInBuildingInfo->hide();
m_ui->pbMounted->hide();
}
void ParticipantInfoDialog::onUpdatePosition(int participantId, const Core::GeoPosition &position, qint64 sampleTime)
{
m_lastPositionMSec = sampleTime;
if (participantId == 0 || std::isnan(position.lon()) || std::isnan(position.lat()))
{
m_ui->lblPositionData->setText(tr("Invalid Position"));
m_ui->pbMovementTrack->hide();
m_ui->pbFindOnMap->hide();
}
else
{
QString mgrs = LtsCoordTrans::mgrsFromGeographic(position.lon(), position.lat());
if (!qFuzzyIsNull(position.z()))
mgrs += QStringLiteral(" | ") + QString::number(position.z(), 'f', 2);
m_ui->lblPositionData->setText(mgrs);
m_ui->pbMovementTrack->show();
m_ui->pbFindOnMap->show();
}
LtsDialog::setMinWidthForWidgetHelper(m_ui->lblPositionData);
}
void ParticipantInfoDialog::onParticipantChanged(const Participant &participant, DataModification modType)
{
if (participant.id() != m_participant.id())
return;
// Do not continue on modType == DataModification::eRemove
// otherwise for example the icon would look bad (clover with black on black...)
if (modType == DataModification::eRemoved)
return;
if (m_participant.typeId() != participant.typeId())
{
m_ui->lblType->setText(ParticipantManagement::trTypeName(m_dtc->type(participant.typeId()).name()));
TypeClass typeClass = m_dtc->type(participant.typeId()).typeClass();
// If TypeClass changes, close window. Shouldn't ever happen, but for initialization.
if (m_typeClass != TypeClass_def::Unknown && m_typeClass != typeClass)
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Close)->click();
}
m_typeClass = typeClass;
}
if (m_participant.partyId() != participant.partyId())
m_ui->lblParty->setText(ParticipantManagement::trPartyName(m_dtc->party(participant.partyId()).name()));
m_participant = participant;
m_ui->lblHierarchy->setText(m_dtc->hierarchyFromParticipant(m_participant.id()));
m_ui->lblDesignator->setText(QString::fromStdString(m_participant.designator()));
m_ui->lblTactitcalIdentifier->setText(QString::fromStdString(m_participant.tacticalIdentifier()));
if (participant.equipmentNumber().is_set())
m_ui->lblEquipNr->setText(QString::number(m_participant.equipmentNumber().get()));
else
m_ui->lblEquipNr->setText(QLatin1String("-"));
#ifdef LTS_DEBUG
m_ui->lblEquipNr->setToolTip(QString::number(m_participant.id()));
#endif
//hide Info if not exists
m_ui->lblInfoText->setText(QString::fromStdString(m_participant.info()));
m_ui->lblInfoText->setVisible(m_participant.info().size() > 0);
m_ui->lblInfo->setVisible(m_participant.info().size() > 0);
onDynamicParticipantDataChanged(m_dtc->dynamicParticipantData(m_participant.id()));
}
void ParticipantInfoDialog::onTypeChanged(const Type &type, DataModification)
{
if (m_participant.typeId() != type.id())
return;
m_ui->lblType->setText(ParticipantManagement::trTypeName(type.name()));
}
void ParticipantInfoDialog::updateCurrentIcon()
{
if (m_participant.id() == 0)
return;
updateIcon(m_participant);
}
void ParticipantInfoDialog::updateIcon(const Participant &participant)
{
m_symbolWatcher->setSymbolResult(m_asbiIfc->findImage(participant));
}
void ParticipantInfoDialog::updateIcon(const QColor &color, const QString &sidc)
{
AdvancedSymbology::SymbolDataToRender symDataToRender(sidc);
symDataToRender.injury = AdvancedSymbology::Injury::NoInjury;
symDataToRender.injuryColor = QColor();
symDataToRender.fillColor = color;
symDataToRender.fillColorReplace = true;
m_symbolWatcher->setSymbolResult(m_asbiIfc->findImage(symDataToRender));
}
void ParticipantInfoDialog::setSanitationLabelColor(SanitationResult proceduresDone)
{
QPalette pal = QApplication::palette(m_ui->lbKind);
QString toolTip;
switch (proceduresDone.underlying())
{
case SanitationResult::NoEffect:
return;
case SanitationResult::Insufficient:
pal.setColor(QPalette::Window, Qt::red);
toolTip = tr("Insufficient Care");
break;
case SanitationResult::Sufficient:
pal.setColor(QPalette::Window, Qt::yellow);
toolTip = tr("Sufficient Care");
break;
case SanitationResult::Optimal:
pal.setColor(QPalette::Window, Qt::green);
toolTip = tr("Optimal Care");
break;
case SanitationResult::Unhandled:
pal.setColor(QPalette::Window, QColor::fromRgb(179, 0, 0));
toolTip = tr("No Care");
break;
case SanitationResult::deprecatedNA:
break;
}
DEBUG_LOG(m_logger) << "Set Color to: " << proceduresDone.underlying();
m_ui->lblKind->setPalette(pal);
m_ui->lblKind->setAutoFillBackground(true);
m_ui->lblKind->setToolTip(toolTip);
}
void ParticipantInfoDialog::setKindVisible(bool bVisible)
{
// const bool showVulnerabilityKindProject = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("ParticipantInformation"),
// QStringLiteral("ShowVulnerabilityKind"));
if (!m_showVulnerabilityKindProject)
bVisible = false;
m_ui->lblKind->setVisible(bVisible);
m_ui->lbKind->setVisible(bVisible);
}
/*!
* \brief ParticipantInfoDialog::setBottomSpacerVisibility
* \param isOneListActive
* \details If Weapon Table or/and SanMat table is visible -> Hide Bottom Spacer
* \author Niklas Schmidt
*/
void ParticipantInfoDialog::setBottomSpacerVisibility(bool isOneListActive)
{
if(isOneListActive == true)
{
m_ui->vsBottom->changeSize(0,0, QSizePolicy::Maximum, QSizePolicy::Maximum);
m_ui->vsBottom->invalidate();
}else
{
m_ui->vsBottom->changeSize(0,0, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
m_ui->vsBottom->invalidate();
}
}
void ParticipantInfoDialog::setStatusVisible(bool bVisible)
{
m_ui->lblStatus->setVisible(bVisible);
m_ui->lbStatus->setVisible(bVisible);
m_ui->pbSetStatus->setVisible(bVisible);
}
void ParticipantInfoDialog::setHistoryVisible(bool bVisible)
{
m_ui->pbHistory->setVisible(bVisible);
}
void ParticipantInfoDialog::setEquipNrVisible(bool bVisible)
{
m_ui->lblEquipNr->setVisible(bVisible);
m_ui->lbEquipNr->setVisible(bVisible);
}
void ParticipantInfoDialog::setBiteVisible(bool bVisible)
{
m_ui->pbBite->setVisible(bVisible);
}
void ParticipantInfoDialog::setMessageVisible(bool bVisible)
{
m_ui->pbMessage->setVisible(bVisible);
}
void ParticipantInfoDialog::onSymbolAppearanceSettingsChanged(FilterManagement::SymbolAppearanceSettings::Part part)
{
if (part != FilterManagement::SymbolAppearanceSettings::Part::Symbol)
return;
if (m_typeClass != TypeClass::Unit &&
m_typeClass != TypeClass::SupportUnit)
return;
onUnitPositionChanged(m_dtc->unitPosition(m_participant.id()));
}
void ParticipantInfoDialog::setBackgroundColor(QWidget *w, Qt::GlobalColor color, bool bSetColor)
{
if (!w)
return;
if (bSetColor)
{
QPalette pal = QApplication::palette(w);
pal.setColor(QPalette::Window, color);
w->setPalette(pal);
w->setAutoFillBackground(true);
}
else
{
// reset to default palette
w->setPalette(QApplication::palette(w));
w->setAutoFillBackground(false);
}
}
void ParticipantInfoDialog::onOpenSetStatusDialog()
{
ParticipantConfigDialog *diag = new ParticipantConfigDialog(m_participant.id(), ParticipantConfigDialog::DialogType::Config, this);
if (diag->init(m_session, m_dtc, m_ftc))
addDialog(diag, m_menuGroup, QStringLiteral("ParticipantConfig") + QString::number(m_participant.id()), LtsWidgets::LayoutArea::eDialogTab);
else
delete diag;
}
void ParticipantInfoDialog::onOpenSetInjuryDialog()
{
ParticipantSetInjuryDialog *diag = new ParticipantSetInjuryDialog(m_participant.id(), this);
if (diag->init(m_session, m_dtc, m_ftc, m_pdmDtc))
addDialog(diag, m_menuGroup, QStringLiteral("ParticipantSetInjury") + QString::number(m_participant.id()), LtsWidgets::LayoutArea::eDialogTab);
else
delete diag;
}
void ParticipantInfoDialog::onOpenSetSanitationDialog()
{
ParticipantSetSanitationDialog *diag = new ParticipantSetSanitationDialog(m_participant.id(), this);
if (diag->init(m_session, m_dtc, m_ftc, m_pdmDtc))
addDialog(diag, m_menuGroup, QStringLiteral("ParticipantSetSanitationDialog") + QString::number(m_participant.id()), LtsWidgets::LayoutArea::eDialogTab);
else
delete diag;
}
void ParticipantInfoDialog::onOpenHistory()
{
if (!m_aesDtc)
return;
// {
// ParticipantTargetConfigurationDialog* diag = new ParticipantTargetConfigurationDialog(this);
// if (diag->init(m_participant.id(), m_dtc, m_ftc, /*m_pdmDtc,*/ m_sitMapGuiIfc))
// addDialog(diag, m_menuGroup, QStringLiteral("ParticipantHistory") + QString::number(m_participant.id()), LtsWidgets::LayoutArea::eDialogTab);
// else
// delete diag;
// }
// return;
ParticipantHistoryDialog *diag = new ParticipantHistoryDialog(this);
if (diag->init(m_participant.id(), m_dtc, m_pdmDtc, m_aesDtc))
addDialog(diag, m_menuGroup, QStringLiteral("ParticipantHistory") + QString::number(m_participant.id()), LtsWidgets::LayoutArea::eDialogTab);
else
delete diag;
}
void ParticipantInfoDialog::onOpenBite()
{
const bool bWithSelfTest = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
ParticipantBiteDialog *diag = new ParticipantBiteDialog(m_participant.id(), this);
if (diag->init(m_dtc, m_ftc, m_pdmDtc, bWithSelfTest))
addDialog(diag, m_menuGroup, QStringLiteral("ParticipantBit") + QString::number(m_participant.id()), LtsWidgets::LayoutArea::eInfoTab);
else
delete diag;
}
void ParticipantInfoDialog::onOpenMessage()
{
ParticipantConfigDialog *diag = new ParticipantConfigDialog(m_participant.id(), ParticipantConfigDialog::DialogType::Message, this);
if (diag->init(m_session, m_dtc, m_ftc))
addDialog(diag, m_menuGroup, QStringLiteral("ParticipantMessage") + QString::number(m_participant.id()), LtsWidgets::LayoutArea::eDialogTab);
else
delete diag;
}
void ParticipantInfoDialog::onFindOnMap()
{
if (m_sitMapGuiIfc)
m_sitMapGuiIfc->centerMapToParticipant(m_participant.id());
}
void ParticipantInfoDialog::onMovementTrack()
{
if (m_sitMapGuiIfc)
m_sitMapGuiIfc->enableMovementTrack(m_participant.id(), m_ui->pbMovementTrack->isChecked());
}
void ParticipantInfoDialog::onParticipantMountedOn()
{
if (m_ppmGuiIfc)
m_ppmGuiIfc->showParticipantInfoWindow(m_dtc->participant(m_dtc->participantPosition(m_participant.id()).mountedOn().get()).id());
}
void ParticipantInfoDialog::onMountedParticipants()
{
ParticipantsMountedTableDialog *diag = new ParticipantsMountedTableDialog(m_participant.id(), this);
if (diag->init(m_dtc, m_ppmGuiIfc))
addDialog(diag, m_menuGroup, QStringLiteral("ParticipantsMounted") + QString::number(m_participant.id()), LtsWidgets::LayoutArea::eDialogTab);
else
delete diag;
}
void ParticipantInfoDialog::onPartitionTimeChanged(qint64 newPartitionTime)
{
if (LtsUtils::isPositionTimeOutdated(newPartitionTime, m_lastPositionMSec) )
{
DEBUG_LOG(m_logger)<< "setBackgroundColor ="<< LtsUtils::isPositionTimeOutdated(newPartitionTime, m_lastPositionMSec);
setBackgroundColor(m_ui->lblPositionData, Qt::red, true);
}
qint64 lastPosSec = (newPartitionTime - m_lastPositionMSec) / 1000;
QString ts;
if (lastPosSec < 60)
ts = tr("%1 seconds").arg(QString::number(lastPosSec, 'f', 0));
else if (lastPosSec < 60 * 60)
ts = tr("%1 minutes").arg(QString::number(lastPosSec / 60, 'f', 0));
else if (lastPosSec < 24 * 60 * 60)
ts = tr("%1 hours").arg(QString::number(lastPosSec / 3600, 'f', 0));
else
ts = tr("%1 days").arg(QString::number(lastPosSec / 86400, 'f', 0));
QString updateString = tr("Last Position update: %1 ago").arg(ts);
m_ui->lblPositionData->setToolTip(updateString);
}
void ParticipantInfoDialog::onGearRanges()
{
if (m_sitMapGuiIfc)
m_sitMapGuiIfc->enableGearRanges(m_participant.id(), m_ui->pbGearRanges->isChecked());
}
///////////////////////////////////////////////
/// Target
///////////////////////////////////////////////
bool ParticipantInfoDialog::initTargetConfig(bool bShow)
{
if (bShow)
{
m_ui->pbMessage->hide();
m_ui->pbMovementTrack->hide();
m_ui->pbSetInjury->hide();
m_ui->pbSetSanitation->hide();
// Combobox Weapon:
// TODO woher kommen die Waffen?
m_ui->cbTargetWeapon->addItem(QStringLiteral("AK47"), 1);
m_ui->cbTargetWeapon->addItem(QStringLiteral("Pistol"), 5);
m_ui->cbTargetWeapon->addItem(QStringLiteral("Shotgun"), 7);
// Combobox Mode:
m_ui->cbTargetMode->addItem(TargetManagement::toString(TargetManagement::Mode_def::Deactivated),
TargetManagement::Mode_def::Deactivated);
m_ui->cbTargetMode->addItem(TargetManagement::toString(TargetManagement::Mode_def::ShootBack),
TargetManagement::Mode_def::ShootBack);
m_ui->cbTargetMode->addItem(TargetManagement::toString(TargetManagement::Mode_def::ShootFirst),
TargetManagement::Mode_def::ShootFirst);
m_ui->cbTargetMode->addItem(TargetManagement::toString(TargetManagement::Mode_def::NoWeapon),
TargetManagement::Mode_def::NoWeapon);
connect(m_ui->btTarget, &QToolButton::clicked, this, &ParticipantInfoDialog::onTargetConfig);
connect(m_ui->cbTargetMode, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ParticipantInfoDialog::onTargetModeChangeed);
connect(m_ui->cbTargetWeapon, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ParticipantInfoDialog::onTargetWeaponChanged);
m_session->getDtc<TargetManagement::DataInterface>(m_tgtDtc);
m_tgtDtc->enableTargetConfig();
m_session->getFtc<TargetManagement::DataInterface>(m_tgtFtc);
if (m_tgtDtc)
{
connect(m_tgtDtc.get(), &TargetManagement::Interface::Dtc::targetConfigChanged,
this, &ParticipantInfoDialog::onTargetConfigChanged);
}
}
else
{
m_ui->lbTarget->setVisible(false);
m_ui->btTarget->setVisible(false);
}
m_ui->pbTarget->setVisible(false);
m_ui->lbTargetMode->setVisible(false);
m_ui->lbTargetWeapon->setVisible(false);
m_ui->cbTargetMode->setVisible(false);
m_ui->cbTargetWeapon->setVisible(false);
return true;
}
bool ParticipantInfoDialog::initTargetConfigL400(bool bShow)
{
m_ui->pbTarget->setVisible(bShow);
if (bShow)
{
connect(m_ui->pbTarget, &QPushButton::clicked,
this, &ParticipantInfoDialog::onOpenTargetConfigurationL400, Qt::UniqueConnection);
}
return true;
}
void ParticipantInfoDialog::onTargetConfig()
{
if (!m_tgtFtc)
return;
INFO_LOG(m_logger) << "onTargetConfig send TargetConfigRequest";
TargetManagement::ConfigureTargetRequest request;
request.id(0);
request.participantId(m_participant.id());
request.tgtCommand(TargetManagement::TgtCommand_def::RequestTechnicalState);
auto cb = [request, this]()
{
return m_tgtFtc->configureTargetRequest(request, this);
};
m_requestHelper->startSingleRequest(cb);
} // end of onTargetConfig
void ParticipantInfoDialog::onTargetConfigChanged(const TargetManagement::TargetConfig &data, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
INFO_LOG(m_logger) << "onTargetConfigChanged participantId = " << m_participant.id()
<< " data.participantId = " << data.participantId();
if (data.participantId() != m_participant.id())
return;
m_ui->lbTargetMode->setVisible(true);
m_ui->lbTargetWeapon->setVisible(true);
m_ui->cbTargetMode->setVisible(true);
m_ui->cbTargetWeapon->setVisible(true);
m_ui->cbTargetMode->setCurrentIndex(m_ui->cbTargetMode->findData(data.mode().underlying()));
m_ui->cbTargetWeapon->setCurrentIndex(m_ui->cbTargetWeapon->findData(data.weapon()));
} // end of onTargetConfigChanged
void ParticipantInfoDialog::onTargetModeChangeed()
{
if (!m_tgtFtc)
return;
INFO_LOG(m_logger) << "onTargetModeChangeed";
TargetManagement::ConfigureTargetRequest request;
request.id(0);
request.participantId(m_participant.id());
request.tgtCommand(TargetManagement::TgtCommand_def::SetMode);
int modeInt = m_ui->cbTargetMode->currentData().toInt();
TargetManagement::Mode mode = static_cast <TargetManagement::Mode_def::type>(modeInt);
INFO_LOG(m_logger) << "onTargetModeChangeed=" << mode;
request.mode(mode);
auto cb = [request, this]()
{
return m_tgtFtc->configureTargetRequest(request, this);
};
m_requestHelper->startSingleRequest(cb);
}
void ParticipantInfoDialog::onTargetWeaponChanged()
{
if (!m_tgtFtc)
return;
TargetManagement::ConfigureTargetRequest request;
request.id(0);
request.participantId(m_participant.id());
request.tgtCommand(TargetManagement::TgtCommand_def::SetWeapon);
request.weapon(m_ui->cbTargetWeapon->currentData().toInt());
INFO_LOG(m_logger) << "onTargetWeaponChangeed = " << request.weapon();
auto cb = [request, this]()
{
return m_tgtFtc->configureTargetRequest(request, this);
};
m_requestHelper->startSingleRequest(cb);
}
void ParticipantInfoDialog::onOpenTargetConfigurationL400()
{
// ParticipantTargetConfigurationDialog -> L400
ParticipantTargetConfigurationDialog* diag = new ParticipantTargetConfigurationDialog(this);
if (diag->init(m_participant.id(), m_dtc, m_ftc, m_sitMapGuiIfc))
addDialog(diag, m_menuGroup, QStringLiteral("TargetConfigurationL400") + QString::number(m_participant.id()), LtsWidgets::LayoutArea::eDialogTab);
else
delete diag;
}
void ParticipantInfoDialog::onContextMenuRequested(const QPoint &position)
{
QTableWidgetItem* pointedItem = m_ui->twGear->itemAt(position);
if (!pointedItem || pointedItem->column() != 0)
return;
GearInformation &gear = m_gearList[pointedItem->row()];
DEBUG_LOG(m_logger) << "gear type selected = " << gear.gearTypeId();
DEBUG_LOG(m_logger) << "gear Id = " << gear.gearId();
QList<QAction*> actions;
if (m_pdmDtc->canRestock(gear.gearTypeId()))
{
QAction *restockNowAction = new QAction(tr("Restock Defaults"), this);
connect(restockNowAction, &QAction::triggered, this, [=](){ onRestockNow(gear.gearId(), gear.gearTypeId()); });
actions << restockNowAction;
}
// if (m_pdmDtc->canSetDefaults(gear.gearTypeId()))
// {
// QAction *restockDefaultsAction = new QAction(tr("Restock Defaults"), this);
// connect(restockDefaultsAction, &QAction::triggered, this, [=](){ onRestockDefaults(gear.gearId(), gear.gearTypeId()); });
// actions << restockDefaultsAction;
// }
if (actions.isEmpty())
return;
QMenu menu(m_ui->twGear);
menu.addActions(actions);
menu.exec(m_ui->twGear->viewport()->mapToGlobal(position));
}
void ParticipantInfoDialog::onRestockNow(int gearId,int gearTypeId)
{
ParticipantGearRestock *diag = new ParticipantGearRestock(gearId, gearTypeId, m_participant, ParticipantGearRestock::DialogMode::DM_Restock, this);
if (diag->init(m_session))
addDialog(diag, m_menuGroup, QStringLiteral("ParticipantGearRestockNow") + QString::number(gearId), LtsWidgets::LayoutArea::eDialogTab);
else
delete diag;
}
void ParticipantInfoDialog::onRestockDefaults(int gearId, int gearTypeId)
{
ParticipantGearRestock *diag = new ParticipantGearRestock(gearId, gearTypeId, m_participant, ParticipantGearRestock::DialogMode::DM_SetRestockDefaults, this);
if (diag->init(m_session))
addDialog(diag, m_menuGroup, QStringLiteral("ParticipantGearRestockDefaults") + QString::number(gearId), LtsWidgets::LayoutArea::eDialogTab);
else
delete diag;
}
void ParticipantInfoDialog::onUasChanged(const UAS &uas)
{
// check if changed uas is this uas, on this participant, in this exercise
if (uas.id() != m_uasId || uas.exerciseId() != m_session->exerciseId() || uas.participantId() != m_participant.id())
{
return;
}
// set text & text color for uas operating mode
const QString operatingMode(ProjectDataManagement::toString(uas.uasState()));
static const QString textHtml { QStringLiteral("<font color='%1'>%2</font>") };
switch (uas.uasState().underlying())
{
case ProjectDataManagement::UasState::Auto:
{
m_ui->lblOperatingMode->setText(textHtml.arg(QStringLiteral("green")).arg(operatingMode));
break;
}
case ProjectDataManagement::UasState::Manual:
{
m_ui->lblOperatingMode->setText(textHtml.arg(QStringLiteral("orange")).arg(operatingMode));
break;
}
default:
{
m_ui->lblOperatingMode->setText(operatingMode);
break;
}
}
}
void ParticipantInfoDialog::onUnlockUAS()
{
UAS uas = m_dtc->getUasByParticipantId(m_participant.id(), m_session->exerciseId());
m_uasId = uas.id();
DEBUG_LOG(m_logger)<<" -- onUnlockUAS uasId: "<< uas.id() <<" /// participantId: "<<uas.participantId()<<" /// equipmentNumber: "<<m_participant.equipmentNumber();
if (uas.id() <= 0 )
{
ERROR_LOG(m_logger)<<" -- onUnlockUAS invalid uasId: "<<uas.id()<<" !!!";
return;
}
if (!m_participant.equipmentNumber().is_set())
{
ERROR_LOG(m_logger)<<" -- onUnlockUAS invalid EquipmentNumber for UAS: "<<uas.id()<<" !!!";
return;
}
ModifyUasStateRequest req;
req.uasId(uas.id());
req.uasState(ProjectDataManagement::UasState_def::Auto);
req.equipmentNumber(m_participant.equipmentNumber().get());
auto cb = [req, this]()
{
return m_ftc->modifyUasStateRequest(req, this);
};
m_requestHelper->startSingleRequest(cb);
}
} // namespace ParticipantManagement