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>
This commit is contained in:
torstenandCopilot committed 2026-09-15 18:20:51 +00:00
1 parent c9e245a211
commit 3028302f7b
310 files changed
+2823 -740

No files matched your search

@@ -470,6 +470,8 @@ void ExplosionsEditAdler::onEffectClusterChanged(const EffectCluster &ecData, Da
m_ui->pbStateChange->setEnabled(false);
m_ui->gbEffectMarkingInTa->setEnabled(false);
}
__unchange__();
}
QPointF ExplosionsEditAdler::centerOfFiringUnitGeo(int particpantUnitId)
@@ -283,6 +283,15 @@ ExplosionsEditAdlerStandAlone::ExplosionsEditAdlerStandAlone(const QString &menu
if (enableRocket)
m_gearClassFilter += ProjectDataManagement::GearClass::Rocket;
m_uiRequirements->addRequirement({m_ui->lblPosition, [this]() { return (!m_coord.isNull()); }});
m_uiRequirements->addRequirement({m_ui->lblPosition_2, [this]() {
// Im Fall (Zielgeometrie == Linear) ist positionEdit_2 enabled. Ansonsten disabled.
// Daher: Wenn enabled, muss auch ein Wert enthalten sein.
// Andernfalls wird in apply() die cornerBottomLeft aufgrund fehlerhafter Werte berechnet.
// Die dabei resultierenden Werte haben bereits mal zu einem Absturz gefuehrt.
// LS-693 [Stand-Alone] Koordinatenberechnung Linear...
return (!m_ui->positionEdit_2->isEnabled()) || // Ok, wenn disabled
(!m_ui->positionEdit_2->coordinate().isNull()); } // oder coordinate not null
});
m_uiRequirements->addRequirement({m_ui->lblRadiusBreite, [this]() { return (m_ui->sbDimensionX_BreiteRadius->value() >= s_minWidth); }});
m_uiRequirements->addRequirement({m_ui->lblDimensionY_Tiefe, [this]() { return (m_ui->sbDimensionY_Tiefe->value() >= s_minHeight); }});
// m_uiRequirements->addRequirement({m_ui->lblName, [this]() { return (!m_ui->leElement->text().isEmpty()); }});
@@ -1669,6 +1678,13 @@ void ExplosionsEditAdlerStandAlone::onEffectClusterChanged(const EffectCluster &
if (m_aesItem.effectStateId() == AreaEffectSimulation::AesEffectState::EsCreated ||
m_aesItem.effectStateId() == AreaEffectSimulation::AesEffectState::EsPrepared)
enableUiElements(!unchangeable());
else if (m_aesItem.effectStateId() == AreaEffectSimulation::AesEffectState::EsExpired ||
m_aesItem.effectStateId() == AreaEffectSimulation::AesEffectState::EsFired ||
m_aesItem.effectStateId() == AreaEffectSimulation::AesEffectState::EsActivated)
{
if (hasUnsavedChanges())
__unchange__();
}
if(!unchangeable())
setFireBtnState();
@@ -2107,12 +2123,8 @@ bool ExplosionsEditAdlerStandAlone::apply()
if (m_ui->dteEffectStart->isChecked() && m_ui->dteEffectStart->isVisible())
{
const FiringType::type firingType = static_cast<FiringType::type>(m_ui->cbFiringType->currentData().toInt());
if (firingType != FiringType::FireWithIndicationTTF)
{
// we use the effect start as usual
request.effectStart().set(m_ui->dteEffectStart->msecsSinceEpoch());
}
// we use the effect start as usual
request.effectStart().set(m_ui->dteEffectStart->msecsSinceEpoch());
}
if (m_ui->sbDurationSec->isVisible())
request.effectDuration(m_ui->sbDurationSec->value() * 1000);
@@ -2293,13 +2305,16 @@ bool ExplosionsEditAdlerStandAlone::apply()
const QString properties = QString::fromUtf8(QJsonDocument(propertiesObj).toJson());
DEBUG_LOG(m_logger) << "properties: " << properties;
request.properties(properties.toStdString());
DEBUG_LOG(m_logger) << "request abschicken";
// Rocket-Spezifika:
const QVariant currentData = m_ui->cbGearClass->currentData();
const ProjectDataManagement::GearClass::type currentGearClass = static_cast<ProjectDataManagement::GearClass::type>(currentData.toInt());
if (currentGearClass == ProjectDataManagement::GearClass::Rocket)
{
RocketUtility::addRocketPropertiesToRequest(request, m_ppmDtc);
}
DEBUG_LOG(m_logger) << "request abschicken, request = '" << request << "'";
m_requestHelper->addRequest([this, request]() { return m_ftc->effectClusterModifyRequest(request, this); });
@@ -179,6 +179,7 @@ void addRocketPropertiesForLinearGeometry(EffectClusterModifyRequest &request, c
const double flightTimeStep = currentEffector.flightTime() / static_cast<double>(trajectoryWithoutTime.size());
double currentFlightTime = 0.0;
currentEffector.trajectoryRelative().clear(); // LS_711_akkumulierende_flugkurven_bei_rakete
const LtsCoordTrans::UtmCoordinate utmStartPos = LtsCoordTrans::UtmCoordinate::fromGeographic(participantPosition.pos().lon(), participantPosition.pos().lat());
for (const Core::GeoPosition &pos : trajectoryWithoutTime)
{
@@ -240,6 +241,7 @@ void addRocketPropertiesForPointGeometry(EffectClusterModifyRequest &request, co
const double flightTimeStep = currentEffector.flightTime() / static_cast<double>(trajectoryWithoutTime.size());
double currentFlightTime = 0.0;
currentEffector.trajectoryRelative().clear(); // LS_711_akkumulierende_flugkurven_bei_rakete
const LtsCoordTrans::UtmCoordinate utmStartPos = LtsCoordTrans::UtmCoordinate::fromGeographic(participantPosition.pos().lon(), participantPosition.pos().lat());
for (const Core::GeoPosition &pos : trajectoryWithoutTime)
{
@@ -250,7 +252,7 @@ void addRocketPropertiesForPointGeometry(EffectClusterModifyRequest &request, co
currentFlightTime += flightTimeStep;
}
}
} // for (EffectorData &currentEffector : request.effectors())
}
} // namespace RocketUtility
@@ -1,8 +1,8 @@
#include "flm_hq_report_converter.h"
#include <FileManagement/flm_data_plugin_interface.h>
#include <FileManagement/flm_ftc.h>
#include <FileManagement/flm_ftc_types.h>
#include <FileManagement/flm_data_plugin_interface.h>
#include <Symbology/sidc_builder_base.h>
#include <Symbology/sidc_codec.h>
@@ -11,20 +11,20 @@
#include <GeometryModel/geometry_model_factory.h>
#include <LtsUtilsCore/dds_vector.h>
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <LtsUtilsCore/dds_vector.h>
#include <ParticipantManagement/ppm_data_plugin_interface.h>
#include <AreaEffectSimulation/Utils/polygons.h>
#include <ParticipantManagement/ppm_data_plugin_interface.h>
namespace FileManagement
{
FlmHqReportConverter::FlmHqReportConverter() : m_logger(getLogger("HQReportConverter"))
FlmHqReportConverter::FlmHqReportConverter()
: m_logger(getLogger("HQReportConverter"))
{
connect(this, &FlmHqReportConverter::allRequestsFinished,
this, &FlmHqReportConverter::onRequestsFinished);
connect(this, &FlmHqReportConverter::allRequestsFinished, this, &FlmHqReportConverter::onRequestsFinished);
}
bool FlmHqReportConverter::init(LtsSession::LtsSession *session, int currentPartyId)
@@ -82,11 +82,20 @@ bool FlmHqReportConverter::init(LtsSession::LtsSession *session, int currentPart
return true;
}
void FlmHqReportConverter::addHqToPlanIds(const QMap<int, QList<int>> &hqToPlanIds)
void FlmHqReportConverter::addHqToPlanIds(const QMap<int, QSet<int>> &hqToPlanIds)
{
for (auto it = hqToPlanIds.constBegin(); it != hqToPlanIds.constEnd(); ++it)
{
m_hqToPlanIds[it.key()].append(it.value());
int planFileId = it.key();
const QSet<int> &hqMessageIds = it.value();
for (int id : hqMessageIds)
{
if (id == planFileId) // Eventueller Eintrag in Map wegen QTreeView verhindern
continue;
m_hqToPlanIds[planFileId].append(id);
}
}
}
@@ -94,15 +103,17 @@ void FlmHqReportConverter::processCollectedHqs()
{
for (auto it = m_hqToPlanIds.constBegin(); it != m_hqToPlanIds.constEnd(); ++it)
{
m_pendingRequests += it.value().size();
int planId = it.key();
for (int id : it.value())
m_pendingRequests++;
}
for (auto it = m_hqToPlanIds.constBegin(); it != m_hqToPlanIds.constEnd(); ++it)
{
int planId = it.key();
const QList<int> &reportIds = it.value();
// Request file content for each HqReport
for (int id : reportIds)
const QList<int> &hqMessageIds = it.value();
for (int id : hqMessageIds)
{
DEBUG_LOG(m_logger) << "Request File with ID: " << id << " from plan with ID: " << planId;
FileManagement::GetFileContentDataRequest request(id);
@@ -110,46 +121,21 @@ void FlmHqReportConverter::processCollectedHqs()
}
}
}
void FlmHqReportConverter::createGeometryFromReport(const HqReportData &data)
{
m_symbolFactory.build(data.art, data, m_geometryModel);
}
void FlmHqReportConverter::createGeometryFromReport(const HqReportData &data) { m_symbolFactory.build(data.art, data, m_geometryModel); }
void FlmHqReportConverter::checkIfAllFinished()
{
if (m_pendingRequests <= 0) emit allRequestsFinished();
if (m_pendingRequests <= 0)
emit allRequestsFinished();
}
void FlmHqReportConverter::onGetFileContentDataReply(
const FileManagement::GetFileContentDataReply &reply)
void FlmHqReportConverter::onGetFileContentDataReply(const FileManagement::GetFileContentDataReply &reply)
{
m_pendingRequests--;
if (reply.errorString().size() > 0)
{
ERROR_LOG(m_logger) << "Got onGetFileContentDataReply error: " << reply.errorString();
return;
}
int id = static_cast<int>(reply.id());
const int id = static_cast<int>(reply.id());
int planId = -1;
DEBUG_LOG(m_logger) << "Reply File with ID: " << id << " from plan with ID: " << planId;
INFO_LOG(m_logger) << "Got reply with id " << id << " and errorString " << reply.errorString();
QByteArray fileContent = QByteArray(reinterpret_cast<const char*>(reply.content().data()), reply.content().size());
FlmHqReportJsonParser m_parser = FlmHqReportJsonParser();
HqReportData data = m_parser.parse(fileContent);
data.contentFileId = id;
DEBUG_LOG(m_logger) << "Party: " << m_partyId << " has Color: "<< QColor::fromRgb(QRgb(m_ppmDtc->party(m_partyId).color())).value();
data.partyColor = QColor::fromRgb(QRgb(m_ppmDtc->party(m_partyId).color()));
for (auto it = m_hqToPlanIds.constBegin(); it != m_hqToPlanIds.constEnd(); ++it)
{
if (it.value().contains(id))
@@ -159,7 +145,24 @@ void FlmHqReportConverter::onGetFileContentDataReply(
}
}
m_convertedHqToPlanIds[planId].append(data);
DEBUG_LOG(m_logger) << "Reply File with ID: " << id << " from plan with ID: " << planId;
INFO_LOG(m_logger) << "Got reply with id " << id;
QByteArray fileContent = QByteArray::fromRawData(reinterpret_cast<const char *>(reply.content().data()), reply.content().size());
DEBUG_LOG(m_logger) << "fileContent: " << fileContent;
FileManagement::FileContent flc = m_flmDtc->fileContent(reply.id());
DEBUG_LOG(m_logger) << "FlmHqReportConverter::onGetFileContentDataReply FILECONTENTNAME: " << flc.name();
HqReportData data = m_parser.parse(fileContent);
data.contentFileId = id;
data.name = QString::fromStdString(flc.name());
data.partyColor = QColor::fromRgb(m_ppmDtc->party(m_partyId).color());
m_convertedHqToPlanIds[planId].append(std::move(data));
DEBUG_LOG(m_logger) << "Content size: " << reply.content().size();
@@ -171,10 +174,7 @@ void FlmHqReportConverter::onFileContentModifyReply(const Core::FunctionReplyObj
DEBUG_LOG(m_logger) << "Got FileContentModify Reply: " << reply.translated();
if (reply.error())
{
ERROR_LOG(m_logger) << "Error while insert HX Message: " << reply.translated()
<< ", error: " << reply.error();
}
ERROR_LOG(m_logger) << "Error while insert HX Message: " << reply.translated() << ", error: " << reply.error();
}
void FlmHqReportConverter::onFileContentRemoveReply(const Core::FunctionReplyObject &reply)
@@ -182,49 +182,83 @@ void FlmHqReportConverter::onFileContentRemoveReply(const Core::FunctionReplyObj
DEBUG_LOG(m_logger) << "Got FileContentRemove Reply: " << reply.translated();
if (reply.error())
{
ERROR_LOG(m_logger) << "Error while insert HX Message: " << reply.translated()
<< ", error: " << reply.error();
}
ERROR_LOG(m_logger) << "Error while insert HX Message: " << reply.translated() << ", error: " << reply.error();
}
void FlmHqReportConverter::onRequestsFinished()
{
DEBUG_LOG(m_logger) << "ALL REQUESTS FINISHED";
DEBUG_LOG(m_logger) << "ALL REQUESTS FINISHED -> STARTING CONTENT FETCH";
for (auto it = m_convertedHqToPlanIds.constBegin(); it != m_convertedHqToPlanIds.constEnd(); ++it)
{
int planId = it.key();
const QList<HqReportData> &reportDatas = it.value();
QList<HqReportData> reportDatas = it.value();
const FileManagement::FileContent flc = m_flmDtc->fileContent(planId);
FileManagement::GetFileContentDataRequest req;
req.fileContentId(planId);
for (auto &reportData : reportDatas)
{
DEBUG_LOG(m_logger) << "createGeometryFromReport :" << reportData.art;
createGeometryFromReport(reportData);
}
m_flmFtc->getFileContentDataRequest(req,
[this, planId, reportDatas = std::move(reportDatas), flc = std::move(flc)](const FileManagement::GetFileContentDataReply &reply)
{
const auto &fetchedFlc = reply;
if (fetchedFlc.content().size() > 0)
{
QByteArray existingContent
= QByteArray::fromRawData(reinterpret_cast<const char *>(fetchedFlc.content().data()), fetchedFlc.content().size());
const FileManagement::FileContent &flc = m_flmDtc->fileContent(planId);
if (!m_geometryModel->fromByteArray(existingContent))
WARNING_LOG(m_logger) << "Could not load existing geometry content for planId" << planId;
}
FileManagement::FileContentModifyRequest data;
QJsonArray jsonNameArray;
QJsonDocument existingDocs = QJsonDocument::fromJson(QByteArray::fromRawData(flc.properties().data(), flc.properties().size()));
DEBUG_LOG(m_logger) << "FILE CONTENT: " << flc.name() << " " << flc.folderId();
if (existingDocs.isArray())
jsonNameArray = existingDocs.array();
data.id(flc.id());
data.name(flc.name());
data.isTemplate(false);
data.isHidden(false);
data.folderId(flc.folderId());
data.fileStatus(FileManagement::FileStatus::Valid);
data.fileCategory(FileManagement::FileCategory::Exercise);
data.fileType(FileManagement::FileType::TacticalPlan);
data.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
data.lastModified(QDateTime::currentMSecsSinceEpoch());
data.content(LtsUtils::convert<std::vector<uint8_t>>(m_geometryModel->toByteArray()));
data.exerciseId(m_session->exerciseId());
for (const auto &reportData : reportDatas)
{
m_flmFtc->fileContentModifyRequest(data, this);
m_geometryModel->clearModel();
bool alreadyExists = false;
for (const QJsonValue &value : jsonNameArray)
{
if (value.toString() == reportData.name)
{
alreadyExists = true;
break;
}
}
if (!alreadyExists)
{
createGeometryFromReport(reportData);
jsonNameArray.append(reportData.name);
}
}
QJsonDocument jsonDoc(jsonNameArray);
QString combinedNames = QString::fromUtf8(jsonDoc.toJson(QJsonDocument::Compact));
FileManagement::FileContentModifyRequest data;
DEBUG_LOG(m_logger) << "FILE CONTENT: " << flc.name() << " " << flc.folderId();
data.id(flc.id());
data.name(flc.name());
data.isTemplate(false);
data.isHidden(false);
data.folderId(flc.folderId());
data.fileStatus(FileManagement::FileStatus::Valid);
data.fileCategory(FileManagement::FileCategory::Exercise);
data.fileType(FileManagement::FileType::TacticalPlan);
data.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
data.lastModified(QDateTime::currentMSecsSinceEpoch());
data.content(LtsUtils::convert<std::vector<uint8_t>>(m_geometryModel->toByteArray()));
data.exerciseId(m_session->exerciseId());
data.properties(combinedNames.toStdString());
m_flmFtc->fileContentModifyRequest(data, this);
m_geometryModel->clearModel();
});
}
}
} // namespace FileManagement
} // namespace FileManagement
@@ -16,15 +16,16 @@ namespace Interface
{
class Dtc;
class Ftc;
} // namespace Interface
} // namespace Interface
class FlmHqReportConverter : public QObject,
public Interface::Ftc::GetFileContentDataReplyHandler,
public Interface::Ftc::FileContentModifyReplyHandler,
public Interface::Ftc::FileContentRemoveReplyHandler
class FlmHqReportConverter
: public QObject
, public Interface::Ftc::GetFileContentDataReplyHandler
, public Interface::Ftc::FileContentModifyReplyHandler
, public Interface::Ftc::FileContentRemoveReplyHandler
{
Q_OBJECT
public:
public:
FlmHqReportConverter();
~FlmHqReportConverter() = default;
@@ -33,7 +34,7 @@ public:
* @brief add hqToPlanIds to m_hqToPlanIds
* @param const QMap<int, QList<int>> &hqToPlanIds -> <planId, QList<HqIds>>
*/
void addHqToPlanIds(const QMap<int, QList<int>> &hqToPlanIds);
void addHqToPlanIds(const QMap<int, QSet<int>> &hqToPlanIds);
/**
* @brief Iterate and send GetFileContentDataRequest to get File Information HQ
*/
@@ -44,27 +45,27 @@ public:
*/
void createGeometryFromReport(const HqReportData &data);
private:
private:
void checkIfAllFinished();
protected:
protected:
void onGetFileContentDataReply(const FileManagement::GetFileContentDataReply &reply) override;
void onFileContentModifyReply(const Core::FunctionReplyObject &reply) override;
void onFileContentRemoveReply(const Core::FunctionReplyObject &reply) override;
public slots:
public slots:
void onRequestsFinished();
signals:
signals:
/**
* @brief checks if all getFileContentDataRequests are finished
*/
void allRequestsFinished();
private:
private:
LOGGER_T m_logger;
LtsSession::LtsSession *m_session{nullptr};
std::shared_ptr<Interface::Dtc> m_flmDtc;
std::shared_ptr<Interface::Ftc> m_flmFtc;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
SituationMap::GeometryModel *m_geometryModel{nullptr};
QList<SituationMap::GeometryModel::Node> m_planNodes;
@@ -72,9 +73,9 @@ private:
int m_partyId;
int m_pendingRequests{0};
QMap<int, QList<int>> m_hqToPlanIds; /// Map<planIds, QList<HQMessageId>>
QMap<int, int> m_hqToPlanIdsLookup; /// Map<planIds, HQMessageId> for Lookup
QMap<int, QList<HqReportData>> m_convertedHqToPlanIds; /// Map<planIds, QList<convertedHqMessage>>
}; // class FlmHqReportConverter
} // namespace FileManagement
FlmHqReportJsonParser m_parser;
QMap<int, QList<int>> m_hqToPlanIds; /// Map<planIds, QList<HQMessageId>>
QMap<int, int> m_hqToPlanIdsLookup; /// Map<planIds, HQMessageId> for Lookup
QMap<int, QList<HqReportData>> m_convertedHqToPlanIds; /// Map<planIds, QList<convertedHqMessage>>
}; // class FlmHqReportConverter
} // namespace FileManagement
@@ -136,7 +136,7 @@ bool HQReportEdit::init(LtsSession::LtsSession *session, int partyId)
m_ui->listViewPlan->setDragDropMode(QAbstractItemView::DropOnly);
m_ui->listViewPlan->setDefaultDropAction(Qt::CopyAction);
m_ui->listViewPlan->setDropIndicatorShown(true);
m_ui->listViewPlan->setHeaderHidden(true);
// configure listViewMessage
m_ui->listViewMessage->setDragDropMode(QAbstractItemView::DragOnly);
m_ui->listViewMessage->setDefaultDropAction(Qt::CopyAction);
@@ -151,31 +151,6 @@ bool HQReportEdit::init(LtsSession::LtsSession *session, int partyId)
return false;
}
// init models
qDeleteAll(m_hqModels);
m_hqModels.clear();
qDeleteAll(m_planModels);
m_planModels.clear();
for (int index = 0; index < m_ui->cboParties->count(); ++index)
{
const int partyId = m_ui->cboParties->itemData(index).toInt();
createModels(partyId);
}
// configure listViewPlan
m_ui->listViewPlan->setDragDropMode(QAbstractItemView::DropOnly);
m_ui->listViewPlan->setDefaultDropAction(Qt::MoveAction);
m_ui->listViewPlan->setDropIndicatorShown(true);
// configure listViewMessage
m_ui->listViewMessage->setDragDropMode(QAbstractItemView::DragOnly);
m_ui->listViewMessage->setDefaultDropAction(Qt::MoveAction);
m_ui->listViewMessage->setDropIndicatorShown(true);
onPartyChanged();
connect(m_ui->cboParties, qOverload<int>(&QComboBox::currentIndexChanged), this, &HQReportEdit::onPartyChanged);
int partyIndex = m_ui->cboParties->findData(partyId); // in case of notification: onPartyChanged() is called when index changes
@@ -190,11 +165,16 @@ void HQReportEdit::createModels(const int partyId)
if (partyFolderId == 0)
{
WARNING_LOG(m_logger) << "No partyFolderId found for partyId " << partyId;
delete m_planModels.take(partyId);
delete m_hqModels.take(partyId);
return;
}
const int hqReportFolderId = m_flmDtc->findFolder(partyFolderId, QStringLiteral("Messages"));
delete m_planModels.take(partyId);
delete m_hqModels.take(partyId);
auto *planModel = new FlmHQReportModel(m_ui->listViewPlan);
if (!planModel->init(m_session, partyFolderId, FileType::inner_enum::TacticalPlan))
{
@@ -220,17 +200,15 @@ void HQReportEdit::createModels(const int partyId)
bool HQReportEdit::apply()
{
QMap<int, QList<int>> allHqToPlanIds;
QMap<int, QSet<int>> allHqToPlanIds;
for (auto it = m_planModels.begin(); it != m_planModels.end(); ++it)
{
QMap<int, QList<int>> hqToPlanIds = it.value()->getHQToPlan(); // <planId, hq-message ids>
QMap<int, QSet<int>> hqToPlanIds = it.value()->getChangedPlans(); // <planId, hq-message ids>
for (auto planId : hqToPlanIds.keys())
for (auto it = hqToPlanIds.constBegin(); it != hqToPlanIds.constEnd(); ++it)
{
allHqToPlanIds[planId].append(hqToPlanIds[planId]);
it.value()->clearMovedData();
allHqToPlanIds[it.key()] += it.value();
}
}
@@ -254,14 +232,10 @@ void HQReportEdit::retranslate() { translate(m_ui, tr("HQ Report")); }
void HQReportEdit::onPartyChanged(int index)
{
Q_UNUSED(index);
const int currentPartyId = m_ui->cboParties->currentData().toInt();
DEBUG_LOG(m_logger) << "onPartyChanged " << currentPartyId;
if (!m_planModels.contains(currentPartyId) || !m_hqModels.contains(currentPartyId))
{
INFO_LOG(m_logger) << "Models for party" << currentPartyId << "not found. Attempting to create...";
createModels(currentPartyId);
}
createModels(currentPartyId);
QAbstractItemModel *hqModel = m_hqModels.value(currentPartyId, nullptr);
QAbstractItemModel *planModel = m_planModels.value(currentPartyId, nullptr);
@@ -15,7 +15,7 @@
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="2">
<widget class="QListView" name="listViewPlan"/>
<widget class="QTreeView" name="listViewPlan"/>
</item>
<item row="2" column="2">
<widget class="QLabel" name="lblPlans">
@@ -1,14 +1,15 @@
#include "flm_hq_report_model.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <LtsSession/lts_session.h>
#include <Plugins/FileManagement/flm_data_plugin_interface.h>
namespace FileManagement
{
FlmHQReportModel::FlmHQReportModel(QObject *parent)
: QAbstractListModel(parent)
, m_logger(getLogger("HQReportModel"))
{
: QAbstractItemModel(parent)
, m_logger(getLogger("HQReportModel"))
{
}
bool FlmHQReportModel::init(LtsSession::LtsSession *session, int contentFolderId, const FileType &fileType)
@@ -32,7 +33,7 @@ bool FlmHQReportModel::init(LtsSession::LtsSession *session, int contentFolderId
m_flmDtc->enableFileContent();
m_flmDtc->waitForHistoricalDataFileContent(3000);
m_flmDtc->fileContents([this](const FileContent &content){onFileContentChanged(content, DataModification::eAdded);});
m_flmDtc->fileContents([this](const FileContent &content) { onFileContentChanged(content, DataModification::eAdded); });
connect(m_flmDtc.get(), &Interface::Dtc::fileContentChanged, this, &FlmHQReportModel::onFileContentChanged);
@@ -41,25 +42,74 @@ bool FlmHQReportModel::init(LtsSession::LtsSession *session, int contentFolderId
int FlmHQReportModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
if (!parent.isValid())
return m_data.count();
if (parent.internalId() != 0)
return 0;
return m_data.count();
if (parent.row() >= 0 && parent.row() < m_data.size())
{
const HQData &data = m_data.at(parent.row());
auto it = m_movedData.constFind(data.id);
if (it != m_movedData.constEnd())
return it.value().count();
}
return 0;
}
QModelIndex FlmHQReportModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
quintptr internalId = index.internalId();
if (internalId == 0)
return QModelIndex();
int parentRow = static_cast<int>(internalId) - 1;
return createIndex(parentRow, 0, quintptr(0));
}
QVariant FlmHQReportModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
return {};
if (role == Qt::DisplayRole)
return createText(index.row());
{
quintptr internalId = index.internalId();
return QVariant();
if (internalId == 0)
{
if (index.row() >= 0 && index.row() < m_data.size())
return m_data.at(index.row()).name;
}
else // Child-Item
{
int parentRow = static_cast<int>(internalId) - 1;
if (parentRow >= 0 && parentRow < m_data.size())
{
const HQData &parentData = m_data.at(parentRow);
auto it = m_movedData.constFind(parentData.id);
if (it != m_movedData.constEnd())
{
const QList<HQData> &children = it.value();
if (index.row() >= 0 && index.row() < children.size())
return children.at(index.row()).name;
}
}
}
}
return {};
}
Qt::ItemFlags FlmHQReportModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index);
Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);
if (!index.isValid())
return defaultFlags;
@@ -67,15 +117,9 @@ Qt::ItemFlags FlmHQReportModel::flags(const QModelIndex &index) const
return defaultFlags | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
}
Qt::DropActions FlmHQReportModel::supportedDropActions() const
{
return Qt::CopyAction;
}
Qt::DropActions FlmHQReportModel::supportedDropActions() const { return Qt::CopyAction; }
Qt::DropActions FlmHQReportModel::supportedDragActions() const
{
return Qt::CopyAction;
}
Qt::DropActions FlmHQReportModel::supportedDragActions() const { return Qt::CopyAction; }
QStringList FlmHQReportModel::mimeTypes() const
{
@@ -109,8 +153,34 @@ QMimeData *FlmHQReportModel::mimeData(const QList<QModelIndex> &indexes) const
{
if (index.isValid())
{
HQData md = m_data.at(index.row());
stream << md.id << md.name;// Serialize your custom metadata to QByteArray
HQData md;
QString visibleName = index.data(Qt::DisplayRole).toString();
if (index.internalId() != 0)
{
int parentRow = static_cast<int>(index.internalId()) - 1;
if (parentRow >= 0 && parentRow < m_data.size())
{
const HQData &parentData = m_data.at(parentRow);
const auto &children = m_movedData.value(parentData.id);
if (index.row() >= 0 && index.row() < children.size())
{
md = children.at(index.row());
}
}
}
else
{
if (index.row() >= 0 && index.row() < m_data.size())
{
const HQData &originalData = m_data.at(index.row());
md.id = originalData.id;
md.name = visibleName;
md.properties = originalData.properties;
}
}
md.name = visibleName;
stream << md.id << md.name;
}
}
mimeData->setData(mimeType, encodedData);
@@ -128,17 +198,20 @@ bool FlmHQReportModel::dropMimeData(const QMimeData *data, Qt::DropAction action
QByteArray encodedData = data->data(mimeType);
QDataStream stream(&encodedData, QIODevice::ReadOnly);
if (parent.isValid() && parent.row() >= 0 && parent.row() < m_data.size())
DEBUG_LOG(m_logger) << "DROP ZIEL (Parent im Tree): " << m_data.at(parent.row()).name;
while (!stream.atEnd())
{
HQData md;
stream >> md.id >> md.name;
addMovedData(parent.row(), md);
DEBUG_LOG(m_logger) << "DROP INHALT aus Stream -> ID: " << md.id << ", NAME: " << md.name;
addMovedData(parent, md);
}
emit dataAddedOrRemoved();
return true;
}
@@ -147,52 +220,106 @@ bool FlmHQReportModel::canDropMimeData(const QMimeData *data, Qt::DropAction act
Q_UNUSED(row)
Q_UNUSED(column)
if (!parent.isValid() ||
!data->hasFormat(mimeType) ||
action != Qt::CopyAction ||
parent.row() < 0 ||
parent.row() >= m_data.size())
if (!parent.isValid() || !data->hasFormat(mimeType) || action != Qt::CopyAction || parent.row() < 0 || parent.row() >= m_data.size())
return false;
QByteArray encodedData = data->data(mimeType);
QDataStream stream(&encodedData, QIODevice::ReadOnly);
const HQData &currentData = m_data.at(parent.row());
if (!m_movedData.contains(currentData.id))
const HQData &currentParentData = m_data.at(parent.row());
if (!m_movedData.contains(currentParentData.id))
return true;
const QList<HQData> &movedDataListForCurrentData = m_movedData.value(currentData.id);
const QList<HQData> &existingChildren = m_movedData.value(currentParentData.id);
while (!stream.atEnd())
{
HQData movedData;
HQData incomingData;
stream >> incomingData.id >> incomingData.name;
stream >> movedData.id >> movedData.name;
if (movedDataListForCurrentData.contains(movedData)) // we do not allow double entries
return false;
for (const HQData &child : existingChildren)
{
if (child.id == incomingData.id)
return false;
}
}
return true;
}
QModelIndex FlmHQReportModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
if (!parent.isValid())
{
if (row >= 0 && row < m_data.size())
return createIndex(row, column, quintptr(0)); // internalId = 0 für Parents
}
else
{
if (parent.internalId() == 0)
{
int parentRow = parent.row();
return createIndex(row, column, quintptr(parentRow + 1));
}
}
return QModelIndex();
}
void FlmHQReportModel::addHQReportData(const HQData &data)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_data.append(data);
QList<HQData> childProperties;
HQData copyData = data;
if (!data.properties.empty())
{
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromStdString(data.properties));
// Hole Einträge aus den properties
if (doc.isArray())
{
QJsonArray jsonArray = doc.array();
for (const QJsonValue &value : jsonArray)
{
QString prop = value.toString().trimmed();
if (!prop.isEmpty() && prop != data.name)
{
HQData childData;
childData.id = data.id;
childData.name = prop;
copyData.children.insert(childData.id);
childProperties.append(childData);
}
}
}
else
{
QString prop = QString::fromStdString(data.properties).trimmed();
if (!prop.isEmpty() && prop != data.name)
{
HQData childData;
childData.id = data.id;
childData.name = prop;
childProperties.append(childData);
}
}
}
beginInsertRows(QModelIndex(), m_data.count(), m_data.count());
m_data.append(copyData);
if (!childProperties.isEmpty())
m_movedData.insert(data.id, childProperties);
endInsertRows();
}
void FlmHQReportModel::deleteHQReportData(const HQData &data)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
endInsertRows();
const int zeile = m_data.indexOf(data);
if (zeile == -1) {
if (zeile == -1)
return;
}
beginRemoveRows(QModelIndex(), zeile, zeile);
m_data.removeAt(zeile);
@@ -202,41 +329,54 @@ void FlmHQReportModel::deleteHQReportData(const HQData &data)
void FlmHQReportModel::onFileContentChanged(const FileContent &content, DataModification modType)
{
if (content.folderId() != m_contentFolderId || content.fileType() != m_fileType)
return;
HQData data;
data.id = content.id();
data.name = QString::fromStdString(content.name());
if (content.folderId() != m_contentFolderId || content.fileType() != m_fileType)
return;
data.properties = content.properties();
if (content.fileStatus() == FileStatus::Deleted) {
if (modType == DataModification::eModified || modType == DataModification::eAdded) {
deleteHQReportData(data);
}
} else if (modType == DataModification::eAdded) {
addHQReportData(data);
DEBUG_LOG(m_logger) << "FlmHQReportModel::onFileContentChanged " << "properties " << data.properties << " " << " Name: " << data.name;
if (content.fileStatus() == FileStatus::Deleted)
{
if (modType == DataModification::eModified || modType == DataModification::eAdded)
deleteHQReportData(data);
}
else if (modType == DataModification::eAdded)
{
addHQReportData(data);
}
}
int FlmHQReportModel::folderId() const
{
return m_contentFolderId;
}
int FlmHQReportModel::folderId() const { return m_contentFolderId; }
QMap<int, QList<int>> FlmHQReportModel::getHQToPlan() const
QMap<int, QSet<int>> FlmHQReportModel::getChangedPlans() const
{
QMap<int, QList<int>> hqToPlan;
QMap<int, QSet<int>> hqToPlan;
for (auto it = m_movedData.constBegin(); it != m_movedData.constEnd(); ++it)
{
const QList<HQData> &movedData = it.value();
QList<int> hqIds;
QSet<int> hqIds;
hqIds.reserve(movedData.size());
for (const HQData &currentData : movedData)
hqIds.append(currentData.id);
hqIds.insert(currentData.id);
hqToPlan.insert(it.key(), hqIds);
HQData myPlan;
for (const auto &plan : m_data)
{
if (plan.id == it.key())
{
myPlan = plan;
break;
}
}
if (myPlan.children != hqIds)
hqToPlan.insert(it.key(), hqIds);
}
return hqToPlan;
@@ -244,51 +384,47 @@ QMap<int, QList<int>> FlmHQReportModel::getHQToPlan() const
void FlmHQReportModel::clearMovedData()
{
if (m_movedData.isEmpty())
return;
beginResetModel();
m_movedData.clear();
endResetModel();
emit dataAddedOrRemoved();
emit dataChanged(index(0, 0), index(rowCount() - 1, 0));
}
QString FlmHQReportModel::createText(int dataIndex) const
void FlmHQReportModel::addMovedData(const QModelIndex &parentIndex, const HQData &movedData)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " dataIndex: " << dataIndex;
if (dataIndex < 0 || dataIndex >= m_data.size())
return QString();
const HQData &data = m_data.at(dataIndex);
if (!m_movedData.contains(data.id))
{
DEBUG_LOG(m_logger) << "No moved data for " << data.name;
return data.name;
}
const QList<HQData> &movedData = m_movedData.value(data.id);
QStringList movedDataNames;
movedDataNames.reserve(movedData.size());
for (const HQData &currentMovedData : movedData)
movedDataNames.append(currentMovedData.name);
return QString(QStringLiteral("%1 (%2)")).arg(data.name).arg(movedDataNames.join(QLatin1Char(',')));
}
void FlmHQReportModel::addMovedData(int dataIndex, const HQData &movedData)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " dataIndex: " << dataIndex << ", movedData.id: " << movedData.id << ", movedData.name: " << movedData.name;
int dataIndex = parentIndex.row();
if (dataIndex < 0 || dataIndex >= m_data.size())
return;
const HQData &data = m_data.at(dataIndex);
if (data.id == movedData.id)
{
DEBUG_LOG(m_logger) << "DROP ABGEWIESEN: PlanId entspricht der ReportId (" << data.id << ")";
return;
}
if (!m_movedData.contains(data.id))
m_movedData.insert(data.id, QList<HQData>());
m_movedData[data.id].append(movedData);
}
const QList<HQData> &existingChildren = m_movedData[data.id];
for (const HQData &child : existingChildren)
{
if (child.id == movedData.id || child.name.trimmed() == movedData.name.trimmed())
{
DEBUG_LOG(m_logger) << "DROP ABGEWIESEN: Element '" << movedData.name << "' ist bereits vorhanden.";
return;
}
}
int newRow = m_movedData[data.id].size();
beginInsertRows(parentIndex, newRow, newRow);
m_movedData[data.id].append(movedData);
endInsertRows();
}
} // namespace FileManagement
@@ -1,14 +1,13 @@
#pragma once
#include <QObject>
#include <QAbstractListModel>
#include <QStandardItemModel>
#include <QList>
#include <QMimeData>
#include <QByteArray>
#include <QDataStream>
#include <QMimeData>
#include <QObject>
#include <QSet>
#include <QStandardItemModel>
#include <FileManagement/flm_enums.hpp>
#include <FileManagement/logger.h>
@@ -22,7 +21,7 @@ namespace Interface
{
class Dtc;
}
}
} // namespace FileManagement
namespace LtsSession
{
@@ -33,21 +32,19 @@ namespace FileManagement
{
struct HQData
{
int id;
int id{0};
QString name;
std::string properties;
QSet<int> children;
bool operator==(const HQData &other) const
{
return id == other.id &&
name == other.name;
}
bool operator==(const HQData &other) const { return id == other.id && name == other.name; }
};
class FlmHQReportModel : public QAbstractListModel
class FlmHQReportModel : public QAbstractItemModel
{
Q_OBJECT
public:
public:
explicit FlmHQReportModel(QObject *parent = nullptr);
bool init(LtsSession::LtsSession *session, int contentFolderId, const FileManagement::FileType &fileType);
@@ -63,35 +60,37 @@ public:
QMimeData *mimeData(const QList<QModelIndex> &indexes) const override;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override { return 1; }
QModelIndex parent(const QModelIndex &index) const override;
void addHQReportData(const HQData &data);
void deleteHQReportData(const HQData &data);
int folderId() const;
QMap<int, QList<int>> getHQToPlan() const;
QMap<int, QSet<int>> getChangedPlans() const;
void clearMovedData();
private:
QString createText(int dataIndex) const;
void addMovedData(int dataIndex, const HQData &movedData);
private:
void addMovedData(const QModelIndex &parentIndex, const HQData &movedData);
private Q_SLOTS:
private Q_SLOTS:
void onFileContentChanged(const FileContent &content, DataModification modType);
Q_SIGNALS:
Q_SIGNALS:
void dataAddedOrRemoved();
private:
private:
QList<HQData> m_data;
QMap<int, QList<HQData>> m_movedData;
const QString mimeType = QStringLiteral("application/x-custom-hqdata");
int m_contentFolderId {-1};
int m_contentFolderId{-1};
FileManagement::FileType m_fileType;
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
LOGGER_T m_logger;
};
}//namespace FileManagement
} // namespace FileManagement
Q_DECLARE_METATYPE(FileManagement::HQData)
@@ -15,7 +15,7 @@
#include <FileManagement/flm_ftc.h>
#include <FileManagement/flm_dtc.h>
#include <OperatorManagement/opm_dtc.h>
#include <Core/core_dtc.h>
#include <DDS/Core/core_dtc.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsSession/lts_session.h>
#include <PluginInterfaces/gui_plugin_interface.h>
@@ -101,3 +101,11 @@ ADD_INTERFACE_LIBRARY(
${CMAKE_CURRENT_SOURCE_DIR}/../../
)
ENDIF()
# GuiElementInterface
ADD_INTERFACE_LIBRARY(
GuiElementInterface
${CMAKE_CURRENT_SOURCE_DIR}/participant_info_gui_element_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/..
Qt5::Core LtsWidgets
)
@@ -100,6 +100,8 @@ NGL_TARGET_LINK_LIBRARIES(PpmParticipantInfoGuiPlugin
AesDataPluginInterface
LtsDataView
IsmDataPluginInterface
LtsPluginLoader
GuiElementInterface
)
NGL_INSTALL_TARGET(PpmParticipantInfoGuiPlugin)
@@ -33,8 +33,10 @@
#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>
@@ -471,8 +473,38 @@ bool ParticipantInfoDialog::setUiValues()
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)
@@ -110,6 +110,7 @@ private:
bool initTargetConfig(bool bShow);
// Target (L400)
bool initTargetConfigL400(bool bShow);
bool loadGuiElementPLugin(const LtsPluginManager::PluginInstance &pi);
private Q_SLOTS:
@@ -54,7 +54,7 @@ PartyEdit::~PartyEdit()
void PartyEdit::retranslate()
{
translate(m_ui, m_dtc->party(m_partyId), tr("Party"));
translate(m_ui, m_dtc->party(m_partyId), trPartyName(m_dtc->party(m_partyId).name()), tr("Party"));
m_ppmGuiCbxIfc->fillRoleComboBox(m_ui->cbRole);
m_ppmGuiCbxIfc->fillHlaForceIdentifierComboBox(m_ui->cbHlaForceIdentifier);
}
@@ -105,14 +105,11 @@ QVariant PartyModel::data(const QModelIndex &index, int role) const
QString connectState;
switch (status.underlying())
{
case ParticipantManagement::ConnectState::Connected:
connectState = tr("Connected");
break;
case ParticipantManagement::ConnectState::NoHeartbeat:
connectState = tr("No Heartbeat");
case ParticipantManagement::ConnectState::Undefined:
connectState = QStringLiteral("");
break;
default:
connectState = QStringLiteral("");
connectState = ParticipantManagement::toString(status);
break;
}
return connectState;
@@ -0,0 +1,23 @@
#pragma once
#include <QtPlugin>
#include <QWidget>
namespace LtsSession
{
class LtsSession;
}
class GuiElementInterface
{
public:
GuiElementInterface() = default;
virtual ~GuiElementInterface() = default;
virtual QString pluginName() = 0;
virtual QWidget* createGuiElement(QWidget *parent = nullptr) = 0;
virtual bool init(LtsSession::LtsSession *session, int participantId = 0) = 0;
};
// Eindeutige ID für das Qt-Plugin-System
#define IGuiElementPlugin "gui_element:3:participantInfo.guiElement"
Q_DECLARE_INTERFACE(GuiElementInterface, IGuiElementPlugin)
@@ -15,7 +15,7 @@
#include "pre_storyboard.h" // QPointer
#include "filter_topic.h"
#include <Core/core_dtc.h>
#include <DDS/Core/core_dtc.h>
#include <PluginInterfaces/topic_replay_interface.h>
#include <LtsPluginManager/lts_plugin_manager.h>
#include <LtsWidgets/lts_dialog.h>
@@ -14,7 +14,7 @@
#include "pre_journal_types.h"
#include "pre_utils.h"
#include <Core/core_dtc.h>
#include <DDS/Core/core_dtc.h>
#include <LtsPluginManager/lts_plugin_manager.h>
#include <LtsSession/lts_session.h>
#include <LtsUtilsGuiDds/request_helper.h>
@@ -9,12 +9,12 @@
#include "srm_data_plugin.h"
#include <Core/core_dtc.h>
#include <DDS/Core/core_dtc.h>
#include <SituationReplayManagement/srm_ftc.h>
#include <LtsSession/lts_session_data_dds.h>
#include <DDS/DDSConnector/dds_connector.h>
#include <DDS/QosProfile/DDS_DefaultQos.h>
#include <Core/core_dts_types.h>
#include <DDS/Core/core_dts_types.h>
#include <DDS/DTS/generic_dts_impl.h>
#include <SituationReplayManagement/logger.h>
#include <LtsUtilsCore/await.h>
@@ -12,7 +12,7 @@
#include <Services/SituationReplayManagement/srm_ftc.h>
#include <Plugins/SituationReplayManagement/srm_data_plugin_interface.h>
#include <Services/SituationReplayManagement/logger.h>
#include <Core/core_dtc.h>
#include <DDS/Core/core_dtc.h>
#include <LtsSession/lts_session.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
@@ -10,7 +10,7 @@
#pragma once
#include <SituationReplayManagement/srm_dtc.h>
#include <Core/core_dtc.h>
#include <DDS/Core/core_dtc.h>
#include <SituationReplayManagement/logger.h>
#include <LtsWidgets/lts_abstract_table_model.h>
@@ -11,7 +11,7 @@
#include <PluginInterfaces/data_plugin_interface.h>
#include <SituationReplayManagement/srm_ftc.h>
#include <Core/core_dtc.h>
#include <DDS/Core/core_dtc.h>
namespace Core
{