Files
qt5-legatus-legacy/Lts/Plugins/ParticipantManagement/Gui/ParticipantInfo/participant_info_gui_plugin.cpp
T
2026-08-13 18:33:10 +02:00

542 lines
19 KiB
C++
Executable File

/**
* @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 <Common/participant_search_modal.h>
#include <LtsWidgets/lts_base_layout_widget.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsWidgets/lts_events.h>
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <ParticipantManagement/ppm_operator_rights.h>
#include <LtsUtilsSettings/settings.h>
#include <LtsNotification/lts_notification.h>
#include <QShortcut>
#include <QApplication>
#include <QDebug>
namespace ParticipantManagement
{
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
{
return std::make_shared<InterfaceImpl>(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<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> 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<SituationMap::ForeignGuiInterface>(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<ParticipantManagement::DataInterface>(m_dtc))
return false;
if (!m_session->getFtc<ParticipantManagement::DataInterface>(m_ftc))
return false;
if (!m_session->getDtc<ProjectDataManagement::DataInterface>(m_pdmDtc))
return false;
if (!m_session->getForeignGuiInterface<ProjectDataManagement::ForeignGuiInterface>(m_pdmGuiIfc))
return false;
if (!m_session->getForeignDataInterface<AdvancedSymbology::DataInterface>(m_asbIfc))
return false;
//optional
m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(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<int> &entityIds)
{
for (auto id : entityIds)
this->showParticipantInfoWindow(id);
}
void InterfaceImpl::showHitLineInfoWindow(const QVector<int> &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<ParticipantManagement::ForeignParticipantInfoGuiInterface>(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<ParticipantManagement::ForeignParticipantInfoGuiInterface>(m_ppmGuiIfc);
if (!m_ppmOcGuiIfc)
m_session->getForeignGuiInterface<OcSituationClient::ForeignParticipantInfoGuiInterface>(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<ParticipantManagement::ForeignParticipantInfoGuiInterface>(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<LtsWidgets::LtsLinkEvent*>(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<LtsWidgets::LinkEvent *>(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<FilterManagement::ForeignFltParticipantGuiInterface>(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