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

488 lines
16 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_area_dialog.h"
#include "ui_tgt_area_dialog.h"
#include "tgt_area_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/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include "tgt_target_area_assignment_dialog.h"
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
namespace TargetManagement
{
AreaDialog::AreaDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_session(session)
, m_ui(new Ui::AreaDialog)
, m_menuGroup(menuGroup)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("AreaDialog"))
{
m_ui->setupUi(this);
setOnlineHelpFilename(QStringLiteral("Situation-Assign/Configure_Targets"));
}
AreaDialog::~AreaDialog()
{
clearSelectionOfMapObjects();
delete m_ui;
}
bool AreaDialog::init()
{
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->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
return false;
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc))
return false;
// initialize model:
INFO_LOG(m_logger) << "AreaDialog::init";
m_areaModel = new AreaModel(this);
m_areaModel->initModel(m_dtc);
// proxyModel:
auto proxyModel = new AreaProxyModel(this);
proxyModel->setSourceModel(m_areaModel);
proxyModel->setDynamicSortFilter(false);
// set view: (LtsDataView)
m_ui->widget->setModel(proxyModel);
// to allow remove off some rows at once. Anoying in all other cases -> stay at singleSelection
// m_ui->widget->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
m_assignTargetBtn = m_buttonBox->getButton(LtsWidgets::DialogButton::Import);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Import, this, &AreaDialog::onAssignTargetButtonClicked);
// connects for gui
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
this, &AreaDialog::onSelectionChanged);
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked,
this, &AreaDialog::onEditArea);
connect(this, &AreaDialog::escapePressed, this,
&AreaDialog::onEscapePressed, Qt::UniqueConnection);
// Create Add-Button
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &AreaDialog::onNewArea);
// Create Remove-Button
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &AreaDialog::onRemoveArea);
// Create Modify-Button
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &AreaDialog::onEditArea);
// connect signals of TableView/CustomView:
connect(m_ui->widget, &LtsDataView::LtsDataView::clicked, this, &AreaDialog::onTableViewClicked);
// it´s possible to evaluate signalEntered, but seems to be overkill here:
// connect(m_ui->widget, &LtsDataView::LtsDataView::signalEntered, this, &AreaDialog::onObjectEntered);
#ifndef LTS_DEBUG
m_ui->widget->hideColumn(AreaModel::Columns::Id);
#endif
// Save/Load from Library Button
m_buttonBox->connectLibraryButton(this,
&AreaDialog::onImportButtonClicked,
&AreaDialog::onExportButtonClicked);
if (!m_flmGui)
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Library, false);
// 'Map' Button(s)
m_buttonBox->connectButton(LtsWidgets::DialogButton::CenterMap, this, &AreaDialog::onMapCenterClicked);
m_buttonBox->connectButton(LtsWidgets::DialogButton::ZoomMapTo, this, &AreaDialog::onMapZoomToClicked);
if (!m_sitMapGuiIfc)
{
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::CenterMap, false);
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::ZoomMapTo, false);
}
// call eneDisa / onSelectionChanged once:
onSelectionChanged();
return true;
}
void AreaDialog::retranslate()
{
translate(m_ui, tr("Configure Areas"));
m_assignTargetBtn->setText(tr("Assign Targets"));
}
void AreaDialog::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape)
emit escapePressed();
return BaseClass::keyPressEvent(event);
}
void AreaDialog::onNewArea()
{
INFO_LOG(m_logger) << "onNewArea";
AreaEdit *dialog = new AreaEdit(this);
if (!dialog->init(m_dtc, m_ftc, m_sitMapGuiIfc, m_areaModel))
{
ERROR_LOG(m_logger) << QLatin1String("Can't initialize AreaEdit!");
delete dialog;
return;
}
addDialog(dialog, m_menuGroup, QStringLiteral("Add Target"), LtsWidgets::LayoutArea::eDialogTab, true, true);
}
void AreaDialog::onRemoveArea()
{
const QModelIndexList &selectedRows = m_ui->widget->selectedRows();
for (const auto &mi : selectedRows)
{
Core::RemoveElementRequest req;
req.id(m_areaModel->getRowData(mi.row()).id());
m_requestHelper->addRequest([req, this]()
{
return m_ftc->shootbackAreaRemoveRequest(req, this);
});
}
m_requestHelper->startRequests();
}
void AreaDialog::onEditArea()
{
QModelIndexList selectedRows = m_ui->widget->selectedRows();
if (selectedRows.isEmpty())
return;
const QModelIndex curIdx = selectedRows.first();
if (!curIdx.isValid())
return;
INFO_LOG(m_logger) << " onEditTargetPart";
AreaEdit *dialog = new AreaEdit(this);
const TargetManagement::ShootbackArea &area = m_areaModel->getRowData(curIdx.row());
if (!dialog->init(m_dtc, m_ftc, m_sitMapGuiIfc, m_areaModel, area))
{
ERROR_LOG(m_logger) << LOGFUNCTION << QLatin1String("Can't initialize AreaEdit!");
delete dialog;
return;
}
addDialog(dialog, m_menuGroup, QStringLiteral("Edit Area"), LtsWidgets::LayoutArea::eDialogTab, true, true);
}
QByteArray AreaDialog::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::TGTShootbackArea);
{
const QVector<TargetManagement::ShootbackArea>& modelData = m_areaModel->getData();
QJsonArray jArray;
for (const TargetManagement::ShootbackArea &area : modelData)
{
ShootbackAreaData sbad;
sbad.id = area.id();
sbad.name = QString::fromStdString(area.name());
sbad.position = GeoPosition2D(area.position());
sbad.width = area.width();
sbad.height = area.height();
jArray.append(sbad.toJson());
}
obj[QStringLiteral("ShootbackAreas")] = jArray;
}
QJsonDocument doc(obj);
DEBUG_LOG(m_logger) << " json = " << doc.toJson();
return doc.toJson(QJsonDocument::Compact);
}
QVector<ShootbackArea> AreaDialog::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("ShootbackAreas")].toArray();
QVector<TargetManagement::ShootbackArea> vecData;
vecData.reserve(jArray.size());
for (const auto &item : jArray)
{
const ShootbackAreaData &sbad = ShootbackAreaData::fromJson(item.toObject());
TargetManagement::ShootbackArea area;
area.id(sbad.id);
area.name(sbad.name.toStdString());
area.position({sbad.position.lon, sbad.position.lat}); // GeoPosition2D( double lon, double lat);
area.width(sbad.width);
area.height(sbad.height);
vecData.push_back(std::move(area));
}
return vecData;
}
void AreaDialog::onEscapePressed()
{
m_ui->widget->clearSelection();
}
void AreaDialog::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 AreaDialog::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, &AreaDialog::onImport);
}
void AreaDialog::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::TGTShootbackArea));
if (fileId > 0)
{
if (!m_flmGui->isXmlType(content, FileManagement::toString(FileManagement::XmlType::TGTShootbackArea)))
{
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<ShootbackArea> &curData = m_areaModel->getData();
for (auto item : curData)
{
Core::RemoveElementRequest req(item.id());
m_requestHelper->addRequest([this, req]()
{
return m_ftc->shootbackAreaRemoveRequest(req, this);
});
}
// 2) re-insert:
const QVector<TargetManagement::ShootbackArea> vecDataCandidate(fromJson(content));
for (ShootbackArea area : vecDataCandidate)
{
DEBUG_LOG(m_logger) << "area " <<area;
area.id(0); // force create
m_requestHelper->addRequest([this, area]()
{
return m_ftc->shootbackAreaModifyRequest(area, this);
});
}
// clear view *before* performing the requests:
m_areaModel->clear();
m_requestHelper->startRequests();
}
}
}
void AreaDialog::onAssignTargetButtonClicked()
{
QModelIndexList selectedRows = m_ui->widget->selectedRows();
if (selectedRows.isEmpty())
return;
const QModelIndex curIdx = selectedRows.first();
if (!curIdx.isValid())
return;
const int areaId = m_areaModel->getRowData(curIdx.row()).id();
// instead of emit a signal, create the according dialog frome here directly
// emit assignTargetsRequested(areaId);
auto dlg = new AssignmentDialog(menuGroup(), m_session, this->parentWidget());
if (!dlg->init(AssignmentDialog::MODE::FILTERED_TO_SINGLE_AREA, areaId))
{
dlg->deleteLater();
return;
}
if (!m_session->addWidget(dlg, menuGroup(), QStringLiteral("ConfigureTargetsToAreaId_%1").arg(areaId), LtsWidgets::LayoutArea::eDialogTab))
dlg->deleteLater();
}
void AreaDialog::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 id = m_areaModel->getRowData(curIdx.row()).id();
m_sitMapGuiIfc->centerMapToMapObject(SituationMap::MapObjectType::MOT_ShootbackArea, id);
}
void AreaDialog::onMapZoomToClicked()
{
QModelIndexList selectedRows = m_ui->widget->selectedRows();
if (selectedRows.isEmpty())
return;
QModelIndex index = selectedRows.first();
if (!index.isValid())
return;
if (!m_areaModel || !m_sitMapGuiIfc)
return;
int areaId = m_areaModel->getRowData(index.row()).id();
if (areaId<=0)
return;
// Assigned Targets:
QVector<int> assignedTargets;
auto cb = [areaId, &assignedTargets](const TargetManagement::TargetAreaAssignment &assignment)
{
if (assignment.areaId() == areaId)
assignedTargets.push_back(assignment.targetParticipantId());
};
m_dtc->targetAreaAssignments(cb);
{
QVector<QPair<SituationMap::MapObjectType, int>> entities;
entities.reserve(assignedTargets.size()+1);
entities.push_back({SituationMap::MapObjectType::MOT_ShootbackArea, areaId});
for (auto item : assignedTargets)
entities.push_back({SituationMap::MapObjectType::MOT_Participant, item});
m_sitMapGuiIfc->zoomMapTo(entities);
}
}
void AreaDialog::onObjectEntered(const QModelIndex &index)
{
if (!m_sitMapGuiIfc)
return;
if (!index.isValid())
{
m_sitMapGuiIfc->removeObjectIndicator();
return;
}
int areaId = m_areaModel->getRowData(index.row()).id();
if (areaId>0)
{
// Area
m_sitMapGuiIfc->objectIndicatorToMapObject(SituationMap::MapObjectType::MOT_ShootbackArea, areaId, true);
// Assigned Targets:
QVector<int> assignedTargets;
auto cb = [areaId, &assignedTargets](const TargetManagement::TargetAreaAssignment &assignment)
{
if (assignment.areaId() == areaId)
assignedTargets.push_back(assignment.targetParticipantId());
};
m_dtc->targetAreaAssignments(cb);
m_sitMapGuiIfc->setMapObjectSelected(SituationMap::MapObjectType::MOT_Participant, assignedTargets, true);
}
else
m_sitMapGuiIfc->removeObjectIndicator();
}
void AreaDialog::onTableViewClicked(const QModelIndex &index)
{
if (!index.isValid())
return;
if (QGuiApplication::keyboardModifiers().testFlag(Qt::KeyboardModifier::ShiftModifier))
onMapCenterClicked();
}
void AreaDialog::clearSelectionOfMapObjects()
{
if (!m_sitMapGuiIfc)
return;
// remove MapObjectIndicator:
m_sitMapGuiIfc->removeObjectIndicator();
}
void AreaDialog::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_assignTargetBtn->setEnabled(cntSelectedRows == 1); // LtsWidgets::DialogButton::Library
if (selectedRows.isEmpty())
onObjectEntered({}); // use invalid Idx to removeObjectIndicator
else
onObjectEntered(selectedRows.first());
}
//-----------------------------------------------------------------------------
} // namespace TargetManagement