/** * @RDE_HEADER@ * AreaEffectSimulation - Contamination Edit Dialog * $Id$ * $HeadURL$ * $Author$ * Created by Patric Karwat, SLSE, 2016-07-07 */ #include "aes_bccontamination_edit.h" #include "ui_aes_bccontamination_edit.h" #include "../AesInfo/aes_danger_area_aes_item_info.h" #include #include #include #include #include #include #include #include #include namespace AreaEffectSimulation { double BCContaminationEdit::s_minRadius; double BCContaminationEdit::s_maxRadius; double BCContaminationEdit::s_stepRadius; int BCContaminationEdit::s_minDurationHours; int BCContaminationEdit::s_maxDurationHours; double BCContaminationEdit::s_minAltitude; double BCContaminationEdit::s_maxAltitude; static int s_lastChargeTypeB = 0; static int s_lastChargeTypeC = 0; // Todo: Höhe und Radius in Abhängigkeit der Munitionsart berechnen BCContaminationEdit::BCContaminationEdit(const QString &menuGroup, bool isChemical, QWidget *parent) : BaseEdit(menuGroup, QLatin1String("BCContaminationEdit"), parent) , m_isChemical(isChemical) , m_ui(new Ui::BCContaminationEdit) { m_ui->setupUi(this); s_minRadius = 50; s_maxRadius = 2500; s_stepRadius = 5; s_minDurationHours = 1; s_maxDurationHours = 4; s_minAltitude = 2; s_maxAltitude = 50; m_ui->sbRadius->setMinimum(s_minRadius); m_ui->sbRadius->setMaximum(s_maxRadius); m_ui->sbRadius->setSingleStep(s_stepRadius); m_ui->sbDurationHours->setMinimum(s_minDurationHours); m_ui->sbDurationHours->setMaximum(s_maxDurationHours); m_ui->sbAltitude->setMinimum(s_minAltitude); m_ui->sbAltitude->setMaximum(s_maxAltitude); m_uiRequirements->addRequirement({m_ui->lblPosition, [this]() { return (!m_ui->positionEdit->coordinate().isNull()); }}); m_uiRequirements->addRequirement({m_ui->lblIdentifier, [this]() { return (!m_ui->leIdentifier->text().isEmpty()); }}); m_uiRequirements->addRequirement({m_ui->lblEffectStart, [this]() { return hasValidEffectStart(m_ui->dteEffectStart); }}); m_uiRequirements->addRequirement({m_ui->lblChargeType, [this]() { return (m_ui->cbChargeType->currentData().toInt() > 0); }}); connect(m_ui->pbDangerArea, &QPushButton::clicked, this, &BCContaminationEdit::onPbDangerAreaClicked); connect(m_ui->pbClear, &QPushButton::clicked, m_ui->positionEdit, &LtsCoordWidget::LtsCoordWidget::clear); connect(m_ui->sbRadius, &QSpinBox::editingFinished, this, &BCContaminationEdit::correctSpinBoxValue); // [GUEZE-2833] Inkonsistenz - Wetter Einstellungen bei A und C Feldern // Order changed AwsDynamic = 0, AwsStatic = 1, m_ui->cbWeather->addItem(toString(AesWeatherSource::AwsDynamic), AesWeatherSource::AwsDynamic); m_ui->cbWeather->addItem(toString(AesWeatherSource::AwsStatic), AesWeatherSource::AwsStatic); LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance(); const bool enableShowMeteoDataStations = ps->value(QStringLiteral("mdm"), QStringLiteral("enableShowMeteoDataStations")).toBool(); if (!enableShowMeteoDataStations) { m_ui->cbWeather->hide(); m_ui->lblWeather->hide(); // cbWeather per default auf AesWeatherSource::AwsStatic } m_ui->lblAltitude->show(); m_ui->sbAltitude->show(); // Not yet needed, as no step is defined: // connect(m_ui->sbAltitude, &QSpinBox::editingFinished, this, &BCContaminationEdit::correctSpinBoxValue); // connect(m_ui->sbDurationMinutes, &QSpinBox::editingFinished, this, &BCContaminationEdit::correctSpinBoxValue); // party is (currently) not user-visible // m_ui->lblParty->setVisible(false); // m_ui->cbParty->setVisible(false); enaDisa(); if (m_isChemical) setOnlineHelpFilename(QStringLiteral("Situation-Add_C-Contamination")); else setOnlineHelpFilename(QStringLiteral("Situation-Add_B-Contamination")); } BCContaminationEdit::~BCContaminationEdit() { delete m_ui; } void BCContaminationEdit::retranslate() { translate(m_ui, m_aesItem, m_isChemical ? tr("C-Contamination") : tr("B-Contamination")); if (m_isChemical) m_pdmGuiIfc->fillCComboBox(m_ui->cbChargeType); else m_pdmGuiIfc->fillBComboBox(m_ui->cbChargeType); setCombobxToValueIfPossible(m_ui->cbChargeType, m_isChemical ? s_lastChargeTypeC : s_lastChargeTypeB); } void BCContaminationEdit::enableUiElements(bool enable) { m_ui->leIdentifier->setMaxLength(30); m_ui->cbChargeType->setEnabled(enable); m_ui->sbDurationHours->setEnabled(enable); m_ui->cbParty->setEnabled(enable); setEffectStartEnabled(m_ui->dteEffectStart, enable); m_ui->pbPosition->setEnabled(m_sitMapGuiIfc && enable); m_ui->positionEdit->setEnabled(enable); m_ui->sbAltitude->setEnabled(enable); m_ui->cbLowerLimit->setEnabled(enable); m_ui->sbRadius->setEnabled(enable); m_ui->leIdentifier->setEnabled(enable || isOnlyNameModifiable()); m_ui->cbWeather->setEnabled(enable); m_ui->pbClear->setEnabled(enable); if (m_aesItem.effectStateId() == AesEffectState_def::EsExpired) { m_ui->leIdentifier->setText(QString::fromStdString(m_aesItem.name())); __unchange__(); } if (m_aesItem.effectStateId() == AesEffectState_def::EsActivated) { QString name = m_ui->leIdentifier->text(); auto baseData = m_dtc->bCContamination(m_aesItem.id()); setData(baseData, false); __unchange__(); if (name != m_ui->leIdentifier->text()) m_ui->leIdentifier->setText(name); } } bool BCContaminationEdit::init(int aesItemId, bool copy, LtsSession::LtsSession *session) { if (!BaseEdit::init(aesItemId, session)) return false; bool editable = (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::CContaminationsEdit) && m_isChemical) || (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::BContaminationsEdit) && !m_isChemical) || m_session->app() == LtsAppDescriptor::App::OC; bool readable = (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::CContaminationsShow) && m_isChemical) || (LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::BContaminationsShow) && !m_isChemical) ; setPbDangerAreaText(); if (!readable && !editable) return false; // FIXME: in GUI plugin, nicht ausserhalb! if (!m_session->getForeignGuiInterface(m_pdmGuiIfc)) return false; m_ui->dteEffectStart->setMinimumTimeMSec(m_session->partitionTime()); m_ui->dteEffectStart->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); }); if (m_sitMapGuiIfc) connect(m_ui->pbPosition, &QPushButton::clicked, this, &BCContaminationEdit::getPosition); else m_ui->pbPosition->setEnabled(false); if (m_isChemical) m_pdmGuiIfc->fillCComboBox(m_ui->cbChargeType); else m_pdmGuiIfc->fillBComboBox(m_ui->cbChargeType); m_ppmGuiCbxIfc->fillPartyComboBox(m_ui->cbParty); if (aesItemId > 0) { auto baseData = m_dtc->bCContamination(aesItemId); setData(baseData, copy); } auto cb = [this](const DangerAreaCorrelatedAesItem &item) { if (item.aesItemId() == m_aesItem.id()) m_dangerAreaIds << item.dangerAreaId(); }; m_dtc->dangerAreaCorrelatedAesItems(cb); setPbDangerAreaText(); enableUiElements(editable && isModifiable() && !isOnlyNameModifiable()); connect(m_dtc.get(), &AreaEffectSimulation::Interface::Dtc::dangerAreaCorrelatedAesItemChanged, this, &BCContaminationEdit::onDangerAreaChanged); connect(m_dtc.get(), &AreaEffectSimulation::Interface::Dtc::bCContaminationChanged, this, &BaseEdit::onAreaChanged); auto cbDangerArea = [this](const DangerArea &data) { if (data.effectStateId() != AesEffectState::EsRemoved && data.associatedAesId() == m_aesItem.id()) m_associatedDangerId = data.id(); }; m_dtc->dangerAreas(cbDangerArea); if (m_associatedDangerId) { m_ui->chbDangerArea->setChecked(true); m_ui->chbDangerArea->setEnabled(false); } return true; } void BCContaminationEdit::setPbDangerAreaText() { QStringList sl; sl.reserve(m_dangerAreaIds.size()); for (int idx : qAsConst(m_dangerAreaIds)) { sl << QString::fromStdString(m_dtc->dangerArea(idx).name()); } m_ui->pbDangerArea->setEnabled(sl.size()); m_ui->pbDangerArea->setText(sl.join(QStringLiteral(", "))); } void BCContaminationEdit::onDangerAreaChanged(const DangerAreaCorrelatedAesItem &data, DataModification modType) { if (data.aesItemId() != m_aesItem.id()) return; if (modType == DataModification::eAdded) m_dangerAreaIds += data.dangerAreaId(); if (modType == DataModification::eRemoved) m_dangerAreaIds -= data.dangerAreaId(); // Note: Modification cannot happen as the key is unique for the combination. setPbDangerAreaText(); } void BCContaminationEdit::onPbDangerAreaClicked() { if (m_dangerAreaIds.isEmpty()) return; std::shared_ptr infoGuiInterface; if (!m_session->getForeignGuiInterface(infoGuiInterface)) return; LtsWidgets::LtsDialog *dialog = infoGuiInterface->showDangerAreaAesItemInfo(m_dangerAreaIds, {m_aesItem.id()}); addDialog(dialog, m_menuGroup, tr("Danger Areas for %1 %2").arg(m_isChemical ? tr("C-Contamination") : tr("B-Contamination"), m_ui->leIdentifier->text()), LtsWidgets::LayoutArea::eInfoTab); } void BCContaminationEdit::setData(const BCContamination &contamination, bool copy) { m_aesItem = contamination; if (copy) { m_aesItem.id(0); m_aesItem.effectStateId(AreaEffectSimulation::AesEffectState_def::get_default()); } m_ui->leIdentifier->setText(QString::fromStdString(contamination.name())); m_ui->dteEffectStart->setMsecsSinceEpoch(contamination.effectStart().is_set() ? contamination.effectStart().get() : 0); m_ui->cbChargeType->setCurrentIndex(m_ui->cbChargeType->findData(contamination.chargeStruct().chargeTypeId())); // not user-visible m_ui->sbDurationHours->setValue(contamination.effectDuration() / 1000 / 60/ 60); // msecs -> mins -> hours m_ui->sbRadius->setValue(contamination.impactRadius()); m_ui->cbParty->setCurrentIndex(m_ui->cbParty->findData(contamination.partyId().is_set() ? contamination.partyId().get() : 0)); m_ui->cbWeather->setCurrentIndex(contamination.weatherSource().underlying()); QPointF impactPosition(contamination.impactPosition().lon(), contamination.impactPosition().lat()); if (!impactPosition.isNull()) m_ui->positionEdit->setCoordinate(impactPosition); m_ui->sbAltitude->setValue(contamination.upperOffset()); m_ui->cbLowerLimit->setChecked(qFuzzyIsNull(contamination.lowerOffset())); } void BCContaminationEdit::getPosition() { if (!has2DMap()) return; m_sitMapGuiIfc->getCircle(this, SLOT(onCircleData(QPointF, double)), nullptr, s_minRadius, s_maxRadius, m_ui->positionEdit->coordinate(), m_ui->sbRadius->value()); //max } void BCContaminationEdit::onCircleData(const QPointF &position, double radius) { m_previewCircleCenter = position; // SB corrects value acc. singleStep m_ui->sbRadius->setValue(radius); m_previewCircleRadius = m_ui->sbRadius->value(); m_ui->positionEdit->setCoordinate(position); DEBUG_LOG(m_logger) << "Pos X: " << position.x() << " Y: " << position.y() << " R: " << radius; showPreviewObject(); } bool BCContaminationEdit::apply() { std::string name = m_ui->leIdentifier->text().toStdString(); qint64 effectStart = m_ui->dteEffectStart->msecsSinceEpoch(); int duration = m_ui->sbDurationHours->value() * 60 * 1000 * 60; //hours -> mins -> msecs int chargeType = m_ui->cbChargeType->currentData().toInt(); if (m_isChemical) s_lastChargeTypeC = chargeType; else s_lastChargeTypeB = chargeType; int partyId = m_ui->cbParty->currentData().toInt(); int participantId = 0; int radius = m_ui->sbRadius->value(); int weathersource = m_ui->cbWeather->currentData().toInt(); double extrusionHeight = m_ui->sbAltitude->value(); double lowerOffset = 0.0; if (!m_ui->cbLowerLimit->isChecked()) lowerOffset = -1000.0; QPointF p(m_ui->positionEdit->coordinate()); const Core::GeoPosition2D pos(p.x(), p.y()); const BCContaminationModifyRequest req(m_aesItem.id(), name, LtsUtils::toOptional(effectStart), duration, chargeType, pos, radius, static_cast(weathersource), LtsUtils::toOptional(partyId), LtsUtils::toOptional(participantId), dds::core::optional(), dds::core::optional(), dds::core::optional(), dds::core::optional(), dds::core::optional(), extrusionHeight, lowerOffset, m_ui->chbDangerArea->isChecked()); INFO_LOG(m_logger) << "apply " << " extrusionHeight=" << extrusionHeight << " req.upperOffset=" << req.upperOffset() << " lowerOf" "fset=" << lowerOffset << " req.lowerOffset=" << req.lowerOffset(); m_requestHelper->addRequest([this,req]() { return m_ftc->bCContaminationModifyRequest(req, this); }); bool ret= m_requestHelper->startRequests(); if (m_ui->chbDangerArea->isChecked() && ret) m_ui->chbDangerArea->setEnabled(false); return ret; } void BCContaminationEdit::showPreviewObject() { if (!m_sitMapGuiIfc) return; if (m_previewCircleCenter.isNull()) return; m_sitMapGuiIfc->displayPreviewObject(this, m_previewCircleCenter, m_previewCircleRadius); } } // namespace AreaEffectSimulation