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,487 @@
/**
* @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