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,557 @@
/**
* @RDE_HEADER@
* Target Configuration
* $Id$
* $HeadURL$
* $Author$
* Created by Norbert Thoden, NLE, 2020-06-29
*/
#include "tgt_target_part_dialog.h"
#include "ui_tgt_target_part_dialog.h"
#include "tgt_shootback_target_edit.h"
#include "tgt_telegrams.h"
#include <LtsSession/lts_session_data.h>
#include <FileManagement/flm_translation.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/TargetManagement/tgt_data_plugin_interface.h>
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
#include <Plugins/ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include "tgt_target_area_assignment_dialog.h"
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QDebug>
namespace TargetManagement
{
TargetPartDialog::TargetPartDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_session(session)
, m_ui(new Ui::TargetPartDialog)
, m_menuGroup(menuGroup)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("TargetPartDialog"))
{
m_ui->setupUi(this);
setOnlineHelpFilename(QStringLiteral("Situation-Assign/Configure_Targets"));
}
TargetPartDialog::~TargetPartDialog()
{
clearSelectionOfMapObjects();
delete m_ui;
}
bool TargetPartDialog::init(TargetManagement::TargetPartDialog::MODE mode)
{
if (!m_session)
return false;
if (!m_session->getDtc<TargetManagement::DataInterface>(m_dtc))
return false;
if (!m_session->getFtc<TargetManagement::DataInterface>(m_ftc))
return false;
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
return false;
if (!m_session->getForeignGuiInterface<ParticipantManagement::ForeignGuiComboboxInterface>(m_ppmGuiCbxIfc))
return false;
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
return false;
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc))
return false;
// initialize model:
INFO_LOG(m_logger) << "TargetPartDialog::init";
m_targetParticipantModel = new TargetParticipantModel(this);
m_targetParticipantModel->initModel(m_dtc, m_ppmDtc, m_ppmGuiCbxIfc, m_session);
// proxyModel:
auto proxyModel = new TargetParticipantProxyModel(this);
proxyModel->setSourceModel(m_targetParticipantModel);
proxyModel->setDynamicSortFilter(false);
// set view: (LtsDataView)
m_ui->widget->setModel(m_targetParticipantModel);
// to allow remove off some rows at once. Anoying in all other cases -> stay at singleSelection
// m_ui->widget->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
m_assignAreaBtn = m_buttonBox->getButton(LtsWidgets::DialogButton::Import);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Import, this, &TargetPartDialog::onAssignAreaClicked);
// connects for gui
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
this, &TargetPartDialog::onSelectionChanged);
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked,
this, &TargetPartDialog::onEditTargetPart);
connect(this, &TargetPartDialog::escapePressed, this,
&TargetPartDialog::onEscapePressed, Qt::UniqueConnection);
// Create Add-Button
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Add, true);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &TargetPartDialog::onNewTargetPart);
// Create Remove-Button
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &TargetPartDialog::onRemoveTargetPart);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
// Create Modify-Button
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &TargetPartDialog::onEditTargetPart);
// connect signals of TableView/CustomView:
connect(m_ui->widget, &LtsDataView::LtsDataView::clicked, this, &TargetPartDialog::onTableViewClicked);
// it´s possible to evaluate signalEntered, but seems to be overkill here:
// connect(m_ui->widget, &LtsDataView::LtsDataView::signalEntered, this, &TargetPartDialog::onObjectEntered);
#ifndef LTS_DEBUG
m_ui->widget->hideColumn(TargetParticipantModel::Columns::Id);
m_ui->widget->hideColumn(TargetParticipantModel::Columns::TargetPartipantId);
#endif
// Save/Load from Library Button
m_buttonBox->connectLibraryButton(this,
&TargetPartDialog::onImportButtonClicked,
&TargetPartDialog::onExportButtonClicked);
if (!m_flmGui)
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Library, false);
// 'Map' Button(s)
m_buttonBox->connectButton(LtsWidgets::DialogButton::CenterMap, this, &TargetPartDialog::onMapCenterClicked);
m_buttonBox->connectButton(LtsWidgets::DialogButton::ZoomMapTo, this, &TargetPartDialog::onMapZoomToClicked);
// call eneDisa / onSelectionChanged once:
onSelectionChanged();
setMode(mode);
return true;
}
void TargetPartDialog::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape)
emit escapePressed();
return BaseClass::keyPressEvent(event);
}
void TargetPartDialog::setMode(TargetPartDialog::MODE mode)
{
m_mode = mode;
switch (m_mode)
{
case MODE::TARGET_BASE_CONFIGURATION:
m_assignAreaBtn->setVisible(false);
break;
case MODE::TARGET_OVERVIEW:
m_assignAreaBtn->setVisible(true);
m_ui->widget->hideColumn(TargetParticipantModel::Columns::TargetPartipantId);
m_ui->widget->hideColumn(TargetParticipantModel::Columns::ActivateLaserDesignation);
m_ui->widget->hideColumn(TargetParticipantModel::Columns::ActivateLights);
m_ui->widget->hideColumn(TargetParticipantModel::Columns::ActivatePopupAutomatic);
m_ui->widget->hideColumn(TargetParticipantModel::Columns::HitsToKill);
m_ui->widget->hideColumn(TargetParticipantModel::Columns::PermanentInstalledTarget);
m_ui->widget->hideColumn(TargetParticipantModel::Columns::VisibleParticipants);
break;
} // switch
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Add, (m_mode == MODE::TARGET_BASE_CONFIGURATION));
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Edit, (m_mode == MODE::TARGET_BASE_CONFIGURATION));
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Remove, (m_mode == MODE::TARGET_BASE_CONFIGURATION));
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Library, (m_mode == MODE::TARGET_BASE_CONFIGURATION));
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::CenterMap, m_sitMapGuiIfc && (m_mode == MODE::TARGET_BASE_CONFIGURATION));
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::ZoomMapTo, m_sitMapGuiIfc && (m_mode == MODE::TARGET_BASE_CONFIGURATION));
}
void TargetPartDialog::retranslate()
{
switch (m_mode)
{
case MODE::TARGET_BASE_CONFIGURATION:
translate(m_ui, tr("Assign/Configure Targets"));
m_assignAreaBtn->setText(tr("Assign Area"));
break;
case MODE::TARGET_OVERVIEW:
translate(m_ui, tr("Configure Shootback"));
m_assignAreaBtn->setText(tr("Assign Area"));
break;
}
}
void TargetPartDialog::onNewTargetPart()
{
INFO_LOG(m_logger) << "onNewTargetPart";
ShootbackTargetEdit *dialog = new ShootbackTargetEdit(this);
if (!dialog->init(m_dtc, m_ftc, m_targetParticipantModel))
{
ERROR_LOG(m_logger) << QLatin1String("Can't initialize shootbackTargetEdit!");
delete dialog;
return;
}
addDialog(dialog, m_menuGroup, QStringLiteral("Add Target"), LtsWidgets::LayoutArea::eDialogTab, true, true);
}
void TargetPartDialog::onRemoveTargetPart()
{
const QModelIndexList &selectedRows = m_ui->widget->selectedRows();
for (const auto &mi : selectedRows)
{
Core::RemoveElementRequest req;
req.id(m_targetParticipantModel->getRowData(mi.row()).id());
m_requestHelper->addRequest([req, this]()
{
return m_ftc->shootbackTargetRemoveRequest(req, this);
});
}
m_requestHelper->startRequests();
}
void TargetPartDialog::onEditTargetPart()
{
if (m_mode == MODE::TARGET_OVERVIEW)
return;
QModelIndexList selectedRows = m_ui->widget->selectedRows();
if (selectedRows.isEmpty())
return;
const QModelIndex curIdx = selectedRows.first();
if (!curIdx.isValid())
return;
INFO_LOG(m_logger) << " onEditTargetPart";
ShootbackTargetEdit *dialog = new ShootbackTargetEdit(this);
const TargetManagement::ShootbackTarget &tgt = m_targetParticipantModel->getRowData(curIdx.row());
if (!dialog->init(m_dtc, m_ftc, m_targetParticipantModel, tgt))
{
ERROR_LOG(m_logger) << LOGFUNCTION << QLatin1String("Can't initialize shootbackTargetEdit!");
delete dialog;
return;
}
addDialog(dialog, m_menuGroup, QStringLiteral("Edit Target"), LtsWidgets::LayoutArea::eDialogTab, true, true);
}
QByteArray TargetPartDialog::toJson() const
{
QJsonObject obj;
// operatorId just for convenience:
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
obj[QStringLiteral("OperatorId")] = operatorId;
obj[QStringLiteral("XmlType")] = FileManagement::toString(FileManagement::XmlType::TGTShootbackTargetBaseConfiguration);
{
const QVector<TargetManagement::ShootbackTarget> &modelData = m_targetParticipantModel->getData();
QJsonArray jArray;
for (const TargetManagement::ShootbackTarget &sbt : modelData)
{
ShootbackTargetData sbtd;
sbtd.id = sbt.id();
sbtd.name = QString::fromStdString(sbt.name());
sbtd.targetParticipantEquipmentNumber = -1;
if (m_ppmDtc)
{
const ParticipantManagement::Participant &participant = m_ppmDtc->participant(sbt.targetParticipantId());
if (participant.id() == sbt.targetParticipantId() &&
participant.equipmentNumber().is_set())
sbtd.targetParticipantEquipmentNumber = participant.equipmentNumber().get();
}
sbtd.activateLaserDesignation = sbt.activateLaserDesignation();
sbtd.activateLights = sbt.activateLights();
sbtd.activatePopupAutomatic = sbt.activatePopupAutomatic();
sbtd.hitsToKill = sbt.hitsToKill();
sbtd.permanentInstalledTarget = sbt.permanentInstalledTarget();
// volatile data: position, visibleParticipants -> do not save -> skip
jArray.append(sbtd.toJson());
}
obj[QStringLiteral("ShootbackTargets")] = jArray;
}
QJsonDocument doc(obj);
DEBUG_LOG(m_logger) << " json = " << doc.toJson();
return doc.toJson(QJsonDocument::Compact);
}
QVector<TargetManagement::ShootbackTarget> TargetPartDialog::fromJson(const QByteArray &content)
{
const QJsonDocument doc(QJsonDocument::fromJson(content));
const QJsonObject obj(doc.object());
// operatorId just for convenience:
const int operatorId = obj[QStringLiteral("operatorId")].toInt();
Q_UNUSED(operatorId);
const QJsonArray &jArray = obj[QStringLiteral("ShootbackTargets")].toArray();
QVector<TargetManagement::ShootbackTarget> vecData;
vecData.reserve(jArray.size());
for (const auto &item : jArray)
{
const ShootbackTargetData &sbtd = ShootbackTargetData::fromJson(item.toObject());
TargetManagement::ShootbackTarget sbt;
sbt.id(sbtd.id);
sbt.name(sbtd.name.toStdString());
if (m_ppmDtc)
sbt.targetParticipantId(m_ppmDtc->participantIdByEquipmentNumber(sbtd.targetParticipantEquipmentNumber));
sbt.activateLaserDesignation(sbtd.activateLaserDesignation);
sbt.activateLights(sbtd.activateLights);
sbt.activatePopupAutomatic(sbtd.activatePopupAutomatic);
sbt.hitsToKill(sbtd.hitsToKill);
sbt.permanentInstalledTarget(sbtd.permanentInstalledTarget);
vecData.push_back(std::move(sbt));
}
return vecData;
}
void TargetPartDialog::onEscapePressed()
{
m_ui->widget->clearSelection();
}
void TargetPartDialog::onExportButtonClicked()
{
QByteArray byteArray = toJson();
int fileId = m_flmGui->saveFileContent(this, FileManagement::FileType::Xml, m_session->exerciseId(), byteArray);
if (fileId > 0)
DEBUG_LOG(m_logger) << LOGFUNCTION << "Saved file with id = " << fileId;
else
ERROR_LOG(m_logger) << LOGFUNCTION << "Could not save file in library ";
}
void TargetPartDialog::onImportButtonClicked()
{
QHash<LtsWidgets::Button, QString> buttonTexts;
buttonTexts.insert(LtsWidgets::Button::Ok, tr("Overwrite"));
buttonTexts.insert(LtsWidgets::Button::Cancel, tr("Cancel"));
LtsWidgets::LtsMessageDialogNew *dlg = new LtsWidgets::LtsMessageDialogNew(this,
tr("Overwrite existing data?"),
tr("Load from Library"),
LtsWidgets::Behaviour::Popup,
LtsWidgets::Button::Ok | LtsWidgets::Button::Cancel,
buttonTexts);
connect(dlg, &LtsWidgets::LtsMessageDialogNew::ok,
this, &TargetPartDialog::onImport);
}
void TargetPartDialog::onImport()
{
INFO_LOG(m_logger) << LOGFUNCTION << "--- onImportButtonClicked() ";
QByteArray content;
int fileId = m_flmGui->loadFileContent(this, content, {FileManagement::FileType::Xml},
m_session->exerciseId(),
FileManagement::toString(FileManagement::XmlType::TGTShootbackTargetBaseConfiguration));
if (fileId > 0)
{
if (!m_flmGui->isXmlType(content, FileManagement::toString(FileManagement::XmlType::TGTShootbackTargetBaseConfiguration)))
{
QHash<LtsWidgets::Button, QString> texts({{LtsWidgets::Button::Yes, tr("Ok")}});
LtsWidgets::LtsMessageDialog::showMessage(this,
tr("Invalid xml file content"),
windowTitle(),
LtsWidgets::Behaviour::Modal,
LtsWidgets::Button::Yes,
texts);
}
else
{
// update svc via clear and (re-)insert:
// 1) clear svc:
const QVector<ShootbackTarget> &curData = m_targetParticipantModel->getData();
for (auto item : curData)
{
Core::RemoveElementRequest req(item.id());
m_requestHelper->addRequest([this, req]()
{
return m_ftc->shootbackTargetRemoveRequest(req, this);
});
}
// 2) re-insert:
const QVector<TargetManagement::ShootbackTarget> vecDataCandidate(fromJson(content));
for (ShootbackTarget shootbackTargetCandidate : vecDataCandidate)
{
shootbackTargetCandidate.id(0); // force create
m_requestHelper->addRequest([this, shootbackTargetCandidate]()
{
return m_ftc->shootbackTargetModifyRequest(shootbackTargetCandidate, this);
});
}
// clear view *before* performing the requests:
m_targetParticipantModel->clear();
m_requestHelper->startRequests();
}
}
}
void TargetPartDialog::onAssignAreaClicked()
{
QModelIndexList selectedRows = m_ui->widget->selectedRows();
if (selectedRows.isEmpty())
return;
const QModelIndex curIdx = selectedRows.first();
if (!curIdx.isValid())
return;
const int targetParticipantId = m_targetParticipantModel->getRowData(curIdx.row()).targetParticipantId();
// instead of emit a signal, create the according dialog frome here directly
//emit assignAreasRequested(targetParticipantId);
auto dlg = new AssignmentDialog(menuGroup(), m_session, this->parentWidget());
if (!dlg->init(AssignmentDialog::MODE::FILTERED_TO_SINGLE_TARGET_PARTICPANT, targetParticipantId))
{
dlg->deleteLater();
return;
}
if (!m_session->addWidget(dlg, menuGroup(), QStringLiteral("ConfigureAreasToTargetParticipantId_%1").arg(targetParticipantId), LtsWidgets::LayoutArea::eDialogTab))
dlg->deleteLater();
}
void TargetPartDialog::onMapCenterClicked()
{
if (!m_sitMapGuiIfc)
return;
QModelIndexList selectedRows = m_ui->widget->selectedRows();
if (selectedRows.isEmpty())
return;
const QModelIndex curIdx = selectedRows.first();
if (!curIdx.isValid())
return;
const int pId = m_targetParticipantModel->getRowData(curIdx.row()).targetParticipantId();
m_sitMapGuiIfc->centerMapToMapObject(SituationMap::MapObjectType::MOT_Participant, pId);
}
void TargetPartDialog::onMapZoomToClicked()
{
QModelIndexList selectedRows = m_ui->widget->selectedRows();
if (selectedRows.isEmpty())
return;
QModelIndex index = selectedRows.first();
if (!index.isValid())
return;
if (!m_targetParticipantModel || !m_sitMapGuiIfc)
return;
int pId = m_targetParticipantModel->getRowData(index.row()).targetParticipantId();
if (pId<=0)
return;
// Assigned Areas:
QVector<int> assignedAreas;
auto cb = [pId, &assignedAreas](const TargetManagement::TargetAreaAssignment &assignment)
{
if (assignment.targetParticipantId() == pId)
assignedAreas.push_back(assignment.areaId());
};
m_dtc->targetAreaAssignments(cb);
{
QVector<QPair<SituationMap::MapObjectType, int>> entities;
entities.reserve(assignedAreas.size()+1);
entities.push_back({SituationMap::MapObjectType::MOT_Participant, pId});
for (auto item : assignedAreas)
entities.push_back({SituationMap::MapObjectType::MOT_ShootbackArea, item});
m_sitMapGuiIfc->zoomMapTo(entities);
}
}
void TargetPartDialog::onObjectEntered(const QModelIndex &index)
{
if (!m_sitMapGuiIfc)
return;
if (!index.isValid())
{
m_sitMapGuiIfc->removeObjectIndicator();
return;
}
int pId = m_targetParticipantModel->getRowData(index.row()).targetParticipantId();
if (pId>0)
{
// Target/Participant
m_sitMapGuiIfc->objectIndicatorToMapObject(SituationMap::MapObjectType::MOT_Participant, pId, true);
// Assigned Areas:
QVector<int> assignedAreas;
auto cb = [pId, &assignedAreas](const TargetManagement::TargetAreaAssignment &assignment)
{
if (assignment.targetParticipantId() == pId)
assignedAreas.push_back(assignment.areaId());
};
m_dtc->targetAreaAssignments(cb);
m_sitMapGuiIfc->setMapObjectSelected(SituationMap::MapObjectType::MOT_ShootbackArea, assignedAreas, true);
}
else
m_sitMapGuiIfc->removeObjectIndicator();
}
void TargetPartDialog::onTableViewClicked(const QModelIndex &index)
{
if (!index.isValid())
return;
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
onMapCenterClicked();
}
void TargetPartDialog::clearSelectionOfMapObjects()
{
if (!m_sitMapGuiIfc)
return;
// remove MapObjectIndicator:
m_sitMapGuiIfc->removeObjectIndicator();
}
void TargetPartDialog::onSelectionChanged()
{
QModelIndexList selectedRows = m_ui->widget->selectedRows();
const int cntSelectedRows = selectedRows.size();
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, cntSelectedRows == 1);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, cntSelectedRows == 1);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::CenterMap, cntSelectedRows == 1);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::ZoomMapTo, cntSelectedRows == 1);
m_assignAreaBtn->setEnabled(cntSelectedRows == 1); // LtsWidgets::DialogButton::Library
if (selectedRows.isEmpty())
onObjectEntered({}); // use invalid Idx to removeObjectIndicator
else
onObjectEntered(selectedRows.first());
}
//-----------------------------------------------------------------------------
} // namespace TargetManagement