/** * @RDE_HEADER@ * Gui Plugin for Demand Situation * $Id$ * $HeadURL$ * $Author$ * Created by Patric Karwat, SLSE, 2018-03-27 */ #include "osc_terminal_gui_plugin.h" #include "osc_fault_message.h" #include "osc_equip_player.h" #include "osc_demand_situation_filter.h" #include "osc_edit_folder_content.h" #include #include #include #include #include #include #include #include // Interface #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("OcTerminal.InterfaceImpl")) , m_timer(new QTimer(this)) , m_requestHelper( new LtsUtils::RequestHelper(this)) , m_shortcutDemandSituation(nullptr) , m_mapTimeLabelHideTimer(new QTimer(this)) , m_demandSituation(nullptr) { m_timer->setInterval(3*60*1000); //3 minutes connect(m_timer, &QTimer::timeout, this, &InterfaceImpl::onNoDataTimerTick); m_mapTimeLabelHideTimer->setInterval(1000); m_mapTimeLabelHideTimer->setSingleShot(true); connect(m_mapTimeLabelHideTimer, &QTimer::timeout, this, &InterfaceImpl::onShortcutDemandSituationIconChanged); } InterfaceImpl::~InterfaceImpl() {} void InterfaceImpl::onSendDemandSituationReply(const Core::FunctionReplyObject &replyObject) { m_requestHelper->requestReply(replyObject); } void InterfaceImpl::stopSituationDemand() { const int range = 0; const int participant = 0; const Core::GeoPosition2D pos(0,0); std::vector partyIds{}; std::vector typesClass{}; SendDemandSituationRequest req(participant, range, dds::core::optional(), false, partyIds, typesClass); m_requestHelper->startSingleRequest([req, this]() { return m_ftc->sendDemandSituationRequest(req, this); }); setShortcutDemandSituationIconData(true); } bool InterfaceImpl::fetchInterfaces() { std::shared_ptr ppmCbxGui; if (!m_session->getDtc(m_dtcPpm)) return false; if (!m_session->getForeignGuiInterface(ppmCbxGui)) return false; if (!m_session->getDtc(m_dtcTab)) return false; if (!m_session->getFtc(m_ftc)) return false; if (!m_session->getForeignGuiInterface(m_sitMapGuiIfc)) return false; return true; } void InterfaceImpl::clearInterfaces() { m_ftc = nullptr; } QString InterfaceImpl::menuGroup() const { return tr("Terminal"); } QVector InterfaceImpl::getActions() { QVector ret; LtsWidgets::PluginData plData; plData.menuGroup = menuGroup(); if(m_shortcutDemandSituation == nullptr) { m_shortcutDemandSituation = m_session->createNotification(QStringLiteral("oscShortcutDemandSituation")); m_shortcutDemandSituation->setIcon(QIcon(QStringLiteral("icon:demand_situation.svg"))); m_shortcutDemandSituation->setToolTip(tr("Demand Situation not started")); m_shortcutDemandSituation->setAction([this]() { m_session->addWidget(onShowDemandSituation(nullptr), menuGroup(), QStringLiteral("oscDemandSituation"), LtsWidgets::LayoutArea::eDialogTab); }); connect(m_dtcTab.get(), &TrainingAreaBaseOC::Interface::Dtc::participantsOverloadChanged, this, &InterfaceImpl::onParticipantsOverloadChanged); connect(m_dtcTab.get(), &TrainingAreaBaseOC::Interface::Dtc::centralAesOverloadChanged, this, &InterfaceImpl::onCentralAesOverloadChanged); connect(m_session->baseLayout(), &LtsWidgets::LtsBaseLayoutWidget::signalLogout, this, [this]{ stopSituationDemand(); }); } // Action 'Demand Situation' plData.menuText = tr("Demand Situation"); plData.identifier = QStringLiteral("oscDemandSituation"); plData.menuIcon = QIcon(QLatin1String("icon:demand_situation.svg")); plData.operatorRight = 0; plData.createWidgetFunc = [this](QWidget * parent) { return onShowDemandSituation(parent); }; ret.append(plData); { // Action 'Demand Situation Filter' LtsWidgets::PluginData plData2; plData2.menuGroup = menuGroup(); plData2.menuText = tr("Demand Situation Filter"); plData2.identifier = QStringLiteral("oscDemandSituationFilter"); plData2.menuIcon = QIcon(QLatin1String("icon:demand_situation_filter.svg")); plData2.operatorRight = 0; plData2.createWidgetFunc = [this](QWidget * parent) { return onShowDemandSituationFilter(parent); }; ret.append(plData2); } if (strcmp(PROJECTBUILD, "guez") != 0) //not guez add fault message { // Action 'Equipment Fault' plData.menuText = tr("Fault Message"); plData.identifier = QStringLiteral("oscFaultMessage"); plData.menuIcon = QIcon(QLatin1String("icon:player_equipment_fault.svg")); plData.operatorRight = 0; plData.createWidgetFunc = [this](QWidget * parent) { return onShowFaultMessage(parent); }; ret.append(plData); }else //is guez add folder content { // Action 'Edit folder content' plData.menuText = tr(" Folder Content"); plData.identifier = QStringLiteral("oscEditFolderContent"); plData.menuIcon = QIcon(QLatin1String("icon:organize_library.svg")); plData.operatorRight = 0; plData.createWidgetFunc = [this](QWidget * parent) { return onShowEditFolderContentDialog(parent); }; ret.append(plData); } if (strcmp(PROJECTBUILD, "guez") != 0) { // Action 'Equipment Fault' plData.menuText = tr("Equip Player"); plData.identifier = QStringLiteral("oscEquipPlayer"); plData.menuIcon = QIcon(QLatin1String("icon:force_player_configuration.svg")); plData.operatorRight = 0; plData.createWidgetFunc = [this](QWidget * parent) { return onShowEquipPlayer(parent); }; ret.append(plData); } //now send request for old QTimer::singleShot(2000, this, &InterfaceImpl::onTimerTick); m_dtcTab->enableParticipantsOverload(); return ret; } void InterfaceImpl::onTimerTick() { connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::participantPositionChanged, this, &InterfaceImpl::onParticipantPosition, Qt::UniqueConnection); connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::dynamicParticipantDataChanged, this, &InterfaceImpl::onParticipantDynamic, Qt::UniqueConnection); LtsUtils::OperatorSettings *settings = LtsUtils::OperatorSettings::getInstance(); QString ocString = QStringLiteral("ObserverControllerDemand"); const int range = settings->value(ocString, QStringLiteral("Range"), 0).toInt(); // if (range <= 0) // return; /// stop sending demand situation on initialization const int participant = 0; const Core::GeoPosition2D pos(0,0); std::vector partyIds{}; std::vector typesClass{}; const QStringList partyList = settings->value(ocString, QStringLiteral("Partys"),-1).toStringList(); const QStringList typeClassList = settings->value(ocString, QStringLiteral("TypeClass"),-1).toStringList(); partyIds.reserve(partyList.size()); for (const auto &party: partyList) { partyIds.push_back(party.toInt()); } typesClass.reserve(typeClassList.size()); for (const auto &typeCl: typeClassList) { typesClass.push_back(typeCl.toInt()); } SendDemandSituationRequest req(participant, range, dds::core::optional(), settings->value(ocString, QStringLiteral("FilterActive"),false).toBool(), partyIds, typesClass); if (pos.lat() > 0) { req.position().set(pos); } m_requestHelper->startSingleRequest([req, this]() { return m_ftc->sendDemandSituationRequest(req, this); }); setShortcutDemandSituationIconData(true); } void InterfaceImpl::onNoDataTimerTick() { //We stop the timer until the first overload message arrives again m_timer->stop(); setShortcutDemandSituationIconData(true); } void InterfaceImpl::onParticipantDynamic(const ParticipantManagement::DynamicParticipantData &data) { if (m_dtcPpm->participant(data.participantId()).equipmentNumber() == m_dtcTab->specificsEquipment(1).equipmentNumber()) return; onParticipantData(); } void InterfaceImpl::onParticipantPosition(const ParticipantManagement::ParticipantPosition &data) { if (m_dtcPpm->participant(data.participantId()).equipmentNumber() == m_dtcTab->specificsEquipment(1).equipmentNumber()) return; onParticipantData(); } void InterfaceImpl::onCentralAesOverloadChanged(const TrainingAreaBaseOC::CentralAesOverload &data, DataModification modType) { Q_UNUSED(modType) m_hasCentralAesOverload = data.hasOverload(); setShortcutDemandSituationIconData(); m_timer->start(); } void InterfaceImpl::onParticipantsOverloadChanged(const TrainingAreaBaseOC::ParticipantsOverload &data, DataModification modType) { Q_UNUSED(modType) m_hasParticipantOverload = data.hasOverload(); setShortcutDemandSituationIconData(); m_timer->start(); } void InterfaceImpl::onShortcutDemandSituationIconChanged() { if (!m_sitMapGuiIfc) { m_mapTimeLabelHideTimer->start(); return; } m_sitMapGuiIfc->map()->showTimeString(m_demandSituationActive); m_sitMapGuiIfc->map()->setTimeString(DTG::toStringMSec(m_session->partitionTime())); } void InterfaceImpl::setShortcutDemandSituationIconData(bool hasToBeDisabled) { if (m_shortcutDemandSituation == nullptr) return; m_demandSituationActive = true; if (hasToBeDisabled) { m_shortcutDemandSituation->setIcon(QIcon(QStringLiteral("icon:demand_situation_disabled.svg"))); m_shortcutDemandSituation->setToolTip(tr("Demand Situation not started")); m_demandSituationActive = false; } else { m_shortcutDemandSituation->setIcon(getOverloadIcon()); m_shortcutDemandSituation->setToolTip(getOverLoadTooltip()); } if (m_mapTimeLabelHideTimer != nullptr) m_mapTimeLabelHideTimer->start(); } QString InterfaceImpl::getOverLoadTooltip() const { if (m_hasParticipantOverload && m_hasCentralAesOverload) { return tr("Demand Situation: Participant and Central AES count out of range"); } else if (m_hasParticipantOverload) { return tr("Demand Situation: Participant count out of range"); } else if (m_hasCentralAesOverload) { return tr("Demand Situation: Central AES count out of range"); } else { return tr("Demand Situation"); } } QIcon InterfaceImpl::getOverloadIcon() const { qint32 size = 100; QImage image(size, size, QImage::Format_ARGB32); image.fill(Qt::transparent); QPainter painter(&image); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); painter.setPen(Qt::transparent); QColor centralAesOverloadColor = m_hasCentralAesOverload ? Qt::red : Qt::green; QColor participantOverloadColor = m_hasParticipantOverload ? Qt::red : Qt::green; QRect arcRect(0, 0, size , size); QRadialGradient arcGradient(arcRect.center(), size * 0.6); arcGradient.setColorAt(1.0, Qt::transparent); // participant overload arcGradient.setColorAt(0.0, participantOverloadColor); painter.setBrush(QBrush(arcGradient)); painter.drawPie(arcRect, 90 * 16, 180 * 16); // central aes overload arcGradient.setColorAt(0.0, centralAesOverloadColor); painter.setBrush(QBrush(arcGradient)); painter.drawPie(arcRect, 270 * 16, 180 * 16); QFont font = painter.font() ; font.setPointSize(30); font.setBold(true); painter.setFont(font); painter.setBrush(QBrush(Qt::black, Qt::NoBrush)); painter.setPen(Qt::black); painter.drawText(55, 65, tr("W")); painter.setBrush(QBrush(Qt::black, Qt::NoBrush)); painter.setPen(Qt::black); painter.drawText(17, 65, tr("T")); painter.end(); return QIcon(QPixmap::fromImage(image)); } void InterfaceImpl::onParticipantData() { if (!m_sitMapGuiIfc) return; m_sitMapGuiIfc->map()->showTimeString(m_demandSituationActive); m_sitMapGuiIfc->map()->setTimeString(DTG::toStringMSec(m_session->partitionTime())); } LtsWidgets::LtsDialog *InterfaceImpl::onShowDemandSituation(QWidget *parent) { m_demandSituation = new DemandSituation(m_session, parent); connect(m_demandSituation, &DemandSituation::destroyed, this,[this]() { m_demandSituation = nullptr; }); connect(m_demandSituation, &DemandSituation::demandSituationStopped, this, [this]() { stopSituationDemand(); }, Qt::UniqueConnection); return LtsWidgets::initDialog(m_demandSituation, m_ftc); } LtsWidgets::LtsDialog *InterfaceImpl::onShowDemandSituationFilter(QWidget *parent) { return LtsWidgets::initDialog(new DemandSituationFilter(m_session, parent), m_ftc); } LtsWidgets::LtsDialog *InterfaceImpl::onShowFaultMessage(QWidget *parent) { return LtsWidgets::initDialog(new FaultMessage(m_session, parent), m_ftc); } LtsWidgets::LtsDialog *InterfaceImpl::onShowEquipPlayer(QWidget *parent) { return LtsWidgets::initDialog(new EquipPlayer(m_session, parent), m_ftc); } LtsWidgets::LtsDialog *InterfaceImpl::onShowEditFolderContentDialog(QWidget *parent) { return LtsWidgets::initDialog(new FolderContentEditDialog(parent),m_session); } } // namespace OcSituationClient