/** * @RDE_HEADER@ * Gui Plugin for ObserverController * $Id$ * $HeadURL$ * $Author$ * Created by Patric Karwat, SLSE, 2017-01-14 */ #include "osc_system_gui_plugin.h" #include "osc_selftest.h" #include "osc_settings.h" #include "osc_close_aes_list.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace OcSituationClient { std::shared_ptr GuiPlugin::createGuiInterface(LtsSession::LtsSession *session) { return std::make_shared(session); } InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session) : GuiPluginBase::Interface(session, getLogger("System.InterfaceImpl")) , m_closeAreaIdentifier(QStringLiteral("ocrCloseAesList")) { m_enterSound.setVolume(90); m_enterSound.setSource(QUrl(QStringLiteral("qrc:/effectarea-enter.wav"))); m_leaveSound.setVolume(90); m_leaveSound.setSource(QUrl(QStringLiteral("qrc:/effectarea-leave.wav"))); m_nearInSound.setVolume(90); m_nearInSound.setSource(QUrl(QStringLiteral("qrc:/entryNew.wav"))); m_nearOutSound.setVolume(90); m_nearOutSound.setSource(QUrl(QStringLiteral("qrc:/leaveNew.wav"))); } InterfaceImpl::~InterfaceImpl() { } bool InterfaceImpl::fetchInterfaces() { std::shared_ptr ppmDtc; if (!m_session->getDtc(ppmDtc)) return false; std::shared_ptr pdmDtc; if (!m_session->getDtc(pdmDtc)) return false; if (!m_session->getDtc(m_aesDtc)) return false; if (!m_session->getDtc(m_tabocDtc)) return false; return true; } void InterfaceImpl::clearInterfaces() { m_aesDtc = nullptr; m_tabocDtc = nullptr; } QString InterfaceImpl::menuGroup() const { return tr("System"); } QVector InterfaceImpl::getActions() { QVector ret; LtsWidgets::PluginData plData; plData.menuGroup = menuGroup(); // Action 'SelfTest' plData.menuText = tr("Self Test"); plData.identifier = QStringLiteral("ocrSelftest"); plData.menuIcon = QIcon(QLatin1String("icon:pi_show_bite.svg")); plData.operatorRight = 0; plData.createWidgetFunc = [this](QWidget * parent) { return onShowSelfTest(parent); }; ret.append(plData); // Action 'Settings' plData.menuText = tr("Settings"); plData.identifier = QStringLiteral("ocrSettings"); plData.menuIcon = QIcon(QLatin1String("icon:presets.svg")); plData.operatorRight = 0; plData.createWidgetFunc = [this](QWidget * parent) { return onShowSettings(parent); }; ret.append(plData); // Action 'AES List' plData.menuText = tr("AES List"); plData.identifier = m_closeAreaIdentifier; plData.menuIcon = QIcon(QLatin1String("icon:aes_list.svg")); plData.operatorRight = 0; plData.createWidgetFunc = [this](QWidget * parent) { return onShowCloseAes(parent); }; ret.append(plData); if (m_tabocDtc) { m_tabocDtc->enableAll(); connect(m_tabocDtc.get(), &TrainingAreaBaseOC::Interface::Dtc::enterLeaveAesChanged, this, &InterfaceImpl::onEnterLeaveAesChanged); if (m_aesDtc) connect(m_tabocDtc.get(), &TrainingAreaBaseOC::Interface::Dtc::ownPositionChanged, this, &InterfaceImpl::onCheckAllEffectAreas); // connect(m_tabocDtc.get(), &TrainingAreaBaseOC::Interface::Dtc::technicalStateSfmChanged, // this, &InterfaceImpl::onEnterLeaveAesChanged); } return ret; } void InterfaceImpl::onEnterLeaveAesChanged(const TrainingAreaBaseOC::EnterLeaveAes &data, DataModification modType) { if (modType == DataModification::eRemoved) return; if (LtsUtils::OperatorSettings::getInstance()) { bool playSound = LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("ObserverController"), QStringLiteral("AcousticWarning"), false).toBool(); if (playSound) { DEBUG_LOG(m_logger) << "Got new ENterLeave event and play sound"; if (data.cAreaType()) //entered/leaved directly { if(data.aesEntered()) { m_enterSound.play(); } else { m_leaveSound.play(); } DEBUG_LOG(m_logger) << "enter leave direvly " << data.aesEntered(); } else //not entered but warning range { if (data.aesEntered()) { m_nearInSound.play(); } else { m_nearOutSound.play(); } DEBUG_LOG(m_logger) << "enter leave near " << data.aesEntered(); } } if (data.aesEntered() && LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("ObserverController"), QStringLiteral("VisualWarning"), false).toBool() ) //new one { bool bWidgetExists = m_session->widgetExists(menuGroup(), m_closeAreaIdentifier, LtsWidgets::LayoutArea::eDialogTab); if (!bWidgetExists) m_session->addWidget(onShowCloseAes(), menuGroup(), m_closeAreaIdentifier, LtsWidgets::LayoutArea::eDialogTab); } } } void InterfaceImpl::onCheckAllEffectAreas() { if (!m_tabocDtc || !m_aesDtc) return; TrainingAreaBaseOC::OwnPosition pos = m_tabocDtc.get()->ownPosition(1); TrainingAreaBaseOC::EnterLeaveAes elAes; //create radios QPolygonF circle; //5deg steps +1 circle.reserve(73); int radius = LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("ObserverController"), QStringLiteral("WarningRange"), 1).toInt(); DEBUG_LOG(m_logger) << "My warning range is:" << radius; for (int i=0; i<360; i+=5) { double angle = i * M_PI / 180.0; circle << QPointF(cos(angle) * radius, sin(angle) * radius); } LtsCoordTrans::UtmCoordinate posUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(pos.position().lon(), pos.position().lat()); int zone = posUtm.zone; circle << circle.value(0); circle.translate(posUtm.x, posUtm.y); QPolygonF circleLonLat; circleLonLat.reserve(circle.size()); for (int i=0; i < circle.size(); i++) { LtsCoordTrans::UtmCoordinate posUtmC(zone, circle.at(i).x(), circle.at(i).y()); circleLonLat << posUtmC.geographic(); } //now check all areas const QMap views = m_aesDtc.get()->aesItemViews(); DEBUG_LOG(m_logger) << "new position " << posUtm.mgrs(); for(const AreaEffectSimulation::AesItemView &view: qAsConst(views)) { if (view.aesTypeId() == AreaEffectSimulation::AesType::AtExplosionAreaSingleExplosions || view.aesTypeId() == AreaEffectSimulation::AesType::AtMineAreaSingleMines || view.aesTypeId() == AreaEffectSimulation::AesType::AtTechnicalArea ) continue; bool contains = m_closeAes.contains(view.id()); if (m_closeAes.contains(view.id()) && view.effectStateId() != AreaEffectSimulation::AesEffectState::EsActivated) { DEBUG_LOG(m_logger) << "outdatet " ; m_closeAes.remove(view.id()); elAes.aesEntered(false); } else if (view.effectStateId() == AreaEffectSimulation::AesEffectState::EsActivated) { //not inside and is active QPolygonF poly(view.form().size()); int i=0; for(const auto &point : view.form()) { poly[i++] = QPointF(point.lon(), point.lat()); } #if QT_VERSION < QT_VERSION_CHECK(5,10,0) bool inters = poly.intersected(circleLonLat).size() > 0; #else bool inters = poly.intersects(circleLonLat); #endif DEBUG_LOG(m_logger) << "active " << view.id() << " intersect=" << inters << " inside map=" << contains ; if (inters && contains) { DEBUG_LOG(m_logger) << "already inside" ; continue; //already inside } else if (inters && !contains) { // is new DEBUG_LOG(m_logger) << "is new inside" ; m_closeAes.insert(view.id()); elAes.aesEntered(true); } else if (!inters && contains) { //not inside anymore DEBUG_LOG(m_logger) << "now outside" ; m_closeAes.remove(view.id()); elAes.aesEntered(false); } else { continue; } } else { DEBUG_LOG(m_logger) << "missed " << view.id() << " "; continue; } elAes.aesId(view.aesItemId()); elAes.chargeTypeId(view.chargeStruct().chargeTypeId()); //now send event onEnterLeaveAesChanged(elAes,DataModification::eModified); emit updateAesList(m_closeAes); } } LtsWidgets::LtsDialog *InterfaceImpl::onShowSelfTest(QWidget *parent) { SelfTest *dialog = new SelfTest(m_session, parent); return dialog; } LtsWidgets::LtsDialog *InterfaceImpl::onShowSettings(QWidget *parent) { Settings *dialog = new Settings(m_session, parent); return dialog; } LtsWidgets::LtsDialog *InterfaceImpl::onShowCloseAes(QWidget *parent) { CloseAesList *dialog = new CloseAesList(m_session, parent); connect (this, &InterfaceImpl::updateAesList, dialog, &CloseAesList::updateAesList); emit updateAesList(m_closeAes); return dialog; } } // namespace OcSituationClient