Files
qt5-legatus-legacy/Lts/Plugins/SituationReplayManagement/Gui/ReplayManagement/replay_management_gui_plugin.cpp
T
2026-08-13 18:33:10 +02:00

293 lines
9.4 KiB
C++
Executable File

/**
* @RDE_HEADER@
* GUI Plugin for SituationReplayManagement - Replay Management
* $Id$
* $HeadURL$
* $Author$
* Created by Patric Karwar, SLSE, 2016-07-19
*/
#include "replay_management_gui_plugin.h"
#include "replay_dialog.h"
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <LtsSession/lts_session_manager.h>
#include <LtsUtilsCore/await.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsWidgets/lts_global_wait_dialog.h>
#include <LtsWidgets/lts_wait_dialog.h>
#include <LtsAppManager/lts_app_manager.h>
#include <FilterManagement/flt_data_plugin_aes_display_filter.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <Services/SituationReplayManagement/srm_operator_rights.h>
#include <QTimer>
#include <QDebug>
namespace SituationReplayManagement
{
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("Plugins.Gui.Srm.ReplayManagement"))
, m_requestHelper(nullptr)
{}
InterfaceImpl::~InterfaceImpl()
{
}
bool InterfaceImpl::fetchInterfaces()
{
if (!m_session->getDtc<DataInterface>(m_coreDtc))
return false;
if (!m_session->getForeignDataInterface<DataInterface>(m_sitRepIfc))
return false;
if (!m_session->getForeignGuiInterface<FilterManagement::ForeignFltParticipantGuiInterface>(m_fltParticipantIfc))
{
DEBUG_LOG(m_logger) << "getForeignGuiInterface for Filter Management Participant Gui failed.";
return false;
}
if (!m_session->getForeignGuiInterface<FilterManagement::ForeignAesGuiInterface>(m_fltAesIfc))
{
DEBUG_LOG(m_logger) << "getForeignGuiInterface for Filter Management Aes Gui failed.";
return false;
}
if (!m_session->getFtc<FilterManagement::DataInterface>(m_fltFtc))
{
DEBUG_LOG(m_logger) << "getFtc for FilterManagement::Interface failed.";
return false;
}
return true;
}
void InterfaceImpl::clearInterfaces()
{
m_coreDtc = nullptr;
m_sitRepIfc = nullptr;
m_fltParticipantIfc = nullptr;
m_fltAesIfc = nullptr;
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
#ifndef LTS_DEBUG
if (LtsSessionData::LtsSessionData::getInstance()->debugFlagValue(QStringLiteral("ShowReplayManagementAction")) == QVariant(true))
#endif
{
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.menuText = tr("Replay Management");
plData.identifier = QLatin1String("ReplayManagement");
plData.menuIcon = QIcon(QLatin1String("icon:playback_situation.svg"));
plData.operatorRight = OperatorRights::ReplayManagement;
plData.exercisePart = LtsWidgets::ExercisePart::eAfterAction;
plData.createWidgetFunc = [this](QWidget *parent)
{
return LtsWidgets::initDialog(new SituationReplayManagementDialog(m_session, parent),
m_coreDtc, m_sitRepIfc);
};
ret.append(plData);
}
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Situation Playback");
plData.identifier = QLatin1String("ReplayManagementStart");
plData.menuIcon = QIcon(QLatin1String("icon:playback_situation_start.svg"));
plData.operatorRight = OperatorRights::ReplayManagement;
if (m_session->partitionType() == IDL::PartitionType::Exercise)
{
plData.exercisePart = LtsWidgets::ExercisePart::eAfterAction;
plData.directFunc = [this](const LtsWidgets::PluginData &)
{
return startReplay();
};
ret.append(plData);
}
// Zusaetzlich auch in 'Apps' aufschalten
//????? wie kann man das auch in 'Apps' anzeigen die keinen exercisePart haben ?? z.B. RessourcenManagement, Timeline
plData.menuGroup = tr("Apps");
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
plData.directFunc = [this](const LtsWidgets::PluginData &)
{
return startReplay();
};
ret.append(plData);
return ret;
}
QString InterfaceImpl::menuGroup() const
{
return tr("Playbacks");
}
void InterfaceImpl::startReplay() // blocks!
{
std::unique_ptr<LtsWidgets::LtsWaitDialog> _(new LtsWidgets::LtsWaitDialog(tr("Waiting for Situation Replay app")));
int replayId;
try
{
replayId = m_sitRepIfc->replayPartitionCreateRequest(m_session->partitionId(),
LtsSessionData::LtsSessionData::getInstance()->getWorkstationId(),
LtsSessionData::LtsSessionData::getInstance()->getOperatorId(),
Core::ReplayType::SituationData);
}
catch(...)
{
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("Failed to start replay partition for replay!"));
return;
}
bool found = false;
Core::ReplayPartition rp;
for (int i = 0; i < 40; i++)
{
rp = m_coreDtc->replayPartition(replayId);
if (rp.id() == replayId)
{
found = true;
break;
}
try{
LtsUtils::awaitTimeout(250);
}catch(...){}
}
auto rmPartFn = [this, replayId]()
{
try
{
m_sitRepIfc->replayPartitionRemoveRequest(replayId, LtsSessionData::LtsSessionData::getInstance()->getWorkstationId(),
LtsSessionData::LtsSessionData::getInstance()->getOperatorId()); // NOTE: unfortunately waits...
}
catch (...)
{
ERROR_LOG(m_logger) << "[timeout] Failed to remove failed-to-start replay. domainId: " << m_session->domainId()
<< " - replay id: " << replayId
<< " - url " << m_session->tcpConnectionUrl().toString();
}
};
if (!found)
{
LtsWidgets::LtsMessageDialog::showMessage(m_session->baseLayout(), tr("Error trying to create a replay session"));
WARNING_LOG(m_logger) << "[timeout] Error while trying to create a replay session: domainId: " << m_session->domainId()
<< " - replay partition does not exist - replay id: " << replayId
<< " - url " << m_session->tcpConnectionUrl().toString();
rmPartFn();
return;
}
startReplayApp(rp); // calls done() on global wait dlg
}
void InterfaceImpl::startReplayApp(const Core::ReplayPartition &data)
{
m_aesTransfered = false;
m_symbolAppearanceTransfered = false;
m_data = data;
// could we supply the operator-specific default settings???
// available vi opm plugin (OperatorManagement -> defaultFilterPresetId)???
if (!transferFilter(data))
ERROR_LOG(m_logger) << LOGFUNCTION << " transferFilter failed.";
// to avoid race conditions, continued in 'startReplayAppInternal', called by
// onAesFilterUpdateReply / onSymbolAppearanceUpdateReply
}
void InterfaceImpl::startReplayAppInternal()
{
const LtsSession::DdsConnectionParams connParams(m_data);
// what's the difference?
// LtsAppManager::LtsAppManager::getInstance()->createApp(static_cast<int>(LtsSession::LtsSession::App::Situation), connParams);
m_session->getSessionManager()->createSession(connParams, true, false /* no payloads! */);
}
bool InterfaceImpl::transferFilter(const Core::ReplayPartition &data)
{
if (m_requestHelper == nullptr)
m_requestHelper = new LtsUtils::RequestHelper(this);
// copy last filter from current session to replay:
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
const QString context = m_session->workspaceId();
const QString replayContext = QStringLiteral("replay_%1").arg(data.id());
// AES:
auto fOrig = m_fltAesIfc->aesFilterForOperator(operatorId, context);
auto fReplay = m_fltAesIfc->aesFilterForOperator(operatorId, replayContext); // AesDisplayFilter
fReplay->setFilterFromData(fOrig->filterToData());
auto cb1 = [this, fReplay]()
{
return m_fltFtc->aesFilterUpdateRequest(fReplay->filterToData(), this);
};
m_requestHelper->addRequest(cb1);
// SymbolAppearance:
auto sOrig = m_fltParticipantIfc->symbolAppearanceForOperator(operatorId, context);
auto sReplay = m_fltParticipantIfc->symbolAppearanceForOperator(operatorId, replayContext);
sReplay->setSettings(sOrig->settings(), FilterManagement::SymbolAppearanceSettings::Part::All);
auto cb2 = [this, sReplay]()
{
return m_fltFtc->symbolAppearanceUpdateRequest(sReplay->settingsToData(), this);
};
m_requestHelper->addRequest(cb2);
return m_requestHelper->startRequests();
}
void InterfaceImpl::onAesFilterUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
// the last replay should trigger startReplayAppInternal to continue, but
// give flt some time publish data (race condition)
m_aesTransfered = true;
if (m_aesTransfered && m_symbolAppearanceTransfered)
QTimer::singleShot(2000, this, &InterfaceImpl::startReplayAppInternal);
}
void InterfaceImpl::onSymbolAppearanceUpdateReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
// the last replay should trigger startReplayAppInternal to continue, but
// give flt some time publish data (race condition)
m_symbolAppearanceTransfered = true;
if (m_aesTransfered && m_symbolAppearanceTransfered)
QTimer::singleShot(2000, this, &InterfaceImpl::startReplayAppInternal);
}
} // namespace SituationReplayManagement