/** * @RDE_HEADER@ * Dialog to Simulate drone * $Id$ * $HeadURL$ * $Author$ * Created by Steve Kemayou, ESZS, 2025-04-08 */ #include #include #include #include #include #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(m_ppmDtc)) { ERROR_LOG(m_logger) << " failed to get ppmDtc"; return false; } if (!m_session->getFtc(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(mp.items().size())) return WayPointsStatus::Active; else if (mp.itemsFulfilled() == static_cast(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