/** * @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 #include #include #include #include #include #include #include "participant_move_dialog.h" #include #include #include #include #include #include #include #include #include #include #include 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 &ppmDtc, const std::shared_ptr &cesDtc, const std::shared_ptr &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(m_ppmCbxIfc)) return false; if (!m_session->getFtc(m_ftc)) return false; std::shared_ptr exmDtc; if (!m_session->getDtc(exmDtc)) { ERROR_LOG(m_logger) << "failed to get exmDtc "; return false; } std::shared_ptr asmDtc; if (!m_session->getDtc(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: "<getDtc(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 asb; session->getForeignDataInterface(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(&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(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 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 &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(" Following Parameter(s) must be set to proceed. "), 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 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 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 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: "< degree: "<< mil2Deg(angleMil)<<" final position(°): "<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 fltParticipantIfc; m_session->getForeignGuiInterface(fltParticipantIfc); // not in global if (!fltParticipantIfc) return false; int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId(); QString workspaceId = m_session->workspaceId(); std::shared_ptr 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 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