/** * @RDE_HEADER@ * Dialog to edit drone Simulation * $Id$ * $HeadURL$ * $Author$ * Created by Steve Kemayou, ESZS, 2025-04-08 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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(m_pdmDtc)) { ERROR_LOG(m_logger) << " failed to get pdmDtc"; return false; } if (!m_session->getDtc(m_ppmDtc)) { ERROR_LOG(m_logger) << " failed to get ppmDtc"; return false; } if (!m_session->getFtc(m_ppmFtc)) { ERROR_LOG(m_logger) << " failed to get ppmFtc"; return false; } if (!m_session->getForeignGuiInterface(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(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(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::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::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("%2") .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(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(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: "<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 MissionPlanEdit::itemsRequestContent() { const int missionItemCount = m_ui->tableWidget->rowCount(); std::vector missionItems; using ParticipantManagement::MissionActionType; const QVector 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(nameWidget)->text(); QWidget *altitudeWidget = m_ui->tableWidget->cellWidget(i, Altitude); const int altitude = static_cast(altitudeWidget)->value(); QWidget *posWidget = m_ui->tableWidget->cellWidget(i, Position); const QPointF point = static_cast(posWidget)->coordinate(); Core::GeoPosition geoPos(point.x(), point.y(), altitude); QWidget *idleTimeWidget = m_ui->tableWidget->cellWidget(i, IdleTime); const int idleTime = static_cast(idleTimeWidget)->value(); QWidget *chargesWidget = m_ui->tableWidget->cellWidget(i, Charges); const int chargeTypeId = static_cast(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 &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 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 &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(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