324 lines
9.3 KiB
C++
Executable File
324 lines
9.3 KiB
C++
Executable File
/**
|
|
* @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 <OcSituationClient/logger.h>
|
|
|
|
#include <LtsSession/lts_session.h>
|
|
#include <LtsSession/lts_session_data.h>
|
|
#include <LtsNotification/lts_notification.h>
|
|
|
|
#include <LtsUtilsSettings/settings.h>
|
|
|
|
#include <QNetworkSession>
|
|
#include <QNetworkConfigurationManager>
|
|
#include <QNetworkConfiguration>
|
|
#include <QTimer>
|
|
#include <QPolygonF>
|
|
#include <LtsCoordTrans/lts_coord_trans.h>
|
|
|
|
#include <ProjectDataManagement/pdm_data_plugin_interface.h>
|
|
#include <ParticipantManagement/ppm_data_plugin_interface.h>
|
|
|
|
namespace OcSituationClient
|
|
{
|
|
|
|
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
|
{
|
|
return std::make_shared<InterfaceImpl>(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<ParticipantManagement::Interface::Dtc> ppmDtc;
|
|
if (!m_session->getDtc<ParticipantManagement::DataInterface>(ppmDtc))
|
|
return false;
|
|
|
|
std::shared_ptr<ProjectDataManagement::Interface::Dtc> pdmDtc;
|
|
if (!m_session->getDtc<ProjectDataManagement::DataInterface>(pdmDtc))
|
|
return false;
|
|
|
|
if (!m_session->getDtc<AreaEffectSimulation::DataInterface>(m_aesDtc))
|
|
return false;
|
|
if (!m_session->getDtc<TrainingAreaBaseOC::DataInterface>(m_tabocDtc))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void InterfaceImpl::clearInterfaces()
|
|
{
|
|
m_aesDtc = nullptr;
|
|
m_tabocDtc = nullptr;
|
|
}
|
|
|
|
QString InterfaceImpl::menuGroup() const
|
|
{
|
|
return tr("System");
|
|
}
|
|
|
|
|
|
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
|
{
|
|
QVector<LtsWidgets::PluginData> 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<qint32, AreaEffectSimulation::AesItemView> 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
|