Files
qt5-legatus-legacy/Lts/Plugins/TargetManagement/Gui/ShootbackTargetConfiguration/tgt_target_part_dialog.cpp
T
2026-08-13 18:33:10 +02:00

558 lines
20 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @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