/** * @RDE_HEADER@ * GUI Plugin for ParticipantManagement - ParticipantInfo * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, SLSE, 2016-02-29 */ #include "participant_info_gui_plugin.h" #include "participant_info_dialog.h" #include "participant_info_table_dialog.h" #include "participant_config_dialog.h" #include "participant_search_dialog.h" #include "participant_follow_dialog.h" #include "participant_hitline_info_dialog.h" #include "participant_bite_dialog.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace ParticipantManagement { std::shared_ptr GuiPlugin::createGuiInterface(LtsSession::LtsSession *session) { return std::make_shared(session); } const QString InterfaceImpl::s_participantInfoScheme = QStringLiteral("ParticipantInfo"); InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session) : GuiPluginBase::Interface(session, getLogger("Plugins.Gui.Ppm.ParticipantInfo")) { qApp->installEventFilter(this); // for link events } QString participantFollowIdentifier() { return QStringLiteral("ParticipantFollow"); } void InterfaceImpl::onShowSearchParticipant() { if (m_participantShowModalPtr) return; m_participantShowModalPtr = new ParticipantSearchModal(m_session->baseLayout()); // #define TEST_LIFETIME #ifdef TEST_LIFETIME // Ein Test fuer wen's interessiert QTimer *t = new QTimer(m_participantShowModalPtr.data()); connect(t, &QTimer::timeout, this, [this, t]() { ERROR_LOG(m_logger) << "TEST_LIFETIME: " << (qintptr)t << " @ " << (qintptr)m_session->baseLayout() << " still alive"; }); t->start(1000); #endif if (!m_participantShowModalPtr->init(m_dtc)) { ERROR_LOG(m_logger) << "initialization of ParticipantSearchModal failed - cannot show participant search modal"; m_participantShowModalPtr->deleteLater(); return; } connect(m_participantShowModalPtr.data(), &ParticipantSearchModal::participantSelected, this, [this](int participantId) { showParticipantInfoWindow(participantId); }); m_participantShowModalPtr->setAttribute(Qt::WA_DeleteOnClose); // auto delete on close m_participantShowModalPtr->show(); } QVector InterfaceImpl::getActions() { QVector ret; LtsWidgets::PluginData plData; plData.menuGroup = menuGroup(); if (appId() != LtsAppDescriptor::App::BuildingViewer) { plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab; plData.menuText = tr("Participant Search"); plData.identifier = QLatin1String("ParticipantSearch"); plData.menuIcon = QIcon(QLatin1String("icon:select_player.svg")); plData.operatorRight = OperatorRights::ParticipantInfo::ParticipantInfoSearch; plData.exercisePart = LtsWidgets::ExercisePart::eSpecial; plData.createWidgetFunc = [this](QWidget * parent) { return onShowParticipantSearchDialog(parent); }; ret.append(plData); } if (appId() != LtsAppDescriptor::App::OC) { if (appId() != LtsAppDescriptor::App::BuildingViewer) { LtsWidgets::PluginData plData1; plData1.menuGroup = menuGroup(); plData1.layoutArea = LtsWidgets::LayoutArea::eDialogTab; plData1.menuText = tr("Participant Follow"); plData1.identifier = participantFollowIdentifier(); plData1.menuIcon = QIcon(QLatin1String("icon:center_to_object.svg")); plData1.operatorRight = OperatorRights::ParticipantInfo::ParticipantInfoSearch; plData1.exercisePart = LtsWidgets::ExercisePart::eSpecial; plData1.createWidgetFunc = [this](QWidget * parent) { return onShowParticipantFollowDialog(parent); }; ret.append(plData1); plData.layoutArea = LtsWidgets::LayoutArea::eInfoTab; plData.menuText = tr("Participant Info Table"); plData.identifier = QLatin1String("ParticipantInfoTable"); plData.menuIcon = QIcon(QLatin1String("icon:service_group.svg")); plData.operatorRight = OperatorRights::ParticipantInfo::ParticipantInfoTableShow; plData.exercisePart = LtsWidgets::ExercisePart::eSpecial; plData.createWidgetFunc = [this](QWidget * parent) { return onShowParticipantInfoTableDialog(parent); }; ret.append(plData); plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab; plData.menuText = tr("Set Participant Status"); plData.identifier = QLatin1String("ParticipantSetStatus"); plData.menuIcon = QIcon(QLatin1String("icon:set_player_status.svg")); plData.operatorRight = OperatorRights::ParticipantInfo::ParticipantInfoSendConfig; plData.exercisePart = LtsWidgets::ExercisePart::eExecution; plData.createWidgetFunc = [this](QWidget * parent) { return onShowParticipantConfigDialog(false, parent); }; ret.append(plData); LtsUtils::ProjectSettings *ps = LtsUtils::ProjectSettings::getInstance(); const bool enableMassages = ps->value(QStringLiteral("msg"), QStringLiteral("enableMessages")).toBool(); if (enableMassages) { plData.menuText = tr("Send Participant Messages"); plData.identifier = QLatin1String("ParticipantSendMessages"); plData.menuIcon = QIcon(QLatin1String("icon:send_player_message.svg")); plData.operatorRight = OperatorRights::ParticipantInfo::ParticipantInfoSendMessage; plData.exercisePart = LtsWidgets::ExercisePart::eExecution; plData.createWidgetFunc = [this](QWidget * parent) { return onShowParticipantConfigDialog(true, parent); }; ret.append(plData); } } LtsWidgets::PluginData plData2; plData2.menuGroup = menuGroup(); plData2.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction; plData2.directFunc = [this](const LtsWidgets::PluginData &) { if (m_session->app() != LtsAppDescriptor::App::Situation && m_session->app() != LtsAppDescriptor::App::OrgChart && m_session->app() != LtsAppDescriptor::App::Snapshot && m_session->app() != LtsAppDescriptor::App::BuildingViewer && m_session->app() != LtsAppDescriptor::App::ScriptEditorEssentialsView) return; if (m_scSearchParticipant != nullptr) return; m_scSearchParticipant = new QShortcut(QKeySequence(Qt::Key_F4), m_session->baseLayout()); m_scSearchParticipant->setContext(Qt::WindowShortcut); connect(m_scSearchParticipant, &QShortcut::activated, this, &InterfaceImpl::onShowSearchParticipant); }; ret.append(plData2); // // only pariticpant search and function Key-F4 in replay // if (m_session->partitionType() == IDL::PartitionType::Replay) return ret; m_session->getForeignGuiInterface(m_sitMapGuiIfc); connect(m_dtc.get(), &ParticipantManagement::Interface::Dtc::participantPositionChanged, this, &InterfaceImpl::onParticipantPositionChanged); connect(m_dtc.get(), &ParticipantManagement::Interface::Dtc::unitPositionChanged, this, &InterfaceImpl::onUnitPositionChanged); } else // if (appId() != LtsAppDescriptor::App::OC) { LtsWidgets::PluginData plData3; plData3.menuGroup = menuGroup(); plData3.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction; plData3.directFunc = [this](const LtsWidgets::PluginData &) { m_notiSearchParticipant = m_session->createNotification(QStringLiteral("TabOcSearchParticipant")); m_notiSearchParticipant->setIcon(QIcon(QLatin1String("icon:search.svg"))); m_notiSearchParticipant->setToolTip(tr("Search Participant")); m_notiSearchParticipant->setAction([this]() { if (m_participantSearchWidget) { m_participantSearchWidget->show(); m_participantSearchWidget->raise(); m_participantSearchWidget->activateWindow(); return; } m_participantSearchWidget = new ParticipantSearchWidget(m_session->baseLayout()); m_participantSearchWidget->setAttribute(Qt::WA_DeleteOnClose); // auto delete on close if (!m_participantSearchWidget->init(this->m_dtc)) { ERROR_LOG(m_logger) << "initialization of ParticipantSearchModal failed - cannot show participant search modal"; m_participantSearchWidget->deleteLater(); return; } connect(m_participantSearchWidget, &ParticipantSearchWidget::participantSelected, this, [this](int participantId) { showParticipantInfoWindow(participantId); }); connect(m_participantSearchWidget, &QObject::destroyed, this, [this]() { m_participantSearchWidget = nullptr; }); m_participantSearchWidget->setWindowFlags( Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint ); // hints.. QPoint wPos = m_session->baseLayout()->geometry().center(); wPos.setX(wPos.x() - m_participantSearchWidget->size().width()); wPos.setY(wPos.y()/2); m_participantSearchWidget->move(wPos); m_participantSearchWidget->show(); }); }; ret.append(plData3); } return ret; } QString InterfaceImpl::menuGroup() const { return tr("Participants"); } bool InterfaceImpl::fetchInterfaces() { // if (appId() == LtsAppDescriptor::App::OC) // do the hack now // return true; if (!m_session->getDtc(m_dtc)) return false; if (!m_session->getFtc(m_ftc)) return false; if (!m_session->getDtc(m_pdmDtc)) return false; if (!m_session->getForeignGuiInterface(m_pdmGuiIfc)) return false; if (!m_session->getForeignDataInterface(m_asbIfc)) return false; //optional m_session->getForeignGuiInterface(m_sitmapGuIfc); return true; } void InterfaceImpl::clearInterfaces() { m_sitmapGuIfc = nullptr; m_asbIfc = nullptr; m_pdmGuiIfc = nullptr; m_pdmDtc = nullptr; m_ppmGuiIfc = nullptr; m_ftc = nullptr; m_dtc = nullptr; if (m_sitMapGuiIfc) m_sitMapGuiIfc->removeObjectIndicator(); } // ForeignDataInterface void InterfaceImpl::showParticipantInfoWindow(const QVector &entityIds) { for (auto id : entityIds) this->showParticipantInfoWindow(id); } void InterfaceImpl::showHitLineInfoWindow(const QVector &hitLineIds) { for (auto id : hitLineIds) this->showHitLineInfoWindow(id); } void InterfaceImpl::showBiteWindow(const QJsonObject &detailData) { static int s_counter = 1234567890; m_session->addWidget(LtsWidgets::initDialog(new ParticipantBiteDialog(-1), m_dtc, m_ftc, m_pdmDtc, false, detailData), menuGroup(), QStringLiteral("BiteInfo%1").arg(s_counter++ /* FIXME: UGLY HACK!! missing unique id here.. */), LtsWidgets::LayoutArea::eInfoTab); } void InterfaceImpl::showParticipantInfoWindow(int entityId, bool hideSituationMapRelatedButtons) { if (!m_ppmGuiIfc) m_session->getForeignGuiInterface(m_ppmGuiIfc); ParticipantInfoDialog *ti = new ParticipantInfoDialog(entityId, menuGroup()); bool ok = ti->init(m_session, m_dtc, m_ftc, m_pdmDtc, hideSituationMapRelatedButtons ? nullptr: m_sitmapGuIfc, m_asbIfc, m_ppmGuiIfc); if (!ok) { delete ti; return; } m_session->addWidget(ti, menuGroup(), QStringLiteral("TlnInfo%1").arg(entityId), LtsWidgets::LayoutArea::eInfoTab); } void InterfaceImpl::showHitLineInfoWindow(int hitLineId) { HitLineInfoDialog *hli = new HitLineInfoDialog(hitLineId); bool bOk = hli->init(m_dtc, m_pdmDtc, m_sitmapGuIfc); if (!bOk) { delete hli; return; } m_session->addWidget(hli, menuGroup(), QStringLiteral("HitLineInfo%1").arg(hitLineId), LtsWidgets::LayoutArea::eInfoTab); } LtsWidgets::LtsDialog *InterfaceImpl::onShowParticipantInfoTableDialog(QWidget *parent) { return LtsWidgets::initDialog(new ParticipantInfoTableDialog(menuGroup(), parent), m_session, m_dtc); } LtsWidgets::LtsDialog *InterfaceImpl::onShowParticipantConfigDialog(bool isMessage, QWidget *parent) { ParticipantConfigDialog::DialogType type = isMessage ? ParticipantConfigDialog::DialogType::MessageMulti : ParticipantConfigDialog::DialogType::ConfigMulti; return LtsWidgets::initDialog(new ParticipantConfigDialog(0, type, parent), m_session, m_dtc, m_ftc); } LtsWidgets::LtsDialog *InterfaceImpl::onShowParticipantSearchDialog(QWidget *parent) { if (!m_ppmGuiIfc) m_session->getForeignGuiInterface(m_ppmGuiIfc); if (!m_ppmOcGuiIfc) m_session->getForeignGuiInterface(m_ppmOcGuiIfc); return LtsWidgets::initDialog(new ParticipantSearchDialog(parent), m_session, m_dtc, m_ppmGuiIfc, m_ppmOcGuiIfc); } LtsWidgets::LtsDialog *InterfaceImpl::onShowParticipantFollowDialog(QWidget *parent) { if (!m_ppmGuiIfc) m_session->getForeignGuiInterface(m_ppmGuiIfc); DEBUG_LOG(m_logger) << "initDialog"; ParticipantFollowDialog *participantFollowDialogPtr =new ParticipantFollowDialog(parent); connect (participantFollowDialogPtr, &ParticipantFollowDialog::newFollowEquipment, this, &InterfaceImpl::onNewFollowEquipment); participantFollowDialogPtr->setFollower(m_followEquipmentNumber, m_followParticipantId); return LtsWidgets::initDialog(participantFollowDialogPtr, m_session, m_dtc, m_ppmGuiIfc); } bool InterfaceImpl::eventFilter(QObject *obj, QEvent *event) { if (obj == qApp && !event->isAccepted() && event->type() == LtsWidgets::LtsLinkEvent::eventTypeId()) { auto ev = static_cast(event); const auto isChildOfSession = [this](QWidget *w) { if (!w) return true; auto baseLayout = m_session->baseLayout(); return baseLayout->isAncestorOf(w); }; if (isChildOfSession(ev->sourceBaseLayoutWidget()) && ev->url().host() == s_participantInfoScheme.toLower()) { bool ok = false; const int pId = ev->url().path().mid(1).toInt(&ok); if (ok) { showParticipantInfoWindow(pId); event->accept(); return true; } } } return QObject::eventFilter(obj, event); } // bool InterfaceImpl::event(QEvent *event) // show participant info dialog on link clicked // { // if (event->type() != LtsWidgets::LinkEvent::eventId()) // { // qWarning() << "no link"; // return QObject::event(event); // } // qWarning() << "LINK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"; // LtsWidgets::LinkEvent *linkEvent = dynamic_cast(event); // if (linkEvent == nullptr || linkEvent->url().scheme() != s_participantInfoScheme) // { // return false; // } // bool ok = false; // const int eqId = linkEvent->url().host().toInt(&ok); // if (!ok) // { // return false; // } // showParticipantInfoWindow(eqId); // return true; // } void InterfaceImpl::onNewFollowEquipment(const int equipmentNumber, const int participantId) { DEBUG_LOG(m_logger) << "onNewFollowEquipment equipmentNumber=" << equipmentNumber << " participantId=" << participantId; m_followEquipmentNumber = equipmentNumber; m_followParticipantId = participantId; if (m_followParticipantId > 0) { DEBUG_LOG(m_logger) << "createNotification"; if (!m_noti) { m_noti = m_session->createNotification(QStringLiteral("FollowMap")); m_noti->setIcon(QIcon(QStringLiteral("icon:center_to_object.svg"))); m_noti->setToolTip(tr("The map follows the participant")); m_noti->setAction([this]() { m_session->addWidget(onShowParticipantFollowDialog(nullptr), menuGroup(), participantFollowIdentifier(), LtsWidgets::LayoutArea::eDialogTab); }); } QString labeltext = tr("Map follows Participant: %1").arg(m_dtc->hierarchyFromParticipant(m_followParticipantId)); if (m_followEquipmentNumber > 0) labeltext += QStringLiteral(" (%1)").arg(m_followEquipmentNumber); m_noti->setToolTip(labeltext); } else { if (m_noti) { m_noti->deleteLater(); m_noti = nullptr; } } } void InterfaceImpl::onParticipantPositionChanged(const ParticipantManagement::ParticipantPosition &data, DataModification modType) { DEBUG_LOG(m_logger) << "onParticipantPositionChanged id=" << data.participantId() << " m_followParticipantId=" << m_followParticipantId ; if (m_followParticipantId == 0) return; if (modType == DataModification::eRemoved) { DEBUG_LOG(m_logger) << "m_participantsOutsideMap.remove participantId: " << data.participantId(); //m_participantsOutsideMap.remove(data.participantId()); } else { if (data.participantId() == m_followParticipantId) { DEBUG_LOG(m_logger) << "Center Map to participantId=" << data.participantId(); DEBUG_LOG(m_logger) << "onParticipantPositionChanged()" << " participantId; " << data.participantId() << " participantTypeId: " << data.participantTypeId() << " partyId: " << data.partyId(); if (m_sitMapGuiIfc) m_sitMapGuiIfc->setCenterPoint(QPointF(data.pos().lon(), data.pos().lat())); } } } // end of onParticipantPositionChanged() void InterfaceImpl::onUnitPositionChanged(const ParticipantManagement::UnitPosition &data, DataModification modType) { DEBUG_LOG(m_logger) << "onUnitPositionChanged id=" << data.participantId() << " m_followParticipantId=" << m_followParticipantId ; if (m_followParticipantId == 0) return; if (modType == DataModification::eRemoved) return; if (data.participantId() == m_followParticipantId) { DEBUG_LOG(m_logger) << "Center Map to participantId=" << data.participantId() << ", onUnitPositionChanged()" << " participantId; " << data.participantId(); if (m_sitMapGuiIfc) { const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId(); if (!m_fltParticipantIfc) m_session->getForeignGuiInterface(m_fltParticipantIfc); m_symbolAppearanceSettings = m_fltParticipantIfc->symbolAppearanceForOperator(operatorId, m_session->workspaceId()); const bool bCenter = m_symbolAppearanceSettings && (m_symbolAppearanceSettings->settings().symbolSettings.unitSymbolPosition == FilterManagement::SymbolAppearanceSettings::UnitSymbolPosition::Center); if (bCenter) m_sitMapGuiIfc->setCenterPoint(QPointF(data.positionCenter().lon(), data.positionCenter().lat())); else m_sitMapGuiIfc->setCenterPoint(QPointF(data.positionLeader().lon(), data.positionLeader().lat())); } } } } // namespace ParticipantManagement