224 lines
7.3 KiB
C++
Executable File
224 lines
7.3 KiB
C++
Executable File
/**
|
||
* @RDE_HEADER@
|
||
* Plugin to watch the currently active Exercise and keep track of the Exc Name, Exc Phase, etc.
|
||
* $Id$
|
||
* $HeadURL$
|
||
* $Author$
|
||
* Created by Mike Wille, SLSE, 2017-09-29
|
||
*/
|
||
|
||
#include "exm_watch_gui_plugin.h"
|
||
|
||
#include <LtsSession/lts_session.h>
|
||
#include <LtsWidgets/lts_message_dialog.h>
|
||
#include <LtsWidgets/lts_base_layout_widget.h>
|
||
#include <ExerciseManagement/exm_translation.h>
|
||
#include <ngltools/ngltools_dtg.h>
|
||
|
||
namespace ExerciseManagement
|
||
{
|
||
|
||
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.Exm.Watch"))
|
||
, m_dtc(nullptr)
|
||
, m_isDeleted(false)
|
||
{}
|
||
|
||
|
||
bool InterfaceImpl::fetchInterfaces()
|
||
{
|
||
if (!m_session->getDtc<ExerciseManagement::DataInterface>(m_dtc))
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||
{
|
||
QVector<LtsWidgets::PluginData> ret;
|
||
|
||
{
|
||
LtsWidgets::PluginData plData;
|
||
plData.menuGroup = menuGroup();
|
||
plData.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction;
|
||
plData.directFunc = [this](const LtsWidgets::PluginData &)
|
||
{
|
||
connect(m_dtc.get(), &ExerciseManagement::Interface::Dtc::exerciseChanged,
|
||
this, &InterfaceImpl::slotExerciseChanged);
|
||
connect(m_dtc.get(), &ExerciseManagement::Interface::Dtc::exercisePhaseChanged,
|
||
this, &InterfaceImpl::slotExercisePhaseChanged);
|
||
|
||
if (m_session->isInitializationDone())
|
||
slotSetExerciseData();
|
||
else
|
||
connect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession,
|
||
this, &InterfaceImpl::slotSetExerciseData); // wait until session is initialized
|
||
};
|
||
ret.append(plData);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
LtsWidgets::ExcState InterfaceImpl::convertState(ExerciseState state)
|
||
{
|
||
int underlying = state.underlying() - 1;
|
||
if (underlying >= 0)
|
||
{
|
||
int i_state = (1 << static_cast<int>(underlying));
|
||
return static_cast<LtsWidgets::ExcState>(i_state);
|
||
}
|
||
return LtsWidgets::ExcState::eUnknown;
|
||
}
|
||
|
||
|
||
void InterfaceImpl::clearInterfaces()
|
||
{
|
||
m_dtc = nullptr;
|
||
}
|
||
|
||
QColor InterfaceImpl::exerciseStateColor(ExerciseManagement::ExerciseState state)
|
||
{
|
||
switch(state.underlying())
|
||
{
|
||
case ExerciseState::Unknown: return Qt::black;
|
||
case ExerciseState::Created: return Qt::cyan;
|
||
case ExerciseState::Started: return Qt::darkGreen;
|
||
case ExerciseState::Paused: return Qt::darkYellow;
|
||
case ExerciseState::Stopped: return Qt::magenta;
|
||
case ExerciseState::Terminated: return Qt::red;
|
||
}
|
||
return QColor();
|
||
}
|
||
|
||
void InterfaceImpl::slotExerciseChanged(const ExerciseManagement::Exercise &data, DataModification modType)
|
||
{
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, this=" << this << ", exId=" << data.id();
|
||
if (m_isDeleted)
|
||
return;
|
||
|
||
if (data.id() != m_session->exerciseId())
|
||
return;
|
||
|
||
switch (modType)
|
||
{
|
||
case DataModification::eRemoved:
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " eRemoved" << ", this=" << this << ", exId=" << data.id();
|
||
m_previouslyRemoved = true;
|
||
WARNING_LOG(m_logger) << "Partition has been removed from the DDS bus! Session: " << m_session->toString();
|
||
if (m_session->baseLayout())
|
||
m_session->baseLayout()->showMessage(tr("Connection to server lost"), tr("Trying to reconnect. You will be notified."), LtsWidgets::LtsNotificationBox::MessageType::Error);
|
||
break;
|
||
}
|
||
|
||
case DataModification::eAdded:
|
||
{
|
||
WARNING_LOG(m_logger) << LOGFUNCTION << ", Partition added to DDS bus! Session: " << m_session->toString();
|
||
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " eAdded, m_previouslyRemoved=" << m_previouslyRemoved << ", this=" << this << ", exId=" << data.id();
|
||
if (m_previouslyRemoved)
|
||
{
|
||
m_previouslyRemoved = false;
|
||
if (m_session->baseLayout())
|
||
m_session->baseLayout()->showMessage(tr("Successfully reconnected"), tr("Connection to server was successfully reestablished."), LtsWidgets::LtsNotificationBox::MessageType::Success);
|
||
}
|
||
Q_FALLTHROUGH();
|
||
}
|
||
|
||
case DataModification::eModified:
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " eModified, m_previouslyRemoved=" << m_previouslyRemoved << ", this=" << this << ", exId=" << data.id();
|
||
slotSetExerciseData();
|
||
break;
|
||
}
|
||
}
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, this=" << this << ", exId=" << data.id();
|
||
}
|
||
|
||
|
||
void InterfaceImpl::slotExercisePhaseChanged(const ExerciseManagement::ExercisePhase &data, DataModification modType)
|
||
{
|
||
Q_UNUSED(modType);
|
||
if (m_isDeleted)
|
||
return;
|
||
|
||
if (data.exerciseId() != m_session->exerciseId() ||
|
||
data.id() != m_session->exerciseData()->phId)
|
||
return;
|
||
|
||
slotExerciseChanged(m_dtc->exercise(m_session->exerciseId()), DataModification::eModified);
|
||
}
|
||
|
||
|
||
QString InterfaceImpl::partitionTypeString() const
|
||
{
|
||
switch (m_session->partitionType())
|
||
{
|
||
case IDL::PartitionType::Global: return QStringLiteral("<font color='grey'>%1</font>").arg(tr("Admin"));
|
||
case IDL::PartitionType::Exercise: return QStringLiteral("<font color='green'>%1</font>").arg(tr("Live"));
|
||
case IDL::PartitionType::Replay: return QStringLiteral("<font color='red'>%1</font>").arg(tr("Replay"));
|
||
default: return tr("unknown");
|
||
}
|
||
}
|
||
|
||
|
||
void InterfaceImpl::slotSetExerciseData()
|
||
{
|
||
disconnect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession,
|
||
this, nullptr);
|
||
|
||
LtsWidgets::ExerciseData exData;
|
||
|
||
// 26.06.2023, Norbert Thoden
|
||
// Sometimes the ScriptEditorEssentialsView doesn´t have any buttons at the right menue.
|
||
// Reason:
|
||
// "Partition has been removed from the DDS bus"
|
||
// So afterwards slotSetExerciseData has called.
|
||
// With a virgin dtc leads to invalid data Exercise.
|
||
// So add waitForHistoricalData :-)
|
||
// Addtionally:
|
||
// Within slotExerciseChanged it´s handled as not m_previouslyRemoved
|
||
// and 'break' had skipped the rest of the slot - especially eModified.
|
||
|
||
// Now: If DDS partiton is newly created, the slot is called,
|
||
// eAdded and via Q_FALLTHROUGH eModified is executed also!
|
||
// To avoid signalExerciseDataChanged to be emiited multiple times,
|
||
// data is checked (operator==())
|
||
|
||
m_dtc->waitForHistoricalDataExercise(2000);
|
||
m_dtc->waitForHistoricalDataExercisePhase(2000);
|
||
|
||
const ExerciseManagement::Exercise &ex = m_dtc->exercise(m_session->exerciseId());
|
||
|
||
if (ex.id() != m_session->exerciseId())
|
||
FATAL_LOG(m_logger) << LOGFUNCTION << ", requested exId and return exId do not match!!!";
|
||
// no assert here to not desturb debugging
|
||
|
||
const ExerciseManagement::ExercisePhase &ph = m_dtc->exercisePhase(ex.activePhaseId());
|
||
|
||
exData.exName = QString::fromStdString(ex.name());
|
||
exData.exDescription = QString::fromStdString(ex.description());
|
||
exData.exStateString = ExerciseManagement::toString(ex.state());
|
||
exData.exState = convertState(ex.state());
|
||
exData.exStateCol = exerciseStateColor(ex.state());
|
||
exData.partitionType = partitionTypeString();
|
||
|
||
exData.phId = ph.id();
|
||
exData.phName = QString::fromStdString(ph.name());
|
||
exData.phDescription = QString::fromStdString(ph.description());
|
||
|
||
m_session->setExerciseData(exData);
|
||
DTG::setTimezone(ex.defaultTimeZone(), false);
|
||
}
|
||
|
||
} // namespace ExerciseManagement
|