Files
qt5-legatus-legacy/Lts/Plugins/CentralEffectSimulation/Gui/ParticipantUAS/mission_plan_dialog.cpp
T
2026-08-13 18:33:10 +02:00

342 lines
12 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Dialog to Simulate drone
* $Id$
* $HeadURL$
* $Author$
* Created by Steve Kemayou, ESZS, 2025-04-08
*/
#include <CentralEffectSimulation/ces_data_plugin_interface.h>
#include <AreaEffectSimulation/aes_data_plugin_interface.h>
#include <ParticipantManagement/ppm_data_plugin_interface.h>
#include <LtsUtilsSettings/settings.h>
#include <CentralEffectSimulation/ces_operator_rights.h>
#include "mission_plan_dialog.h"
#include "ui_mission_plan_dialog.h"
namespace CentralEffectSimulation
{
MissionPlanDialog::MissionPlanDialog(const QString &menuGroup, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_ppmDtc(nullptr)
, m_ppmFtc(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_session(nullptr)
, m_menuGroup(menuGroup)
, m_logger(getLogger("MissionPlanDialog"))
, m_ui(new Ui::MissionPlanDialog)
{
m_ui->setupUi(this);
m_updateMissionTimer.setSingleShot(true);
m_updateMissionTimer.setInterval(500);
connect(&m_updateMissionTimer, &QTimer::timeout, this, &MissionPlanDialog::enaDisa);
setOnlineHelpFilename(QStringLiteral("Situation-UAS-Mission"));
}
MissionPlanDialog::~MissionPlanDialog()
{
delete m_ui;
}
bool MissionPlanDialog::init(LtsSession::LtsSession *session)
{
m_session = session;
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
{
ERROR_LOG(m_logger) << " failed to get ppmDtc";
return false;
}
if (!m_session->getFtc<ParticipantManagement::DataInterface>(m_ppmFtc))
{
ERROR_LOG(m_logger) << " failed to get ppmFtc";
return false;
}
m_ppmDtc->enableUnitPosition();
m_ppmDtc->waitForHistoricalDataUnitPosition(1000);
delete m_missionPlanModel;
m_missionPlanModel = new MissionPlanModel(this);
m_missionPlanModel->initModel(m_ppmDtc, m_session->exerciseId());
m_missionPlanProxyModel = new MissionPlanProxyModel(this);
m_missionPlanProxyModel->setSourceModel(m_missionPlanModel);
m_ui->participantsDataView->setModel(m_missionPlanProxyModel);
//Lock Button
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load, this, &MissionPlanDialog::onLockModifications);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false);
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Lock"));
m_buttonBox->setIcon(LtsWidgets::DialogButton::Load, QIcon(QStringLiteral("icon:drone_remote_connection.svg")));
//hide for now
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->hide();
//unlock Button
m_buttonBox->connectButton(LtsWidgets::DialogButton::Save, this, &MissionPlanDialog::onUnlockModifications);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, false);
m_buttonBox->getButton(LtsWidgets::DialogButton::Save)->setText(tr("Unlock"));
m_buttonBox->setIcon(LtsWidgets::DialogButton::Save, QIcon(QStringLiteral("icon:drone_remote_connection.svg")));
//hide for now
m_buttonBox->getButton(LtsWidgets::DialogButton::Save)->hide();
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &MissionPlanDialog::onAddMissionPlan); // wird für das Verblockung missbraucht
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Add, true);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &MissionPlanDialog::onEditMissionPlan);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &MissionPlanDialog::onRemoveMissionPlanClicked);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
connect(m_ui->participantsDataView, &LtsDataView::LtsDataView::signalSelectionChanged, this, &MissionPlanDialog::enaDisa);
const bool &hasOperatorRightParticipantUAS = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::ParticipantMove);
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setVisible(hasOperatorRightParticipantUAS);
m_buttonBox->getButton(LtsWidgets::DialogButton::Add)->setVisible(hasOperatorRightParticipantUAS);
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::missionPlanChanged,
this, &MissionPlanDialog::onMissionPlanChanged);
connect(m_ui->participantsDataView, &LtsDataView::LtsDataView::doubleClicked, this, &MissionPlanDialog::onEditMissionPlan);
return true;
}
void MissionPlanDialog::onModifyMissionPlanReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void MissionPlanDialog::onRemoveMissionPlanReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void MissionPlanDialog::retranslate()
{
translate(m_ui, tr("UAS Mission Plans"));
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setText(tr("Edit"));
m_buttonBox->getButton(LtsWidgets::DialogButton::Remove)->setText(tr("Delete"));
}
bool MissionPlanDialog::removeMissionPlan(int32_t missionplanId)
{
if (missionplanId <= 0)
return false;
ParticipantManagement::RemoveMissionPlanRequest req(missionplanId);
m_requestHelper->startSingleRequest([req, this]()
{
return m_ppmFtc->removeMissionPlanRequest(req, this);
});
return m_requestHelper->startRequests();
}
MissionPlanDialog::WayPointsStatus MissionPlanDialog::wayPointCurrentStatus(const ParticipantManagement::MissionPlan &mp) const
{
WayPointsStatus state = WayPointsStatus::Undefined;
//prepared
if (mp.missionStart() > m_session->partitionTime())
return WayPointsStatus::Prepared;
else if (mp.itemsFulfilled() != static_cast<int32_t>(mp.items().size()))
return WayPointsStatus::Active;
else if (mp.itemsFulfilled() == static_cast<int32_t>(mp.items().size()))
return WayPointsStatus::Expired;
//aborted
WARNING_LOG(m_logger)<<" -- Status Wegpunktkette Abgebrochen muss definiert werden";
return state;
}
bool MissionPlanDialog::canBeLocked() const
{
auto missionPlan = currentMissionPlan();
if (missionPlan.id()<= 0)
return false;
const auto wpStatus = wayPointCurrentStatus(missionPlan);
const auto uas = m_ppmDtc->getUasByParticipantId(missionPlan.participantId(), m_session->exerciseId());
if (uas.uasState() == ProjectDataManagement::UasState_def::Manual
|| wpStatus == WayPointsStatus::Active )
return true;
return false;
}
bool MissionPlanDialog::canBeUnlocked() const
{
auto missionPlan = currentMissionPlan();
if (missionPlan.id()<= 0)
return false;
if (missionPlan.aborted())
return false;
const auto wpStatus = wayPointCurrentStatus(missionPlan);
const auto uas = m_ppmDtc->getUasByParticipantId(missionPlan.participantId(), m_session->exerciseId());
if ( uas.uasState() == ProjectDataManagement::UasState_def::Manual
|| wpStatus != WayPointsStatus::Active)
return true;
return false;
}
MissionPlanEdit *MissionPlanDialog::currentMissionPlanEditor() const
{
QModelIndexList indexList = m_ui->participantsDataView->selectedRows();
if (indexList.isEmpty())
return nullptr;
const ParticipantManagement::MissionPlan mp = m_missionPlanModel->getRowData(indexList.front().row());
if (mp.id() < 0)
return nullptr;
return m_participantUasEditMap.value(mp.participantId(), nullptr);
}
ParticipantManagement::MissionPlan MissionPlanDialog::currentMissionPlan() const
{
QModelIndexList indexList = m_ui->participantsDataView->selectedRows();
if (indexList.isEmpty())
return {};
return m_missionPlanModel->getRowData(indexList.front().row());
}
void MissionPlanDialog::tableColumnOrganiserSetting()
{
//LtsColumnOrganiser
m_ui->participantsDataView->setColumnsOrganiserEnabled(identifier(), true);
}
void MissionPlanDialog::enaDisa()
{
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, false);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, false); // lock button
QModelIndexList indexList = m_ui->participantsDataView->selectedRows();
bool bOk = !indexList.isEmpty();
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, bOk);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, bOk);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, bOk && canBeLocked());
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, bOk && canBeUnlocked()); // lock button
}
void MissionPlanDialog::onUnlockModifications()
{
auto dialog = currentMissionPlanEditor();
if (!dialog)
return;
if (canBeUnlocked())
dialog->setAllUiElementsEnabled(true);
else
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot unlock selected Mission Plan:\n mission plan still activ"));
}
void MissionPlanDialog::onLockModifications()
{
auto dialog = currentMissionPlanEditor();
if (!dialog)
return;
if (canBeLocked())
dialog->setAllUiElementsEnabled(false);
else {
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot Lock selected Mission Plan."));
}
}
void MissionPlanDialog::onAddMissionPlan()
{
static QString newMissionPlanIdentifier(QStringLiteral("NewMissionPlan"));
// selecting an existing mission plan and clicking 'add' must create a new mission plan dialog as a copy of the existing mission plan
const QModelIndexList indexList = m_ui->participantsDataView->selectedRows();
if (indexList.isEmpty())
{
addDialog(LtsWidgets::initDialog(new MissionPlanEdit(this), 0, m_session),
m_menuGroup, newMissionPlanIdentifier, LtsWidgets::LayoutArea::eDialogTab);
return;
}
const ParticipantManagement::MissionPlan mp = m_missionPlanModel->getRowData(indexList.front().row());
if (mp.id() <= 0)
{
return;
}
addDialog(LtsWidgets::initDialog(new MissionPlanEdit(this), mp.id(), m_session, true /*as copy*/),
m_menuGroup, newMissionPlanIdentifier, LtsWidgets::LayoutArea::eDialogTab);
}
void MissionPlanDialog::onRemoveMissionPlanClicked()
{
const QModelIndexList indexList = m_ui->participantsDataView->selectedRows();
const bool isOne = (indexList.size() == 1);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, isOne);
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
if (!isOne)
return;
const ParticipantManagement::MissionPlan mp = m_missionPlanModel->getRowData(indexList.front().row());
delete m_participantUasEditMap.value(mp.id());
m_participantUasEditMap.remove(mp.id());
removeMissionPlan(mp.id());
}
void MissionPlanDialog::onEditMissionPlan()
{
QModelIndexList indexList = m_ui->participantsDataView->selectedRows();
if (indexList.isEmpty())
return;
const ParticipantManagement::MissionPlan mp = m_missionPlanModel->getRowData(indexList.front().row());
if (mp.id() <= 0)
return;
const QString dialogIdentifier = QStringLiteral("Edit-MissionPlan_%1").arg(mp.id());
if (!m_participantUasEditMap.contains(mp.participantId()))
{
MissionPlanEdit *dialog = new MissionPlanEdit(this);
m_participantUasEditMap.insert(mp.participantId(), dialog);
connect(dialog, &MissionPlanEdit::editUasDialogClosed, this, &MissionPlanDialog::onEditDialogClosed);
addDialog(LtsWidgets::initDialog(dialog, mp.id(), m_session)
, m_menuGroup
, dialogIdentifier
, LtsWidgets::LayoutArea::eDialogTab);
}
else
focusDialog(m_menuGroup, dialogIdentifier, LtsWidgets::LayoutArea::eDialogTab);
}
void MissionPlanDialog::onEditDialogClosed(const int participantId)
{
m_participantUasEditMap.remove(participantId);
}
void MissionPlanDialog::onMissionPlanChanged(const ParticipantManagement::MissionPlan &data, const DataModification modType)
{
Q_UNUSED(data)
Q_UNUSED(modType)
m_updateMissionTimer.start();
}
} // namespace CentralEffectSimulation