929 lines
37 KiB
C++
Executable File
929 lines
37 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* Model to handle datail data for the different event types
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*
|
|
* Created by Mike Wille, SLSE, 2017-09-04
|
|
*/
|
|
|
|
#include "detail_data.h"
|
|
#include "logger.h"
|
|
#include "tln_legend.h"
|
|
#include "attribute_value_lookup.h"
|
|
|
|
#include <LtsTimelineClassic/Event.h>
|
|
#include <LtsWidgets/lts_date_time_edit.h>
|
|
#include <LtsSession/lts_session.h>
|
|
#include <LtsUtilsSettings/settings.h>
|
|
|
|
// Dtc lookups: (data ifc libs)
|
|
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
|
|
#include <Plugins/MarkerManagement/mrk_data_plugin_interface.h>
|
|
#include <Plugins/InfrastructureManagement/ism_data_plugin_interface.h>
|
|
#include <Plugins/OperatorManagement/opm_data_plugin_interface.h>
|
|
#include <Plugins/AudioVideoManagement/avm_data_plugin_interface.h>
|
|
#include <Plugins/ProjectDataManagement/pdm_data_plugin_interface.h>
|
|
|
|
|
|
// Enums only: (svc libs only)
|
|
#include <Services/ExerciseEventManagement/eem_enums.hpp>
|
|
#include <Services/ExerciseEventManagement/eem_translation.h>
|
|
#include <Services/ProjectDataManagement/pdm_translation.h>
|
|
#include <Services/AreaEffectSimulation/aes_translation.h>
|
|
#include <Services/MarkerManagement/mrk_translation.h>
|
|
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QJsonValue>
|
|
#include <QVariant>
|
|
|
|
|
|
namespace Timeline
|
|
{
|
|
|
|
static inline QString removeSpaces(const QString &str)
|
|
{
|
|
// no QString::erase(it) available...
|
|
QString ret;
|
|
ret.reserve(str.size());
|
|
for (const QChar c : str)
|
|
{
|
|
if (!c.isSpace())
|
|
ret += c;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
DetailData::DetailData(LtsSession::LtsSession *session, QObject *parent)
|
|
: QObject(parent)
|
|
, m_session(session)
|
|
, __already_populated__(false)
|
|
, m_logger(getLogger("DetailData"))
|
|
{
|
|
populate();
|
|
}
|
|
|
|
void DetailData::addRedirectedAttributeType(const QString &newAttributeTypeId, const QString &attributeText, const QString &redirectToAttributeTypeId)
|
|
{
|
|
attributeTypeLookup.addAttributeText(newAttributeTypeId, attributeText);
|
|
attributeRedirectionLookup.addRedirection(newAttributeTypeId, redirectToAttributeTypeId);
|
|
}
|
|
|
|
|
|
void DetailData::addAttributeType(const QString &attributeTypeId, const QString &attributeText, const int uiTypeId, const int interpreterTypeId)
|
|
{
|
|
attributeTypeLookup.addAttributeText(attributeTypeId, attributeText);
|
|
attributeUITypeLookup.addUITypeToAttribute(attributeTypeId, uiTypeId);
|
|
attributeInterpreterLookup.addInterpreterTypeToAttribute(attributeTypeId, interpreterTypeId);
|
|
}
|
|
|
|
|
|
void DetailData::addEventType(int eventTypeId, const QString &eventTypeString) // with default attribute types [time, etc.]
|
|
{
|
|
eventTypeLookup.addEventType(eventTypeId, eventTypeString);
|
|
attributeEventLookup.addAttributesToEvent(eventTypeId, {QStringLiteral("TimeRange")});
|
|
}
|
|
|
|
|
|
void DetailData::addEventType(const ProjectDataManagement::EventType &eventType) // with default attribute types [time, etc.]
|
|
{
|
|
addEventType(eventType.underlying(), ProjectDataManagement::toString(eventType));
|
|
}
|
|
|
|
|
|
void DetailData::populate() // call on any retranslate
|
|
{
|
|
if (__already_populated__) // TODO: repopulate!!
|
|
return;
|
|
__already_populated__ = true;
|
|
|
|
|
|
|
|
// TODO: clear all lookups !
|
|
|
|
// populate Event Types - see build/Lts/Services/ExerciseEventManagement/eem_enums.hpp
|
|
// * retrieved as of 2017-09-01
|
|
|
|
addEventType(0, tr("General")); // would be type 'unknown' in EventType_def DE: "Allgemein"
|
|
|
|
addEventType(markerTypeId, tr("Marker"));
|
|
attributeEventLookup.addAttributesToEvent(markerTypeId, {QStringLiteral("MarkerName"),
|
|
QStringLiteral("MarkerNote"),
|
|
QStringLiteral("Operator"),
|
|
QStringLiteral("MarkerOffset"),
|
|
QStringLiteral("IsSituationType"),
|
|
QStringLiteral("IsVideoType"),
|
|
QStringLiteral("IsAudioType")});
|
|
|
|
|
|
using namespace ProjectDataManagement;
|
|
const auto possibleEventTypes = TimelineLegendDialog::possibleEvents();
|
|
for (const auto eventType : possibleEventTypes)
|
|
{
|
|
switch (eventType.underlying())
|
|
{
|
|
case EventType::Hit:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("VulnerabilityState"),
|
|
QStringLiteral("OriginatorChargeTypeId"),
|
|
QStringLiteral("FriendlyFire"),
|
|
//QStringLiteral("OriginatorId"), // TODO: kann ich nix mit anfangen..
|
|
//QStringLiteral("OriginatorType"), // not really useful - see EEM HandlerDynamicParticipantData::tryCreateHitEvent()
|
|
QStringLiteral("OriginatorEquipmentNumber")});
|
|
break;
|
|
case EventType::BiteMessage:
|
|
break;
|
|
case EventType::WeaponAssignment:
|
|
case EventType::FireEvent:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {//<< QStringLiteral("GearId"), // is a unique serial number not known to excon operator
|
|
QStringLiteral("GearTypeId"),
|
|
QStringLiteral("ChargeTypeId")});
|
|
break;
|
|
case EventType::HitBuilding:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("AesType"),
|
|
QStringLiteral("ChargeTypeId"),
|
|
QStringLiteral("OriginatorEquipmentNumber"),
|
|
QStringLiteral("MainStructureElementId"),
|
|
QStringLiteral("VulnerabilityState"),
|
|
QStringLiteral("damagePercent"), // range
|
|
//QStringLiteral("damagePercentOld"),
|
|
}); // range
|
|
break;
|
|
case EventType::Manipulation:
|
|
break;
|
|
case EventType::Sanitation:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("Vitality"),
|
|
QStringLiteral("SanitationProceduresNeeded"),
|
|
QStringLiteral("SanitationProceduresTaken")});
|
|
break;
|
|
case EventType::CameraVideo:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("PartyId"),
|
|
QStringLiteral("MainStructureElementId"),
|
|
QStringLiteral("duration"),
|
|
QStringLiteral("streamName")});
|
|
break;
|
|
case EventType::RadioCnr:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("PartyId"),
|
|
QStringLiteral("duration"),
|
|
QStringLiteral("streamName")});
|
|
break;
|
|
case EventType::RadioTvc:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("duration"),
|
|
QStringLiteral("streamName")});
|
|
|
|
break;
|
|
case EventType::HitEffectSimulation:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("AesType"),
|
|
QStringLiteral("AesName"),
|
|
QStringLiteral("OriginatorChargeTypeId")});
|
|
break;
|
|
case EventType::HitC:
|
|
case EventType::HitB:
|
|
case EventType::HitMine:
|
|
case EventType::EnterMineArea:
|
|
case EventType::LeaveMineArea:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("AesName"),
|
|
QStringLiteral("OriginatorChargeTypeId")});
|
|
break;
|
|
case EventType::HitN:
|
|
case EventType::HitGasPipe:
|
|
case EventType::EnterDangerArea:
|
|
case EventType::LeaveDangerArea:
|
|
case EventType::CrossLocalBorderline:
|
|
case EventType::CrossGlobalBorderline:
|
|
case EventType::EnterFunctionalArea:
|
|
case EventType::LeaveFunctionalArea:
|
|
case EventType::EnterNuclear:
|
|
case EventType::LeaveNuclear:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("AesName")});
|
|
break;
|
|
case EventType::Borderline:
|
|
case EventType::NContamination:
|
|
case EventType::DangerArea:
|
|
case EventType::FunctionalArea:
|
|
case EventType::MineCorridor:
|
|
case ProjectDataManagement::EventType::GasPipe:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("AesName"),
|
|
QStringLiteral("duration")});
|
|
break;
|
|
case EventType::MineArea:
|
|
case EventType::BCContamination:
|
|
attributeEventLookup.addAttributesToEvent(eventType, {QStringLiteral("AesName"),
|
|
QStringLiteral("duration"),
|
|
QStringLiteral("ChargeTypeId")});
|
|
break;
|
|
case EventType::Unknown:
|
|
case EventType::FriendlyFire:
|
|
case EventType::TechnicalArea:
|
|
case EventType::EquipmentErrorReport:
|
|
case EventType::EmergencyCall:
|
|
Q_ASSERT(false);
|
|
continue;
|
|
}
|
|
addEventType(eventType);
|
|
}
|
|
|
|
// populate Attribute Types - see /home/ref/TDS/src/Lts/Services/ExerciseEventManagement/eem_service.xml:52
|
|
/*
|
|
* retrieved as of 2017-09-04
|
|
*
|
|
*
|
|
* FireEvent:
|
|
* GearId
|
|
* GearTypeId
|
|
* ChargeTypeId
|
|
* Remain
|
|
*
|
|
* WeaponAssignment:
|
|
* GearId
|
|
* GearTypeId
|
|
* DryFire
|
|
*
|
|
* Manipulation: => show bite window
|
|
* DeviceType
|
|
* BiteMessage
|
|
* BatteryState
|
|
* BiteState
|
|
* ConfigState
|
|
* JsonArray BiteErrors:
|
|
* ErrorNo
|
|
* CanDeviceNumber
|
|
* SubDeviceNumber
|
|
* UniqueId
|
|
*
|
|
* HitBuilding:
|
|
* ChargetTypeId
|
|
* damagePercent
|
|
* damagePercentOld
|
|
* AesId
|
|
* VunerabilityState
|
|
* OriginatorParticipantId
|
|
* MainStructureElementId
|
|
*
|
|
*
|
|
* >>> Ab hier bin ich mir nicht mehr Sicher, was genau im Comment gemeint ist...
|
|
* HitIndrect:
|
|
* HitMine:
|
|
* HitN:
|
|
* HitC:
|
|
* EnterDangerArea:
|
|
* LeaveDangerArea:
|
|
* CES:
|
|
* AesId
|
|
* FriendlyFire
|
|
*/
|
|
|
|
/* Jedes Attribute benoetigt einen Interpreter Typen. Ein Interpreter Typ sagt dem Interpreter, wie er den Wert eines Attributs auf den Filter anwenden kann. Hier als Beispiel:
|
|
* "OriginatorChargeTypeId" ist ein Attribut, welches bloß eine Value ID zurueckgibt. D.h. id:9000 (wird dann später einem lesbaren Wert zugeordnet: z.B: "30mm Irgendwas")
|
|
* SOll der Wert im Filter also verglichen werden, muessen hier die IDs verglichen werden. Id 9000 => Id 9000.
|
|
* Hier ist also folgender Interpreter korrekt: INTERPRETER_TYPE_ID_COMPARE
|
|
*
|
|
* Anderes Beispiel:
|
|
* Zeit. Wird als Filter eine Zeit zwischen X und Y angegeben, muss geschaut werden, ob die Zeit Z sich zwischen X und Y befindet. Mit "INTERPRETER_TYPE_ID_COMPARE" wuerde das
|
|
* nicht funktionieren, da sonst nur EINE Zeit (naemlich genau Zeitpunkt Z) beim Interpreter korrekt ist. Fuer diesen Fall gibt es "INTERPRETER_TYPE_RANGE".
|
|
* Dieser Interpreter prueft, ob etwas in der Range zwischen X und Y ist.
|
|
*/
|
|
|
|
// AttributeUiTypeLookup: Wie wird das Attribut angezeigt? Bei einer Liste aus Einträgen: COmboBox, oder wenn z.B. es nur 2 Zustände gib: FriendlyFire => Yes / No => CheckBox
|
|
|
|
addAttributeType(QStringLiteral("TimeRange"), tr("Time range:"), ATTRIBUTE_UI_TYPE_TIME_RANGE_WIDGET /* TODO: none! */, INTERPRETER_TYPE_TIME); // is added in getDetailData as dummy so that the filter has a value to filter with TimeRange
|
|
|
|
|
|
// Vulnerability State:
|
|
addAttributeType(QStringLiteral("VulnerabilityState"), tr("Vulnerability State:"));
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::CombatReady);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::LightDamage);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::MediumDamage);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::HeavyDamage);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::MobilityKill);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::VisibleMobilityKill);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::WeaponSystemDamage);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::VisibleWeaponSystemDamage);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::CatastrophicKill);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::TemporarySeverance);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::NearMiss);
|
|
addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::HitWithNoEffect);
|
|
//addAttributeValue(QStringLiteral("VulnerabilityState"), ProjectDataManagement::VulnerabilityState::NotReady);
|
|
|
|
|
|
// Marker Types:
|
|
addAttributeTypeWithYesAndNo(QStringLiteral("IsSituationType"), tr("Is situation type:"));
|
|
addAttributeTypeWithYesAndNo(QStringLiteral("IsVideoType"), tr("Is video type:"));
|
|
addAttributeTypeWithYesAndNo(QStringLiteral("IsAudioType"), tr("Is audio type:"));
|
|
|
|
|
|
// AES Types:
|
|
// addRedirectedAttributeType(QStringLiteral("AesId"), tr("Aes Type:"), QStringLiteral("AesType")); // because the result type is Aes Type (but has to be resolved by looking at the AES behind the AesId
|
|
addAttributeType(QStringLiteral("AesType"), tr("Aes Type:"));
|
|
|
|
//addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtUnknown);
|
|
addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtNContamination);
|
|
addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtBCContamination);
|
|
addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtExplosionArea);
|
|
addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtExplosionSingle);
|
|
addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtMineArea);
|
|
addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtDangerArea);
|
|
addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtFunctionalArea);
|
|
addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtMineCorridor);
|
|
addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtBorderline);
|
|
//addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtTechnicalArea);
|
|
//addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtExplosionAreaSingleExplosions);
|
|
addAttributeValue(QStringLiteral("AesType"), AreaEffectSimulation::AesType::AtMineAreaSingleMines);
|
|
|
|
|
|
// Friendly Fire
|
|
addAttributeTypeWithYesAndNo(QStringLiteral("FriendlyFire"), tr("Friendly Fire:"));
|
|
|
|
// Attribute: Dry Fire
|
|
addAttributeTypeWithYesAndNo(QStringLiteral("DryFire"), tr("Dry Fire:"));
|
|
|
|
|
|
|
|
|
|
// non-filterables:
|
|
addAttributeType(QStringLiteral("MarkerName"), tr("Name:"), ATTRIBUTE_UI_TYPE_CHECKBOX /* TODO: FIXME: none! */, INTERPRETER_TYPE_NONE);
|
|
addAttributeType(QStringLiteral("MarkerNote"), tr("Note:"), ATTRIBUTE_UI_TYPE_CHECKBOX /* TODO: FIXME: none! */, INTERPRETER_TYPE_NONE);
|
|
|
|
|
|
// TODO:
|
|
//(QStringLiteral("Remain"), tr("Remain:")); was ist "remain" ?
|
|
|
|
|
|
// Marker offset:
|
|
addAttributeType(QStringLiteral("MarkerOffset"), tr("Offset [msecs]:"), ATTRIBUTE_UI_TYPE_DEFAULT_RANGE_WIDGET /* 0 - x */, INTERPRETER_TYPE_RANGE);
|
|
{
|
|
DetailData::AttributeParameterLookup::ParameterMap pm;
|
|
pm.insert(DetailData::UI_PARAM_TYPE_MIN, QVariant::fromValue<unsigned int>(0));
|
|
pm.insert(DetailData::UI_PARAM_TYPE_MAX, QVariant::fromValue<unsigned int>(9999999));
|
|
pm.insert(DetailData::UI_PARAM_TYPE_SUFFIX, QVariant::fromValue<QString>(QString()));
|
|
pm.insert(DetailData::UI_PARAM_TYPE_PREFIX, QVariant::fromValue<QString>(QString()));
|
|
attributeParameterLookup.addParameter(QStringLiteral("MarkerOffset"), pm);
|
|
}
|
|
|
|
|
|
// Duration:
|
|
addAttributeType(QStringLiteral("duration"), tr("Duration [msecs]:"), ATTRIBUTE_UI_TYPE_DEFAULT_RANGE_WIDGET /* 0 - x */, INTERPRETER_TYPE_RANGE);
|
|
{
|
|
DetailData::AttributeParameterLookup::ParameterMap pm;
|
|
pm.insert(DetailData::UI_PARAM_TYPE_MIN, QVariant::fromValue<unsigned int>(0));
|
|
pm.insert(DetailData::UI_PARAM_TYPE_MAX, QVariant::fromValue<unsigned int>(99999999));
|
|
pm.insert(DetailData::UI_PARAM_TYPE_SUFFIX, QVariant::fromValue<QString>(QString()));
|
|
pm.insert(DetailData::UI_PARAM_TYPE_PREFIX, QVariant::fromValue<QString>(QString()));
|
|
attributeParameterLookup.addParameter(QStringLiteral("duration"), pm);
|
|
}
|
|
|
|
|
|
// Damage:
|
|
addAttributeType(QStringLiteral("damagePercent"), tr("Damage [%]:"), ATTRIBUTE_UI_TYPE_DEFAULT_RANGE_WIDGET /* 0 - 100 */, INTERPRETER_TYPE_RANGE);
|
|
addRedirectedAttributeType(QStringLiteral("damagePercentOld"), tr("Damage before [%]:"), QStringLiteral("damagePercent"));
|
|
|
|
{
|
|
DetailData::AttributeParameterLookup::ParameterMap pm;
|
|
pm.insert(DetailData::UI_PARAM_TYPE_MIN, QVariant::fromValue<unsigned int>(0));
|
|
pm.insert(DetailData::UI_PARAM_TYPE_MAX, QVariant::fromValue<unsigned int>(100));
|
|
pm.insert(DetailData::UI_PARAM_TYPE_SUFFIX, QVariant::fromValue<QString>(tr(" %")));
|
|
pm.insert(DetailData::UI_PARAM_TYPE_PREFIX, QVariant::fromValue<QString>(QString()));
|
|
attributeParameterLookup.addParameter(QStringLiteral("damagePercent"), pm); // only for filters (event filter), so only filtereable attributes like MUNITION_LEFT_BETWEEN (not MUNITION_LEFT!)
|
|
}
|
|
|
|
// Equipment Numbers: (Achtung! Uebersetzt nur direkt eqid zu eqid !)
|
|
std::shared_ptr<ParticipantManagement::Interface::Dtc> dtcPpm;
|
|
m_session->getDtc<ParticipantManagement::DataInterface>(dtcPpm);
|
|
addAttributeType(QStringLiteral("EquipmentNumber"), tr("Equip. No.:"));
|
|
m_attributeValueLookupDtc.addHandlerForDtc(QStringLiteral("EquipmentNumber"), new AvmEquipmentNumber(dtcPpm));
|
|
addRedirectedAttributeType(QStringLiteral("OriginatorEquipmentNumber"), tr("Equip. No. of Originator:"), QStringLiteral("EquipmentNumber"));
|
|
|
|
std::shared_ptr<ProjectDataManagement::Interface::Dtc> dtcPdm;
|
|
m_session->getDtc<ProjectDataManagement::DataInterface>(dtcPdm);
|
|
// Charge Types:
|
|
addAttributeType(QStringLiteral("ChargeTypeId"), tr("Charge Type:")); // Achtung: OriginatorChargeTypeId wird auf den Generellen Typ "ChargeTypeId" weitergeleitet, daher muss nur der Interpreter Type des Haupt-Typen gesetzt werden!
|
|
addRedirectedAttributeType(QStringLiteral("OriginatorChargeTypeId"), tr("Originator Charge Type:"), QStringLiteral("ChargeTypeId"));
|
|
m_attributeValueLookupDtc.addHandlerForDtc(QStringLiteral("ChargeTypeId"), new AvmChargeType(dtcPdm));
|
|
|
|
// Gear Types:
|
|
addAttributeType(QStringLiteral("GearTypeId"), tr("Gear Type:"));
|
|
m_attributeValueLookupDtc.addHandlerForDtc(QStringLiteral("GearTypeId"), new AvmGearType(dtcPdm));
|
|
|
|
// Originator Types:
|
|
addAttributeType(QStringLiteral("OriginatorType"), tr("Originator Type:"));
|
|
addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::Unknown);
|
|
addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::Participant);
|
|
addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::AreaEffectSimulation);
|
|
addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::ObserverController);
|
|
addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::ExerciseControl);
|
|
//addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::WoundTreatmentDevice);
|
|
//addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::MaintainanceDevice);
|
|
addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::FunctionalArea);
|
|
addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::Initialization);
|
|
addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::ImprovisedExplosiveDevice);
|
|
addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::DusMine);
|
|
const bool showPvSan = LtsUtils::ProjectSettings::isFunctionEnabled(QStringLiteral("ParticipantInformation"),
|
|
QStringLiteral("HasPvSan"));
|
|
if (showPvSan)
|
|
addAttributeValue(QStringLiteral("OriginatorType"), ProjectDataManagement::StateChangeOriginator::Sanitation);
|
|
|
|
|
|
// (ISM) Structure Elements:
|
|
std::shared_ptr<InfrastructureManagement::Interface::Dtc> dtcIsm;
|
|
m_session->getDtc<InfrastructureManagement::DataInterface>(dtcIsm);
|
|
addAttributeType(QStringLiteral("MainStructureElementId"), tr("Building:"));
|
|
m_attributeValueLookupDtc.addHandlerForDtc(QStringLiteral("MainStructureElementId"), new AvmBuilding(dtcIsm));
|
|
|
|
// (PPM) Parties
|
|
addAttributeType(QStringLiteral("PartyId"), tr("Party:"));
|
|
m_attributeValueLookupDtc.addHandlerForDtc(QStringLiteral("PartyId"), new AvmParty(dtcPpm));
|
|
|
|
// (OPM) Operator Management:
|
|
std::shared_ptr<OperatorManagement::Interface::Dtc> dtcOpm;
|
|
m_session->getDtc<OperatorManagement::DataInterface>(dtcOpm);
|
|
addAttributeType(QStringLiteral("Operator"), tr("Operator:"));
|
|
m_attributeValueLookupDtc.addHandlerForDtc(QStringLiteral("Operator"), new AvmOperator(dtcOpm));
|
|
|
|
|
|
// (AVM) Streams
|
|
std::shared_ptr<AudioVideoManagement::Interface::Dtc> dtcAvm;
|
|
m_session->getDtc<AudioVideoManagement::DataInterface>(dtcAvm);
|
|
addAttributeType(QStringLiteral("streamName"), tr("Stream Name:"));
|
|
m_attributeValueLookupDtc.addHandlerForDtc(QStringLiteral("streamName"), new AvmStreamName(dtcAvm));
|
|
}
|
|
|
|
DetailData::GetDetailDataResultList DetailData::getDetailData(const LtsTimelineClassic::Event *event)
|
|
{
|
|
GetDetailDataResultList result;
|
|
|
|
if (event->detailData().isEmpty()) // no detail data so search in
|
|
return result;
|
|
|
|
const QJsonObject &root = event->detailData();
|
|
for (auto i = root.constBegin(); i != root.constEnd(); ++i)
|
|
{
|
|
DEBUG_LOG(m_logger) << "Adding Detail Data for: " << i.key();
|
|
result.append(getDetailDataForAttribute(i.key(), *i));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
DetailData::GetDetailDataForAttributeResult DetailData::getDetailDataForAttribute(const LtsTimelineClassic::Event *event, const QString &attributeType)
|
|
{
|
|
GetDetailDataForAttributeResult result;
|
|
|
|
const QJsonObject &root = event->detailData();
|
|
root[QStringLiteral("TimeRange")] = event->startTime() / 1000 /* as value would be too big for int => see getDetailDataForAttribute(..) */; // event time as temporary detail data
|
|
root[QStringLiteral("PartyId")] = event->partyId();
|
|
|
|
const QJsonValue attribute = root[attributeType];
|
|
|
|
if (attribute.isNull() || attribute.isUndefined())
|
|
{
|
|
WARNING_LOG(m_logger) << "DetailData::getDetailDataForAttribute: no attribute type " << attributeType
|
|
<< " in " << QJsonDocument(root).toJson();
|
|
|
|
result.requestResult = DetailData::RequestResult::InvalidAttributeType;
|
|
return result;
|
|
}
|
|
|
|
return getDetailDataForAttribute(attributeType, attribute);
|
|
}
|
|
|
|
|
|
DetailData::GetDetailDataForAttributeResult DetailData::getDetailDataForAttribute(const QString &attributeType, const QJsonValue &attributeValueJson)
|
|
{
|
|
GetDetailDataForAttributeResult result;
|
|
result.attributeTypeId = attributeType;
|
|
result.attributeValueId = -1;
|
|
result.requestResult = DetailData::RequestResult::Error;
|
|
QString attributeTypeTranslated = attributeTypeLookup.getAttributeText(attributeType);
|
|
|
|
if (attributeTypeTranslated.isEmpty())
|
|
{
|
|
result.requestResult = DetailData::RequestResult::InvalidAttributeType;
|
|
//ERROR_LOG(m_logger) << "getDetailDataForAttribute: Invalid Attribute Type for " << attributeType;
|
|
return result;
|
|
}
|
|
|
|
result.attributeType = attributeTypeTranslated;
|
|
|
|
int attributeValueId = -1;
|
|
|
|
/*
|
|
enum Type
|
|
{
|
|
Null = 0x0,
|
|
Bool = 0x1,
|
|
Double = 0x2,
|
|
String = 0x3,
|
|
Array = 0x4,
|
|
Object = 0x5,
|
|
Undefined = 0x80
|
|
};
|
|
*/
|
|
|
|
switch (attributeValueJson.type())
|
|
{
|
|
// sorted by frequency of occurrence
|
|
case QJsonValue::Double:
|
|
{
|
|
attributeValueId = attributeValueJson.toInt(-1);
|
|
break;
|
|
}
|
|
|
|
case QJsonValue::Null:
|
|
case QJsonValue::Undefined:
|
|
{
|
|
WARNING_LOG(m_logger) << "Timeline: DetailData::getDetailDataForAttribute: attribute value is null or undefined! " << attributeValueJson.toString();
|
|
result.requestResult = DetailData::RequestResult::InvalidAttributeTypeJson;
|
|
return result;
|
|
}
|
|
|
|
case QJsonValue::Bool:
|
|
{
|
|
attributeValueId = attributeValueJson.toBool() ? 1 : 0;
|
|
break;
|
|
}
|
|
|
|
case QJsonValue::String:
|
|
{
|
|
bool k = false;
|
|
QString attributeValueString = attributeValueJson.toString();
|
|
|
|
if (attributeValueString.isEmpty())
|
|
{
|
|
attributeValueId = -1;
|
|
break;
|
|
}
|
|
|
|
attributeValueId = attributeValueString.toInt(&k);
|
|
|
|
if (!k) // not a number but treat as text... NOTE: has no id
|
|
{
|
|
result.attributeValue = attributeValueString;
|
|
result.requestResult = DetailData::RequestResult::Okay;
|
|
return result;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
WARNING_LOG(m_logger) << "Timeline: DetailData::getDetailDataForAttribute: attribute value cannot be handled. Type " << attributeValueJson.type() << attributeValueJson.toString();
|
|
result.requestResult = DetailData::RequestResult::InvalidAttributeType;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
if (attributeValueId == -1)
|
|
{
|
|
result.requestResult = DetailData::RequestResult::InvalidAttributeType;
|
|
return result;
|
|
}
|
|
|
|
result.attributeValueId = attributeValueId;
|
|
|
|
|
|
// there are values that do not have to be translated:
|
|
int attributeUiType = attributeUITypeLookup.getUIType(attributeType);
|
|
switch (attributeUiType)
|
|
{
|
|
// do not translate
|
|
case ATTRIBUTE_UI_TYPE_TIME_RANGE_WIDGET:
|
|
case ATTRIBUTE_UI_TYPE_DEFAULT_RANGE_WIDGET:
|
|
case ATTRIBUTE_UI_TYPE_RAD_RANGE_WIDGET:
|
|
case ATTRIBUTE_UI_TYPE_AREA_RANGE_WIDGET:
|
|
{
|
|
result.attributeValue = QString::number(attributeValueId); // use "id" as "translated" string
|
|
result.requestResult = DetailData::RequestResult::Okay;
|
|
|
|
break;
|
|
}
|
|
|
|
// translate
|
|
case ATTRIBUTE_UI_TYPE_COMBO_BOX:
|
|
case ATTRIBUTE_UI_TYPE_CHECKBOX:
|
|
{
|
|
result.attributeValue = attributeValueLookup.getValueStringFromValueId(attributeType, attributeValueId);
|
|
if (result.attributeValue.isEmpty())
|
|
result.attributeValue = m_attributeValueLookupDtc.getValueStringFromValueId(attributeType, attributeValueId);
|
|
result.requestResult = DetailData::RequestResult::Okay;
|
|
break;
|
|
}
|
|
|
|
|
|
default: // -1
|
|
{
|
|
// maybe the type was redirected?
|
|
QString concreteAttributeType = attributeRedirectionLookup.getRedirection(attributeType);
|
|
|
|
if (concreteAttributeType == attributeType) // it was not redirected - give up!
|
|
{
|
|
ERROR_LOG(m_logger) << "getDetailDataForAttribute: attribute type " << attributeType << " does not have an UiType !!!";
|
|
result.requestResult = DetailData::RequestResult::NoUiTypeForAttribute;
|
|
}
|
|
else // there is a redirection, try this method with the redirection
|
|
{
|
|
//qWarning() << "trying redirection for attribute type" << attributeType;
|
|
|
|
// save some results, as getDetailDataForAttribute will set ALL the results for the redirection, instead of ONLY the value..
|
|
QString attributeType = result.attributeType;
|
|
QString attributeTypeId = result.attributeTypeId;
|
|
|
|
result = getDetailDataForAttribute(concreteAttributeType, attributeValueJson);
|
|
|
|
result.attributeType = attributeType;
|
|
result.attributeTypeId = attributeTypeId;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
void DetailData::createRetrieveCurrentTimeCallback(LtsWidgets::LtsDateTimeEdit *dateTimeEdit)
|
|
{
|
|
dateTimeEdit->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
|
|
}
|
|
|
|
|
|
// LOOKUP BASE
|
|
DetailData::LookupBase::LookupBase(const QString &lookupClassName)
|
|
: m_lookupClassName(lookupClassName)
|
|
, m_logger(getLogger(QStringLiteral("DetailData.") + lookupClassName))
|
|
{
|
|
|
|
}
|
|
|
|
|
|
// EVENT TYPE LOOKUP
|
|
DetailData::EventTypeLookup::EventTypeLookup()
|
|
: LookupBase(QStringLiteral("EventTypeLookup"))
|
|
{
|
|
}
|
|
|
|
void DetailData::EventTypeLookup::addEventType(const int key, const QString &value)
|
|
{
|
|
m_eventTypeMap.insert(key, value);
|
|
}
|
|
|
|
int DetailData::EventTypeLookup::getEventType(const QString &eventText) const
|
|
{
|
|
// as eventText is simplified, method 'key' would not work
|
|
|
|
const QString paramText = removeSpaces(eventText);
|
|
for (auto i = m_eventTypeMap.constBegin(); i != m_eventTypeMap.constEnd(); ++i)
|
|
{
|
|
const QString mapText = removeSpaces(i.value());
|
|
if (mapText == paramText)
|
|
return i.key();
|
|
}
|
|
|
|
return -1; // -1 = invalid !
|
|
}
|
|
|
|
QString DetailData::EventTypeLookup::getEventText(const int eventType) const
|
|
{
|
|
return m_eventTypeMap.value(eventType);
|
|
}
|
|
|
|
bool DetailData::EventTypeLookup::isEventExists(const int eventType) const
|
|
{
|
|
return m_eventTypeMap.contains(eventType);
|
|
}
|
|
|
|
QStringList DetailData::EventTypeLookup::getEventTexts() const
|
|
{
|
|
return m_eventTypeMap.values();
|
|
}
|
|
|
|
|
|
|
|
// ATTRIBUTE EVENT LOOKUP
|
|
DetailData::AttributeEventLookup::AttributeEventLookup()
|
|
: LookupBase(QStringLiteral("AttributeEventLookup"))
|
|
{
|
|
}
|
|
|
|
void DetailData::AttributeEventLookup::addAttributesToEvent(const int eventType, const AttributeList &attributeTypeList)
|
|
{
|
|
AttributeList &al = m_attributeEventLookupMap[eventType];
|
|
al += attributeTypeList;
|
|
}
|
|
|
|
void DetailData::AttributeEventLookup::addAttributesToEvent(const ProjectDataManagement::EventType &eventType, const AttributeList &attributeTypeList)
|
|
{
|
|
addAttributesToEvent(eventType.underlying(), attributeTypeList);
|
|
}
|
|
|
|
bool DetailData::AttributeEventLookup::isAttributeInEvent(const int eventType, const QString &attributeType)
|
|
{
|
|
auto eventTypeIt = m_attributeEventLookupMap.constFind(eventType);
|
|
|
|
if (eventTypeIt == m_attributeEventLookupMap.constEnd())
|
|
return false; // event does not even exist
|
|
|
|
const AttributeList &attributeList = *eventTypeIt;
|
|
|
|
if (attributeList.contains(attributeType))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
DetailData::AttributeEventLookup::AttributeList DetailData::AttributeEventLookup::getEventsAttributeList(const int eventType) const // get all attribute types from the event
|
|
{
|
|
return m_attributeEventLookupMap.value(eventType);
|
|
}
|
|
|
|
|
|
|
|
// ATTRIBUTE TEXT LOOKUP
|
|
DetailData::AttributeTypeLookup::AttributeTypeLookup()
|
|
: LookupBase(QStringLiteral("AttributeTypeLookup"))
|
|
{
|
|
}
|
|
|
|
void DetailData::AttributeTypeLookup::addAttributeText(const QString &attributeType, const QString &attributeText)
|
|
{
|
|
m_attributeTypeLookupMap.insert(attributeType, attributeText);
|
|
}
|
|
|
|
QString DetailData::AttributeTypeLookup::getAttributeType(const QString &attributeText) const
|
|
{
|
|
const QString paramText = removeSpaces(attributeText);
|
|
// as eventText is simplified, method 'key' would not work
|
|
for (auto i = m_attributeTypeLookupMap.constBegin(); i != m_attributeTypeLookupMap.constEnd(); ++i)
|
|
{
|
|
const QString mapText = removeSpaces(i.value());
|
|
if (mapText == paramText)
|
|
return i.key();
|
|
}
|
|
|
|
WARNING_LOG(m_logger) << "getAttributeType: attribute type not found by text '" << attributeText << "'";
|
|
return QString(); // invalid
|
|
}
|
|
|
|
DetailData::AttributeTypeLookup::AttributeTypeList DetailData::AttributeTypeLookup::getAttributeTypes() const
|
|
{
|
|
return m_attributeTypeLookupMap.keys();
|
|
}
|
|
|
|
QString DetailData::AttributeTypeLookup::getAttributeText(const QString &attributeType, const QString &defaultReturnValue) const
|
|
{
|
|
return m_attributeTypeLookupMap.value(attributeType, defaultReturnValue);
|
|
}
|
|
|
|
DetailData::AttributeTypeLookup::AttributeTextList DetailData::AttributeTypeLookup::getAttributeTexts() const
|
|
{
|
|
return m_attributeTypeLookupMap.values();
|
|
}
|
|
|
|
|
|
// ATTRIBUTE PARAMETER LOOKUP
|
|
DetailData::AttributeParameterLookup::AttributeParameterLookup()
|
|
: LookupBase(QStringLiteral("AttributeParameterLookup"))
|
|
{
|
|
}
|
|
|
|
void DetailData::AttributeParameterLookup::addParameter(const QString &attributeType, const ParameterMap ¶meterMap)
|
|
{
|
|
if (!parameterMap.count())
|
|
{
|
|
WARNING_LOG(m_logger) << "addParameter: parameter map is empty!";
|
|
return;
|
|
}
|
|
|
|
m_attributeParameterMap.insert(attributeType, parameterMap);
|
|
}
|
|
|
|
DetailData::AttributeParameterLookup::ParameterMap DetailData::AttributeParameterLookup::getParameterMap(const QString &attributeType) const
|
|
{
|
|
return m_attributeParameterMap.value(attributeType);
|
|
}
|
|
|
|
QVariant DetailData::AttributeParameterLookup::getParameterValue(const QString &attributeType, const int parameterType) const
|
|
{
|
|
const ParameterMap &pm = getParameterMap(attributeType);
|
|
|
|
auto pmci = pm.constFind(parameterType);
|
|
|
|
if (pmci == pm.constEnd()) // exists? FIXME: in NGLDAO Timeline: "!=" !!
|
|
return QVariant();
|
|
|
|
return *pmci;
|
|
}
|
|
|
|
|
|
|
|
// ATTRIBUTE UI TYPE
|
|
DetailData::AttributeUITypeLookup::AttributeUITypeLookup()
|
|
: LookupBase(QStringLiteral("AttributeUITypeLookup"))
|
|
{
|
|
}
|
|
|
|
void DetailData::AttributeUITypeLookup::addUITypeToAttribute(const QString &attributeType, const int uiType)
|
|
{
|
|
m_attributeUITypeLookupMap.insert(attributeType, uiType);
|
|
}
|
|
|
|
int DetailData::AttributeUITypeLookup::getUIType(const QString &attributeType) const
|
|
{
|
|
return m_attributeUITypeLookupMap.value(attributeType, -1); // -1 = invalid
|
|
}
|
|
|
|
|
|
// INTERPRETER LOOKUP
|
|
DetailData::AttributeInterpreterLookup::AttributeInterpreterLookup()
|
|
: LookupBase(QStringLiteral("AttributeInterpreterLookup"))
|
|
{
|
|
}
|
|
|
|
void DetailData::AttributeInterpreterLookup::addInterpreterTypeToAttribute(const QString &attributeType, const int interpreterType)
|
|
{
|
|
m_attributeInterpreterLookupMap.insert(attributeType, interpreterType);
|
|
}
|
|
|
|
int DetailData::AttributeInterpreterLookup::getInterpreterType(const QString &attributeType) const
|
|
{
|
|
return m_attributeInterpreterLookupMap.value(attributeType);
|
|
}
|
|
|
|
|
|
|
|
// ATTRIBUTE VALUE LOOKUP
|
|
DetailData::AttributeValueLookup::AttributeValueLookup()
|
|
: LookupBase(QStringLiteral("AttributeValueLookup"))
|
|
{
|
|
}
|
|
|
|
|
|
void DetailData::AttributeValueLookup::removeValueFromAttributeValueMap(const QString &attributeType, const int valueKey)
|
|
{
|
|
auto attributeTypeValueMapIt = m_attributeTypeValueMap.find(attributeType);
|
|
|
|
if (attributeTypeValueMapIt == m_attributeTypeValueMap.end()) // there are currently no values for this attribute type, insert all new values
|
|
return; // attribute type not even found!
|
|
|
|
AttributeValueMap ¤tAttributeValueMap = *attributeTypeValueMapIt;
|
|
currentAttributeValueMap.remove(valueKey);
|
|
}
|
|
|
|
|
|
void DetailData::AttributeValueLookup::addValueToAttributeValueMap(const QString &attributeType, const int valueKey, const QString &valueValue)
|
|
{
|
|
AttributeValueMap &avm = m_attributeTypeValueMap[attributeType];
|
|
avm.insert(valueKey, valueValue);
|
|
}
|
|
|
|
|
|
void DetailData::AttributeValueLookup::addValuesToAttributeValueMap(const QString &attributeType, const AttributeValueMap &avm) // add a VALUE (consisting of id & string) to the map coresponding to the attribute type
|
|
{
|
|
AttributeValueMap &thisAvm = m_attributeTypeValueMap[attributeType];
|
|
for (auto i = avm.constBegin(); i != avm.constEnd(); ++i)
|
|
{
|
|
thisAvm.insert(i.key(), i.value());
|
|
}
|
|
}
|
|
|
|
AttributeValueMap DetailData::AttributeValueLookup::getAttributeValueMap(const QString &attributeType) const
|
|
{
|
|
return m_attributeTypeValueMap.value(attributeType);
|
|
}
|
|
|
|
QString DetailData::AttributeValueLookup::getValueStringFromValueId(const QString &attributeType, const int attributeValueId, const QString& defaultValue) const
|
|
{
|
|
return getAttributeValueMap(attributeType).value(attributeValueId, defaultValue);
|
|
}
|
|
|
|
void DetailData::AttributeValueLookup::clear()
|
|
{
|
|
m_attributeTypeValueMap.clear();
|
|
}
|
|
|
|
|
|
// ATTRIBUTE REDIRECTION LOOKUP
|
|
DetailData::AttributeRedirectionLookup::AttributeRedirectionLookup()
|
|
: LookupBase(QStringLiteral("AttributeRedirectionLookup"))
|
|
{
|
|
}
|
|
|
|
void DetailData::AttributeRedirectionLookup::addRedirection(const QString &attributeType, const QString &redirectTo)
|
|
{
|
|
m_attributeRedirectionMap.insert(attributeType, redirectTo);
|
|
}
|
|
|
|
QString DetailData::AttributeRedirectionLookup::getRedirection(const QString &attributeType) const
|
|
{
|
|
auto it = m_attributeRedirectionMap.find(attributeType);
|
|
if (it == m_attributeRedirectionMap.end())
|
|
return attributeType;
|
|
return it.value();
|
|
}
|
|
|
|
|
|
} // namespace Timeline
|