Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,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