Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,928 @@
/**
* @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 &parameterMap)
{
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 &currentAttributeValueMap = *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