Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Hannes Baeuerle, SLSE, 2017-02-24
|
||||
#
|
||||
|
||||
SET(ces_participant_uas_gui_SRCS
|
||||
logger.cpp
|
||||
logger.h
|
||||
ces_participant_uas_gui_plugin.h
|
||||
ces_participant_uas_gui_plugin.cpp
|
||||
mission_plan_model.h
|
||||
mission_plan_model.cpp
|
||||
mission_plan_edit.h
|
||||
mission_plan_edit.cpp
|
||||
mission_plan_dialog.h
|
||||
mission_plan_dialog.cpp
|
||||
)
|
||||
|
||||
NGL_WRAP_UI (ces_participant_uas_gui_SRCS
|
||||
mission_plan_dialog.ui
|
||||
mission_plan_edit.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(WS CesParticipantUASGuiPlugin MODULE ${ces_participant_uas_gui_SRCS})
|
||||
|
||||
if (TARGET CesParticipantUASGuiPlugin)
|
||||
target_sources(CesParticipantUASGuiPlugin
|
||||
PRIVATE
|
||||
mission_plan_model.h mission_plan_model.cpp
|
||||
)
|
||||
|
||||
target_sources(CesParticipantUASGuiPlugin
|
||||
PRIVATE
|
||||
mission_plan_edit.h mission_plan_edit.cpp mission_plan_edit.ui
|
||||
)
|
||||
endif()
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(CesParticipantUASGuiPlugin
|
||||
AsbDataPluginInterface
|
||||
LtsCoordTrans
|
||||
LtsPrinting
|
||||
PpmDataPluginInterface
|
||||
PpmGuiParticipantsPluginInterface
|
||||
CesDataPluginInterface
|
||||
GuiPluginInterface
|
||||
AsmGuiPluginInterface
|
||||
ExmDataPluginInterface
|
||||
Qt5::Widgets
|
||||
PpmCommon
|
||||
FlmDataPluginInterface
|
||||
LtsUtilsGuiDds
|
||||
LtsWidgets
|
||||
LtsSession
|
||||
LtsSessionData
|
||||
LtsDataView
|
||||
SituationMapGuiPluginInterface
|
||||
LtsUtilsGuiDds
|
||||
ltsCoordWidget
|
||||
LtsUtilsSettings
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(CesParticipantUASGuiPlugin)
|
||||
Executable
+107
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for UAS Participant
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Steve Kemayou, ESZS, 2025-04-08
|
||||
*/
|
||||
|
||||
#include "ces_participant_uas_gui_plugin.h"
|
||||
|
||||
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
|
||||
#include <Services/CentralEffectSimulation/ces_operator_rights.h>
|
||||
#include <Plugins/CentralEffectSimulation/ces_data_plugin_interface.h>
|
||||
#include <Plugins/CentralEffectSimulation/Gui/ParticipantUAS/mission_plan_edit.h>
|
||||
#include "mission_plan_dialog.h"
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
|
||||
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
||||
{
|
||||
return std::make_shared<InterfaceImpl>(session);
|
||||
}
|
||||
|
||||
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
|
||||
: GuiPluginBase::Interface(session, getLogger("Plugins.Gui.Ces.ParticipantUAS"))
|
||||
{
|
||||
}
|
||||
|
||||
bool InterfaceImpl::fetchInterfaces()
|
||||
{
|
||||
if (!m_session->getDtc<CentralEffectSimulation::DataInterface>(m_cesDtc))
|
||||
return false;
|
||||
if (!m_session->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc))
|
||||
return false;
|
||||
if (!m_session->getFtc<ParticipantManagement::DataInterface>(m_ppmFtc))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InterfaceImpl::clearInterfaces()
|
||||
{
|
||||
m_ppmDtc = nullptr;
|
||||
m_ppmFtc = nullptr;
|
||||
m_cesDtc = nullptr;
|
||||
}
|
||||
|
||||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||||
{
|
||||
QVector<LtsWidgets::PluginData> ret;
|
||||
|
||||
LtsWidgets::PluginData plData;
|
||||
if (!m_session->isReplayPartition())
|
||||
{
|
||||
// UAS LIST
|
||||
{
|
||||
plData.menuGroup = menuGroup();
|
||||
plData.menuText = tr("Mission Plans");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:define_movement_simulation_drone.svg"));
|
||||
plData.identifier = QLatin1String("Mission plans");
|
||||
plData.operatorRight = OperatorRights::UasControl;
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::eExecution;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return LtsWidgets::initDialog(new MissionPlanDialog(menuGroup(), parent),
|
||||
m_session);
|
||||
};
|
||||
ret.append(plData);
|
||||
}
|
||||
// Add UAS
|
||||
{
|
||||
plData.menuGroup = menuGroup();
|
||||
plData.menuText = tr("Add Mission plan");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:define_movement_simulation_drone.svg"));
|
||||
plData.identifier = QLatin1String("ParticipantUAS");
|
||||
plData.operatorRight = OperatorRights::UasControl;
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::eExecution;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return onShowAddUASDialog(parent);
|
||||
};
|
||||
ret.append(plData);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LtsWidgets::LtsDialog *InterfaceImpl::onShowAddUASDialog(QWidget *parent)
|
||||
{
|
||||
|
||||
MissionPlanEdit *editWidget = new MissionPlanEdit(parent);
|
||||
if (editWidget->init(0, m_session))
|
||||
return editWidget;
|
||||
|
||||
delete editWidget;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace CentralEffectSimulation
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for Simulated Movement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLSE, 2017-12-19
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <ParticipantManagement/ppm_ftc.h>
|
||||
#include <CentralEffectSimulation/ces_dtc.h>
|
||||
|
||||
namespace ParticipantManagement
|
||||
{
|
||||
class ForeignGuiComboboxInterface;
|
||||
}
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
|
||||
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "gui:3:ces.participant_uas")
|
||||
Q_INTERFACES(GuiPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GuiPlugin() = default;
|
||||
~GuiPlugin() = default;
|
||||
|
||||
QString pluginName() override { return QLatin1String("CesParticipantUASGui"); }
|
||||
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return (partition == IDL::PartitionType::Exercise);
|
||||
}
|
||||
};
|
||||
|
||||
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InterfaceImpl(LtsSession::LtsSession *session);
|
||||
|
||||
bool fetchInterfaces() override;
|
||||
void clearInterfaces() override;
|
||||
QString menuGroup() const override { return tr("Air Support"); }
|
||||
QVector<LtsWidgets::PluginData> getActions() override;
|
||||
|
||||
|
||||
LtsWidgets::LtsDialog *onShowAddUASDialog(QWidget *parent);
|
||||
private: // attributes
|
||||
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Ftc> m_ppmFtc;
|
||||
std::shared_ptr<CentralEffectSimulation::Interface::Dtc> m_cesDtc;
|
||||
};
|
||||
|
||||
} // namespace CentralEffectSimulation
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Building Config - logging facility
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "CES.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
|
||||
getNGLLogger(loggerName);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace CentralEffectSimulation
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for CentralEffectSimulation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
typedef NGL::INGLLogger &LOGGER_T;
|
||||
|
||||
LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace CentralEffectSimulation
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
/**
|
||||
* @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
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Dialog to Simulate drone
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Steve Kemayou, ESZS, 2025-04-08
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsWidgets/lts_frameless_dialog.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <ParticipantManagement/ppm_ftc.h>
|
||||
|
||||
#include <CentralEffectSimulation/ces_dtc.h>
|
||||
#include <CentralEffectSimulation/ces_ftc.h>
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <Plugins/CentralEffectSimulation/ces_gui_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_participants_gui_plugin_interface.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include "mission_plan_model.h"
|
||||
#include "mission_plan_edit.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class MissionPlanDialog;
|
||||
}
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
class MissionPlanDialog : public LtsWidgets::LtsDialog
|
||||
, protected ParticipantManagement::Interface::Ftc::RemoveMissionPlanReplyHandler
|
||||
, protected ParticipantManagement::Interface::Ftc::ModifyMissionPlanReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MissionPlanDialog(const QString &menuGroup, QWidget *parent = nullptr);
|
||||
~MissionPlanDialog();
|
||||
|
||||
|
||||
bool init(LtsSession::LtsSession *session);
|
||||
|
||||
|
||||
void onModifyMissionPlanReply(const Core::FunctionReplyObject &replyObject) override;
|
||||
void onRemoveMissionPlanReply(const Core::FunctionReplyObject &replyObject) override;
|
||||
|
||||
enum class WayPointsStatus
|
||||
{
|
||||
Undefined = 0,
|
||||
Prepared,
|
||||
Active,
|
||||
Aborted,
|
||||
Expired,
|
||||
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
void retranslate() override;
|
||||
void changeParty();
|
||||
bool removeMissionPlan(int32_t missionplanId);
|
||||
WayPointsStatus wayPointCurrentStatus(const ParticipantManagement::MissionPlan &mp) const;
|
||||
bool canBeLocked() const;
|
||||
bool canBeUnlocked() const;
|
||||
MissionPlanEdit * currentMissionPlanEditor() const;
|
||||
ParticipantManagement::MissionPlan currentMissionPlan() const ;
|
||||
void tableColumnOrganiserSetting() override;
|
||||
|
||||
|
||||
protected slots:
|
||||
void enaDisa();
|
||||
void onUnlockModifications();
|
||||
void onLockModifications();
|
||||
void onAddMissionPlan();
|
||||
void onRemoveMissionPlanClicked();
|
||||
void onEditMissionPlan();
|
||||
void onEditDialogClosed(const int participantId);
|
||||
void onMissionPlanChanged(const ParticipantManagement::MissionPlan &data, const DataModification modType);
|
||||
private:
|
||||
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Ftc> m_ppmFtc;
|
||||
|
||||
LtsUtils::RequestHelper *m_requestHelper;
|
||||
QTimer m_updateMissionTimer;
|
||||
|
||||
LtsSession::LtsSession *m_session;
|
||||
QString m_menuGroup;
|
||||
QMap<int, MissionPlanEdit *> m_participantUasEditMap;
|
||||
LOGGER_T m_logger;
|
||||
|
||||
Ui::MissionPlanDialog *m_ui;
|
||||
|
||||
MissionPlanModel *m_missionPlanModel{nullptr};
|
||||
MissionPlanProxyModel *m_missionPlanProxyModel{nullptr};
|
||||
};
|
||||
} // namespace CentralEffectSimulation
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MissionPlanDialog</class>
|
||||
<widget class="QWidget" name="MissionPlanDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1177</width>
|
||||
<height>290</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="LtsDataView::LtsDataView" name="participantsDataView" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsDataView::LtsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsDataView/lts_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+829
@@ -0,0 +1,829 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Dialog to edit drone Simulation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Steve Kemayou, ESZS, 2025-04-08
|
||||
*/
|
||||
|
||||
#include <LtsWidgets/lts_message_dialog.h>
|
||||
#include <Common/LtsCoordTrans/lts_coord_widget.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
|
||||
#include <Plugins/CentralEffectSimulation/ces_data_plugin_interface.h>
|
||||
#include <Plugins/ProjectDataManagement/pdm_gui_plugin_interface.h>
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
|
||||
#include <ParticipantManagement/ppm_translation.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <ProjectDataManagement/pdm_translation.h>
|
||||
#include <ProjectDataManagement/pdm_to_string.h>
|
||||
#include <FileManagement/flm_translation.h>
|
||||
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QTimer>
|
||||
#include "mission_plan_edit.h"
|
||||
#include "ui_mission_plan_edit.h"
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
//static constexpr double s_msConversion = 3.6; // = 3.6 Convert from [km/h] to [m/s]
|
||||
//static constexpr int s_timeMilliConversion = 1000; // 1000 Convert from [s] to [ms]
|
||||
|
||||
MissionPlanEdit::MissionPlanEdit(QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_missionPlanId(0)
|
||||
, m_uiEnabled(false)
|
||||
, m_sitMapGuiIfc(nullptr)
|
||||
, m_ppmCbxGui(nullptr)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_participantTimer(new QTimer(this))
|
||||
, m_logger(getLogger("MissionPlanEdit"))
|
||||
, m_ui(new Ui::MissionPlanEdit)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->nameLineEdit->clear();
|
||||
m_ui->lePrefix->setText(tr("Waypoint"));
|
||||
m_uiRequirements->addRequirement({m_ui->lblMoveStart, [this]() { return hasValidEffectStart(m_ui->dteStartTime); }, tr("Begin time is smaller than current time")});
|
||||
m_uiRequirements->addRequirement({m_ui->lblUASParty, [this]() {return ( !m_ui->cbParty->currentData().isNull());}});
|
||||
m_uiRequirements->addRequirement({m_ui->lblUasParticipant, [this]() {return ( !m_ui->participantCBox->currentData().isNull());}});
|
||||
|
||||
if (!QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
|
||||
{
|
||||
m_uiRequirements->addRequirement({m_ui->lblParticipantStateText, [this]() { return m_participantReady; }});
|
||||
}
|
||||
|
||||
connect(this, &MissionPlanEdit::signalFocused, this, &MissionPlanEdit::onFocus);
|
||||
m_participantTimer->setSingleShot(true);
|
||||
m_participantTimer->setInterval(500);
|
||||
|
||||
connect(m_participantTimer, &QTimer::timeout, this, &MissionPlanEdit::onParticipantTimerTimedout);
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-UAS-Mission-Edit"));
|
||||
}
|
||||
|
||||
MissionPlanEdit::~MissionPlanEdit()
|
||||
{
|
||||
m_sitMapGuiIfc = nullptr;
|
||||
delete m_ui;
|
||||
emit editUasDialogClosed(m_participantData.id());
|
||||
}
|
||||
|
||||
bool MissionPlanEdit::init(const int missionPlanId, LtsSession::LtsSessionDataDds *session, bool asCopy)
|
||||
{
|
||||
m_session = session;
|
||||
m_missionPlanId = missionPlanId;
|
||||
|
||||
if (!m_session->getDtc<ProjectDataManagement::DataInterface>(m_pdmDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << " failed to get pdmDtc";
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (!m_session->getForeignGuiInterface<ParticipantManagement::ForeignGuiComboboxInterface>(m_ppmCbxGui))
|
||||
{
|
||||
ERROR_LOG(m_logger) << " failed to get ppmCbxGui";
|
||||
return false;
|
||||
}
|
||||
// Hide Unused Buttons for now
|
||||
m_ui->cbJumpToStart->hide();
|
||||
m_ui->cbRepeat->hide();
|
||||
//m_ui->chargesCBox->hide();
|
||||
//m_ui->chargesLabel->hide();
|
||||
|
||||
m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc);
|
||||
m_buttonBox->setText(LtsWidgets::DialogButton::Edit, tr("Start Now"));
|
||||
m_buttonBox->setIcon(LtsWidgets::DialogButton::Edit, QIcon(QStringLiteral("icon:media-play.svg")));
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &MissionPlanEdit::onApplyNow);
|
||||
|
||||
m_missionPlan = m_ppmDtc->missionPlan(m_missionPlanId);
|
||||
auto cb = [this, asCopy](const ParticipantManagement::MissionPlan &mission)
|
||||
{
|
||||
//allow participant id of current mission to be displayed.
|
||||
//for other missions if mission start is in future, and not abortet uas participants will not be displayed in the combobox
|
||||
if ((((mission.participantId() == m_missionPlan.participantId()) && !asCopy ) || mission.participantId() <= 0)
|
||||
&& mission.missionStart() <= m_missionPlan.missionStart() && !mission.aborted())
|
||||
return;
|
||||
// if mission is completed or aborted uas participant should be available.
|
||||
if (static_cast<int>(mission.items().size()) == mission.itemsFulfilled() || mission.aborted())
|
||||
return;
|
||||
|
||||
m_usedUasSet.insert(mission.participantId());
|
||||
};
|
||||
m_ppmDtc->missionPlans(cb);
|
||||
|
||||
m_ppmDtc->waitForHistoricalDataParty(1000);
|
||||
m_ppmDtc->waitForHistoricalDataUAS(1000);
|
||||
m_ppmDtc->waitForHistoricalDataParticipant(1000);
|
||||
|
||||
|
||||
connect(m_ui->participantCBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int /*index*/)
|
||||
{
|
||||
setReady(false);
|
||||
const auto pId = m_ui->participantCBox->currentData().toInt();
|
||||
m_participant = m_ppmDtc->participant(pId);
|
||||
const auto dpd = m_ppmDtc->dynamicParticipantData(m_participant.id());
|
||||
DEBUG_LOG(m_logger) << "idx changed! pId: " << pId << ", m_participant.id(): " << m_participant.id() << ", dpd.participantId(): " << dpd.participantId();
|
||||
|
||||
if (dpd.participantId() < 1) // aka. no data for that uas yet, aka. not ready
|
||||
{
|
||||
ERROR_LOG(m_logger) << "no dynamic pdata yet for pId " << pId;
|
||||
setReady(false);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "calling onDynamicParticipantDataChanged !";
|
||||
onDynamicParticipantDataChanged(dpd, DataModification::eAdded);
|
||||
});
|
||||
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::dynamicParticipantDataChanged,
|
||||
this, &MissionPlanEdit::onDynamicParticipantDataChanged);
|
||||
|
||||
|
||||
connect(m_ui->cbParty, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, &MissionPlanEdit::onPartyChanged);
|
||||
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::uASChanged,
|
||||
this, &MissionPlanEdit::onUasChanged);
|
||||
// set Party & UAS Participants Combobox
|
||||
fillParties();
|
||||
setUASCharges();
|
||||
|
||||
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::missionPlanChanged,
|
||||
this, &MissionPlanEdit::onMissionPlanChanged);
|
||||
|
||||
|
||||
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::participantChanged,
|
||||
this, &MissionPlanEdit::onParticipantChanged);
|
||||
if (m_sitMapGuiIfc)
|
||||
{
|
||||
connect(m_ui->pbPosition, &QPushButton::clicked, this, &MissionPlanEdit::onGetPolyline);
|
||||
connect(m_ui->pbClear, &QPushButton::clicked, this, &MissionPlanEdit::clearCoordinates);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->pbPosition->setEnabled(false);
|
||||
m_ui->pbClear->setEnabled(false);
|
||||
}
|
||||
|
||||
// use missionplan data as default if exist
|
||||
setData(missionPlanId);
|
||||
|
||||
enaDisa();
|
||||
|
||||
if(m_participant.id() <= 0 )
|
||||
setReady(false);
|
||||
|
||||
if (m_missionPlanId > 0 && m_session->partitionTime() > m_missionPlan.missionStart() && !asCopy)
|
||||
{
|
||||
enableUiElements(false);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(false);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(false);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(false);
|
||||
}
|
||||
|
||||
if (asCopy)
|
||||
{
|
||||
m_missionPlanId = 0; // mark the edit dialog as new, which makes it a create dialog
|
||||
// if the UAS from the copy already is in used we need to reset to default again
|
||||
if (m_ui->participantCBox->currentIndex()<0)
|
||||
m_ui->participantCBox->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MissionPlanEdit::retranslate()
|
||||
{
|
||||
translate(m_ui, ((m_missionPlanId <= 0) ? QString() : QString::fromStdString(m_missionPlan.name())), m_missionPlanId <= 0, tr("UAS-Waypoints"));
|
||||
}
|
||||
|
||||
|
||||
void MissionPlanEdit::setReady(bool isReady)
|
||||
{
|
||||
m_participantReady = isReady;
|
||||
m_ui->lblParticipantState->setText(QStringLiteral("<span style=\"color:#%1;\">%2</span>")
|
||||
.arg(isReady ? QStringLiteral("00dd00") : QStringLiteral("dd0000"))
|
||||
.arg(isReady ? tr("Ready") : tr("Not ready")));
|
||||
}
|
||||
|
||||
// stolen from Lts/Plugins/ParticipantManagement/Gui/ParticipantInfo/participant_info_dialog.cpp
|
||||
void MissionPlanEdit::onDynamicParticipantDataChanged(const ParticipantManagement::DynamicParticipantData &data, DataModification modType)
|
||||
{
|
||||
if (data.participantId() != m_participant.id() && data.participantId() != 0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "### " << data.participantId() << " != " << m_participant.id() << " (" << (int)modType << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "### " << data.participantId() << " == " << m_participant.id() << " (" << (int)modType << ") !!!";
|
||||
|
||||
// Do not continue on modType == DataModification::eRemove
|
||||
// otherwise for example the icon would look bad (clover with black on black...)
|
||||
if (modType == DataModification::eRemoved)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//Current State
|
||||
if (data.stateHistory().empty())
|
||||
{
|
||||
setReady(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &history = data.stateHistory();
|
||||
|
||||
//LasState is the last "real" state, that has a VBG <=8 (Castastrophic)
|
||||
//It's not the last state received, as there can be other state changes like Sanitation, or NearMiss
|
||||
auto lastState = m_ppmDtc->youngestStateInformation(history/*, true*/ /* debug */);
|
||||
decltype(lastState) youngestState;
|
||||
youngestState.stateTime(0);
|
||||
for (const auto &si : history)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "StateInformation "
|
||||
<< " time=" << si.stateTime()
|
||||
<< " vulnerabilityBits=" << si.vulnerabilityBits()
|
||||
<< " vulnerabilityKindId=" << si.vulnerabilityKindId();
|
||||
if ( youngestState.stateTime() < si.stateTime())
|
||||
youngestState = si;
|
||||
}
|
||||
|
||||
setReady(youngestState.vulnerabilityState() == ProjectDataManagement::VulnerabilityState::CombatReady);
|
||||
}
|
||||
|
||||
void MissionPlanEdit::onMissionPlanChanged(const ParticipantManagement::MissionPlan &data, const DataModification modType)
|
||||
{
|
||||
Q_UNUSED(modType)
|
||||
if (data.id() != m_missionPlanId)
|
||||
{
|
||||
// Check, if mission is completed
|
||||
if (static_cast<int>(data.items().size()) != data.itemsFulfilled())
|
||||
return;
|
||||
if (m_usedUasSet.contains(data.participantId()))
|
||||
{
|
||||
m_usedUasSet.remove(data.participantId());
|
||||
fillParticipants();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool enabled;
|
||||
if (m_session->partitionTime() > m_missionPlan.missionStart() && !m_missionPlan.aborted())
|
||||
enabled = false;
|
||||
else
|
||||
enabled = true;
|
||||
|
||||
enableUiElements(enabled);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(enabled);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(enabled);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(enabled);
|
||||
|
||||
if (static_cast<int>(data.items().size()) == data.itemsFulfilled()
|
||||
&& m_usedUasSet.remove(data.participantId()))
|
||||
fillParticipants();
|
||||
|
||||
}
|
||||
|
||||
void MissionPlanEdit::onModifyMissionPlanReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
if (!replyObject.error())
|
||||
m_sitMapGuiIfc->removePreviewObject();
|
||||
}
|
||||
|
||||
void MissionPlanEdit::onSetMissionActionFulfilledReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
DEBUG_LOG(m_logger)<<" -- MissionPlanEdit - onSetMissionActionFulfilledReply: "<<replyObject.error();
|
||||
}
|
||||
|
||||
QStringList MissionPlanEdit::tableColLabelList() const
|
||||
{
|
||||
QStringList wayPointsHeaders;
|
||||
wayPointsHeaders << tr("Identifier")
|
||||
<< tr("Position")
|
||||
<< tr("Altitude")
|
||||
<< tr("Idle Time [s]")
|
||||
<< tr("Charges");
|
||||
return wayPointsHeaders;
|
||||
}
|
||||
|
||||
void MissionPlanEdit::setAllUiElementsEnabled(bool enable)
|
||||
{
|
||||
enableUiElements(enable);
|
||||
}
|
||||
|
||||
ParticipantManagement::MissionPlan MissionPlanEdit::missionPlan() const
|
||||
{
|
||||
return m_missionPlan;
|
||||
}
|
||||
|
||||
bool MissionPlanEdit::isUiEnabled() const
|
||||
{
|
||||
return m_uiEnabled;
|
||||
}
|
||||
void MissionPlanEdit::enaDisa()
|
||||
{
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled((m_ui->tableWidget->rowCount() > 0));
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled((m_ui->tableWidget->rowCount() > 0));
|
||||
}
|
||||
|
||||
bool MissionPlanEdit::apply()
|
||||
{
|
||||
// check uas switched to manual mode before proceeding
|
||||
ParticipantManagement::UAS uasP = m_ppmDtc->getUasByParticipantId(m_ui->participantCBox->currentData().toInt(), m_session->exerciseId());
|
||||
|
||||
if (uasP.uasState() == ProjectDataManagement::UasState_def::Manual
|
||||
&& uasP.participantId() != m_missionPlan.participantId())
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Waypoints can't be saved!: Uas switched to %1-Mode").arg(ProjectDataManagement::toString(uasP.uasState())));
|
||||
return false;
|
||||
}
|
||||
ParticipantManagement::ModifyMissionPlanRequest req;
|
||||
req.id(m_missionPlanId);
|
||||
req.missionStart(m_ui->dteStartTime->msecsSinceEpoch());
|
||||
req.participantId(m_ui->participantCBox->currentData().toInt());
|
||||
req.jumpToStart(false);
|
||||
req.repeat(false);
|
||||
req.name(m_ui->nameLineEdit->text().toStdString());
|
||||
req.items(itemsRequestContent());
|
||||
|
||||
return m_requestHelper->startSingleRequest([this, req]()
|
||||
{
|
||||
return m_ppmFtc->modifyMissionPlanRequest(req, this);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void MissionPlanEdit::clearCoordinates()
|
||||
{
|
||||
if (m_ui)
|
||||
{
|
||||
m_ui->tableWidget->clearContents();
|
||||
m_ui->tableWidget->setRowCount(0);
|
||||
enaDisa();
|
||||
}
|
||||
// remove PreviewObject:
|
||||
if ( m_sitMapGuiIfc && this->amIFocused())
|
||||
m_sitMapGuiIfc->removePreviewObject();
|
||||
}
|
||||
|
||||
void MissionPlanEdit::clearContent()
|
||||
{
|
||||
m_ui->lePrefix->clear();
|
||||
m_ui->cbRepeat->setChecked(false);
|
||||
//m_ui->cbJump->setChecked(false);
|
||||
|
||||
clearCoordinates();
|
||||
}
|
||||
|
||||
void MissionPlanEdit::enableUiElements(bool enable)
|
||||
{
|
||||
m_ui->tableWidget->setEnabled(enable);
|
||||
m_ui->pbPosition->setEnabled(enable);
|
||||
m_ui->pbClear->setEnabled(enable);
|
||||
m_ui->spIdleTime->setEnabled(enable);
|
||||
m_ui->dteStartTime->setEnabled(enable);
|
||||
m_ui->cbParty->setEnabled(enable);
|
||||
m_ui->participantCBox->setEnabled(enable);
|
||||
m_ui->chargesCBox->setEnabled(enable);
|
||||
m_ui->nameLineEdit->setEnabled(enable);
|
||||
m_ui->lePrefix->setEnabled(enable);
|
||||
m_ui->cbRepeat->setEnabled(enable);
|
||||
m_ui->cbJumpToStart->setEnabled(enable);
|
||||
m_ui->spAltitude->setEnabled(false);
|
||||
m_uiEnabled = enable;
|
||||
|
||||
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled((m_ui->tableWidget->rowCount() > 0 && !enable)); // in case edit is blocked by user
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled((m_ui->tableWidget->rowCount() > 0 && !enable)); // in case edit is blocked by user
|
||||
}
|
||||
|
||||
bool MissionPlanEdit::hasValidEffectStart(LtsWidgets::LtsDateTimeEdit *dte) const
|
||||
{ // if there is visible a enabled/disable checkbox -> also allow 0 as effect start
|
||||
const bool bEmptyAllowed = dte->isCheckable();
|
||||
const auto ms = dte->msecsSinceEpoch();
|
||||
// no effect start -> ok
|
||||
if (bEmptyAllowed && ms == 0)
|
||||
return true;
|
||||
return ms > m_session->partitionTime();
|
||||
}
|
||||
|
||||
void MissionPlanEdit::initTableHeader()
|
||||
{
|
||||
m_ui->tableWidget->setColumnCount(tableColLabelList().count());
|
||||
m_ui->tableWidget->setHorizontalHeaderLabels(tableColLabelList());
|
||||
m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
void MissionPlanEdit::insertPos(const WayPointParam &wpp)
|
||||
{
|
||||
const int rowCount = m_ui->tableWidget->rowCount();
|
||||
// insert waypoint label
|
||||
m_ui->tableWidget->insertRow(rowCount);
|
||||
QLineEdit *le = new QLineEdit;
|
||||
le->setText(wpp.identifier);
|
||||
m_ui->tableWidget->setCellWidget(rowCount, Name, le);
|
||||
|
||||
//insert Coordinates
|
||||
LtsCoordWidget::LtsCoordWidget *wdg = new LtsCoordWidget::LtsCoordWidget();
|
||||
wdg->setCoordinate(wpp.lon, wpp.lat);
|
||||
wdg->setObjectName(QStringLiteral("positionEdit_") + QString::number(rowCount));
|
||||
wdg->setDisplayType(LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS);
|
||||
m_ui->tableWidget->setCellWidget(rowCount, Position, wdg);
|
||||
|
||||
// insert Altitude [m]
|
||||
QSpinBox *sbAltitude = new QSpinBox;
|
||||
sbAltitude->setMinimum(0);
|
||||
sbAltitude->setMaximum(120);
|
||||
sbAltitude->setValue(wpp.z);
|
||||
m_ui->tableWidget->setCellWidget(rowCount, Altitude, sbAltitude);
|
||||
|
||||
// insert Idle Time [sec]
|
||||
QSpinBox *sbDelay = new QSpinBox;
|
||||
sbDelay->setMinimum(m_ui->spIdleTime->minimum());
|
||||
sbDelay->setMaximum(m_ui->spIdleTime->maximum());
|
||||
sbDelay->setValue(wpp.idleTime);
|
||||
m_ui->tableWidget->setCellWidget(rowCount, IdleTime, sbDelay);
|
||||
|
||||
// insert charges
|
||||
QComboBox *ccbox = new QComboBox;
|
||||
|
||||
ccbox->insertItem(m_ui->chargesCBox->count(), tr("Undefined"));
|
||||
for(const auto &c : m_uasCharges.toStdMap())
|
||||
{
|
||||
ccbox->addItem(c.second, c.first);
|
||||
}
|
||||
int idx = ccbox->findData(QVariant::fromValue(wpp.chargeTypeId));
|
||||
ccbox->setCurrentIndex(idx > 0 ? idx : 0 );
|
||||
m_ui->tableWidget->setCellWidget(rowCount, Charges, ccbox);
|
||||
}
|
||||
|
||||
void MissionPlanEdit::showPreview(bool show)
|
||||
{
|
||||
if (m_sitMapGuiIfc)
|
||||
{
|
||||
if (show)
|
||||
m_sitMapGuiIfc->displayPreviewObject(this, m_polyline, false);
|
||||
else
|
||||
m_sitMapGuiIfc->removePreviewObject();
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<ParticipantManagement::MissionItem> MissionPlanEdit::itemsRequestContent()
|
||||
{
|
||||
const int missionItemCount = m_ui->tableWidget->rowCount();
|
||||
std::vector<ParticipantManagement::MissionItem> missionItems;
|
||||
using ParticipantManagement::MissionActionType;
|
||||
|
||||
const QVector<MissionActionType> actiontypes{
|
||||
MissionActionType::MoveTo, MissionActionType::Loiter, MissionActionType::Attack}; // first action always MoveTo
|
||||
int itemNumber = 0;
|
||||
for (int i = 0; i < missionItemCount; i++)
|
||||
{
|
||||
ParticipantManagement::MissionItem msi;
|
||||
QWidget *nameWidget = m_ui->tableWidget->cellWidget(i, Name);
|
||||
const QString name = static_cast<QLineEdit *>(nameWidget)->text();
|
||||
|
||||
QWidget *altitudeWidget = m_ui->tableWidget->cellWidget(i, Altitude);
|
||||
const int altitude = static_cast<QSpinBox *>(altitudeWidget)->value();
|
||||
|
||||
QWidget *posWidget = m_ui->tableWidget->cellWidget(i, Position);
|
||||
const QPointF point = static_cast<LtsCoordWidget::LtsCoordWidget *>(posWidget)->coordinate();
|
||||
Core::GeoPosition geoPos(point.x(), point.y(), altitude);
|
||||
|
||||
|
||||
QWidget *idleTimeWidget = m_ui->tableWidget->cellWidget(i, IdleTime);
|
||||
const int idleTime = static_cast<QSpinBox *>(idleTimeWidget)->value();
|
||||
|
||||
QWidget *chargesWidget = m_ui->tableWidget->cellWidget(i, Charges);
|
||||
const int chargeTypeId = static_cast<QComboBox *>(chargesWidget)->currentData().toInt();
|
||||
|
||||
// phase 1 // moveTo
|
||||
// phase 2 // idleTime move
|
||||
// phase 3 // attack
|
||||
|
||||
const QString &msiName = name;
|
||||
int actionNumber = 0;
|
||||
const QString &msaName = QStringLiteral("%1_%2").arg(m_ui->nameLineEdit->text()).arg(name);
|
||||
|
||||
{
|
||||
ParticipantManagement::MissionAction actionMoveTo;
|
||||
actionMoveTo.actionType(ParticipantManagement::MissionActionType::MoveTo);
|
||||
actionMoveTo.duration(0); // not define hier
|
||||
actionMoveTo.actionNumber(actionNumber++);
|
||||
actionMoveTo.name(msaName.toStdString());
|
||||
actionMoveTo.itemNumber(itemNumber);
|
||||
actionMoveTo.planId(m_missionPlan.id());
|
||||
|
||||
QJsonObject jsoMoveTo;
|
||||
jsoMoveTo.insert(QStringLiteral("location_x"), point.x());
|
||||
jsoMoveTo.insert(QStringLiteral("location_y"), point.y());
|
||||
jsoMoveTo.insert(QStringLiteral("location_z"), altitude); //
|
||||
const QString props = QString::fromUtf8(QJsonDocument(jsoMoveTo).toJson(QJsonDocument::Compact));
|
||||
actionMoveTo.properties(props.toStdString());
|
||||
msi.actions().push_back(actionMoveTo);
|
||||
}
|
||||
|
||||
|
||||
if (idleTime > 0)
|
||||
{
|
||||
ParticipantManagement::MissionAction actionLoiter;
|
||||
actionLoiter.actionType(ParticipantManagement::MissionActionType::Loiter);
|
||||
actionLoiter.duration(idleTime); // idleTime
|
||||
actionLoiter.actionNumber(actionNumber++);
|
||||
actionLoiter.itemNumber(itemNumber);
|
||||
actionLoiter.name(msaName.toStdString());
|
||||
actionLoiter.planId(m_missionPlan.id());
|
||||
msi.actions().push_back(actionLoiter);
|
||||
}
|
||||
|
||||
|
||||
if (chargeTypeId > 0)
|
||||
{
|
||||
ParticipantManagement::MissionAction actionAttack;
|
||||
actionAttack.actionType(ParticipantManagement::MissionActionType::Attack);
|
||||
actionAttack.duration(idleTime); // idleTime
|
||||
actionAttack.actionNumber(actionNumber++);
|
||||
actionAttack.itemNumber(itemNumber);
|
||||
actionAttack.name(msaName.toStdString());
|
||||
actionAttack.planId(m_missionPlan.id());
|
||||
|
||||
QJsonObject jsoAttack;
|
||||
jsoAttack.insert(QStringLiteral("location_x"), point.x());
|
||||
jsoAttack.insert(QStringLiteral("location_y"), point.y());
|
||||
jsoAttack.insert(QStringLiteral("location_z"), 0); //
|
||||
jsoAttack.insert(QStringLiteral("chargeTypeId"), chargeTypeId); // chargeTypeID
|
||||
const QString props = QString::fromUtf8(QJsonDocument(jsoAttack).toJson(QJsonDocument::Compact));
|
||||
actionAttack.properties(props.toStdString());
|
||||
|
||||
msi.actions().push_back(actionAttack);
|
||||
}
|
||||
|
||||
|
||||
msi.itemNumber(itemNumber++);
|
||||
msi.location(geoPos);
|
||||
msi.name(msiName.toStdString());
|
||||
missionItems.push_back(msi);
|
||||
|
||||
}
|
||||
|
||||
return missionItems;
|
||||
}
|
||||
|
||||
void MissionPlanEdit::setUASCharges()
|
||||
{
|
||||
const auto chargesForGearClass = m_pdmDtc->chargeTypes();
|
||||
m_ui->chargesCBox->clear();
|
||||
m_ui->chargesCBox->insertItem(m_ui->chargesCBox->count(), tr("Undefined"));
|
||||
for (const ProjectDataManagement::ChargeType &chargeType : qAsConst(chargesForGearClass))
|
||||
{
|
||||
// NOTE: igniterType/IgniterFunciton = 0 as long as MissionPlan does not contain values
|
||||
if (!m_pdmDtc->isUasDroppable(chargeType.id(),0,0))
|
||||
continue;
|
||||
DEBUG_LOG(m_logger) << " fillCharges"
|
||||
<< ", id=" << chargeType.id()
|
||||
<< ", name= " << chargeType.name();
|
||||
|
||||
m_ui->chargesCBox->addItem(QString::fromStdString(chargeType.name()), chargeType.id());
|
||||
m_uasCharges.insert(chargeType.id(), QString::fromStdString(chargeType.name()));
|
||||
}
|
||||
m_ui->chargesCBox->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void MissionPlanEdit::setData(int mpId)
|
||||
{
|
||||
initTableHeader();
|
||||
|
||||
if (mpId < 0 )
|
||||
return;
|
||||
|
||||
m_missionPlan = m_ppmDtc->missionPlan(mpId);
|
||||
m_participantData = m_ppmDtc->participant(m_missionPlan.participantId());
|
||||
m_ui->dteStartTime->setMinimumTimeMSec(m_session->partitionTime());
|
||||
m_ui->dteStartTime->setRetrieveCurrentTimeCallback([this](){return m_session->partitionTime();});
|
||||
m_ui->dteStartTime->setMsecsSinceEpoch(m_missionPlan.missionStart());
|
||||
m_ui->nameLineEdit->setText(QString::fromStdString(m_missionPlan.name()));
|
||||
|
||||
// get/set current party
|
||||
if (m_participantData.partyId() > 0)
|
||||
{
|
||||
const int partyIdx = m_ui->cbParty->findData(QVariant::fromValue(m_participantData.partyId()));
|
||||
m_ui->cbParty->setCurrentIndex(partyIdx);
|
||||
|
||||
const int ppIdx = m_ui->participantCBox->findData(QVariant::fromValue(m_missionPlan.participantId()));
|
||||
m_ui->participantCBox->setCurrentIndex(ppIdx);
|
||||
}
|
||||
|
||||
for (const auto &item : qAsConst(m_missionPlan.items()) )
|
||||
{
|
||||
const std::vector<ParticipantManagement::MissionAction> &msaVec = item.actions();
|
||||
WayPointParam wpp;
|
||||
wpp.identifier = QString::fromStdString(item.name());
|
||||
wpp.lat = item.location().lat();
|
||||
wpp.lon = item.location().lon();
|
||||
wpp.z = item.location().z();
|
||||
for (auto const &msa : msaVec)
|
||||
{
|
||||
if (msa.actionType() == ParticipantManagement::MissionActionType::Loiter)
|
||||
wpp.idleTime = msa.duration();
|
||||
|
||||
if (msa.actionType() == ParticipantManagement::MissionActionType::Attack)
|
||||
{
|
||||
const QJsonObject &obj = QJsonDocument::fromJson(QByteArray::fromStdString(msa.properties())).object();
|
||||
wpp.chargeTypeId = obj.value(QLatin1String("chargeTypeId")).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
insertPos(wpp);
|
||||
}
|
||||
|
||||
//
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled((m_ui->tableWidget->rowCount() > 0));
|
||||
|
||||
}
|
||||
|
||||
void MissionPlanEdit::fillParties()
|
||||
{
|
||||
m_ppmCbxGui->fillPartyComboBox(m_ui->cbParty);
|
||||
m_ui->cbParty->setCurrentIndex(0);
|
||||
fillParticipants();
|
||||
}
|
||||
|
||||
void MissionPlanEdit::fillParticipants()
|
||||
{
|
||||
QVector<ParticipantManagement::Participant> participants;
|
||||
const int partyId = m_ui->cbParty->currentData().toInt();
|
||||
gatherUASParticipants(partyId, participants);
|
||||
|
||||
m_ui->participantCBox->clear();
|
||||
for (const auto &participant : participants)
|
||||
{
|
||||
QString uasString = QStringLiteral("%1 (%2)").arg(m_ppmDtc->hierarchyFromParticipant(participant.id()));
|
||||
if (uasString.isEmpty() || m_usedUasSet.contains(participant.id()))
|
||||
continue;
|
||||
const ParticipantManagement::UAS &uasP = m_ppmDtc->getUasByParticipantId(participant.id(), m_session->exerciseId());
|
||||
uasString = uasString.arg(ProjectDataManagement::toString(uasP.uasState()));
|
||||
m_ui->participantCBox->addItem(uasString, participant.id());
|
||||
}
|
||||
if (m_missionPlan.id() > 0)
|
||||
m_ui->participantCBox->setCurrentIndex(m_ui->participantCBox->findData(QVariant::fromValue(m_missionPlan.participantId())));
|
||||
//Fallback to first entry
|
||||
if (m_ui->participantCBox->currentIndex()<0)
|
||||
m_ui->participantCBox->setCurrentIndex(0);
|
||||
|
||||
}
|
||||
|
||||
void MissionPlanEdit::gatherUASParticipants(int partyId, QVector<ParticipantManagement::Participant> &participant)
|
||||
{
|
||||
auto cb = [this, &partyId, &participant](const ParticipantManagement::Participant &p)
|
||||
{
|
||||
if (p.isDeleted() || p.partyId() != partyId)
|
||||
return;
|
||||
const ParticipantManagement::ParticipantData &ppData = m_ppmDtc->convertParticipantToParticipantData(p);
|
||||
const ParticipantManagement::Type &&ppType = m_ppmDtc->type(ppData.typeId());
|
||||
const QJsonObject typeProperties(QJsonDocument::fromJson(QByteArray::fromStdString(ppType.properties())).object());
|
||||
if (typeProperties.isEmpty()
|
||||
|| ppType.typeClass() != ParticipantManagement::TypeClass::Aircraft
|
||||
|| !typeProperties[QStringLiteral("isUAS")].toBool(false))
|
||||
return;
|
||||
|
||||
participant.push_back(p);
|
||||
};
|
||||
m_ppmDtc->participants(cb);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ParticipantUASEdit::onParticipantTimerTimedout
|
||||
* method is called when an participant is updated. Note that onParticipantTimerTimedout()
|
||||
* will be called by once even if many onParticipantChanged signal come in.
|
||||
*/
|
||||
void MissionPlanEdit::onParticipantTimerTimedout()
|
||||
{
|
||||
fillParticipants();
|
||||
}
|
||||
|
||||
void MissionPlanEdit::onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType)
|
||||
{
|
||||
Q_UNUSED(data)
|
||||
Q_UNUSED(modType)
|
||||
|
||||
m_participantTimer->start();
|
||||
}
|
||||
|
||||
void MissionPlanEdit::onPartyChanged()
|
||||
{
|
||||
m_ui->participantCBox->clear();
|
||||
fillParticipants();
|
||||
}
|
||||
|
||||
void MissionPlanEdit::onGetPolyline()
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
|
||||
if (m_sitMapGuiIfc->mapMode() != SituationMap::MapMode::MapMode_2D)
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Only available in 2D mode"));
|
||||
return;
|
||||
}
|
||||
|
||||
QPolygonF coordinates;
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
LtsCoordWidget::LtsCoordWidget *w = findChild<LtsCoordWidget::LtsCoordWidget *>(QStringLiteral("positionEdit_%1").arg(i));
|
||||
if (!w)
|
||||
break;
|
||||
if (!w->coordinate().isNull())
|
||||
coordinates << w->coordinate();
|
||||
++i;
|
||||
}
|
||||
|
||||
m_sitMapGuiIfc->getPolyline(this,
|
||||
SLOT(onPolylineData(QPolygonF)),
|
||||
nullptr,
|
||||
2,
|
||||
11,
|
||||
-1,
|
||||
-1,
|
||||
coordinates);
|
||||
}
|
||||
|
||||
void MissionPlanEdit::onPolylineData(const QPolygonF &polyline)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " numberOfPoints: " << polyline.size();
|
||||
|
||||
if (polyline.size() < 2)
|
||||
return;
|
||||
|
||||
m_polyline = polyline;
|
||||
|
||||
clearCoordinates();
|
||||
|
||||
for (int i = 0; i < polyline.size(); i++)
|
||||
{
|
||||
WayPointParam wp;
|
||||
wp.lon = polyline.at(i).x();
|
||||
wp.lat = polyline.at(i).y();
|
||||
wp.identifier = m_ui->lePrefix->text() + QLatin1Char('_') + QString::number(i + 1);
|
||||
wp.z = m_ui->spAltitude->value();
|
||||
wp.idleTime = m_ui->spIdleTime->value();
|
||||
wp.chargeTypeId = m_ui->chargesCBox->currentIndex();
|
||||
insertPos(wp);
|
||||
}
|
||||
|
||||
// create PreviewObject:
|
||||
m_sitMapGuiIfc->displayPreviewObject(this, polyline, false);
|
||||
enaDisa();
|
||||
|
||||
}
|
||||
|
||||
void MissionPlanEdit::onFocus()
|
||||
{
|
||||
showPreview(true);
|
||||
m_sitMapGuiIfc->displayPreviewObject(this, m_polyline, false);
|
||||
}
|
||||
|
||||
void MissionPlanEdit::onApplyNow()
|
||||
{
|
||||
QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(m_session->partitionTime());
|
||||
m_ui->dteStartTime->setMsecsSinceEpoch(dateTime.addSecs(10).toMSecsSinceEpoch()); //set time first THEN check for requirements
|
||||
if (m_ui->tableWidget->rowCount() < 2 || !m_uiRequirements->checkRequirements())
|
||||
return;
|
||||
if (apply())
|
||||
{
|
||||
enableUiElements(false);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setEnabled(false);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Ok)->setEnabled(false);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Apply)->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MissionPlanEdit::onUasChanged(const ParticipantManagement::UAS &uas)
|
||||
{
|
||||
Q_UNUSED(uas)
|
||||
const int ppId = m_ui->participantCBox->currentData().toInt();
|
||||
fillParticipants();
|
||||
|
||||
const int index = m_ui->participantCBox->findData(ppId);
|
||||
if( index < 0)
|
||||
return;
|
||||
m_ui->participantCBox->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}// namspace CentralEffectSimulation
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Dialog to edit drone Simulation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Steve Kemayou, ESZS, 2025-04-08
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsWidgets/lts_frameless_dialog.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <CentralEffectSimulation/ces_ftc.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <Plugins/ProjectDataManagement/pdm_data_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
|
||||
|
||||
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <ParticipantManagement/ppm_ftc.h>
|
||||
#include <CentralEffectSimulation/ces_dtc.h>
|
||||
#include <LtsWidgets/lts_date_time_edit.h>
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
#include "logger.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class MissionPlanEdit;
|
||||
}
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
struct WayPointParam
|
||||
{
|
||||
double lon;
|
||||
double lat;
|
||||
double z = 0.0;
|
||||
int idleTime = 0;
|
||||
double speed = 0.0;
|
||||
int chargeTypeId = -1;
|
||||
QString identifier;
|
||||
};
|
||||
|
||||
class MissionPlanEdit : public LtsWidgets::LtsDialog
|
||||
, protected ParticipantManagement::Interface::Ftc::ModifyMissionPlanReplyHandler
|
||||
, protected ParticipantManagement::Interface::Ftc::SetMissionActionFulfilledReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum SegmentColumns
|
||||
{
|
||||
Name,
|
||||
Position,
|
||||
Altitude,
|
||||
IdleTime, // [sec]
|
||||
Charges
|
||||
};
|
||||
|
||||
explicit MissionPlanEdit(QWidget *parent = nullptr);
|
||||
~MissionPlanEdit();
|
||||
|
||||
bool init(const int missionPlanId, LtsSession::LtsSessionDataDds *session, bool asCopy = false);
|
||||
|
||||
void retranslate() override;
|
||||
|
||||
void onModifyMissionPlanReply(const Core::FunctionReplyObject &replyObject) override;
|
||||
void onSetMissionActionFulfilledReply(const Core::FunctionReplyObject &replyObject) override;
|
||||
QStringList tableColLabelList() const;
|
||||
void setAllUiElementsEnabled(bool enable);
|
||||
ParticipantManagement::MissionPlan missionPlan() const;
|
||||
bool isUiEnabled() const;
|
||||
signals:
|
||||
void editUasDialogClosed(const int participantId);
|
||||
|
||||
private:
|
||||
void enaDisa();
|
||||
bool apply() override;
|
||||
void clearCoordinates();
|
||||
void clearContent();
|
||||
void enableUiElements(bool enable);
|
||||
bool hasValidEffectStart(LtsWidgets::LtsDateTimeEdit *dte) const;
|
||||
void initTableHeader();
|
||||
void insertPos(const WayPointParam &wpp);
|
||||
void showPreview(bool show);
|
||||
const std::vector<ParticipantManagement::MissionItem> itemsRequestContent();
|
||||
|
||||
void setUASCharges();
|
||||
void setData(int mpId);
|
||||
void fillParties();
|
||||
void fillParticipants();
|
||||
void gatherUASParticipants(int partyId, QVector<ParticipantManagement::Participant> &participant);
|
||||
void setReady(bool isReady);
|
||||
|
||||
private slots:
|
||||
void onParticipantTimerTimedout();
|
||||
void onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType);
|
||||
void onPartyChanged();
|
||||
void onGetPolyline();
|
||||
void onPolylineData(const QPolygonF &polyline); // callback for onGetPolyline()
|
||||
void onFocus();
|
||||
void onApplyNow();
|
||||
void onUasChanged(const ParticipantManagement::UAS &uas);
|
||||
void onDynamicParticipantDataChanged(const ParticipantManagement::DynamicParticipantData &data, DataModification modType);
|
||||
void onMissionPlanChanged(const ParticipantManagement::MissionPlan &data, const DataModification modType);
|
||||
|
||||
private:
|
||||
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
|
||||
std::shared_ptr<ProjectDataManagement::Interface::Dtc> m_pdmDtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Ftc> m_ppmFtc;
|
||||
LtsSession::LtsSessionDataDds *m_session;
|
||||
ParticipantManagement::Participant m_participantData;
|
||||
ParticipantManagement::MissionPlan m_missionPlan;
|
||||
int m_missionPlanId;
|
||||
bool m_uiEnabled;
|
||||
QSet<int> m_usedUasSet;
|
||||
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
|
||||
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> m_ppmCbxGui;
|
||||
LtsUtils::RequestHelper *m_requestHelper;
|
||||
QMap<int, QString> m_uasCharges;
|
||||
QTimer *m_participantTimer; // used when participant were updated
|
||||
|
||||
QPolygonF m_polyline;
|
||||
ParticipantManagement::Participant m_participant;
|
||||
bool m_participantReady { false };
|
||||
LOGGER_T m_logger;
|
||||
|
||||
Ui::MissionPlanEdit *m_ui;
|
||||
};
|
||||
|
||||
}
|
||||
+353
@@ -0,0 +1,353 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MissionPlanEdit</class>
|
||||
<widget class="QWidget" name="MissionPlanEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>839</width>
|
||||
<height>568</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="7" column="3">
|
||||
<widget class="QLabel" name="lblParticipantState">
|
||||
<property name="text">
|
||||
<string notr="true">-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2" rowspan="2">
|
||||
<widget class="QLabel" name="lblUasParticipant">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>UAS Participant:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QCheckBox" name="cbJumpToStart">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Jump To Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" rowspan="2" colspan="3">
|
||||
<widget class="LtsWidgets::LtsDateTimeEdit" name="dteStartTime" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3" rowspan="2">
|
||||
<widget class="QComboBox" name="participantCBox"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lblMoveStart">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start Time:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLabel" name="idleLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Idle Time [s]:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="chargesLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Charge Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" rowspan="2">
|
||||
<widget class="QComboBox" name="cbParty"/>
|
||||
</item>
|
||||
<item row="0" column="7">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="lblUASParty">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>UAS Units:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5" rowspan="2">
|
||||
<widget class="QSpinBox" name="spIdleTime">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="6">
|
||||
<widget class="QCheckBox" name="cbRepeat">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Repeat</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QLabel" name="lblParticipantStateText">
|
||||
<property name="text">
|
||||
<string>Participant state:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="nameLineEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" rowspan="2" colspan="3">
|
||||
<widget class="QComboBox" name="chargesCBox"/>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit Waypoints in Map:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Prefix:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="5">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0">
|
||||
<property name="spacing">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetFixedSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbPosition">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/style/position.svg</normaloff>:/style/position.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbClear">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>:/style/remove.svg</normaloff>:/style/remove.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="5">
|
||||
<widget class="QLineEdit" name="lePrefix">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Altitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="5">
|
||||
<widget class="QSpinBox" name="spAltitude">
|
||||
<property name="maximum">
|
||||
<number>120</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>20</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsWidgets::LtsDateTimeEdit</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsWidgets/lts_date_time_edit.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Dialog to edit drone Simulation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Steve Kemayou, ESZS, 2025-04-08
|
||||
*/
|
||||
|
||||
|
||||
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
#include <ProjectDataManagement/pdm_translation.h>
|
||||
|
||||
#include "mission_plan_model.h"
|
||||
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
/*!
|
||||
* \brief MissionPlanModel::MissionPlanModel
|
||||
* \param parent
|
||||
*/
|
||||
MissionPlanModel::MissionPlanModel(QObject *parent)
|
||||
: LtsWidgets::LtsAbstractTableModel<ParticipantManagement::MissionPlan>(
|
||||
{tr("Name"),
|
||||
tr("Mission Start"),
|
||||
tr("Actions [fulfilled / Count]"),
|
||||
tr("Fulfilled"),
|
||||
tr("Participant"),
|
||||
tr("UAS State"),
|
||||
tr("Current Mission"),
|
||||
tr("Aborted")},
|
||||
parent)
|
||||
, m_ppmDtc(nullptr)
|
||||
, m_logger(getLogger("MissionPlanModel"))
|
||||
{
|
||||
|
||||
}
|
||||
/*!
|
||||
* \brief MissionPlanModel::data
|
||||
* \param index
|
||||
* \param role
|
||||
* \return
|
||||
*/
|
||||
QVariant MissionPlanModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole || !indexIsValid(index))
|
||||
return QVariant();
|
||||
|
||||
const ParticipantManagement::MissionPlan &mp = m_vecData.at(index.row());
|
||||
switch (index.column())
|
||||
{
|
||||
|
||||
case Columns::Name:
|
||||
return QString::fromStdString(mp.name());
|
||||
case Columns::MissionStart:
|
||||
return QDateTime::fromMSecsSinceEpoch(mp.missionStart());
|
||||
case Columns::Fulfilled:
|
||||
return QDateTime::fromMSecsSinceEpoch(mp.fulfilled());
|
||||
case Columns::ItemsCountAndFulfilled:
|
||||
{
|
||||
int actionsFulfilled = 0;
|
||||
int actionsCount = 0;
|
||||
for (const auto &item : mp.items())
|
||||
{
|
||||
actionsFulfilled += item.actionsFulfilled();
|
||||
actionsCount += item.actions().size();
|
||||
}
|
||||
return QStringLiteral("%1/%2").arg(actionsFulfilled).arg(actionsCount);// item fulfilled / item count;
|
||||
}
|
||||
case Columns::Participant:
|
||||
{
|
||||
const auto &participant = m_ppmDtc->participant(mp.participantId());
|
||||
return QString::number(mp.participantId());//QString::fromStdString(participant.designator());
|
||||
}
|
||||
case Columns::UasState:
|
||||
{
|
||||
const auto &uas = m_ppmDtc->getUasByParticipantId(mp.participantId(), m_exerciseId);
|
||||
return ProjectDataManagement::toString(uas.uasState());
|
||||
}
|
||||
case Columns::CurrentMission:
|
||||
{
|
||||
return currentJob2String(mp);
|
||||
}
|
||||
case Columns::Aborted:
|
||||
{
|
||||
return mp.aborted();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief MissionPlanModel::initModel
|
||||
* \param ppmDtc
|
||||
* \return
|
||||
*/
|
||||
bool MissionPlanModel::initModel(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc, int exerciseId)
|
||||
{
|
||||
m_ppmDtc = ppmDtc;
|
||||
m_ppmDtc->enableMissionPlan(true);
|
||||
|
||||
m_exerciseId = exerciseId;
|
||||
|
||||
if (!m_ppmDtc->isUASEnabled())
|
||||
m_ppmDtc->enableUAS();
|
||||
|
||||
m_ppmDtc->waitForHistoricalDataUAS(1000);
|
||||
|
||||
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::missionPlanChanged,
|
||||
this, &MissionPlanModel::onMissionPlanChanged);
|
||||
|
||||
auto cb = [this](const ParticipantManagement::MissionPlan &msp)
|
||||
{
|
||||
onMissionPlanChanged(msp, DataModification::eAdded);
|
||||
};
|
||||
m_ppmDtc->missionPlans(cb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString MissionPlanModel::currentJob2String(const ParticipantManagement::MissionPlan &missionPlan) const
|
||||
{
|
||||
// get current action
|
||||
// get latest actionType
|
||||
ParticipantManagement::MissionAction currAction = m_ppmDtc->currentMissionAction(missionPlan.id());
|
||||
if (currAction.planId() == 0 ||
|
||||
static_cast<int>(missionPlan.items().size()) == missionPlan.itemsFulfilled())
|
||||
return tr(" Mission Complete ");
|
||||
|
||||
switch (currAction.actionType().underlying())
|
||||
{
|
||||
case ParticipantManagement::MissionActionType::MoveTo:
|
||||
{
|
||||
return tr("Move to WP %1").arg(currAction.itemNumber()+1);
|
||||
}
|
||||
case ParticipantManagement::MissionActionType::Loiter:
|
||||
{
|
||||
return tr("WP %1: Loiter %2 sec.").arg(currAction.itemNumber()+1).arg(currAction.duration());
|
||||
}
|
||||
case ParticipantManagement::MissionActionType::Attack:
|
||||
{
|
||||
return tr("WP %1: Drop Charge").arg(currAction.itemNumber()+1);
|
||||
}
|
||||
default:
|
||||
return tr("Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief MissionPlanModel::onParticipantUASChanged
|
||||
* \param data
|
||||
* \param modType
|
||||
*/
|
||||
void MissionPlanModel::onMissionPlanChanged(const ParticipantManagement::MissionPlan &data, const DataModification modType)
|
||||
{
|
||||
const int id = data.id();
|
||||
int row = findRowForId(id);
|
||||
DEBUG_LOG(m_logger)<<"MISSION PLAN CHANGED id ( "<<data.id()<<" ) "<< modType;
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eModified:
|
||||
{
|
||||
if (row < 0)
|
||||
return;
|
||||
setRowData(row, data);
|
||||
break;
|
||||
}
|
||||
case DataModification::eAdded:
|
||||
{
|
||||
if (row != -1)
|
||||
return;
|
||||
else
|
||||
insertRow(data);
|
||||
break;
|
||||
}
|
||||
case DataModification::eRemoved:
|
||||
removeRow(row);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// #####################################
|
||||
/// PARTICIPANT_UAS-POXYMODEL
|
||||
/// #####################################
|
||||
///
|
||||
|
||||
/*!
|
||||
* \brief ParticipantUASProxyModel::setSourceModel
|
||||
* \param sourceModel
|
||||
*/
|
||||
void MissionPlanProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||
{
|
||||
m_sourceModel = qobject_cast<MissionPlanModel*>(sourceModel);
|
||||
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(sourceModel);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ParticipantUASProxyModel::setShowExpired
|
||||
* \param show
|
||||
*/
|
||||
void MissionPlanProxyModel::setShowExpired(bool show)
|
||||
{
|
||||
m_showExpired = show;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ParticipantUASProxyModel::filterAcceptsRow
|
||||
* \param source_row
|
||||
* \param sourceParent
|
||||
* \return
|
||||
*/
|
||||
bool MissionPlanProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
Q_UNUSED(sourceParent)
|
||||
return checkFilter(sourceRow);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ParticipantUASProxyModel::checkFilter
|
||||
* \param sourceRow
|
||||
* \return
|
||||
*/
|
||||
bool MissionPlanProxyModel::checkFilter(int sourceRow) const
|
||||
{
|
||||
Q_UNUSED(sourceRow)
|
||||
//const auto uas = m_sourceModel->getRowData(sourceRow);
|
||||
return true;
|
||||
}
|
||||
|
||||
}// namespace CentralEffectSimulation
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Dialog to edit drone Simulation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Steve Kemayou, ESZS, 2025-04-08
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
//#include <CentralEffectSimulation/logger.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <ParticipantManagement/ppm_ftc.h>
|
||||
#include <ParticipantManagement/ppm.hpp>
|
||||
#include "logger.h"
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
class MissionPlanModel : public LtsWidgets::LtsAbstractTableModel<ParticipantManagement::MissionPlan>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
Name,
|
||||
MissionStart,
|
||||
ItemsCountAndFulfilled, // item Fulfilled / item count
|
||||
Fulfilled,
|
||||
Participant,
|
||||
UasState,
|
||||
CurrentMission,
|
||||
Aborted
|
||||
};
|
||||
explicit MissionPlanModel(QObject *parent = nullptr);
|
||||
QVariant data(const QModelIndex &index, int role) const override final;
|
||||
bool initModel(const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc, int exerciseId);
|
||||
QString currentJob2String(const ParticipantManagement::MissionPlan &missionPlan) const;
|
||||
|
||||
|
||||
private slots:
|
||||
void onMissionPlanChanged(const ParticipantManagement::MissionPlan &data, const DataModification modType);
|
||||
|
||||
private:
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
int m_exerciseId {-1};
|
||||
LOGGER_T m_logger;
|
||||
friend class EmergencyCallProxyModel;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
* UASProxyModel
|
||||
*/
|
||||
class MissionPlanProxyModel : public LtsWidgets::LtsColumnFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
|
||||
bool showExpired() const {return m_showExpired;}
|
||||
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||
|
||||
public slots:
|
||||
void setShowExpired(bool show);
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override final;
|
||||
private:
|
||||
bool checkFilter(int sourceRow)const;
|
||||
private:
|
||||
bool m_showExpired{false};
|
||||
MissionPlanModel *m_sourceModel{nullptr};
|
||||
};
|
||||
} //namespace CentralEffectSimulation
|
||||
|
||||
Reference in new issue
Block a user