Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
#ADD_SUBDIRECTORY(Common)
|
||||
ADD_SUBDIRECTORY(ParticipantMove)
|
||||
ADD_SUBDIRECTORY(ParticipantUAS)
|
||||
@@ -0,0 +1,51 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
# Created by Hannes Baeuerle, SLSE, 2017-02-24
|
||||
#
|
||||
|
||||
SET(ces_participant_move_gui_SRCS
|
||||
logger.cpp
|
||||
logger.h
|
||||
ces_participant_move_gui_plugin.h
|
||||
ces_participant_move_gui_plugin.cpp
|
||||
participants_move_model.h
|
||||
participants_move_model.cpp
|
||||
participants_move_dialog.h
|
||||
participants_move_dialog.cpp
|
||||
participant_move_dialog.h
|
||||
participant_move_dialog.cpp
|
||||
)
|
||||
|
||||
NGL_WRAP_UI (ces_participant_move_gui_SRCS
|
||||
participants_move_dialog.ui
|
||||
participant_move_dialog.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY(WS CesParticipantMoveGuiPlugin MODULE ${ces_participant_move_gui_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(CesParticipantMoveGuiPlugin
|
||||
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(CesParticipantMoveGuiPlugin)
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for Simulated Movement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLSE, 2017-12-19
|
||||
*/
|
||||
|
||||
#include "ces_participant_move_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 "participants_move_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.ParticipantMove"))
|
||||
{
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
plData.menuGroup = menuGroup();
|
||||
plData.menuText = tr("Move Participants");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:define_movement_simulation.svg"));
|
||||
plData.identifier = QLatin1String("ParticipantMove");
|
||||
plData.operatorRight = OperatorRights::ParticipantMove;
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::eExecution;
|
||||
plData.createWidgetFunc = [this](QWidget * parent)
|
||||
{
|
||||
return LtsWidgets::initDialog(new ParticipantsMoveDialog(menuGroup(), parent),
|
||||
m_session, m_ppmDtc, m_cesDtc, m_ppmFtc);
|
||||
};
|
||||
ret.append(plData);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace CentralEffectSimulation
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for Simulated Movement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLSE, 2017-12-19
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "logger.h"
|
||||
|
||||
#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.participantmove")
|
||||
Q_INTERFACES(GuiPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GuiPlugin() = default;
|
||||
~GuiPlugin() = default;
|
||||
|
||||
QString pluginName() override { return QLatin1String("CesParticipantMoveGui"); }
|
||||
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("Participants");}
|
||||
QVector<LtsWidgets::PluginData> getActions() override;
|
||||
|
||||
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
|
||||
+538
@@ -0,0 +1,538 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Dialog for Simulated Movement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLSE, 2018-01-02 */
|
||||
|
||||
#include "participant_move_dialog.h"
|
||||
#include "ui_participant_move_dialog.h"
|
||||
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
|
||||
#include <LtsWidgets/lts_message_dialog.h>
|
||||
#include <Common/LtsCoordTrans/lts_coord_widget.h>
|
||||
#include <Plugins/ProjectDataManagement/pdm_gui_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
|
||||
#include <Plugins/CentralEffectSimulation/ces_data_plugin_interface.h>
|
||||
|
||||
#include "logger.h"
|
||||
#include <ParticipantManagement/ppm_translation.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <FileManagement/flm_translation.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
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]
|
||||
|
||||
ParticipantMoveDialog::ParticipantMoveDialog(QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
|
||||
, m_ftc(nullptr)
|
||||
, m_sitMapGuiIfc(nullptr)
|
||||
, m_ui(new Ui::WaypointsEdit)
|
||||
, m_id(0)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_polyline(QPolygonF())
|
||||
, m_logger(getLogger("ParticipantMoveDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->cbJump->hide();
|
||||
m_ui->label_5->hide();
|
||||
m_ui->spSpeed->setValue(30); // 30km/h per default
|
||||
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")});
|
||||
connect (this, &ParticipantMoveDialog::signalFocused, this, &ParticipantMoveDialog::onFocus);
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Move_Participant_0"));
|
||||
} // end of ctor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ParticipantMoveDialog::~ParticipantMoveDialog()
|
||||
{
|
||||
m_sitMapGuiIfc = nullptr;
|
||||
delete m_ui;
|
||||
emit closeDialog(m_participantData.id());
|
||||
} // end of dtor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ParticipantMoveDialog::enableUiElements(bool enable)
|
||||
{
|
||||
m_ui->pbPosition->setEnabled(enable);
|
||||
m_ui->pbClear->setEnabled(enable);
|
||||
} // end of enableUiElements()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool ParticipantMoveDialog::init(LtsSession::LtsSessionDataDds *session,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<CentralEffectSimulation::Interface::Dtc> &cesDtc,
|
||||
const ParticipantManagement::ParticipantData &data)
|
||||
{
|
||||
m_session = session;
|
||||
m_participantData = data;
|
||||
m_cesDtc = cesDtc;
|
||||
|
||||
//bool editable = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::BorderlinesEdit);
|
||||
//bool readable = LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::BorderlinesShow);
|
||||
//if (!readable && !editable)
|
||||
// return false;
|
||||
|
||||
if (!m_session->getFtc<CentralEffectSimulation::DataInterface>(m_ftc))
|
||||
return false;
|
||||
|
||||
m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc);
|
||||
|
||||
if (m_sitMapGuiIfc)
|
||||
{
|
||||
connect(m_ui->pbPosition, &QPushButton::clicked, this, &ParticipantMoveDialog::onGetPolyline);
|
||||
connect(m_ui->pbClear, &QPushButton::clicked, this, &ParticipantMoveDialog::clearCoordinates);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->pbPosition->setEnabled(false);
|
||||
m_ui->pbClear->setEnabled(false);
|
||||
}
|
||||
|
||||
m_ui->dteStartTime->setMinimumTimeMSec(m_session->partitionTime());
|
||||
m_ui->dteStartTime->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
|
||||
m_ui->lbIdentifier->setText(QString::fromStdString(data.tacticalIdentifier()));
|
||||
QString partyStr = ParticipantManagement::trPartyName(ppmDtc->party(m_participantData.partyId()).name());
|
||||
m_ui->lbParty->setText(partyStr);
|
||||
QString typeStr = ParticipantManagement::trTypeName(ppmDtc->type(m_participantData.typeId()).name());
|
||||
m_ui->lbType->setText(typeStr);
|
||||
|
||||
// enableUiElements(editable && readable);
|
||||
enableUiElements(true);
|
||||
|
||||
initTableHeader();
|
||||
|
||||
connect(cesDtc.get(), &CentralEffectSimulation::Interface::Dtc::simulatedMovementChanged,
|
||||
this, &ParticipantMoveDialog::onSimulatedMovementChanged);
|
||||
|
||||
// Get data for all SimulatedMovements
|
||||
{
|
||||
auto sm = [this](const CentralEffectSimulation::SimulatedMovement & sme)
|
||||
{
|
||||
onSimulatedMovementChanged(sme, DataModification::eAdded);
|
||||
};
|
||||
if (!m_cesDtc->simulatedMovements(sm))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save/Load from Library Button
|
||||
m_buttonBox->connectLibraryButton(this,
|
||||
&ParticipantMoveDialog::onImportButtonClicked,
|
||||
&ParticipantMoveDialog::onExportButtonClicked);
|
||||
|
||||
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Library, false);
|
||||
|
||||
return true;
|
||||
|
||||
} // end of init()
|
||||
|
||||
void ParticipantMoveDialog::onSimulatedMovementChanged(const CentralEffectSimulation::SimulatedMovement &data, DataModification modType)
|
||||
{
|
||||
if (modType == DataModification::eRemoved || m_participantData.id() != data.participantId())
|
||||
return;
|
||||
INFO_LOG(m_logger) << "onSimulatedMovementChanged";
|
||||
|
||||
// Clear data
|
||||
clearContent();
|
||||
// set new Content
|
||||
m_id = data.id();
|
||||
m_ui->lePrefix->setText(QString::fromStdString(data.name()));
|
||||
m_ui->cbRepeat->setChecked(data.repeat());
|
||||
m_ui->cbJump->setChecked(data.jumpToStart());
|
||||
m_ui->dteStartTime->setMsecsSinceEpoch(data.startTime());
|
||||
m_polyline.clear();
|
||||
// Insert data to Vector
|
||||
for (const SimulatedMovementSegment &segment : data.segments())
|
||||
{
|
||||
const Core::GeoPosition2D &pointDds = segment.position();
|
||||
insertPos(pointDds.lon(), pointDds.lat(), QString::fromStdString(segment.name()), segment.delay(), segment.speed());
|
||||
m_polyline.push_back(QPointF(pointDds.lon(), pointDds.lat()));
|
||||
}
|
||||
// Insert data to Map (Preview)
|
||||
if (this->amIFocused())
|
||||
m_sitMapGuiIfc->displayPreviewObject(this, m_polyline, false);
|
||||
}
|
||||
|
||||
void ParticipantMoveDialog::showPreview(bool show)
|
||||
{
|
||||
if (m_sitMapGuiIfc)
|
||||
{
|
||||
if (show)
|
||||
m_sitMapGuiIfc->displayPreviewObject(this, m_polyline, false);
|
||||
else
|
||||
m_sitMapGuiIfc->removePreviewObject();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ParticipantMoveDialog::onSimulatedMovementRemoveReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
if (!replyObject.error())
|
||||
{
|
||||
m_sitMapGuiIfc->cancelActiveRubberbands();
|
||||
m_sitMapGuiIfc->removePreviewObject();
|
||||
}
|
||||
}
|
||||
|
||||
void ParticipantMoveDialog::onSimulatedMovementModifyReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
if (!replyObject.error())
|
||||
m_sitMapGuiIfc->removePreviewObject();
|
||||
}
|
||||
|
||||
void ParticipantMoveDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, QString::fromStdString(m_participantData.tacticalIdentifier()), false, tr("Waypoints")); // TODO: lock topic?
|
||||
DEBUG_LOG(m_logger) << "retranslate";
|
||||
}
|
||||
|
||||
void ParticipantMoveDialog::initTableHeader()
|
||||
{
|
||||
QStringList headers;
|
||||
headers << tr("Identifier") << tr("Idle Time [s]") << tr("Speed [km/h]") << tr("Position");
|
||||
m_ui->tableWidget->setHorizontalHeaderLabels(headers);
|
||||
m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
// idleTime in [s] speed in [m/s]
|
||||
void ParticipantMoveDialog::insertPos(const double lon, const double lat, const QString &identifier, const int idleTime, const double speed)
|
||||
{
|
||||
QLineEdit *le = new QLineEdit;
|
||||
QSpinBox *sbDelay = new QSpinBox;
|
||||
QSpinBox *sbSpeed = new QSpinBox;
|
||||
sbDelay->setMinimum(m_ui->spIdleTime->minimum());
|
||||
sbDelay->setMaximum(m_ui->spIdleTime->maximum());
|
||||
sbSpeed->setMinimum(m_ui->spSpeed->minimum());
|
||||
sbSpeed->setMaximum(m_ui->spSpeed->maximum());
|
||||
int rowCount = m_ui->tableWidget->rowCount();
|
||||
|
||||
LtsCoordWidget::LtsCoordWidget *wdg = new LtsCoordWidget::LtsCoordWidget();
|
||||
//wdg->setCoordinate( 8.794556, 53.080827);
|
||||
wdg->setCoordinate(lon, lat);
|
||||
wdg->setObjectName(QStringLiteral("positionEdit_") + QString::number(rowCount));
|
||||
m_ui->tableWidget->insertRow(rowCount);
|
||||
le->setText(identifier);
|
||||
m_ui->tableWidget->setCellWidget(rowCount, Name, le);
|
||||
sbDelay->setValue(idleTime / s_timeMilliConversion);
|
||||
m_ui->tableWidget->setCellWidget(rowCount, IdleTime, sbDelay);
|
||||
sbSpeed->setValue(speed * s_msConversion);
|
||||
m_ui->tableWidget->setCellWidget(rowCount, Speed, sbSpeed);
|
||||
m_ui->tableWidget->setCellWidget(rowCount, Position, wdg);
|
||||
wdg->setDisplayType(LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS);
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
void WaypointsEdit::setData(const Borderline &borderline, bool copy)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << "borderlineId: " << borderline.id()
|
||||
<< " operatorId: " << borderline.operatorId();
|
||||
|
||||
} // end of setData()
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
void ParticipantMoveDialog::clearContent()
|
||||
{
|
||||
m_ui->lePrefix->clear();
|
||||
m_ui->cbRepeat->setChecked(false);
|
||||
m_ui->cbJump->setChecked(false);
|
||||
|
||||
clearCoordinates();
|
||||
}
|
||||
|
||||
void ParticipantMoveDialog::clearCoordinates()
|
||||
{
|
||||
if (m_ui)
|
||||
{
|
||||
m_ui->tableWidget->clearContents();
|
||||
m_ui->tableWidget->setRowCount(0);
|
||||
}
|
||||
// remove PreviewObject:
|
||||
if ( m_sitMapGuiIfc && this->amIFocused())
|
||||
m_sitMapGuiIfc->removePreviewObject();
|
||||
}
|
||||
|
||||
void ParticipantMoveDialog::onFocus()
|
||||
{
|
||||
showPreview(true);
|
||||
m_sitMapGuiIfc->displayPreviewObject(this, m_polyline, false);
|
||||
}
|
||||
|
||||
void ParticipantMoveDialog::onGetPolyline()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION;
|
||||
|
||||
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);
|
||||
|
||||
} // end of onGetPolyline()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ParticipantMoveDialog::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++)
|
||||
insertPos(polyline.at(i).x(), polyline.at(i).y(),
|
||||
m_ui->lePrefix->text() + QLatin1Char('_') + QString::number(i + 1),
|
||||
m_ui->spIdleTime->value() * s_timeMilliConversion,
|
||||
m_ui->spSpeed->value() / s_msConversion);
|
||||
|
||||
// create PreviewObject:
|
||||
m_sitMapGuiIfc->displayPreviewObject(this, polyline, false);
|
||||
|
||||
} // end of onPolylineData()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool ParticipantMoveDialog::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();
|
||||
}
|
||||
|
||||
SimulatedMovement ParticipantMoveDialog::requestContent() const
|
||||
{
|
||||
std::string name = m_ui->lePrefix->text().toStdString();
|
||||
int32_t repeat = m_ui->cbRepeat->isChecked();
|
||||
//int32_t jumpToStart = m_ui->cbJump->isChecked();
|
||||
int32_t jumpToStart = true;
|
||||
rti::core::int64 startTime = m_ui->dteStartTime->msecsSinceEpoch();
|
||||
int32_t participantId = m_participantData.id();
|
||||
int32_t nextPoint = 0;
|
||||
|
||||
int cntSegments = m_ui->tableWidget->rowCount();
|
||||
std::vector<CentralEffectSimulation::SimulatedMovementSegment> segments;
|
||||
segments.resize(cntSegments);
|
||||
for (int i = 0; i < cntSegments; i++)
|
||||
{
|
||||
QWidget *widget = m_ui->tableWidget->cellWidget(i, Name);
|
||||
const QString nameSeg = static_cast<QLineEdit *>(widget)->text();
|
||||
segments[i].name(nameSeg.toStdString());
|
||||
|
||||
widget = m_ui->tableWidget->cellWidget(i, IdleTime);
|
||||
const int idleTime = static_cast<QSpinBox *>(widget)->value() * s_timeMilliConversion;
|
||||
segments[i].delay(idleTime);
|
||||
|
||||
widget = m_ui->tableWidget->cellWidget(i, Speed);
|
||||
const double speed = static_cast<QSpinBox *>(widget)->value() / s_msConversion;
|
||||
|
||||
segments[i].speed(speed);
|
||||
|
||||
widget = m_ui->tableWidget->cellWidget(i, Position);
|
||||
const QPointF point = static_cast<LtsCoordWidget::LtsCoordWidget *>(widget)->coordinate();
|
||||
const Core::GeoPosition2D pos(Core::GeoPosition2D(point.x(), point.y()));
|
||||
segments[i].position(pos);
|
||||
}
|
||||
|
||||
return SimulatedMovement(m_id,
|
||||
name,
|
||||
startTime,
|
||||
participantId,
|
||||
segments,
|
||||
repeat,
|
||||
jumpToStart,
|
||||
nextPoint
|
||||
);
|
||||
}
|
||||
|
||||
bool ParticipantMoveDialog::apply()
|
||||
{
|
||||
int cntSegments = m_ui->tableWidget->rowCount();
|
||||
if (cntSegments > 0)
|
||||
{
|
||||
const SimulatedMovement req = requestContent();
|
||||
|
||||
INFO_LOG(m_logger) << "--- onApplyMessage() ";
|
||||
|
||||
m_requestHelper->addRequest([this, req]()
|
||||
{
|
||||
return m_ftc->simulatedMovementModifyRequest(req, this);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_id > 0)
|
||||
{
|
||||
Core::RemoveElementRequest req(m_id);
|
||||
m_id = 0; // Next time new Route
|
||||
|
||||
INFO_LOG(m_logger) << "--- onApplyMessage() ";
|
||||
|
||||
m_requestHelper->addRequest([req, this]()
|
||||
{
|
||||
return m_ftc->simulatedMovementRemoveRequest(req, this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Save / Load Simulation in DB
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
QByteArray ParticipantMoveDialog::simulatedMovementToJson() const
|
||||
{
|
||||
const SimulatedMovement req = requestContent();
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("XmlType")] = FileManagement::toString(FileManagement::XmlType::CESParticipantMove);
|
||||
|
||||
obj[QStringLiteral("id")] = req.id();
|
||||
obj[QStringLiteral("jumpToStart")] = req.jumpToStart();
|
||||
obj[QStringLiteral("name")] = QString::fromStdString(req.name());
|
||||
obj[QStringLiteral("nextPoint")] = req.nextPoint();
|
||||
obj[QStringLiteral("participantId")] = req.participantId();
|
||||
obj[QStringLiteral("repeat")] = req.repeat();
|
||||
obj[QStringLiteral("startTime")] = req.startTime();
|
||||
|
||||
QJsonArray arr;
|
||||
for (auto it = req.segments().begin(); it != req.segments().end(); ++it)
|
||||
{
|
||||
QJsonObject inner;
|
||||
inner[QStringLiteral("delay")] = it->delay();
|
||||
inner[QStringLiteral("name")] = QString::fromStdString(it->name());
|
||||
inner[QStringLiteral("speed")] = it->speed();
|
||||
inner[QStringLiteral("lat")] = it->position().lat();
|
||||
inner[QStringLiteral("lon")] = it->position().lon();
|
||||
arr += inner;
|
||||
}
|
||||
obj[QStringLiteral("segments")] = arr;
|
||||
|
||||
QJsonDocument doc(obj);
|
||||
return doc.toJson(QJsonDocument::Compact);
|
||||
}
|
||||
|
||||
SimulatedMovement ParticipantMoveDialog::jsonToSimulatedMovement(const QByteArray &content) const
|
||||
{
|
||||
// already checked that content is not empty, parseable and contains proper XmlType (CESParticipantMove)
|
||||
CentralEffectSimulation::SimulatedMovement result;
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(content));
|
||||
const QJsonObject obj(doc.object());
|
||||
|
||||
result.id(obj[QStringLiteral("id")].toInt()); //TODO Library: check id = 0?
|
||||
result.jumpToStart(obj[QStringLiteral("jumpToStart")].toInt());
|
||||
result.name(obj[QStringLiteral("name")].toString().toStdString());
|
||||
result.nextPoint(obj[QStringLiteral("nextPoint")].toInt());
|
||||
result.participantId(m_participantData.id());
|
||||
result.repeat(obj[QStringLiteral("repeat")].toInt());
|
||||
result.startTime(obj[QStringLiteral("startTime")].toDouble());
|
||||
|
||||
const QJsonArray arr(obj.value(QStringLiteral("segments")).toArray());
|
||||
auto &segments = result.segments();
|
||||
segments.resize(arr.size());
|
||||
for (int i = 0; i < arr.size(); ++i)
|
||||
{
|
||||
CentralEffectSimulation::SimulatedMovementSegment &segment = segments[i];
|
||||
const QJsonObject objArr(arr.at(i).toObject());
|
||||
segment.delay(objArr[QStringLiteral("delay")].toDouble());
|
||||
segment.name(objArr[QStringLiteral("name")].toString().toStdString());
|
||||
|
||||
|
||||
segment.position().lat(objArr[QStringLiteral("lat")].toDouble());
|
||||
segment.position().lon(objArr[QStringLiteral("lon")].toDouble());
|
||||
segment.speed(objArr[QStringLiteral("speed")].toDouble());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ParticipantMoveDialog::onExportButtonClicked()
|
||||
{
|
||||
QJsonObject saveObject;
|
||||
saveObject[QStringLiteral("content")] = QString();
|
||||
|
||||
const QByteArray byteArray = simulatedMovementToJson();
|
||||
|
||||
int fileId = m_flmGui->saveFileContent(this, FileManagement::FileType::Xml, m_session->exerciseId(), byteArray);
|
||||
if (fileId > 0)
|
||||
DEBUG_LOG(m_logger) << "Saved file with id = " << fileId;
|
||||
else
|
||||
ERROR_LOG(m_logger) << "Could not save file in library ";
|
||||
}
|
||||
|
||||
void ParticipantMoveDialog::onImportButtonClicked()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << " onImportButtonClicked() ";
|
||||
|
||||
QByteArray content;
|
||||
int fileId = m_flmGui->loadFileContent(this, content, {FileManagement::FileType::Xml}, m_session->exerciseId(), FileManagement::toString(FileManagement::XmlType::CESParticipantMove));
|
||||
if (fileId > 0)
|
||||
{
|
||||
if (!m_flmGui->isXmlType(content, FileManagement::toString(FileManagement::XmlType::CESParticipantMove)))
|
||||
{
|
||||
QHash<LtsWidgets::Button, QString> texts({{LtsWidgets::Button::Yes, tr("Ok")}});
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this,
|
||||
tr("Invalid xml file content"),
|
||||
windowTitle(),
|
||||
LtsWidgets::Behaviour::Modal,
|
||||
LtsWidgets::Button::Yes,
|
||||
texts);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimulatedMovement req = jsonToSimulatedMovement(content);
|
||||
|
||||
INFO_LOG(m_logger) << "--- onImportButtonClicked() ";
|
||||
|
||||
m_requestHelper->addRequest([this, req]()
|
||||
{
|
||||
return m_ftc->simulatedMovementModifyRequest(req, this);
|
||||
});
|
||||
m_requestHelper->startRequests();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace CentralEffectSimulation
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Dialog for Simulated Movement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLSE, 2018-01-02 */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <CentralEffectSimulation/ces_ftc.h>
|
||||
#include <LtsWidgets/lts_frameless_dialog.h>
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
|
||||
#include <QStandardItemModel>
|
||||
|
||||
#include <LtsUtilsGuiDds/request_helper.h>
|
||||
|
||||
#include <LtsSession/lts_session.h>
|
||||
|
||||
//DDS
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <CentralEffectSimulation/ces_dtc.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class WaypointsEdit;
|
||||
}
|
||||
|
||||
namespace LtsWidgets
|
||||
{
|
||||
class LtsDateTimeEdit;
|
||||
}
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
class TypeModel;
|
||||
|
||||
class ParticipantMoveDialog: public LtsWidgets::LtsDialog
|
||||
, protected CentralEffectSimulation::Interface::Ftc::SimulatedMovementRemoveReplyHandler
|
||||
, protected CentralEffectSimulation::Interface::Ftc::SimulatedMovementModifyReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum SegementColumns
|
||||
{
|
||||
Name,
|
||||
IdleTime,
|
||||
Speed,
|
||||
Position
|
||||
};
|
||||
explicit ParticipantMoveDialog(QWidget *parent = nullptr);
|
||||
~ParticipantMoveDialog();
|
||||
|
||||
bool init(LtsSession::LtsSessionDataDds *session,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<CentralEffectSimulation::Interface::Dtc> &cesDtc,
|
||||
const ParticipantManagement::ParticipantData &data);
|
||||
|
||||
void retranslate() override;
|
||||
|
||||
//virtual functions from CentralEffectSimulation::Interface::Ftc
|
||||
void onSimulatedMovementRemoveReply(const Core::FunctionReplyObject &replyObject) override;
|
||||
void onSimulatedMovementModifyReply(const Core::FunctionReplyObject &replyObject) override;
|
||||
|
||||
void showPreview(bool show);
|
||||
|
||||
signals:
|
||||
void closeDialog(int32_t participantId);
|
||||
|
||||
private:
|
||||
//std::vector<LtsCoordWidget::LtsCoordWidget *> coordWidgets() const override;
|
||||
|
||||
//void setData(const Borderline &borderline, bool copy);
|
||||
void enableUiElements(bool enable);
|
||||
void initTableHeader();
|
||||
void insertPos(const double lon, const double lat, const QString &identifier, const int idleTime, const double speed);
|
||||
//void onApply();
|
||||
void clearCoordinates();
|
||||
void clearContent();
|
||||
bool hasValidEffectStart(LtsWidgets::LtsDateTimeEdit *dte) const;
|
||||
bool apply() override;
|
||||
SimulatedMovement requestContent() const;
|
||||
QByteArray simulatedMovementToJson() const;
|
||||
SimulatedMovement jsonToSimulatedMovement(const QByteArray &content) const;
|
||||
|
||||
private slots:
|
||||
void onGetPolyline();
|
||||
void onPolylineData(const QPolygonF &polyline); // callback for onGetPolyline()
|
||||
void onSimulatedMovementChanged(const CentralEffectSimulation::SimulatedMovement &data, DataModification modType);
|
||||
void onFocus();
|
||||
void onExportButtonClicked();
|
||||
void onImportButtonClicked();
|
||||
|
||||
private:
|
||||
std::shared_ptr<CentralEffectSimulation::Interface::Dtc> m_cesDtc;
|
||||
std::shared_ptr<Interface::Ftc> m_ftc;
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
|
||||
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
|
||||
|
||||
Ui::WaypointsEdit *m_ui;
|
||||
LtsSession::LtsSessionDataDds *m_session;
|
||||
ParticipantManagement::ParticipantData m_participantData;
|
||||
int m_id;
|
||||
LtsUtils::RequestHelper *m_requestHelper;
|
||||
QPolygonF m_polyline;
|
||||
LOGGER_T m_logger;
|
||||
|
||||
};
|
||||
|
||||
} // namespace CentralEffectSimulation
|
||||
+245
@@ -0,0 +1,245 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>WaypointsEdit</class>
|
||||
<widget class="QWidget" name="WaypointsEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>808</width>
|
||||
<height>535</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">MessagingView</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Tact. Identifier:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="lbIdentifier">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Party:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="lbParty">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="lbType">
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lblMoveStart">
|
||||
<property name="text">
|
||||
<string>Start Time:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="LtsWidgets::LtsDateTimeEdit" name="dteStartTime">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Edit Waypoints in Map:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<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 resource="../../../Styles/Light/resources/rme_light_style.qrc">
|
||||
<normaloff>:/style/position.svg</normaloff>:/style/position.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbClear">
|
||||
<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 resource="../../../Styles/Light/resources/rme_light_style.qrc">
|
||||
<normaloff>:/style/remove.svg</normaloff>:/style/remove.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Idle Time [s]:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spIdleTime">
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Prefix:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lePrefix">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Speed [km/h]:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Repeat:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Jump to Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="cbRepeat">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="cbJump">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spSpeed"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
</widget>
|
||||
</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>
|
||||
<include location="../../../Styles/Light/resources/rme_light_style.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
+905
@@ -0,0 +1,905 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* GUI Plugin for ParticipantsMoveDialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLSE, 2018-01-02*/
|
||||
|
||||
#include "participants_move_dialog.h"
|
||||
#include "participants_move_model.h"
|
||||
#include "ui_participants_move_dialog.h"
|
||||
#include <LtsWidgets/lts_column_filter_proxy_model.h>
|
||||
#include <AdvancedSymbology/asb_data_plugin_interface.h>
|
||||
#include <CentralEffectSimulation/ces_data_plugin_interface.h>
|
||||
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
|
||||
#include <Plugins/AssetManagement/asm_data_plugin_interface.h>
|
||||
#include <AreaEffectSimulation/aes_data_plugin_interface.h>
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
|
||||
#include "participant_move_dialog.h"
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <LtsSession/lts_session_data_dds.h>
|
||||
#include <LtsSession/lts_session_data.h>
|
||||
#include <FilterManagement/flt_participant_plugin_interface.h>
|
||||
#include <FilterManagement/flt_symbol_appearance_settings.h>
|
||||
#include <LtsCoordTrans/lts_coord_widget.h>
|
||||
#include <QInputDialog>
|
||||
#include <QLabel>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDebug>
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
ParticipantsMoveDialog::ParticipantsMoveDialog(const QString &menuGroup, QWidget *parent)
|
||||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
|
||||
, m_participantModel(nullptr)
|
||||
, m_ppmDtc(nullptr)
|
||||
, m_ppmCbxIfc(nullptr)
|
||||
, m_ftc(nullptr)
|
||||
, m_ui(new Ui::ParticipantMoveDialog)
|
||||
, m_session(nullptr)
|
||||
, m_menuGroup(menuGroup)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_sitMapGuiIfc(nullptr)
|
||||
, m_logger(getLogger("ParticipantsMoveDialog"))
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
setUnchangeable();
|
||||
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Save, this, &ParticipantsMoveDialog::onSetSimulatedMGRSPosition);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, false);
|
||||
m_buttonBox->setIcon(LtsWidgets::DialogButton::Save, QIcon(QStringLiteral("icon:position.svg")));
|
||||
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit, this, &ParticipantsMoveDialog::onClicked);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
|
||||
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &ParticipantsMoveDialog::onSetPosition);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Add, false);
|
||||
|
||||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove, this, &ParticipantsMoveDialog::onRemove);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
|
||||
|
||||
|
||||
setOnlineHelpFilename(QStringLiteral("Situation-Move_Participant_0"));
|
||||
}
|
||||
|
||||
ParticipantsMoveDialog::~ParticipantsMoveDialog()
|
||||
{
|
||||
m_sitMapGuiIfc = nullptr;
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
static constexpr int s_maxAngleDeg = 360;
|
||||
static constexpr int s_maxAngleMil = 6400;
|
||||
inline constexpr int mil2Deg(const int &mil)
|
||||
{
|
||||
return s_maxAngleDeg * mil / s_maxAngleMil;
|
||||
}
|
||||
inline constexpr int deg2Mil(const int &angleDeg)
|
||||
{
|
||||
return s_maxAngleMil * angleDeg / s_maxAngleDeg;
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::retranslate()
|
||||
{
|
||||
translate(m_ui, tr("Move Participant"));
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Save)->setText(tr("Set Simulated MGRS Position"));
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Add)->setText(tr("Set Simulated Position"));
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Edit)->setText(tr("Edit Simulation"));
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Remove)->setText(tr("Remove Simulation"));
|
||||
}
|
||||
|
||||
bool ParticipantsMoveDialog::init(LtsSession::LtsSession *session,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<CentralEffectSimulation::Interface::Dtc> &cesDtc,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Ftc> &ppmFtc)
|
||||
{
|
||||
m_ppmDtc = ppmDtc;
|
||||
m_cesDtc = cesDtc;
|
||||
m_session = session;
|
||||
m_ppmFtc = ppmFtc;
|
||||
|
||||
if (!m_ppmDtc)
|
||||
return false;
|
||||
|
||||
if (!m_ppmFtc)
|
||||
return false;
|
||||
|
||||
if (!session->getForeignGuiInterface<ParticipantManagement::ForeignGuiComboboxInterface>(m_ppmCbxIfc))
|
||||
return false;
|
||||
|
||||
if (!m_session->getFtc<CentralEffectSimulation::DataInterface>(m_ftc))
|
||||
return false;
|
||||
|
||||
std::shared_ptr<ExerciseManagement::Interface::Dtc> exmDtc;
|
||||
if (!m_session->getDtc<ExerciseManagement::DataInterface>(exmDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "failed to get exmDtc ";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<AssetManagement::Interface::Dtc> asmDtc;
|
||||
if (!m_session->getDtc<AssetManagement::DataInterface>(asmDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "failed to get asmDtc ";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (asmDtc == nullptr || exmDtc == nullptr)
|
||||
return false;
|
||||
|
||||
const ExerciseManagement::Exercise exc = exmDtc->exercise(m_session->exerciseId());
|
||||
AssetManagement::TrainingArea ta = asmDtc->trainingArea(exc.trainingAreaId());
|
||||
if (ta.id() != exc.trainingAreaId())
|
||||
{
|
||||
ERROR_LOG(m_logger)<<" couldn't get Training Area with id: "<<exc.trainingAreaId();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_session ->getDtc<AreaEffectSimulation::DataInterface>(m_aesDtc))
|
||||
{
|
||||
ERROR_LOG(m_logger)<<"failed to get aesDtc";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// get training area Rect
|
||||
const LtsCoordTrans::UtmCoordinate &bottomLeft = LtsCoordTrans::UtmCoordinate::fromGeographic(ta.bottomLeft().lon(), ta.bottomLeft().lat());
|
||||
m_trainingAreaRect = QRectF(bottomLeft.geographic(0, ta.height()), bottomLeft.geographic(ta.width(), 0));
|
||||
|
||||
|
||||
// for relativeMove of units via SetSimulatedPositionRelative:
|
||||
m_ppmDtc->enableUnitPosition();
|
||||
m_ppmDtc->waitForHistoricalDataUnitPosition(1000);
|
||||
|
||||
std::shared_ptr<AdvancedSymbology::ForeignDataInterface> asb;
|
||||
session->getForeignDataInterface<AdvancedSymbology::DataInterface>(asb);
|
||||
m_participantModel = new ParticipantMoveModel(this, m_ppmDtc, asb);
|
||||
// only needed to set recursiveFilteringEnabled
|
||||
auto proxyModel = new ParticipantManagement::ParticipantTreeFilterProxyModel(this);
|
||||
proxyModel->setSourceModel(m_participantModel);
|
||||
proxyModel->setRecursiveFilteringEnabled(true);
|
||||
m_ui->dvParticipants->setModel(proxyModel);
|
||||
m_ui->dvParticipants->setSortIndicator(0, Qt::AscendingOrder);
|
||||
|
||||
connect(m_ui->cbParty,
|
||||
static_cast<void (LtsWidgets::LtsComboBox::*)(int)>(&LtsWidgets::LtsComboBox::currentIndexChanged),
|
||||
this, &ParticipantsMoveDialog::changeParty);
|
||||
connect(m_ui->cbAll, &QCheckBox::toggled, this, &ParticipantsMoveDialog::changeParty);
|
||||
|
||||
connect(m_ui->dvParticipants, &LtsDataView::LtsDataView::selectionChanged,
|
||||
this, &ParticipantsMoveDialog::onSelectionChanged);
|
||||
|
||||
connect(m_participantModel, &ParticipantMoveModel::newData,
|
||||
this, &ParticipantsMoveDialog::onModelChanged);
|
||||
|
||||
connect(m_ui->dvParticipants, &LtsDataView::LtsDataView::signalDoubleClicked,
|
||||
this, &ParticipantsMoveDialog::onDoubleClicked);
|
||||
|
||||
|
||||
m_ppmCbxIfc->fillPartyComboBox(m_ui->cbParty, ParticipantManagement::ForeignGuiComboboxInterface::CbxPartyFilter::All);
|
||||
changeParty();
|
||||
|
||||
m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc);
|
||||
m_buttonBox->getButton(LtsWidgets::DialogButton::Add)->setIcon(QIcon(QStringLiteral("icon:position.svg")));
|
||||
|
||||
#ifndef LTS_DEBUG
|
||||
m_ui->dvParticipants->hideColumn(ParticipantMoveModel::ColParticipantId);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//private
|
||||
|
||||
void ParticipantsMoveDialog::closeDialogReceived(int32_t participantId)
|
||||
{
|
||||
m_participantDialogMap.remove(participantId);
|
||||
}
|
||||
|
||||
|
||||
void ParticipantsMoveDialog::onSelectionChanged()
|
||||
{
|
||||
const QModelIndexList indexList = m_ui->dvParticipants->selectedRows();
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, false);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Add, false);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
|
||||
bool isOne = (indexList.size() == 1);
|
||||
|
||||
// Set remove Btn
|
||||
if (!isOne)
|
||||
return;
|
||||
|
||||
const ParticipantManagement::ParticipantData data(participantFromIndex(indexList.first()));
|
||||
DEBUG_LOG(m_logger) << "ParticipantId: " << data.id();
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, data.isSimulated());
|
||||
// Show preview of selected Simulation
|
||||
if (data.isSimulated() && m_participantDialogMap.contains(data.id()))
|
||||
m_participantDialogMap.value(data.id())->showPreview(true);
|
||||
else
|
||||
{
|
||||
// Remove Preview
|
||||
QMapIterator<int, ParticipantMoveDialog *> i(m_participantDialogMap);
|
||||
while (i.hasNext())
|
||||
{
|
||||
i.next();
|
||||
//cout << i.key() << ": " << i.value() << endl;
|
||||
i.value()->showPreview(false);
|
||||
}
|
||||
}
|
||||
|
||||
// allow moving units (with all its children)
|
||||
{
|
||||
bool isParticipantInUseOrAdler = participantInUse4ExplosionCluster(indexList.first());
|
||||
// Check for Adler Type too
|
||||
if (!isParticipantInUseOrAdler)
|
||||
isParticipantInUseOrAdler = (m_ppmDtc->isAdlerType(data.typeId()) && !data.name().empty());
|
||||
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Add, isOne && !isParticipantInUseOrAdler);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, isOne && !isParticipantInUseOrAdler);
|
||||
}
|
||||
|
||||
if (m_ppmDtc->type(data.typeId()).typeClass() != ParticipantManagement::TypeClass_def::Unit)
|
||||
{
|
||||
|
||||
if (!data.equipmentNumber().is_set() || data.equipmentNumber().get() <= 0)
|
||||
{
|
||||
//No Sim MoveMent for Adler SAA Participants
|
||||
isOne &= !(m_ppmDtc->isAdlerType(data.typeId()) && !data.name().empty());
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, isOne);
|
||||
}
|
||||
else
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::onModelChanged()
|
||||
{
|
||||
m_ui->dvParticipants->expandAll();
|
||||
DEBUG_LOG(m_logger) << "onModelChanged";
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::onDoubleClicked()
|
||||
{
|
||||
if (!m_sitMapGuiIfc)
|
||||
return;
|
||||
|
||||
if (m_sitMapGuiIfc->mapMode() != SituationMap::MapMode::MapMode_2D)
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Only available in 2D mode"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_buttonBox->isButtonEnabled(LtsWidgets::DialogButton::Edit))
|
||||
return;
|
||||
const QModelIndexList indexList = m_ui->dvParticipants->selectedRows();
|
||||
|
||||
bool isOne = (indexList.size() == 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, isOne);
|
||||
|
||||
if (!isOne)
|
||||
return;
|
||||
|
||||
const ParticipantManagement::ParticipantData data(participantFromIndex(indexList.first()));
|
||||
DEBUG_LOG(m_logger) << "ParticipantId: " << data.id();
|
||||
|
||||
if (!m_participantDialogMap.contains(data.id()))
|
||||
{
|
||||
ParticipantMoveDialog *dialog = new ParticipantMoveDialog(this);
|
||||
m_participantDialogMap.insert(data.id(), dialog);
|
||||
connect(dialog, &ParticipantMoveDialog::closeDialog,
|
||||
this, &ParticipantsMoveDialog::closeDialogReceived);
|
||||
|
||||
addDialog(LtsWidgets::initDialog(dialog, m_session, m_ppmDtc, m_cesDtc, data),
|
||||
m_menuGroup, QStringLiteral("cesNewSimulation%1").arg(data.id()), LtsWidgets::LayoutArea::eDialogTab);
|
||||
}
|
||||
else
|
||||
focusDialog(m_menuGroup, QStringLiteral("cesNewSimulation%1").arg(data.id()), LtsWidgets::LayoutArea::eDialogTab);
|
||||
}
|
||||
|
||||
//Slots
|
||||
void ParticipantsMoveDialog::changeParty()
|
||||
{
|
||||
if (m_ui->cbAll->isChecked())
|
||||
{
|
||||
m_ui->cbParty->setEnabled(false);
|
||||
m_ui->dvParticipants->setEnabled(false);
|
||||
m_participantModel->resetModel();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->cbParty->setEnabled(true);
|
||||
m_ui->dvParticipants->setEnabled(true);
|
||||
int partyId = m_ui->cbParty->currentData().toInt();
|
||||
m_participantModel->onReinitModel(partyId);
|
||||
m_ui->dvParticipants->expandAll();
|
||||
}
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Add, m_ui->cbAll->isChecked());
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::onClicked()
|
||||
{
|
||||
onDoubleClicked();
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::onRemove()
|
||||
{
|
||||
const QModelIndexList indexList = m_ui->dvParticipants->selectedRows();
|
||||
|
||||
bool isOne = (indexList.size() == 1);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, isOne);
|
||||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
|
||||
|
||||
if (!isOne)
|
||||
return;
|
||||
|
||||
const ParticipantManagement::ParticipantData data(participantFromIndex(indexList.first()));
|
||||
INFO_LOG(m_logger) << "onRemove ParticipantId: " << data.id();
|
||||
|
||||
// Remove (possible) open Dialogs
|
||||
delete m_participantDialogMap.value(data.id());
|
||||
m_participantDialogMap.remove(data.id());
|
||||
|
||||
removeFtc(data.id());
|
||||
}
|
||||
|
||||
|
||||
void ParticipantsMoveDialog::onSetSimulatedMGRSPosition()
|
||||
{
|
||||
const QModelIndexList &indexList = m_ui->dvParticipants->selectedRows();
|
||||
if (indexList.size() == 1)
|
||||
{
|
||||
QPointF mgrsCoordinate;
|
||||
m_mgrsPosEditCoordinateActive = true;
|
||||
if(!participantInUse4ExplosionCluster(indexList.first()))
|
||||
{
|
||||
onGetCoordinate(mgrsCoordinate);
|
||||
m_mgrsPosEditCoordinateActive = false;
|
||||
}
|
||||
else
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("This Participant Unit is currently in use.\nThe Parameters can't be changed!"));
|
||||
}
|
||||
}
|
||||
|
||||
bool ParticipantsMoveDialog::participantInUse4ExplosionCluster(const QModelIndex &participantIndex)
|
||||
{
|
||||
const ParticipantManagement::ParticipantData participantData(participantFromIndex(participantIndex));
|
||||
bool bret=false;
|
||||
|
||||
const ParticipantManagement::Type &participantType = m_ppmDtc->type(participantData.typeId());
|
||||
bool isUnitType = (participantType.typeClass() == ParticipantManagement::TypeClass::Unit) ||
|
||||
(participantType.typeClass() == ParticipantManagement::TypeClass::SupportUnit);
|
||||
// get parent
|
||||
//only units tell us if participants are in used with explosion cluster
|
||||
if (!isUnitType)
|
||||
{
|
||||
const QModelIndex parentIndex = m_participantModel->indexFromParticipantId(participantData.superiorModId());
|
||||
const ParticipantManagement::ParticipantData parentParticipantData(participantFromIndex(parentIndex));
|
||||
|
||||
const ParticipantManagement::Type &partentParticipantType = m_ppmDtc->type(parentParticipantData.typeId());
|
||||
isUnitType = (partentParticipantType.typeClass() == ParticipantManagement::TypeClass::Unit) ||
|
||||
(partentParticipantType.typeClass() == ParticipantManagement::TypeClass::SupportUnit);
|
||||
bret = isUnitType && isParticipantInUseForExplosionCluster(parentParticipantData.id());;
|
||||
}
|
||||
else
|
||||
bret = isParticipantInUseForExplosionCluster(participantData.id());
|
||||
|
||||
return bret;
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::onSimulatedMovementRemoveByParticipantIdReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::onSetSimulatedPositionReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::onSetSimulatedPositionRelativeReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::onSetSimulatedParticipantFormationReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
m_requestHelper->requestReply(replyObject);
|
||||
}
|
||||
|
||||
bool ParticipantsMoveDialog::removeFtc(int32_t participantId)
|
||||
{
|
||||
if (participantId <= 0)
|
||||
return true;
|
||||
|
||||
CentralEffectSimulation::SimulatedMovementRemoveByParticipantId req(participantId);
|
||||
|
||||
m_requestHelper->addRequest([req, this]()
|
||||
{
|
||||
return m_ftc->simulatedMovementRemoveByParticipantIdRequest(req, this);
|
||||
});
|
||||
return m_requestHelper->startRequests();
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::onGetCoordinate(QPointF coordinate)
|
||||
{
|
||||
const QModelIndexList indexList = m_ui->dvParticipants->selectedRows();
|
||||
if (indexList.size() == 0)
|
||||
return;
|
||||
|
||||
const ParticipantManagement::ParticipantData participantData(participantFromIndex(indexList.first()));
|
||||
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << "ParticipantId=" << participantData.id()
|
||||
<< " EquipmentNr=" << participantData.equipmentNumber()
|
||||
<< " onGetCoordinate x=" << coordinate.x() << " y=" << coordinate.y();
|
||||
if (participantData.id() <= 0)
|
||||
return;
|
||||
|
||||
const ParticipantManagement::Type &participantType = m_ppmDtc->type(participantData.typeId());
|
||||
const bool &isUnitType =
|
||||
(participantType.typeClass() == ParticipantManagement::TypeClass::Unit) ||
|
||||
(participantType.typeClass() == ParticipantManagement::TypeClass::SupportUnit);
|
||||
|
||||
|
||||
// get participant type properties
|
||||
// special handling when participant has Artillery as property
|
||||
m_formationProps.setFormation(QString::fromStdString(participantType.properties()));
|
||||
const bool &withFormation = (isUnitType && m_formationProps.isArtillery);
|
||||
if (withFormation || m_mgrsPosEditCoordinateActive)
|
||||
setFormationAndPositioningUi(participantData, coordinate, withFormation);
|
||||
else if (isUnitType)
|
||||
m_shiftModifierWhileOnSetPosition ? doSetSimulatedPositionRequest(participantData, coordinate) :
|
||||
doSetSimulatedPositionRelativeRequest(participantData, coordinate);
|
||||
else
|
||||
doSetSimulatedPositionRequest(participantData, coordinate); // single (human|vehicle)
|
||||
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::onSetPosition()
|
||||
{
|
||||
|
||||
if (!m_sitMapGuiIfc) //sanity
|
||||
return;
|
||||
|
||||
if (m_sitMapGuiIfc->mapMode() != SituationMap::MapMode::MapMode_2D)
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Only available in 2D mode"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_ui->cbAll->isChecked())
|
||||
{
|
||||
const QModelIndexList indexList = m_ui->dvParticipants->selectedRows();
|
||||
|
||||
bool isOne = (indexList.size() == 1);
|
||||
if (!isOne)
|
||||
return;
|
||||
//const ParticipantManagement::ParticipantData participantData(participantFromIndex(indexList.first()));
|
||||
if (participantInUse4ExplosionCluster(indexList.first()))
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("This Participant Unit is currently in use.\nThe Parameters can't be changed!"));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
m_shiftModifierWhileOnSetPosition = QApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
|
||||
m_sitMapGuiIfc->getCoordinate(this, SLOT(onGetCoordinate(QPointF)), nullptr);
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::setDialogEnable(bool enable)
|
||||
{
|
||||
m_ui->dvParticipants->setEnabled(enable);
|
||||
m_ui->cbParty->setEnabled(enable);
|
||||
m_ui->cbAll->setEnabled(enable);
|
||||
m_buttonBox->setEnabled(enable);
|
||||
}
|
||||
|
||||
bool ParticipantsMoveDialog::isParticipantInUseForExplosionCluster(int id)
|
||||
{
|
||||
if (!m_aesDtc)
|
||||
{
|
||||
ERROR_LOG(m_logger)<<" m_aesDTC is not setted";
|
||||
return true;
|
||||
}
|
||||
|
||||
const QMap<qint32, AreaEffectSimulation::ExplosionCluster> &ecMap = m_aesDtc->explosionClusters();
|
||||
for(const AreaEffectSimulation::ExplosionCluster &aes : qAsConst(ecMap))
|
||||
{
|
||||
if (aes.participantId() == id &&
|
||||
(aes.effectStateId() == AreaEffectSimulation::AesEffectState::EsPrepared ||
|
||||
aes.effectStateId() == AreaEffectSimulation::AesEffectState::EsActivated))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::tableColumnOrganiserSetting()
|
||||
{
|
||||
//LtsColumnOrganiser
|
||||
m_ui->dvParticipants->setColumnsOrganiserEnabled(identifier(), true);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief ParticipantsMoveDialog::setFormationAndPositioningUi
|
||||
* \param withMgrsPos:
|
||||
* \param withFormation
|
||||
* \param mgrsCoordinate
|
||||
* \return
|
||||
*/
|
||||
void ParticipantsMoveDialog::setFormationAndPositioningUi(const ParticipantManagement::ParticipantData &participantData,
|
||||
QPointF &mgrsCoordinate,
|
||||
const bool &unitWithFormation)
|
||||
{
|
||||
if (!unitWithFormation && !m_mgrsPosEditCoordinateActive)
|
||||
return;
|
||||
|
||||
const ParticipantManagement::Type &participantType = m_ppmDtc->type(participantData.typeId());
|
||||
const bool isUnitType =
|
||||
(participantType.typeClass() == ParticipantManagement::TypeClass::Unit) ||
|
||||
(participantType.typeClass() == ParticipantManagement::TypeClass::SupportUnit);
|
||||
|
||||
m_formationProps.setFormation(QString::fromStdString(participantType.properties()));
|
||||
|
||||
if (m_formationProps.hasFormationData())
|
||||
return;
|
||||
|
||||
|
||||
LtsWidgets::LtsFramelessDialog *dialog = new LtsWidgets::LtsFramelessDialog(this, LtsWidgets::Behaviour::Popup);
|
||||
dialog->setFixedSize(390, 300);
|
||||
dialog->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);
|
||||
|
||||
int row = 0;
|
||||
QGridLayout *gla = new QGridLayout(dialog);
|
||||
// Message Infobox
|
||||
{
|
||||
QLabel *msgLbl = new QLabel(tr("<b> Following Parameter(s) must be set to proceed. </b>"), dialog);
|
||||
msgLbl->setWordWrap(true);
|
||||
gla->addWidget(msgLbl, row, 0, 1, 2);
|
||||
}
|
||||
|
||||
// set mgrs Postion edit
|
||||
LtsCoordWidget::LtsCoordWidget *posEdit = new LtsCoordWidget::LtsCoordWidget(LtsCoordWidget::LtsCoordWidget::DisplayType::MGRS, dialog);
|
||||
{
|
||||
QLabel *posEditLbl = new QLabel(tr("MGRS Position:"), dialog);
|
||||
LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance();
|
||||
const QSize offset = QSize(ps->value(QStringLiteral("MgrsSquaresOffsets"), QStringLiteral("xOffset")).toInt(),
|
||||
ps->value(QStringLiteral("MgrsSquaresOffsets"), QStringLiteral("yOffset")).toInt());
|
||||
|
||||
posEdit->setWithSurroundingMgrsSquares(true);
|
||||
posEdit->setMgrsSquareEditable(true);
|
||||
QVector<LtsCoordTrans::UtmCoordinate> geoCoords;
|
||||
|
||||
if (LtsCoordTrans::defaultMgrsSquareWithOffsets().isEmpty())
|
||||
{
|
||||
const QRectF &trainingAreaWithMargin = LtsCoordTrans::addMarginToArea(m_trainingAreaRect, offset);
|
||||
geoCoords = LtsCoordTrans::getMgrsSquares(trainingAreaWithMargin,false,false,true);
|
||||
}
|
||||
else
|
||||
geoCoords = LtsCoordTrans::defaultMgrsSquareWithOffsets();
|
||||
|
||||
posEdit->setMgrsSquares(geoCoords);
|
||||
if (!mgrsCoordinate.isNull())
|
||||
posEdit->setCoordinate(mgrsCoordinate, true);
|
||||
|
||||
++row;
|
||||
gla->addWidget(posEditLbl, row, 0, 1, 1);
|
||||
gla->addWidget(posEdit, row, 1, 1, 1);
|
||||
|
||||
QFrame *line = new QFrame(dialog);
|
||||
line->setObjectName(QString::fromUtf8("line"));
|
||||
line->setGeometry(QRect(110, 110, 118, 3));
|
||||
line->setFrameShape(QFrame::HLine);
|
||||
line->setFrameShadow(QFrame::Sunken);
|
||||
|
||||
++row;
|
||||
gla->addWidget(line, row, 0, 1, 2);
|
||||
}
|
||||
|
||||
// set Angle
|
||||
QSpinBox *angleSBox = nullptr;
|
||||
//if (m_formationProps.angle == -1 && unitWithFormation)
|
||||
{
|
||||
QLabel *angleLbl = new QLabel( tr("Angle:"), dialog); // Grundrichtung
|
||||
angleSBox = new QSpinBox(dialog);
|
||||
angleSBox->setMinimum(0);
|
||||
angleSBox->setMaximum(s_maxAngleMil);
|
||||
angleSBox->setSuffix(tr(" mil"));
|
||||
++row;
|
||||
gla->addWidget(angleLbl, row, 0, 1, 1);
|
||||
gla->addWidget(angleSBox, row, 1, 1, 1);
|
||||
|
||||
}// end setting angle
|
||||
|
||||
// set Distance
|
||||
QSpinBox *distanceSBox = nullptr;
|
||||
QComboBox *distanceCBox = nullptr;
|
||||
{
|
||||
QLabel *distanceLbl = new QLabel(tr("Distance:"), dialog);
|
||||
distanceCBox = new QComboBox(dialog);
|
||||
for(const auto &dis : m_formationProps.distanceSets.toStdMap())
|
||||
{
|
||||
QString str;
|
||||
if (dis.first == QStringLiteral("Locked")) // Geschlossen
|
||||
str = tr("Locked");
|
||||
else if (dis.first == QStringLiteral("Unlocked")) // Aufgelockert
|
||||
str = tr("Unlocked");
|
||||
distanceCBox->addItem(QStringLiteral("%1 (%2m)").arg(str).arg(dis.second.toInt()), dis.second.toInt());
|
||||
}
|
||||
|
||||
++row;
|
||||
gla->addWidget(distanceLbl, row, 0, 1, 1);
|
||||
gla->addWidget(distanceCBox, row, 1, 1, 1);
|
||||
|
||||
}
|
||||
|
||||
// Vertical spacer
|
||||
{
|
||||
QScopedPointer<QSpacerItem> verticalSpacer(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||
row++;
|
||||
gla->addItem(verticalSpacer.take(), row, 0, 1, 1);
|
||||
}
|
||||
|
||||
// dialog button
|
||||
LtsWidgets::LtsDialogButtonBox *btnBox = new LtsWidgets::LtsDialogButtonBox(dialog);
|
||||
btnBox->getButton(LtsWidgets::DialogButton::Ok)->setText(tr("Apply"));
|
||||
btnBox->getButton(LtsWidgets::DialogButton::Close)->setText(tr("Abort"));
|
||||
// horizontal spacer
|
||||
{
|
||||
QScopedPointer <QSpacerItem> horizontalSpacer(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
|
||||
row++;
|
||||
gla->addItem(horizontalSpacer.take(), row, 0, 1, 1);
|
||||
gla->addWidget(btnBox, row, 0, 1, 2);
|
||||
}
|
||||
|
||||
// handle Data
|
||||
auto applyData = [=]()
|
||||
{
|
||||
// angle can be get in ° or mil, but we work with angle in degree. so we habe to convert mil value if defined
|
||||
// 0° orientation is east ouest
|
||||
{ // get angle value
|
||||
int angleMil = angleSBox->value();
|
||||
// angle in mil: convert in degree, then we work in degree
|
||||
m_formationProps.angle = std::fmod((mil2Deg(angleMil) + 90), 360);// 0° ost-west gerichtet
|
||||
|
||||
DEBUG_LOG(m_logger)<<" angle in deg mil: "<<angleMil
|
||||
<<" -> degree: "<< mil2Deg(angleMil)<<" final position(°): "<<m_formationProps.angle;
|
||||
}
|
||||
|
||||
{// get distance value
|
||||
// spinbox is enable when there is no distance sets available. The user will enter a desired distance
|
||||
if (distanceSBox != nullptr)
|
||||
m_formationProps.distance = distanceSBox->value();
|
||||
else if(distanceCBox != nullptr)
|
||||
m_formationProps.distance = distanceCBox->currentData().toInt();
|
||||
}
|
||||
|
||||
const QPointF mgrsCoordinate = posEdit->coordinate();
|
||||
if (mgrsCoordinate.isNull())
|
||||
{
|
||||
WARNING_LOG(m_logger)<<"MGRS Coordinates invalid!";
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Coordinates invalid!\nPlease check them and try again."));
|
||||
return;
|
||||
}
|
||||
if (unitWithFormation && (m_formationProps.hasFormationData() || !mgrsCoordinate.isNull()))
|
||||
{
|
||||
doSetSimulatedParticipantFormationRequest(participantData, mgrsCoordinate, m_formationProps.getFormationDataObjectString());
|
||||
}
|
||||
else if (isUnitType)
|
||||
{
|
||||
// set while user is pressing
|
||||
m_shiftModifierWhileOnSetPosition ? doSetSimulatedPositionRequest(participantData, mgrsCoordinate) :
|
||||
doSetSimulatedPositionRelativeRequest(participantData, mgrsCoordinate);
|
||||
}
|
||||
else
|
||||
doSetSimulatedPositionRequest(participantData, mgrsCoordinate); // single (human|vehicle)
|
||||
|
||||
setDialogEnable(true);
|
||||
dialog->accept();
|
||||
};
|
||||
|
||||
// abort/close
|
||||
connect(btnBox->getButton(LtsWidgets::DialogButton::Close), &QPushButton::clicked, dialog, [=](){
|
||||
setDialogEnable(true);
|
||||
dialog->accept();
|
||||
});
|
||||
// apply
|
||||
connect(btnBox->getButton(LtsWidgets::DialogButton::Ok), &QPushButton::clicked, this, applyData);
|
||||
|
||||
dialog->setLayout(gla);
|
||||
dialog->show();
|
||||
setDialogEnable(false);
|
||||
}
|
||||
|
||||
|
||||
bool ParticipantsMoveDialog::getUnitPosition(int32_t participantId, Core::GeoPosition &unitPositionOut)
|
||||
{
|
||||
// flt
|
||||
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> fltParticipantIfc;
|
||||
m_session->getForeignGuiInterface<FilterManagement::ForeignFltParticipantGuiInterface>(fltParticipantIfc); // not in global
|
||||
|
||||
if (!fltParticipantIfc)
|
||||
return false;
|
||||
|
||||
int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
|
||||
QString workspaceId = m_session->workspaceId();
|
||||
|
||||
std::shared_ptr<FilterManagement::SymbolAppearanceSettings> symbolAppearanceSettings =
|
||||
fltParticipantIfc->symbolAppearanceForOperator(operatorId, workspaceId);
|
||||
|
||||
FilterManagement::SymbolAppearanceSettings::Settings settings =
|
||||
symbolAppearanceSettings->settings();
|
||||
|
||||
FilterManagement::SymbolAppearanceSettings::UnitSymbolPosition usp =
|
||||
settings.symbolSettings.unitSymbolPosition;
|
||||
|
||||
ParticipantManagement::UnitPosition up = m_ppmDtc->unitPosition(participantId);
|
||||
if (up.participantId() != participantId)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << ", unitPosition failed for participantId=" << participantId;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (usp)
|
||||
{
|
||||
case FilterManagement::SymbolAppearanceSettings::UnitSymbolPosition::Center:
|
||||
unitPositionOut = up.positionCenter();
|
||||
return true;
|
||||
break;
|
||||
case FilterManagement::SymbolAppearanceSettings::UnitSymbolPosition::Leader:
|
||||
unitPositionOut = up.positionLeader();
|
||||
return true;
|
||||
break;
|
||||
} // switch
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::doSetSimulatedPositionRequest(const ParticipantManagement::ParticipantData &participantData, const QPointF &coordinate)
|
||||
{
|
||||
// single participant or unit should be move to _one_ origin:
|
||||
const int participantId = participantData.id();
|
||||
if (participantId <= 0) // sanity
|
||||
return;
|
||||
|
||||
ParticipantManagement::SetSimulatedPosition req;
|
||||
bool bAll = m_ui->cbAll->isChecked();
|
||||
bool bAskOutdated = true;
|
||||
if (bAll)
|
||||
req.participantId(-1);
|
||||
else
|
||||
{
|
||||
const ParticipantManagement::TypeClass tc = m_ppmDtc->type(participantData.typeId()).typeClass();
|
||||
|
||||
DEBUG_LOG(m_logger) << "ParticipantId=" << participantData.id()
|
||||
<< " EquipmentNr=" << participantData.equipmentNumber()
|
||||
<< " onGetCoordinate x=" << coordinate.x() << " y=" << coordinate.y()
|
||||
<< ", tc=" << tc;
|
||||
if (participantData.id() <= 0)
|
||||
return;
|
||||
req.participantId(participantData.id());
|
||||
|
||||
bAskOutdated = m_ppmDtc->type(participantData.typeId()).typeClass() == ParticipantManagement::TypeClass_def::Unit;
|
||||
}
|
||||
|
||||
bool bOnlyOutdated = false;
|
||||
if (bAskOutdated)
|
||||
{
|
||||
QHash<LtsWidgets::Button, QString> texts({{LtsWidgets::Button::Yes, tr("All")},
|
||||
{LtsWidgets::Button::No, tr("Only outdated")}
|
||||
});
|
||||
auto b = LtsWidgets::LtsMessageDialog::showMessage(this,
|
||||
tr("Do you want to move all participants or only outdated ones?"),
|
||||
windowTitle(),
|
||||
LtsWidgets::Behaviour::Modal,
|
||||
LtsWidgets::Button::Yes | LtsWidgets::Button::No,
|
||||
texts);
|
||||
if (b == LtsWidgets::Button::Cancel)
|
||||
return;
|
||||
|
||||
bOnlyOutdated = (b == LtsWidgets::Button::No);
|
||||
}
|
||||
|
||||
req.onlyOutdatedParticipants(bOnlyOutdated);
|
||||
req.position(Core::GeoPosition(coordinate.x(), coordinate.y(), 0.0));
|
||||
|
||||
m_requestHelper->startSingleRequest([req, this]()
|
||||
{
|
||||
return m_ppmFtc->setSimulatedPositionRequest(req, this);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void ParticipantsMoveDialog::doSetSimulatedPositionRelativeRequest(const ParticipantManagement::ParticipantData &participantData, const QPointF &coordinate)
|
||||
{
|
||||
// Unit is selected and should be moved relative to it´s current origin:
|
||||
const int participantId = participantData.id();
|
||||
if (participantId <= 0) //sanity
|
||||
return;
|
||||
|
||||
Core::GeoPosition unitPositionOut;
|
||||
if (!getUnitPosition(participantId, unitPositionOut))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << ", getUnitPosition failed for participantId=" << participantId;
|
||||
return;
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << ", getUnitPosition for participantId=" << participantId
|
||||
<< ", unitPositionOut: lon=" << unitPositionOut.lon() << " - lat=" << unitPositionOut.lat();
|
||||
|
||||
LtsCoordTrans::UtmCoordinate curUnitPosUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(unitPositionOut.lon(), unitPositionOut.lat());
|
||||
LtsCoordTrans::UtmCoordinate desiredUnitPosUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(coordinate);
|
||||
QPointF offset = desiredUnitPosUtm.relativeTo(curUnitPosUtm);
|
||||
|
||||
if (offset.isNull())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << ", required offset is zero. not expected... return";
|
||||
return;
|
||||
}
|
||||
|
||||
ParticipantManagement::SetSimulatedPositionRelative req;
|
||||
req.participantId(participantId);
|
||||
req.positionOffsetX(offset.x());
|
||||
req.positionOffsetY(offset.y());
|
||||
|
||||
DEBUG_LOG(m_logger) << "SetSimulatedPositionRelative = " << req;
|
||||
|
||||
m_requestHelper->startSingleRequest([req, this]()
|
||||
{
|
||||
return m_ppmFtc->setSimulatedPositionRelativeRequest(req, this);
|
||||
});
|
||||
}
|
||||
|
||||
void ParticipantsMoveDialog::doSetSimulatedParticipantFormationRequest(const ParticipantManagement::ParticipantData &participantData, const QPointF &coordinate, const QString &formationData)
|
||||
{
|
||||
// Unit is selected and should be moved relative to it´s current origin:
|
||||
const int participantId = participantData.id();
|
||||
if (participantId <= 0) //sanity
|
||||
return;
|
||||
|
||||
Core::GeoPosition unitPositionOut;
|
||||
if (!getUnitPosition(participantId, unitPositionOut))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << ", getUnitPosition failed for participantId=" << participantId;
|
||||
return;
|
||||
}
|
||||
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << ", getUnitPosition for participantId=" << participantId
|
||||
<< ", unitPositionOut: lon=" << unitPositionOut.lon() << " - lat=" << unitPositionOut.lat();
|
||||
|
||||
LtsCoordTrans::UtmCoordinate curUnitPosUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(unitPositionOut.lon(), unitPositionOut.lat());
|
||||
LtsCoordTrans::UtmCoordinate desiredUnitPosUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(coordinate);
|
||||
const QPointF offset = desiredUnitPosUtm.relativeTo(curUnitPosUtm);
|
||||
|
||||
if (offset.isNull())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << ", required offset is zero. not expected... return";
|
||||
return;
|
||||
}
|
||||
|
||||
ParticipantManagement::SetSimulatedParticipantFormation req;
|
||||
req.participantId(participantId);
|
||||
req.position(Core::GeoPosition(coordinate.x(), coordinate.y(), 0.0));
|
||||
req.positionOffsetX(offset.x());
|
||||
req.positionOffsetY(offset.y());
|
||||
req.formation(formationData.toStdString());
|
||||
|
||||
m_requestHelper->startSingleRequest([req, this]()
|
||||
{
|
||||
return m_ppmFtc->setSimulatedParticipantFormationRequest(req, this);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ParticipantManagement::ParticipantData ParticipantsMoveDialog::participantFromIndex(const QModelIndex &idx) const
|
||||
{
|
||||
return m_participantModel->getParticipantData(idx);
|
||||
}
|
||||
|
||||
} // namespace CentralEffectSimulation
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* GUI Plugin for ParticipantsMoveDialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLSE, 2018-01-02
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//Lts
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
#include <LtsWidgets/lts_frameless_dialog.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include "participant_move_dialog.h"
|
||||
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
|
||||
|
||||
#include "participants_move_model.h"
|
||||
|
||||
//DDS
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
#include <ParticipantManagement/ppm_dtc.h>
|
||||
#include <ParticipantManagement/ppm_ftc.h>
|
||||
#include <CentralEffectSimulation/ces_dtc.h>
|
||||
#include <AreaEffectSimulation/aes_dtc.h>
|
||||
#include <AssetManagement/asm_ftc.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_gui_combobox_plugin_interface.h>
|
||||
#include <Plugins/CentralEffectSimulation/ces_gui_plugin_interface.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_participants_gui_plugin_interface.h>
|
||||
|
||||
#include "logger.h"
|
||||
//Qt
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ParticipantMoveDialog;
|
||||
}
|
||||
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
// --------------------------------------------------------
|
||||
// ParticipantMoveDialog
|
||||
// --------------------------------------------------------
|
||||
class ParticipantsMoveDialog : public LtsWidgets::LtsDialog
|
||||
, protected CentralEffectSimulation::Interface::Ftc::SimulatedMovementRemoveByParticipantIdReplyHandler
|
||||
, protected ParticipantManagement::Interface::Ftc::SetSimulatedPositionReplyHandler
|
||||
, protected ParticipantManagement::Interface::Ftc::SetSimulatedPositionRelativeReplyHandler
|
||||
, protected ParticipantManagement::Interface::Ftc::SetSimulatedParticipantFormationReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ParticipantsMoveDialog(const QString &menuGroup, QWidget *parent = nullptr);
|
||||
~ParticipantsMoveDialog();
|
||||
|
||||
bool init(LtsSession::LtsSession *session,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<CentralEffectSimulation::Interface::Dtc> &cesDtc,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Ftc> &ppmFtc);
|
||||
|
||||
void onSimulatedMovementRemoveByParticipantIdReply(const Core::FunctionReplyObject &replyObject) override;
|
||||
void onSetSimulatedPositionReply(const Core::FunctionReplyObject &replyObject) override;
|
||||
void onSetSimulatedPositionRelativeReply(const Core::FunctionReplyObject &replyObject) override;
|
||||
void onSetSimulatedParticipantFormationReply(const Core::FunctionReplyObject &replyObject) override;
|
||||
|
||||
enum class FormationGeometrieType : int
|
||||
{
|
||||
AimPoint,
|
||||
Radial,
|
||||
Area,
|
||||
Line,
|
||||
Point
|
||||
};
|
||||
|
||||
public slots:
|
||||
void onGetCoordinate(QPointF coordinate);
|
||||
|
||||
private:
|
||||
bool getUnitPosition(int32_t participantId, Core::GeoPosition &unitPositionOut);
|
||||
void doSetSimulatedPositionRequest(const ParticipantManagement::ParticipantData &participantData, const QPointF &coordinate);
|
||||
void doSetSimulatedPositionRelativeRequest(const ParticipantManagement::ParticipantData &participantData, const QPointF &coordinate);
|
||||
void doSetSimulatedParticipantFormationRequest(const ParticipantManagement::ParticipantData &participantData, const QPointF &coordinate, const QString &formationData);
|
||||
private slots:
|
||||
void closeDialogReceived(int32_t participantId);
|
||||
void onModelChanged();
|
||||
|
||||
private:
|
||||
void retranslate() override;
|
||||
void onClicked();
|
||||
void onRemove();
|
||||
void onSetSimulatedMGRSPosition();
|
||||
bool participantInUse4ExplosionCluster(const QModelIndex &participantIndex);
|
||||
void changeParty();
|
||||
void onSelectionChanged();
|
||||
void onDoubleClicked();
|
||||
void onSetPosition();
|
||||
void setDialogEnable(bool enable);
|
||||
bool isParticipantInUseForExplosionCluster(int id);
|
||||
void tableColumnOrganiserSetting() override;
|
||||
|
||||
struct ParticipantTypePropertyStruct
|
||||
{
|
||||
QString m_propertiesStr;
|
||||
bool isArtillery = false;
|
||||
QString geometry = QStringLiteral("line");
|
||||
double distance = -1;
|
||||
double angle = -1;
|
||||
QVariantMap distanceSets;
|
||||
QJsonObject distanceSetsObj;
|
||||
|
||||
ParticipantTypePropertyStruct() {}
|
||||
explicit ParticipantTypePropertyStruct(const QString &properties) : m_propertiesStr(properties)
|
||||
{
|
||||
setFormation(properties);
|
||||
}
|
||||
void setDefaultValue()
|
||||
{
|
||||
isArtillery = false;
|
||||
geometry = QStringLiteral("line");
|
||||
distance = -1;
|
||||
angle = -1;
|
||||
distanceSets.clear();
|
||||
}
|
||||
|
||||
void setFormation(const QString &jsData)
|
||||
{
|
||||
setDefaultValue();
|
||||
const QJsonObject typObj = QJsonDocument::fromJson(QByteArray::fromStdString(jsData.toStdString())).object();
|
||||
if (typObj.isEmpty())
|
||||
return;
|
||||
isArtillery = typObj[isArtilleryStr].toBool(false);
|
||||
// Formation data Object
|
||||
const QJsonObject &formationObj = typObj[formationStr].toObject();
|
||||
if (formationObj.isEmpty())
|
||||
{
|
||||
setDefaultValue();
|
||||
return;
|
||||
}
|
||||
geometry = formationObj[geometryStr].toString(QStringLiteral("line"));
|
||||
angle = formationObj[angleStr].toDouble(-1);
|
||||
distance = formationObj[distanceStr].toDouble(-1);
|
||||
distanceSetsObj = formationObj[distanceSetsStr].toObject();
|
||||
distanceSets = distanceSetsObj.toVariantMap();
|
||||
}
|
||||
|
||||
bool hasFormationData() const
|
||||
{
|
||||
if (isArtillery == false)
|
||||
return true; // no need to continue artillery must be set for formation data to be changed
|
||||
else
|
||||
return (angle != -1) && (distance != -1);
|
||||
}
|
||||
QString getFormationDataObjectString() const
|
||||
{
|
||||
QJsonObject obj {{geometryStr, geometry},
|
||||
{angleStr, angle},
|
||||
{distanceStr, distance},
|
||||
{distanceSetsStr, distanceSetsObj} // doesnt change. use in combobox for selection. selection used by distance
|
||||
};
|
||||
return QString::fromStdString(QJsonDocument(obj).toJson(QJsonDocument::Compact).toStdString());
|
||||
}
|
||||
|
||||
const QString isArtilleryStr = QStringLiteral("isArtillery");
|
||||
const QString formationStr = QStringLiteral("formation");
|
||||
const QString geometryStr = QStringLiteral("geometry");
|
||||
const QString angleStr = QStringLiteral("angle");
|
||||
const QString distanceStr = QStringLiteral("distance");
|
||||
const QString distanceSetsStr = QStringLiteral("distanceSets");
|
||||
};
|
||||
|
||||
void setFormationAndPositioningUi(const ParticipantManagement::ParticipantData &participantData, QPointF &mgrsCoordinate, const bool &unitWithFormation);
|
||||
|
||||
bool removeFtc(int32_t participantId);
|
||||
ParticipantManagement::ParticipantData participantFromIndex(const QModelIndex &idx) const;
|
||||
|
||||
private:
|
||||
|
||||
ParticipantMoveModel *m_participantModel{nullptr};
|
||||
|
||||
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
|
||||
std::shared_ptr<ParticipantManagement::Interface::Ftc> m_ppmFtc;
|
||||
std::shared_ptr<AreaEffectSimulation::Interface::Dtc> m_aesDtc;
|
||||
|
||||
std::shared_ptr<CentralEffectSimulation::Interface::Dtc> m_cesDtc;
|
||||
std::shared_ptr<ParticipantManagement::ForeignGuiComboboxInterface> m_ppmCbxIfc;
|
||||
std::shared_ptr<Interface::Ftc> m_ftc;
|
||||
|
||||
Ui::ParticipantMoveDialog *m_ui{nullptr};
|
||||
LtsSession::LtsSession *m_session{nullptr};
|
||||
QString m_menuGroup;
|
||||
QMap<int, ParticipantMoveDialog *> m_participantDialogMap;
|
||||
LtsUtils::RequestHelper *m_requestHelper{nullptr};
|
||||
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
|
||||
bool m_shiftModifierWhileOnSetPosition{false};
|
||||
bool m_mgrsPosEditCoordinateActive{false};
|
||||
LOGGER_T m_logger;
|
||||
QRectF m_trainingAreaRect;
|
||||
ParticipantTypePropertyStruct m_formationProps;
|
||||
};
|
||||
} // namespace CentralEffectSimulation
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ParticipantMoveDialog</class>
|
||||
<widget class="QWidget" name="ParticipantMoveDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1028</width>
|
||||
<height>451</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>692</width>
|
||||
<height>342</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Participant Configuration</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0">
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="LtsWidgets::LtsComboBox" name="cbParty">
|
||||
<property name="currentText">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="4">
|
||||
<widget class="LtsDataView::LtsDataView" name="dvParticipants" native="true">
|
||||
<property name="rootIsDecorated" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lbParty">
|
||||
<property name="text">
|
||||
<string>Party:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QCheckBox" name="cbAll">
|
||||
<property name="text">
|
||||
<string>All Participants</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsWidgets::LtsComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>LtsWidgets/lts_combo_box.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LtsDataView::LtsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsDataView/lts_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>cbParty</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Model for ParticipantsMoveDialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLSE, 2018-01-02
|
||||
*/
|
||||
|
||||
#include "participants_move_model.h"
|
||||
|
||||
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
//----------------------------------------------------------------------------
|
||||
ParticipantMoveModel::ParticipantMoveModel(QObject *parent,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<AdvancedSymbology::ForeignDataInterface> &asbIfc)
|
||||
: ParticipantManagement::ParticipantEditModel(parent, ppmDtc, asbIfc)
|
||||
, m_logger(getLogger("ParticipantMoveModel"))
|
||||
{
|
||||
m_titles += tr("Simulated");
|
||||
|
||||
connect(m_dtc.get(), &ParticipantManagement::Interface::Dtc::participantChanged,
|
||||
this, &ParticipantMoveModel::onParticipantChanged);
|
||||
|
||||
DEBUG_LOG(m_logger) << "ParticipantMoveModel::ParticipantMoveModel";
|
||||
}
|
||||
|
||||
|
||||
QVariant ParticipantMoveModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
// ColSimulated is the last column
|
||||
if (role == Qt::DisplayRole && index.column() == columnCount() - 1)
|
||||
{
|
||||
bool bIsSimulated = false;
|
||||
if (!isSelectableBySimulation(index, &bIsSimulated))
|
||||
return QVariant();
|
||||
return bIsSimulated ? tr("Yes") : tr("No");
|
||||
}
|
||||
|
||||
return ParticipantManagement::ParticipantEditModel::data(index, role);
|
||||
}
|
||||
|
||||
void ParticipantMoveModel::onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType)
|
||||
{
|
||||
Q_UNUSED(modType)
|
||||
if (data.partyId() != m_partyId)
|
||||
return;
|
||||
INFO_LOG(m_logger) << "onParticipantChanged isSimulated=" << data.isSimulated();
|
||||
onReinitModel(partyId());
|
||||
emit newData();
|
||||
}
|
||||
|
||||
bool ParticipantMoveModel::isSelectableBySimulation(const QModelIndex &index, bool *bIsSimulated) const
|
||||
{
|
||||
bool isSimulatable = true;
|
||||
const ParticipantManagement::ParticipantData data(getParticipantData(index));
|
||||
|
||||
if ((data.equipmentNumber().is_set() && data.equipmentNumber().get() > 0) ||
|
||||
m_dtc->type(data.typeId()).typeClass() == ParticipantManagement::TypeClass_def::Unit)
|
||||
isSimulatable = false;
|
||||
|
||||
DEBUG_LOG(m_logger) << "ParticipantId: " << data.id()
|
||||
<< " isSimulated:" << data.isSimulated()
|
||||
<< " equipmentNo:" << data.equipmentNumber()
|
||||
<< " typeId=" << data.typeId()
|
||||
<< " modId=" << data.modId()
|
||||
<< " typeClass=" << m_dtc->type(data.typeId()).typeClass()
|
||||
<< " isSimulatable=" << isSimulatable;
|
||||
|
||||
if (bIsSimulated)
|
||||
*bIsSimulated = data.isSimulated();
|
||||
|
||||
return isSimulatable;
|
||||
}
|
||||
|
||||
} // namespace CentralEffectSimulation
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Model for ParticipantsMoveDialog
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Gerlinde Rudolphus, SLSE, 2018-01-02
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <nglwidgets/ngltreeitem.h>
|
||||
#include <Services/ParticipantManagement/ppm_dtc.h>
|
||||
#include <QStringList>
|
||||
|
||||
//ParticipantManagement
|
||||
#include <Plugins/ParticipantManagement/Gui/Common/participant_edit_model.h>
|
||||
#include "logger.h"
|
||||
|
||||
namespace CentralEffectSimulation
|
||||
{
|
||||
class ParticipantMoveModel final : public ParticipantManagement::ParticipantEditModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ParticipantMoveModel(QObject *parent,
|
||||
const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc,
|
||||
const std::shared_ptr<AdvancedSymbology::ForeignDataInterface> &asbIfc);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
signals:
|
||||
void newData();
|
||||
|
||||
private:
|
||||
void onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType);
|
||||
bool isSelectableBySimulation(const QModelIndex &index, bool *bIsSimulated = nullptr) const;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
} // namespace CentralEffectSimulation
|
||||
@@ -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