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

906 lines
33 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @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