Adds initial intermediate qt6 porting state

This commit is contained in:
torsten committed 2026-08-17 17:54:56 +02:00
1 parent 99136e9460
commit d176b5e0d7
11247 files changed
+1891537

No files matched your search

@@ -0,0 +1,53 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Patric Karwat, SLSE, 2016-07-27
#
SET(replay_control_gui_SRCS
replay_control_gui_plugin.h
replay_control_gui_plugin.cpp
replay_control_dialog.h
replay_control_dialog.cpp
replay_control_widget.h
replay_control_widget.cpp
TopicEditor/topic_editor.h
TopicEditor/topic_editor.cpp
)
NGL_WRAP_UI(replay_control_gui_SRCS
replay_control_widget.ui
TopicEditor/topic_editor.ui
)
NGL_ADD_LIBRARY(WS SrpReplayControlGuiPlugin MODULE ${replay_control_gui_SRCS})
NGL_TARGET_LINK_LIBRARIES(SrpReplayControlGuiPlugin
NGLLogger
ngltools # dtg
SrpGuiPluginInterface
SrpDataPluginInterface
MrkCommon
Qt5::Widgets
LtsWidgets
LtsSession
SituationMapScriptFilterGuiPluginInterface
LtsDataView
LtsUtilsGuiDds
# TopicEditor:
TopicEditorBase
LtsScriptTimeline
MrkDataPluginInterface
MrkGuiPluginInterface
OpmDataPluginInterface
PreGuiScriptCommon
situationMap
)
NGL_INSTALL_TARGET(SrpReplayControlGuiPlugin)
@@ -0,0 +1,594 @@
#include "topic_editor.h"
#include "ui_topic_editor.h"
#include "../replay_control_widget.h"
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <MarkerManagement/Gui/Common/mrk_dialog_model.h>
#include <Plugins/SituationReplay/srp_gui_plugin_interface.h>
#include <Services/MarkerManagement/mrk.hpp>
#include <SituationReplay/logger.h>
#include <TopicEditorBase/topic_previewer.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QtMath>
class QAbstractTableModel;
namespace SituationReplay
{
SituationReplayEditor::SituationReplayEditor(
MarkerManagement::MarkerManagementDialogModel *markerModel,
const QPointer<MarkerManagement::MarkerManagementApplyFilter> &applyFilter,
LtsSession::LtsSession *session, QWidget *parent,
ForeignGuiInterface **essentialsViewsSrpIfc,
SituationMap::ForeignGuiInterface **essentialsViewsSitMapIfc
)
: TopicEditorBase::TopicEditor(parent)
, m_session(session)
, m_essentialsViewsSrpIfc(essentialsViewsSrpIfc)
, m_essentialsViewsSitMapIfc(essentialsViewsSitMapIfc)
, m_markerModel(markerModel)
, m_applyFilter(applyFilter)
, m_ui(new Ui::SituationReplayEditor)
, m_logger(getLogger("SituationReplayEditor"))
{
m_ui->setupUi(this);
m_ui->lblDuration->setText(QStringLiteral(" - "));
m_buttonBox->getButton(LtsWidgets::DialogButton::Show)->setText(tr("Preview Replay"));
if ((*m_essentialsViewsSrpIfc) == nullptr)
m_buttonBox->getButton(LtsWidgets::DialogButton::Show)->setToolTip(tr("To enable replay preview, start the essentials view first."));
else
m_buttonBox->getButton(LtsWidgets::DialogButton::Show)->setToolTip(QString());
m_buttonBox->connectButton(LtsWidgets::DialogButton::Show,
this, &SituationReplayEditor::onPreview);
m_buttonBox->getButton(LtsWidgets::DialogButton::Add)->setText(tr("Show Map Settings"));
m_buttonBox->getButton(LtsWidgets::DialogButton::Add)->setToolTip(tr("Show this topic's map settings in Essentials View"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Add, this, &SituationReplayEditor::onShowMapSettings);
m_buttonBox->getButton(LtsWidgets::DialogButton::Add)->hide();
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Get Map Settings"));
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setToolTip(tr("Get map settings from Essentials View and set this topic's map settings"));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load, this, &SituationReplayEditor::onGetSettings);
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->hide();
onEssentialsViewChanged((*m_essentialsViewsSrpIfc), (*essentialsViewsSitMapIfc));
init(m_ui->widget);
m_ui->dteStartTime->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
m_ui->dteEndTime->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
connect(m_ui->dteStartTime, &LtsWidgets::LtsDateTimeEdit::dateTimeChanged,
this, &SituationReplayEditor::onChangesMade);
connect(m_ui->dteEndTime, &LtsWidgets::LtsDateTimeEdit::dateTimeChanged,
this, &SituationReplayEditor::onChangesMade);
connect(m_ui->sbSpeed, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged),
this, &SituationReplayEditor::onChangesMade);
if (m_markerModel != nullptr)
{
m_markerModel->setParent(this);
m_ui->markersDataView->setModel(m_markerModel);
m_ui->markersDataView->hideColumn(MarkerManagement::MarkerManagementDialogModel::ColImage);
m_ui->markersDataView->hideColumn(MarkerManagement::MarkerManagementDialogModel::ColFileId);
m_ui->markersDataView->hideColumn(MarkerManagement::MarkerManagementDialogModel::ColOffset);
#ifndef LTS_DEBUG
m_ui->markersDataView->hideColumn(MarkerManagement::MarkerManagementDialogModel::ColStreams);
#endif
m_ui->markersDataView->setInitialSearchContent(
MarkerManagement::MarkerManagementDialogModel::ColOperator, LtsSessionData::LtsSessionData::getInstance()->getOperatorId()
);
connect(m_ui->markersDataView, &LtsDataView::LtsDataView::activated,
this, &SituationReplayEditor::onMarkerSelected);
}
else
{
m_ui->markersDataView->hide();
m_ui->lblMrk->hide();
}
if ((*m_essentialsViewsSrpIfc) != nullptr)
{
WARNING_LOG(m_logger) << "essentials view available - using srp replay control widget as editor!";
onAddReplayControlWidget();
}
else
{
WARNING_LOG(m_logger) << "essentials view not available - using traditional editor";
}
setOnlineHelpFilename(QStringLiteral("Script_Editor-Add_Situation_Replay_Topic"));
}
SituationReplayEditor::~SituationReplayEditor()
{
delete m_ui;
}
void SituationReplayEditor::updateInternalData()
{
DEBUG_LOG(m_logger) << LOGFUNCTION;
if (m_firstUpdate)
{
m_firstUpdate = false;
retranslate();
m_filterSettings = m_topicData.properties.value(QStringLiteral("filters"));
m_currentSettings = m_topicData.properties.value(QStringLiteral("settings"));
if (m_topicData.topicType == TopicEditorBase::TopicType::Situation)
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Add)->show();
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->show();
}
}
if (!hasTopicDataProperties())
return;
qint64 start = getTopicDataValue(QStringLiteral("start")).toDouble();
m_ui->dteStartTime->setMsecsSinceEpoch(start);
double speed = getTopicDataValue(QStringLiteral("speed")).toDouble(1.0);
m_ui->sbSpeed->setValue(speed);
updateInternalLength();
if (m_replayControlWidget)
{
m_replayControlWidget->setStartTime(start);
}
}
void SituationReplayEditor::updateInternalLength()
{
DEBUG_LOG(m_logger) << LOGFUNCTION;
qint64 end = calculateEnd(m_ui->dteStartTime->msecsSinceEpoch(), m_topicData.duration, m_ui->sbSpeed->value(), true);
bool hasChanges = hasUnsavedChanges();
m_ui->dteEndTime->setMsecsSinceEpoch(end);
m_ui->lblDuration->setText(tr("%1 sec").arg(m_topicData.duration));
if (!hasChanges)
apply2();
}
void SituationReplayEditor::retranslate()
{
if (m_topicData.id == -1)
translate(m_ui, tr("Topic Editor"));
else
{
if (m_topicData.topicType == TopicEditorBase::TopicType::Situation)
{
translate(m_ui, tr("Situation Topic Editor"));
m_ui->cbFilterSettings->show();
}
else
{
translate(m_ui, tr("Replay Topic Editor"));
m_ui->cbFilterSettings->hide();
}
}
m_uiRequirements->clear();
m_uiRequirements->addRequirement({ m_ui->lbxEndTime, [this]() {
return (m_ui->dteEndTime->msecsSinceEpoch() > m_ui->dteStartTime->msecsSinceEpoch());
}, tr("End time must be greater than the start time") });
m_uiRequirements->addRequirement({ m_ui->lbxStartTime, [this]() {
return (m_ui->dteStartTime->msecsSinceEpoch() < m_ui->dteEndTime->msecsSinceEpoch());
}, tr("Start time must be smaller than the end time") });
}
qint64 SituationReplayEditor::calculateEnd(qint64 startTime, int lengthInSeconds, double speed, bool backwards)
{
double result = (lengthInSeconds * 1000);
if (backwards)
result *= speed;
else
result /= speed;
result += startTime;
DEBUG_LOG(m_logger) << LOGFUNCTION << " result = " << result;
return result;
}
qint64 SituationReplayEditor::calculateDuration(qint64 startTime, qint64 endTime, double speed)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " startTime=" << startTime << " endTime=" << endTime << " speed=" << speed;
qint64 duration = endTime - startTime;
double result = duration;
result /= speed;
qint64 result2 = result;
result2 += 500;
DEBUG_LOG(m_logger) << LOGFUNCTION << " result = " << result2;
return result2;
}
void SituationReplayEditor::setFilterAndSettings(const QByteArray &mapFilter, const QByteArray &mapSettings)
{
setMapFilter(mapFilter);
setMapSettings(mapSettings);
}
void SituationReplayEditor::setMapSettings(const QByteArray &mapSettings)
{
QJsonParseError parseError;
QJsonValue settings = QJsonDocument::fromJson(mapSettings, &parseError).object();
if (parseError.error != QJsonParseError::NoError)
{
ERROR_LOG(m_logger) << "map settings not valid json at" << parseError.errorString();
return;
}
m_currentSettings = settings;
slotChangesMade();
}
void SituationReplayEditor::setMapFilter(const QByteArray &mapFilter)
{
QJsonParseError parseError;
QJsonValue filter = QJsonDocument::fromJson(mapFilter, &parseError).object();
if (parseError.error != QJsonParseError::NoError)
{
ERROR_LOG(m_logger) << "filter settings not valid json at" << parseError.errorString();
return;
}
m_filterSettings = filter;
slotChangesMade();
}
void SituationReplayEditor::onEssentialsViewChanged(SituationReplay::ForeignGuiInterface *essentialsViewsSrpIfc,
SituationMap::ForeignGuiInterface *essentialsViewsSitMapIfc)
{
*m_essentialsViewsSrpIfc = essentialsViewsSrpIfc;
*m_essentialsViewsSitMapIfc = essentialsViewsSitMapIfc;
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Show, !!(*m_essentialsViewsSrpIfc));
}
bool SituationReplayEditor::apply2()
{
qint64 start = m_ui->dteStartTime->msecsSinceEpoch();
qint64 end = m_ui->dteEndTime->msecsSinceEpoch();
double speed = m_ui->sbSpeed->value();
qint64 duration = calculateDuration(start, end, speed) / 1000;
setDescription(m_ui->widget->description());
setTopicDataProperty(QStringLiteral("start"), start);
setTopicDataProperty(QStringLiteral("speed"), speed);
setTopicDataProperty(QStringLiteral("end"), end);
if (m_topicData.channel.isEmpty())
{
m_ui->widget->setEnabled(true);
m_topicDuration = duration;
m_topicData.duration = duration;
if (duration < 0)
m_ui->lblDuration->setText(QStringLiteral(" - "));
else
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " setText length = " << duration;
m_ui->lblDuration->setText(tr("%1 sec").arg(m_topicDuration));
}
}
if (m_ui->cbFilterSettings->isChecked() && m_ui->cbFilterSettings->isVisible())
{
setTopicDataProperty(QStringLiteral("filters"), m_filterSettings);
setTopicDataProperty(QStringLiteral("settings"), m_currentSettings);
}
m_ui->widget->previewer()->setTopicData(m_topicData);
if (m_topicData.channel.isEmpty())
return true;
LtsUtils::Promise *promise = new LtsUtils::Promise(nullptr, this);
promise->resolved([this, duration](const QVariant &)
{
m_topicData.duration = duration;
this->__unchange__();
m_ui->widget->previewer()->setTopicData(m_topicData);
applied();
});
promise->rejected([this](const QVariant &)
{
new LtsWidgets::LtsMessageDialogNew(
this,
tr("The new settings conflict with other topics in this script. <br>"
"Maybe the new topic size would collide with another topic or would be "
"parallel to a topic of a type that cannot be parallelized with this topic's type. <br>"
"You might have changed the size by setting a bigger end time or decreased the "
"replay speed. <br>"
"To fix this issue, check if your topic has enough room to expand if you "
"make changed that would resize it."),
tr("Unable to apply changes"));
});
emit durationCheckRequested(duration, promise);
return false;
}
void SituationReplayEditor::onAddReplayControlWidget()
{
if (m_replayControlWidget)
m_replayControlWidget->deleteLater();
m_replayControlWidget = qobject_cast<SituationReplayControlWidget *>((*m_essentialsViewsSrpIfc)->createControlWidget(true));
if (m_replayControlWidget == nullptr)
return;
m_replayControlWidget->setStartTime(m_ui->dteStartTime->msecsSinceEpoch());
connect(m_replayControlWidget, &QObject::destroyed,
m_ui->traditionalControlWidget, &QWidget::show,
Qt::QueuedConnection );
connect(m_replayControlWidget, &SituationReplayControlWidget::signalSetStart, this, [this](qint64 start)
{
if (m_ui->dteStartTime->msecsSinceEpoch() != start)
{
m_ui->dteStartTime->setMsecsSinceEpoch(start);
onChangesMade();
}
});
connect(m_replayControlWidget, &SituationReplayControlWidget::signalSetEnd, this, [this](qint64 end)
{
if (m_ui->dteEndTime->msecsSinceEpoch() != end)
{
m_ui->dteEndTime->setMsecsSinceEpoch(end);
onChangesMade();
}
});
connect(m_replayControlWidget, &SituationReplayControlWidget::signalSetSpeed, this, [this](double speed)
{
if (m_ui->sbSpeed->value() != speed)
{
m_ui->sbSpeed->setValue(speed);
onChangesMade();
}
});
connect(m_ui->sbSpeed, qOverload<double>(&QDoubleSpinBox::valueChanged), this, [this](double speed)
{
speed *= 10;
if (m_replayControlWidget->speed() != speed)
{
m_replayControlWidget->setSpeed(speed);
}
});
connect(m_replayControlWidget, &SituationReplayControlWidget::signalSetMapSettings,
this, &SituationReplayEditor::setMapSettings);
connect(m_replayControlWidget, &SituationReplayControlWidget::signalSetMapFilter,
this, &SituationReplayEditor::setMapFilter);
connect(m_replayControlWidget, &SituationReplayControlWidget::replayStarted,
this, &SituationReplayEditor::onReplayStarted);
connect(m_replayControlWidget, &SituationReplayControlWidget::replayPaused,
this, &SituationReplayEditor::onReplayPaused);
connect(m_replayControlWidget, &SituationReplayControlWidget::replayStopped,
this, &SituationReplayEditor::onReplayStopped);
m_replayControlWidget->showEditorWidget();
m_ui->traditionalControlWidget->hide();
m_ui->verticalLayout_2->addWidget(m_replayControlWidget);
}
void SituationReplayEditor::onMarkerSelected(const QModelIndex &idx)
{
const MarkerManagement::Marker marker = m_markerModel->getRowData(idx.row());
if (marker.id() <= 0)
{
ERROR_LOG(m_logger) << "marker has id 0";
return;
}
onChangesMade();
setFilterAndSettings(QByteArray(marker.filter().c_str(), marker.filter().size()), QByteArray(marker.mapSettings().c_str(), marker.mapSettings().size()));
slotChangesMade();
}
void SituationReplayEditor::onChangesMade()
{
DEBUG_LOG(m_logger) << LOGFUNCTION;
qint64 start = m_ui->dteStartTime->msecsSinceEpoch();
qint64 end = m_ui->dteEndTime->msecsSinceEpoch();
double speed = m_ui->sbSpeed->value();
qint64 duration = calculateDuration(start, end, speed) / 1000;
DEBUG_LOG(m_logger) << LOGFUNCTION << " duration = " << duration;
if (duration < 0)
m_ui->lblDuration->setText(QStringLiteral(" - "));
else
{
m_topicDuration = duration;
m_topicData.duration = duration;
m_ui->widget->previewer()->setTopicData(m_topicData);
m_ui->lblDuration->setText(tr("%1 sec").arg(m_topicDuration));
DEBUG_LOG(m_logger) << LOGFUNCTION << " setText duration = " << duration;
}
}
void SituationReplayEditor::onPreview()
{
if (m_ui->dteStartTime->msecsSinceEpoch() >= m_ui->dteEndTime->msecsSinceEpoch())
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Start time must be greater than end time"));
return;
}
if ((*m_essentialsViewsSrpIfc) == nullptr)
{
new LtsWidgets::LtsMessageDialogNew(this, tr("Preview could not be started because essentials view is not started."));
return;
}
(*m_essentialsViewsSrpIfc)->startReplay(
m_ui->dteStartTime->msecsSinceEpoch(), m_ui->dteEndTime->msecsSinceEpoch(), m_ui->sbSpeed->value()
);
}
void SituationReplayEditor::onReplayStarted()
{
if (m_topicData.id != -1)
m_ui->widget->setTopicEnabled(false);
}
void SituationReplayEditor::onReplayPaused()
{
if (m_topicData.id != -1)
m_ui->widget->setTopicEnabled(true);
}
void SituationReplayEditor::onReplayStopped()
{
if (m_topicData.id != -1)
m_ui->widget->setTopicEnabled(true);
}
void SituationReplayEditor::onShowMapSettings()
{
if (m_currentSettings.isNull() && m_filterSettings.isNull())
{
new LtsWidgets::LtsMessageDialogNew(this, tr("No saved map and filter settings available to show"));
return;
}
if ((*m_essentialsViewsSitMapIfc) == nullptr)
{
new LtsWidgets::LtsMessageDialogNew(this, tr("Settings could not be shown because essentials view was closed"));
return;
}
if (!m_currentSettings.isNull())
{
if (!(*m_essentialsViewsSitMapIfc)->setOperatorMapSettings(m_currentSettings))
{
new LtsWidgets::LtsMessageDialogNew(this, tr("This topic has invalid map settings"), tr("Could not set map settings from topic"));
return;
}
}
if (!m_filterSettings.isNull())
{
if (m_applyFilter != nullptr)
m_applyFilter->applyFilter(m_filterSettings.toObject());
else
new LtsWidgets::LtsMessageDialogNew(this, tr("Filter settings could not be set because essentials view was closed"));
}
}
void SituationReplayEditor::onGetSettings()
{
if ((*m_essentialsViewsSitMapIfc) == nullptr)
{
new LtsWidgets::LtsMessageDialogNew(this, tr("Map settings could not be received because essentials view was closed"));
return;
}
if (m_applyFilter == nullptr)
{
NOTICE_LOG(m_logger) << "m_applyFilter == nullptr";
new LtsWidgets::LtsMessageDialogNew(this, tr("Filter settings could not be received because essentials view was closed"));
return;
}
m_currentSettings = (*m_essentialsViewsSitMapIfc)->operatorMapSettings();
m_filterSettings = m_applyFilter->getFilterParamsJson();
slotChangesMade();
}
}
@@ -0,0 +1,88 @@
#pragma once
#include <Plugins/MarkerManagement/Gui/Common/mrk_dialog_model.h>
#include <Plugins/MarkerManagement/Gui/Common/mrk_apply_filter.h>
#include <Services/MarkerManagement/mrk.hpp>
#include <TopicEditorBase/topic_preview_widget.h>
#include <TopicEditorBase/topic_previewer.h>
#include <TopicEditorBase/topic_editor_base.h>
namespace LtsSession { class LtsSession; }
namespace MarkerManagement { class MarkerManagementDialogModel; }
namespace NGL { class INGLLogger; }
namespace Ui { class SituationReplayEditor; }
namespace SituationReplay
{
class ForeignGuiInterface;
class SituationReplayControlWidget;
class SituationReplayEditor : public TopicEditorBase::TopicEditor
{
Q_OBJECT
public:
SituationReplayEditor(MarkerManagement::MarkerManagementDialogModel *markerModel,
const QPointer<MarkerManagement::MarkerManagementApplyFilter> &applyFilter,
LtsSession::LtsSession *session, QWidget *parent,
SituationReplay::ForeignGuiInterface **essentialsViewsSrpIfc,
SituationMap::ForeignGuiInterface **essentialsViewsSitMapIfc
);
~SituationReplayEditor();
private:
void updateInternalData() override;
void updateInternalLength() override;
void retranslate() override;
qint64 calculateEnd(qint64 startTime, int lengthInSeconds, double speed, bool backwards = false);
qint64 calculateDuration(qint64 startTime, qint64 endTime, double speed);
void setFilterAndSettings(const QByteArray &mapFilter, const QByteArray &mapSettings);
void setMapSettings(const QByteArray &mapSettings);
void setMapFilter(const QByteArray &mapFilter);
public slots:
void onEssentialsViewChanged(SituationReplay::ForeignGuiInterface *essentialsViewsSrpIfc, SituationMap::ForeignGuiInterface *essentialsViewsSitMapIfc);
private slots:
bool apply2() override final;
void onAddReplayControlWidget();
void onMarkerSelected(const QModelIndex &idx);
void onChangesMade();
void onPreview();
void onReplayStarted();
void onReplayPaused();
void onReplayStopped();
void onShowMapSettings();
void onGetSettings();
private:
LtsSession::LtsSession *m_session{nullptr};
SituationReplay::ForeignGuiInterface **m_essentialsViewsSrpIfc;
SituationMap::ForeignGuiInterface **m_essentialsViewsSitMapIfc { nullptr };
SituationReplayControlWidget *m_replayControlWidget{nullptr};
MarkerManagement::MarkerManagementDialogModel *m_markerModel{nullptr};
QPointer<MarkerManagement::MarkerManagementApplyFilter> m_applyFilter;
QJsonValue m_currentSettings;
QJsonValue m_filterSettings;
bool m_firstUpdate{true};
Ui::SituationReplayEditor *m_ui{nullptr};
NGL::INGLLogger &m_logger;
};
}
@@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SituationReplayEditor</class>
<widget class="QWidget" name="SituationReplayEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>785</width>
<height>540</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Script Editor</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="lbxStartTime">
<property name="text">
<string>Start:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="LtsWidgets::LtsDateTimeEdit" name="dteStartTime">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lbxEndTime">
<property name="text">
<string>End:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="LtsWidgets::LtsDateTimeEdit" name="dteEndTime">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lbxSpeed">
<property name="text">
<string>Speed:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="sbSpeed">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string notr="true">x</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>16.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lbxDuration">
<property name="text">
<string>Duration:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="lblDuration">
<property name="text">
<string notr="true">%1 sec</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="cbFilterSettings">
<property name="text">
<string>Include Filter Settings</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="TopicEditorBase::TopicPreviewWidget" name="widget" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>60</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="traditionalControlWidget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string extracomment="Um einen detailierteren Editor mit Direkt-Abspiel Möglichkeit zu erhalten, starten Sie zuerst die Hilfsansicht und öffnen dann diesen Dialog erneut.">(To obtain a more detailed editor with direct replay controls, open the essentials view, then reopen this dialog.)</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblMrk">
<property name="text">
<string>Set Start &amp; End by markers:</string>
</property>
</widget>
</item>
<item>
<widget class="LtsDataView::LtsDataView" name="markersDataView">
<property name="showColumnCount" stdset="0">
<bool>false</bool>
</property>
<property name="toolButtonsVisible">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsDateTimeEdit</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_date_time_edit.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>TopicEditorBase::TopicPreviewWidget</class>
<extends>QWidget</extends>
<header>TopicEditorBase/topic_preview_widget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,33 @@
#include "replay_control_dialog.h"
#include <QHBoxLayout>
namespace SituationReplay
{
SituationReplayControlDialog::SituationReplayControlDialog(SituationReplayControlWidget *replayWidget, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_logger(getLogger("ReplayControlDialog"))
{
auto l = new QHBoxLayout;
setLayout(l);
l->addWidget(replayWidget);
replayWidget->show();
setOnlineHelpFilename(QStringLiteral("Situation-Start_Situation_Playback"));
}
void SituationReplayControlDialog::retranslate()
{
const QString txt(tr("Replay Control"));
translate(txt);
}
}
@@ -0,0 +1,25 @@
#pragma once
#include "replay_control_widget.h"
#include <SituationReplay/logger.h>
#include <LtsWidgets/lts_dialog.h>
namespace SituationReplay
{
class SituationReplayControlDialog final : public LtsWidgets::LtsDialog
{
Q_OBJECT
public:
explicit SituationReplayControlDialog(SituationReplayControlWidget *replayWidget, QWidget *parent = nullptr);
private:
void retranslate() override;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,448 @@
#include "replay_control_gui_plugin.h"
#include "replay_control_widget.h"
#include "replay_control_dialog.h"
#include "TopicEditor/topic_editor.h"
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <SituationReplay/srp_operator_rights.h>
#include <PresentationManagement/Gui/Script/Common/TakeHomePackageGenerator/export.h>
#include <Plugins/SituationMapPlugin/situation_map_script_filter_gui_plugin_interface.h>
#include <QJsonDocument>
namespace SituationReplay
{
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.Srp.ReplayControl"))
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_mrkDtc(nullptr)
, m_playbackStartTime(-1)
, m_playbackEndTime(-1)
, m_playbackSpeed(-1)
, m_replayWidget(nullptr)
, m_sitMapIfc(nullptr)
{}
bool InterfaceImpl::fetchInterfaces()
{
if (!m_session->getDtc<DataInterface>(m_dtc))
{
DEBUG_LOG(m_logger) << "No Srp Dtc in ReplayControl GUI Plugin with domainId " << m_session->domainId()
<< " partition " << m_session->partitionId()
<< " type " << m_session->partitionType();
return false;
}
if (!m_session->getFtc<DataInterface>(m_ftc))
{
DEBUG_LOG(m_logger) << "No Srp Ftc in ReplayControl GUI Plugin with domainId " << m_session->domainId()
<< " partition " << m_session->partitionId()
<< " type " << m_session->partitionType();
return false;
}
if (!m_session->getDtc<MarkerManagement::DataInterface>(m_mrkDtc))
{
DEBUG_LOG(m_logger) << "(Optional) No Mrk Data Ifc in ReplayControl GUI Plugin with domainId " << m_session->domainId()
<< " partition " << m_session->partitionId()
<< " type " << m_session->partitionType();
}
LtsSession::Fetcher *fetcher = m_session->fetcher(QStringLiteral("Situation Replay Control"));
fetcher->getForeignGuiInterface(m_mrkIfc, QStringLiteral("marker selection in replay control"), true);
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc))
WARNING_LOG(m_logger) << "No Map Gui Ifc: " << m_session->toString();
return fetcher->status();
}
void InterfaceImpl::clearInterfaces()
{
if (m_replayWidget != nullptr)
m_replayWidget->deleteLater();
m_mrkDtc = nullptr;
m_ftc = nullptr;
m_dtc = nullptr;
m_sitMapGuiIfc = nullptr;
m_mrkIfc = nullptr;
}
bool InterfaceImpl::startReplay(const qint64 start, const qint64 end, const double speed, const QJsonObject &attributes)
{
const QJsonValue mapConfig = attributes[QStringLiteral("settings")];
if (mapConfig.isNull())
{
DEBUG_LOG(m_logger) << "Note: Situation Map Script Filter settings is empty";
}
createReplayDialogIfNeeded();
ERROR_LOG(m_logger) << "start = " << start << ", end = " << end << ", speed = " << speed << ", attributes: " << QString::fromUtf8(QJsonDocument(attributes).toJson());
ERROR_LOG(m_logger) << "state = " << m_replayWidget->getReplayState() << ", replay id = " << m_replayWidget->getId();
return m_replayWidget->startReplay(start, end, speed);
}
void InterfaceImpl::pauseReplay()
{
createReplayDialogIfNeeded(false);
m_replayWidget->pauseReplay();
}
void InterfaceImpl::stopReplay()
{
createReplayDialogIfNeeded(false);
m_replayWidget->stopReplay();
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
if (m_session->partitionType() != IDL::PartitionType::Replay)
return ret;
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
LtsSessionData::LtsSessionData *sd = LtsSessionData::LtsSessionData::getInstance();
if (sd->debugFlagValue(QStringLiteral("DoNotCreateInstant.ReplayControl")) == QVariant(true) &&
(!sd->hasDebugFlag(QStringLiteral("DoNotCreateInstant.ReplayControl.Ignore")) || sd->debugFlagValue(QStringLiteral("DoNotCreateInstant.ReplayControl.Ignore")) == QVariant(false)))
sd->setDebugFlagValue(QStringLiteral("DoNotCreateInstant.ReplayControl"), false);
else
plData.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndAddAction;
plData.layoutArea = LtsWidgets::LayoutArea::eDialogTab;
plData.menuText = tr("Playback Control");
plData.identifier = QLatin1String("PlaybackControlDialog");
plData.menuIcon = QIcon(QLatin1String("icon:load.svg"));
plData.exercisePart = LtsWidgets::ExercisePart::eAfterAction;
plData.createWidgetFunc = [this](QWidget *parent)
{
return onShowReplayControlDialog(parent);
};
ret.append(plData);
return ret;
}
QString InterfaceImpl::menuGroup() const
{
return tr("Playbacks");
}
void InterfaceImpl::createReplayDialogIfNeeded(bool useExistingReplay)
{
if (m_replayWidget != nullptr)
return;
m_replayWidget = qobject_cast<SituationReplayControlWidget *>(createControlWidget(useExistingReplay));
}
QWidget *InterfaceImpl::createControlWidget(bool useExistingReplay)
{
auto situationReplayControlWidget = new SituationReplayControlWidget;
bool r = situationReplayControlWidget->init(m_session, m_dtc, m_ftc, m_mrkDtc, m_sitMapGuiIfc, m_session->partitionId(), useExistingReplay);
if (!r)
{
situationReplayControlWidget->deleteLater();
situationReplayControlWidget = nullptr;
}
return situationReplayControlWidget;
}
LtsWidgets::LtsDialog *InterfaceImpl::onShowReplayControlDialog(QWidget *)
{
createReplayDialogIfNeeded();
return new SituationReplayControlDialog(m_replayWidget);
}
TopicEditorBase::TopicEditor *InterfaceImpl::createTopicEditor(const TopicEditorBase::TopicData &data)
{
MarkerManagement::MarkerManagementDialogModel *markerModel = nullptr;
if (m_mrkIfc)
markerModel = m_mrkIfc->createMarkerModel();
else
WARNING_LOG(m_logger) << "No Mrk Ifc for SitRep Topic Editor";
if (m_essentialsViewSrpIfc == nullptr)
WARNING_LOG(m_logger) << "essentials view's srp ifc not available - no preview available";
if (m_applyFilter == nullptr)
WARNING_LOG(m_logger) << "m_applyFilter == nullptr";
SituationReplayEditor *editor = new SituationReplayEditor(markerModel, m_applyFilter,
m_session, nullptr, &m_essentialsViewSrpIfc, &m_essentialsViewSitMapIfc);
QObject::connect(this, &InterfaceImpl::signalEssentialsViewChanged, editor, &SituationReplayEditor::onEssentialsViewChanged);
editor->setTopicData(data);
return editor;
}
void InterfaceImpl::setSitMapIfc(SituationMap::ForeignGuiInterface *sitMapIfc)
{
m_sitMapIfc = sitMapIfc;
}
void InterfaceImpl::setEssentialsViewInterfaces(ForeignGuiInterface *srpIfc, SituationMap::ForeignGuiInterface *sitMapIfc)
{
m_essentialsViewSrpIfc = srpIfc;
m_essentialsViewSitMapIfc = sitMapIfc;
emit signalEssentialsViewChanged(m_essentialsViewSrpIfc, m_essentialsViewSitMapIfc);
}
void InterfaceImpl::setApplyFilter(const QPointer<MarkerManagement::MarkerManagementApplyFilter> &applyFilter)
{
DEBUG_LOG(m_logger) << "setApplyFilter";
m_applyFilter = applyFilter;
}
bool InterfaceImpl::playbackInit(const QJsonObject& attributes)
{
QJsonDocument doc(attributes);
DEBUG_LOG(m_logger) << "attributes=" << doc.toJson(QJsonDocument::Compact);
const QJsonValue mapConfig = attributes[QStringLiteral("settings")];
if (!mapConfig.isNull())
{
m_sitMapIfc->setOperatorMapSettings(mapConfig);
}
else
{
WARNING_LOG(m_logger) << "Note: map settings is empty";
}
const QJsonObject mapFilters = attributes[QStringLiteral("filters")].toObject();
if (m_applyFilter != nullptr && !mapFilters.isEmpty())
{
m_applyFilter->applyFilter(mapFilters);
}
else
{
if (m_applyFilter == nullptr)
WARNING_LOG(m_logger) << "ApplyFilter missing for ReplayControl TopicReplayInterface";
else if (mapFilters.isEmpty())
WARNING_LOG(m_logger) << "Note: filter settings is empty";
}
DEBUG_LOG(m_logger) << "Replay Control playbackInit";
m_playbackStartTime = attributes.value(QStringLiteral("start")).toDouble();
m_playbackEndTime = attributes.value(QStringLiteral("end")).toDouble();
m_playbackSpeed = attributes.value(QStringLiteral("speed")).toDouble();
bool result = (m_playbackStartTime != 0 && m_playbackEndTime != 0 && m_playbackSpeed != 0);
if (!result)
WARNING_LOG(m_logger) << "Invalid data for topic replay: start " << m_playbackStartTime
<< " end " << m_playbackEndTime
<< " speed " << m_playbackSpeed;
return result;
}
bool InterfaceImpl::playbackStart(int secondsOffset)
{
DEBUG_LOG(m_logger) << "Playback start: m_playbackStartTime = " << m_playbackStartTime << ", offset = " << secondsOffset << ", speed = " << m_playbackSpeed;
return startReplay(m_playbackStartTime + ((secondsOffset * m_playbackSpeed) * 1000), 0 , m_playbackSpeed);
}
bool InterfaceImpl::playbackPause()
{
pauseReplay();
return true;
}
InterfaceImpl::TopicReplayInterface::TopicReplayInterface(TopicEditorBase::TopicType type, InterfaceImpl *replayControl)
: m_replayControl(replayControl)
, m_type(type)
{}
InterfaceImpl::TopicReplayInterface::~TopicReplayInterface()
{
m_replayControl->stopReplay();
}
bool InterfaceImpl::TopicReplayInterface::playbackInit(const QJsonObject &attributes)
{
return m_replayControl->playbackInit(attributes);
}
bool InterfaceImpl::TopicReplayInterface::playbackStart(int secondsOffset)
{
return m_replayControl->playbackStart(secondsOffset);
}
bool InterfaceImpl::TopicReplayInterface::playbackPause()
{
return m_replayControl->playbackPause();
}
bool InterfaceImpl::TopicReplayInterface::exportTopic(const QJsonObject &attributes,
const QString &folderPath,
TopicEditorBase::ExportNotifier *pExportNotifier)
{
qint64 playbackStartTime_ms = attributes.value(QStringLiteral("start")).toDouble();
qint64 playbackEndTime_ms = attributes.value(QStringLiteral("end")).toDouble();
if (playbackStartTime_ms == 0 && playbackEndTime_ms == 0)
{
pExportNotifier->setExportFailed();
return false;
}
const QString attributesFileName = QStringLiteral("sitreplay.json");
QFile f(folderPath + attributesFileName);
f.open(QIODevice::WriteOnly);
f.write(QJsonDocument(attributes).toJson(QJsonDocument::Indented));
f.close();
const QString strFileName = QStringLiteral("sitreplay.sqlite");
bool success = TakeHomePackageGenerator::exportSituationMapData(
m_replayControl->getSession()->exerciseId(), folderPath + strFileName, playbackStartTime_ms, playbackEndTime_ms
);
if (success)
pExportNotifier->setExportSuccessful(strFileName);
else
pExportNotifier->setExportFailed();
return success;
}
QVector<TopicEditorBase::TopicData> InterfaceImpl::TopicReplayInterface::additionalTrackEntries(const QJsonObject &attributes, bool &keepOriginalTopic) const
{
keepOriginalTopic = true;
if (m_type != TopicEditorBase::TopicType::Situation)
return {};
keepOriginalTopic = false;
QVector<TopicEditorBase::TopicData> result;
TopicEditorBase::TopicData data;
data.topicType = TopicEditorBase::TopicType::SituationMap;
result.append(data);
std::shared_ptr<SituationMap::ScriptFilterForeignGuiInterface> filterIfc;
if (!m_replayControl->m_session->getForeignGuiInterface<SituationMap::ScriptFilterForeignGuiInterface>(filterIfc))
{
ERROR_LOG(m_replayControl->m_logger) << "sitmap filter ifc missing - map filters for thp will be missing!";
return result;
}
QScopedPointer<TopicReplay::Interface> topicIfc(filterIfc->createInterface(TopicEditorBase::TopicType::SituationMapFilter));
if (topicIfc == nullptr)
{
ERROR_LOG(m_replayControl->m_logger) << "sitmap filter topic replay interface cannot be created - map filters will not be available in thp!";
return result;
}
result += topicIfc->additionalTrackEntries(attributes);
return result;
}
}
@@ -0,0 +1,140 @@
#pragma once
#include <SituationReplay/logger.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <PluginInterfaces/topic_replay_interface.h>
#include <Plugins/SituationReplay/srp_data_plugin_interface.h>
#include <Plugins/SituationReplay/srp_gui_plugin_interface.h>
#include <Plugins/MarkerManagement/mrk_data_plugin_interface.h>
#include <Plugins/MarkerManagement/mrk_gui_plugin_interface.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <MarkerManagement/Gui/Common/mrk_apply_filter.h>
#include <QPointer>
namespace LtsScriptTimeline { class TopicEditor; }
namespace TopicEditorBase { struct TopicData; }
namespace SituationReplay
{
class SituationReplayControlWidget;
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "gui:3:srp")
Q_INTERFACES(GuiPluginBase::Plugin)
Q_OBJECT
public:
GuiPlugin() = default;
~GuiPlugin() = default;
QString pluginName() override { return QStringLiteral("SituationReplayControl"); }
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
bool availableInPartition(IDL::PartitionType partition) const override
{
return partition == IDL::PartitionType::Replay || partition == IDL::PartitionType::Exercise;
}
};
class InterfaceImpl final : public QObject, public ForeignGuiInterface, public GuiPluginBase::Interface
{
Q_OBJECT
signals:
void signalEssentialsViewChanged(SituationReplay::ForeignGuiInterface *essentialsViewSrpIfc,
SituationMap::ForeignGuiInterface *sitMapIfc);
public:
explicit InterfaceImpl(LtsSession::LtsSession *session);
QVector<LtsWidgets::PluginData> getActions() override;
QString menuGroup() const override;
bool fetchInterfaces() override;
void clearInterfaces() override;
bool availableInPartition(IDL::PartitionType partition) const override { return partition == IDL::PartitionType::Replay; }
bool startReplay(const qint64 start, const qint64 end = 0, const double speed = 1.0, const QJsonObject &attributes = QJsonObject()) override;
void pauseReplay() override;
void stopReplay() override;
void setSitMapIfc(SituationMap::ForeignGuiInterface *sitMapIfc) override;
void setEssentialsViewInterfaces(ForeignGuiInterface *srpIfc, SituationMap::ForeignGuiInterface *sitMapIfc) override;
void setApplyFilter(const QPointer<MarkerManagement::MarkerManagementApplyFilter> &applyFilter) override;
bool playbackInit(const QJsonObject &attributes);
bool playbackStart(int secondsOffset);
bool playbackPause();
TopicEditorBase::TopicEditor *createTopicEditor(const TopicEditorBase::TopicData &data) override;
LtsSession::LtsSession* getSession() { return m_session; }
QWidget *createControlWidget(bool useExistingReplay) override;
private:
void createReplayDialogIfNeeded(bool useExistingReplay = true);
LtsWidgets::LtsDialog *onShowReplayControlDialog(QWidget *parent);
private:
std::shared_ptr<SituationReplay::Interface::Dtc> m_dtc;
std::shared_ptr<SituationReplay::Interface::Ftc> m_ftc;
std::shared_ptr<MarkerManagement::Interface::Dtc> m_mrkDtc;
std::shared_ptr<MarkerManagement::ForeignGuiInterface> m_mrkIfc;
SituationReplay::ForeignGuiInterface *m_essentialsViewSrpIfc { nullptr };
SituationMap::ForeignGuiInterface *m_essentialsViewSitMapIfc { nullptr };
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
qint64 m_playbackStartTime;
qint64 m_playbackEndTime;
double m_playbackSpeed;
QPointer<SituationReplayControlWidget> m_replayWidget;
QPointer<MarkerManagement::MarkerManagementApplyFilter> m_applyFilter;
SituationMap::ForeignGuiInterface *m_sitMapIfc { nullptr };
class TopicReplayInterface : public TopicReplay::Interface
{
public:
explicit TopicReplayInterface(TopicEditorBase::TopicType type, InterfaceImpl *replayControl);
~TopicReplayInterface();
bool playbackInit(const QJsonObject &attributes) override;
bool playbackStart(int secondsOffset) override;
bool playbackPause() override;
bool exportTopic(const QJsonObject &attributes,
const QString &folderPath,
TopicEditorBase::ExportNotifier *pExportNotifier) override;
QVector<TopicEditorBase::TopicData> additionalTrackEntries(const QJsonObject &attributes, bool &keepOriginalTopic) const override;
private:
InterfaceImpl *m_replayControl;
TopicEditorBase::TopicType m_type;
};
TopicReplay::Interface *createInterface(TopicEditorBase::TopicType type) override
{
return new TopicReplayInterface(type, this);
}
};
}
@@ -0,0 +1,765 @@
#include "replay_control_widget.h"
#include "replay_control_dialog.h"
#include "ui_replay_control_widget.h"
#include <ngltools/ngltools_dtg.h>
#include <OperatorManagement/opm_data_plugin_interface.h>
#include <MarkerManagement/Gui/Common/mrk_dialog_model.h>
#include <MarkerManagement/Gui/Common/mrk_apply_filter.h>
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <SituationMap/Map/operator_map_settings.h>
#include <QTimer>
namespace SituationReplay
{
SituationReplayControlWidget::SituationReplayControlWidget(QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::SituationReplayControlWidget)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_mrkDtc(nullptr)
, m_markerModel(nullptr)
, m_sitMapGuiIfc(nullptr)
, m_exmDtc(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this, true))
, m_id(0)
, m_partitionId(0)
, m_state(SrpState::Unknown)
, m_toggleStartPauseButton(true)
, m_speedValueChangedTimer(new QTimer(this))
, m_logger(getLogger("SituationReplayControlWidget"))
{
m_ui->setupUi(this);
m_ui->pbStart->setHidden(m_toggleStartPauseButton);
m_ui->pbPause->setHidden(m_toggleStartPauseButton);
m_ui->pbStartPause->setHidden(!m_toggleStartPauseButton);
m_ui->lblCurrentPartitionTime->setProperty("const", true);
m_ui->slPeriodSlider->setProperty("const", true);
m_ui->lblStart->setProperty("const", true);
m_ui->lblEnd->setProperty("const", true);
m_ui->lblSpeedVal->setProperty("const", true);
m_ui->slSpeed->setProperty("const", true);
m_ui->pbStartPause->setProperty("const", true);
m_ui->dteStartTime->setProperty("const", true);
m_ui->dteStartTime->setSubWidgetsProperties(QStringLiteral("const"), true);
connect(m_ui->pbStartPause, &QToolButton::toggled,
this, &SituationReplayControlWidget::onStartPauseButtonToggled);
connect(m_ui->pbStart, &QToolButton::clicked,
this, &SituationReplayControlWidget::onStartReplay);
connect(m_ui->pbStop, &QToolButton::clicked,
this, &SituationReplayControlWidget::onStopReplay);
connect(m_ui->pbPause, &QToolButton::clicked,
this, &SituationReplayControlWidget::onPauseResumeReplay);
m_speedValueChangedTimer->setSingleShot(true);
connect(m_speedValueChangedTimer, &QTimer::timeout,
this, &SituationReplayControlWidget::onSpeedValueChanged);
connect(m_ui->slSpeed, &QSlider::valueChanged, this, [this](int val)
{
m_ui->lblSpeedVal->setText(QStringLiteral("%1").arg(val * 10.0, 0));
m_speedValueChangedTimer->start(500);
});
connect(m_ui->pbSetStart, &QPushButton::clicked,
this, [this]()
{
emit signalSetStart(m_ui->dteStartTime->msecsSinceEpoch());
});
connect(m_ui->pbSetEnd, &QPushButton::clicked,
this, [this]()
{
emit signalSetEnd(m_ui->dteStartTime->msecsSinceEpoch());
});
const QFontMetricsF fm(m_ui->lblSpeedVal->font());
const QRectF rectSpeedVal = fm.boundingRect(QStringLiteral("000.0"));
m_ui->lblSpeedVal->setFixedWidth(qRound(rectSpeedVal.width()));
m_ui->slSpeed->setValue(10.0);
showEditorWidget(false);
}
SituationReplayControlWidget::~SituationReplayControlWidget()
{
delete m_ui;
}
bool SituationReplayControlWidget::init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<MarkerManagement::Interface::Dtc> &mrkDtc,
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMapGuiIfc,
int partitionId, bool useExistingReplay)
{
m_session = session;
m_dtc = dtc;
m_ftc = ftc;
m_mrkDtc = mrkDtc;
m_partitionId = partitionId;
m_sitMapGuiIfc = sitMapGuiIfc;
if (!m_session->getDtc<ExerciseManagement::DataInterface>(m_exmDtc))
{
ERROR_LOG(m_logger)<<" couldn't init exmDtc!";
return false;
}
m_ui->pbStart->setText(tr("Start"));
m_ui->pbStop->setText(tr("Stop"));
m_ui->pbPause->setText(tr("Pause"));
m_ui->pbStartPause->setToolTip(tr("Start"));
m_dtc->waitForHistoricalDataSitReplay(20000);
if (useExistingReplay)
{
useExistingReplay = false;
const QMap<qint32, SituationReplay::SitReplay> replays = m_dtc->sitReplays();
for (const SituationReplay::SitReplay &replay : replays)
{
if (replay.replayPartitionId() == m_partitionId)
{
m_state = replay.state();
m_id = replay.id();
DEBUG_LOG(m_logger) << "recycling replay with id" << m_id;
m_ui->dteStartTime->setMsecsSinceEpoch(replay.beginTime());
useExistingReplay = true;
break;
}
}
}
m_ui->dteStartTime->setRetrieveCurrentTimeCallback([]() { return QDateTime::currentMSecsSinceEpoch(); });
enaDisa();
connect(m_dtc.get(), &Interface::Dtc::sitReplayChanged,
this, &SituationReplayControlWidget::onSitReplayChanged);
connect(m_session, &LtsSession::LtsSession::partitionTimeChanged,
this, &SituationReplayControlWidget::onPartitionTimeChanged);
connect(m_ui->slPeriodSlider, &QSlider::valueChanged, this,
&SituationReplayControlWidget::onPeriodSliderChanged);
connect(m_ui->dteStartTime, &LtsWidgets::LtsDateTimeEdit::dateTimeChanged, this,
&SituationReplayControlWidget::onDteStartChanged);
QTimer *t = new QTimer(this);
t->setInterval(200);
connect(t, &QTimer::timeout,
this, [this]()
{
m_endTime = QDateTime::currentMSecsSinceEpoch();
m_ui->lblEnd->setText(DTG::toStringMSec(m_endTime));
m_ui->slPeriodSlider->setMaximum(getSecs(m_endTime));
});
const ExerciseManagement::Exercise &exercise = m_exmDtc->exercise(m_session->exerciseId());
const qint64 stopTime = exercise.stopTime();
if (stopTime > 0)
{
m_ui->lblEnd->setText(DTG::toStringMSec(stopTime));
m_ui->slPeriodSlider->setMaximum(getSecs(stopTime));
m_endTime = stopTime;
}
else
t->start();
if (!useExistingReplay)
{
std::shared_ptr<ExerciseManagement::Interface::Dtc> excDtc;
if (session->getDtc<ExerciseManagement::DataInterface>(excDtc))
{
int excId = session->exerciseId();
excDtc->waitForHistoricalDataExercise(3000);
ExerciseManagement::Exercise exc = excDtc->exercise(excId);
qint64 startTime = exc.startTime();
if (startTime > 0)
{
m_ui->dteStartTime->setMsecsSinceEpoch(startTime);
}
else
{
qint64 beginTime = exc.beginTime();
if (beginTime > 0)
{
WARNING_LOG(m_logger) << "no exc start time set, using exc begin time " << beginTime;
m_ui->dteStartTime->setMsecsSinceEpoch(beginTime);
}
else
{
WARNING_LOG(m_logger) << "no valid exc for getting exercise start time";
m_ui->dteStartTime->setMsecsSinceEpoch(QDateTime::currentDateTime().addDays(-5).toMSecsSinceEpoch());
}
}
}
else
{
WARNING_LOG(m_logger) << "no exc dtc for getting exercise start time";
m_ui->dteStartTime->setMsecsSinceEpoch(QDateTime::currentDateTime().addDays(-5).toMSecsSinceEpoch());
}
}
qint64 startInSecs = getSecs(m_ui->dteStartTime->msecsSinceEpoch());
qint64 endInSecs = QDateTime::currentSecsSinceEpoch();
m_ui->slPeriodSlider->setMinimum(startInSecs);
m_ui->slPeriodSlider->setMaximum(endInSecs);
{
QSignalBlocker blocker(m_ui->slPeriodSlider);
m_ui->slPeriodSlider->setValue(startInSecs);
}
m_ui->lblStart->setText(DTG::toStringMSec(getMSecs(startInSecs)));
m_ui->lblEnd->setText(DTG::toStringMSec(getMSecs(endInSecs)));
std::shared_ptr<OperatorManagement::Interface::Dtc> opmDtc;
m_session->getDtc<OperatorManagement::DataInterface>(opmDtc);
std::shared_ptr<FileManagement::ForeignGuiInterface> flmGui;
m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(flmGui);
m_markerModel = new MarkerManagement::MarkerManagementDialogModel(this);
m_markerModel->initModel(m_mrkDtc, opmDtc, flmGui);
m_ui->tvMarker->setModel(m_markerModel);
m_ui->tvMarker->hideColumn(MarkerManagement::MarkerManagementDialogModel::ColImage);
m_ui->tvMarker->hideColumn(MarkerManagement::MarkerManagementDialogModel::ColFileId);
m_ui->tvMarker->hideColumn(MarkerManagement::MarkerManagementDialogModel::ColOffset);
#ifndef LTS_DEBUG
m_ui->tvMarker->hideColumn(MarkerManagement::MarkerManagementDialogModel::ColStreams);
#endif
m_ui->tvMarker->setSortIndicator(MarkerManagement::MarkerManagementDialogModel::ColTime, Qt::DescendingOrder);
const int curOpId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
if (!m_ui->tvMarker->setInitialSearchContent(MarkerManagement::MarkerManagementDialogModel::ColOperator, curOpId))
{
QTimer::singleShot(200, this, [this, curOpId]
{
m_ui->tvMarker->setInitialSearchContent(MarkerManagement::MarkerManagementDialogModel::ColOperator, curOpId);
});
}
connect(m_ui->tvMarker, &LtsDataView::LtsDataView::activated, this, &SituationReplayControlWidget::onMarkerClicked);
return true;
}
qint64 SituationReplayControlWidget::startTime() const
{
return m_ui->dteStartTime->msecsSinceEpoch();
}
void SituationReplayControlWidget::setStartTime(qint64 startTime)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " " << startTime;
if (startTime < 0)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " called with invalid start time: " << startTime;
return;
}
if (m_ui->dteStartTime->msecsSinceEpoch() == startTime)
return;
m_ui->dteStartTime->setMsecsSinceEpoch(startTime);
emit signalSetStart(startTime);
}
int SituationReplayControlWidget::speed() const
{
return m_ui->slSpeed->value();
}
void SituationReplayControlWidget::setSpeed(int speed)
{
m_ui->slSpeed->setValue(speed);
}
void SituationReplayControlWidget::showEditorWidget(bool visibility)
{
m_ui->editorWidget->setVisible(visibility);
}
bool SituationReplayControlWidget::startReplay(qint64 start, qint64 end, double speed)
{
stopReplay();
disableAllReplayButtons();
QTimer::singleShot(1 * 647, this, [this, start, end, speed]()
{
startReplayDelayed(start, end, speed);
});
return true;
}
void SituationReplayControlWidget::disableAllReplayButtons()
{
m_ui->pbStart->setEnabled(false);
m_ui->slPeriodSlider->setEnabled(false);
m_ui->dteStartTime->setEnabled(false);
m_ui->tvMarker->setEnabled(false);
m_ui->pbStop->setEnabled(false);
m_ui->pbPause->setEnabled(false);
m_ui->pbStartPause->setEnabled(false);
}
void SituationReplayControlWidget::pauseReplay()
{
if (m_sitMapGuiIfc != nullptr)
m_sitMapGuiIfc->enableFireEventFlashing(false);
if (m_id == 0)
{
WARNING_LOG(m_logger) << "replay pause requested, but no replay active in this context";
return;
}
if (m_state == SrpState::Resumed || m_state == SrpState::Started)
{
disableAllReplayButtons();
ChangeReplayStateRequest req;
req.id(m_id);
req.replayPartitionId(m_partitionId);
req.state(SrpState::Paused);
req.pace(m_ui->slSpeed->value() / 10.);
if (!m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->changeReplayStateRequest(req, this);
}))
{
enaDisa();
ERROR_LOG(m_logger) << "pausing failed for replay " << m_id << ": " << m_requestHelper->getErrorString();
}
else
emit replayPaused();
}
else
ERROR_LOG(m_logger) << "pause requested, but replay state was not resumed or started, but " << m_state << " for " << m_id;
}
void SituationReplayControlWidget::stopReplay()
{
if (m_sitMapGuiIfc != nullptr)
m_sitMapGuiIfc->enableFireEventFlashing(true);
if (m_id == 0)
{
WARNING_LOG(m_logger) << "replay stop requested, but no replay active in this context";
return;
}
disableAllReplayButtons();
ChangeReplayStateRequest req;
req.id(m_id);
req.replayPartitionId(m_partitionId);
req.state(SrpState::Stopped);
const bool wasQuiet = m_requestHelper->quiet();
m_requestHelper->setQuiet(false);
if (m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->changeReplayStateRequest(req, this);
}))
{
m_ui->pbStartPause->setChecked(false);
m_ui->pbStartPause->setToolTip(tr("Start"));
m_id = 0;
}
else
{
enaDisa();
ERROR_LOG(m_logger) << "stopping failed for replay " << m_id << ": " << m_requestHelper->getErrorString();
}
m_requestHelper->setQuiet(wasQuiet);
emit replayStopped();
}
void SituationReplayControlWidget::resumeReplay()
{
if (m_sitMapGuiIfc != nullptr)
m_sitMapGuiIfc->enableFireEventFlashing(true);
disableAllReplayButtons();
ChangeReplayStateRequest req;
req.id(m_id);
req.replayPartitionId(m_partitionId);
req.state(SrpState::Resumed);
req.beginTime(m_ui->dteStartTime->msecsSinceEpoch());
req.endTime(0);
req.pace(m_ui->slSpeed->value() / 10.);
if (!m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->changeReplayStateRequest(req, this);
}))
{
enaDisa();
ERROR_LOG(m_logger) << "resuming failed for replay " << m_id << ": " << m_requestHelper->getErrorString();
}
}
void SituationReplayControlWidget::onSitReplayChanged(const SitReplay &data, DataModification modType)
{
DEBUG_LOG(m_logger) << "onSitReplayChanged: id = " << data.id() << ", exId = " << data.exerciseId() << ", repPartitionId = " << data.replayPartitionId()
<< ", state = " << (int)data.state().underlying() << ", m_partitionId = " << m_partitionId << ", modType = " << (int)modType;
if (m_partitionId != data.replayPartitionId())
return;
if (modType == DataModification::eAdded ||
modType == DataModification::eModified)
m_state = data.state();
else
m_state = SrpState::Stopped;
enaDisa();
}
void SituationReplayControlWidget::onPartitionTimeChanged(qint64 newPartitionTime)
{
const qint64 &partTime = getSecs(newPartitionTime);
if (partTime < getSecs(m_endTime) )
m_ui->lblCurrentPartitionTime->setText(DTG::toStringMSec(newPartitionTime));
else
stopReplay();
m_ui->slPeriodSlider->setValue(getSecs(newPartitionTime));
}
void SituationReplayControlWidget::onMarkerClicked(const QModelIndex &index)
{
if (!index.isValid())
return;
MarkerManagement::Marker marker = m_markerModel->getRowData(index.row());
const qint64 mSecsSinceEpoch = marker.timeStamp() - marker.timeStampOffset();
m_ui->slPeriodSlider->setValue(getSecs(mSecsSinceEpoch));
m_ui->dteStartTime->setMsecsSinceEpoch(mSecsSinceEpoch);
MarkerManagement::MarkerManagementApplyFilter *appFilter = nullptr;
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> fltParticipantIfc;
std::shared_ptr<FilterManagement::ForeignAesGuiInterface> fltAesIfc;
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> fltBuildingComponentGuiIfc;
if (m_session->getForeignGuiInterface(fltParticipantIfc) &&
m_session->getForeignGuiInterface(fltAesIfc)
)
appFilter = new MarkerManagement::MarkerManagementApplyFilter(m_session, fltParticipantIfc, fltAesIfc, fltBuildingComponentGuiIfc);
else
WARNING_LOG(m_logger) << "unable to set filters from marker as flt ifc`s are missing";
if (marker.filter().size() > 0 && appFilter != nullptr)
{
QByteArray mapFilter(QByteArray::fromRawData(marker.filter().c_str(), marker.filter().size()));
if (appFilter->applyFilter(mapFilter))
emit signalSetMapFilter(mapFilter);
else
ERROR_LOG(m_logger) << "Error while setting filters";
}
else
{
if (m_sitMapGuiIfc != nullptr)
{
const std::vector<MarkerManagement::MarkerDescription> &descriptionsRef = marker.descriptions();
QList<MarkerManagement::MarkerType> markerTypes;
markerTypes.reserve(descriptionsRef.size());
for (const MarkerManagement::MarkerDescription &desc : qAsConst(descriptionsRef))
markerTypes.append(desc.markerType());
if (markerTypes.contains(MarkerManagement::MarkerType_def::Situation))
m_sitMapGuiIfc->setCenterPoint(QPointF(marker.position().lon(), marker.position().lat()));
}
}
if (appFilter)
{
QByteArray mapSettings(QByteArray::fromRawData(marker.mapSettings().c_str(), marker.mapSettings().size()));
DEBUG_LOG(m_logger) << "set map settings from marker " << (mapSettings.toStdString());
SituationMap::OperatorMapSettings oms;
oms.fromJson(mapSettings);
DEBUG_LOG(m_logger) << ">>>> oms.orderedLayers.size() " << oms.orderedLayers.size();
static const QLatin1String LayerNameEmergencyCall("EmergencyCall");
auto pos = std::remove_if( oms.orderedLayers.begin(),
oms.orderedLayers.end(),
[](const QPair<QString, SituationMap::LayerParameter> &pair) { return pair.first == LayerNameEmergencyCall; } );
DEBUG_LOG(m_logger) << ">>>> remove iterator: " << pos << " END: " << oms.orderedLayers.end();
if(pos != oms.orderedLayers.end())
oms.orderedLayers.erase(pos);
mapSettings = oms.toJson();
if (appFilter->applyMapSettings(mapSettings))
emit signalSetMapSettings(mapSettings);
else
ERROR_LOG(m_logger) << "Error while setting mapSettings";
}
delete appFilter;
}
void SituationReplayControlWidget::enaDisa()
{
bool enaStart = false;
bool enaStop = false;
bool enaPause = false;
switch (m_state.underlying())
{
case SrpState::Paused:
enaStart = false;
enaStop = true;
enaPause = false;
break;
case SrpState::Resumed:
case SrpState::Started:
enaStart = false;
enaStop = true;
enaPause = true;
break;
case SrpState::Unknown:
case SrpState::Stopped:
enaStart = true;
enaStop = false;
enaPause = false;
break;
}
m_ui->pbStart->setEnabled(enaStart);
m_ui->slPeriodSlider->setEnabled(!enaPause);
m_ui->dteStartTime->setEnabled(!enaPause);
m_ui->tvMarker->setEnabled(enaStart);
m_ui->pbStop->setEnabled(enaStop);
m_ui->pbPause->setEnabled(enaPause);
m_ui->pbStartPause->setEnabled(true);
QSignalBlocker sb(m_ui->pbStartPause);
m_ui->pbStartPause->setChecked(enaPause);
}
bool SituationReplayControlWidget::startReplayDelayed(qint64 start, qint64 end, double speed)
{
SituationMap::SitMapUpdatesEnabledHelper sitMapHelper(m_sitMapGuiIfc);
m_ui->dteStartTime->setMsecsSinceEpoch(start);
{
QSignalBlocker block(m_ui->slSpeed);
m_ui->slSpeed->setValue(qRound(speed * 10));
}
ChangeReplayStateRequest req;
req.id(m_id);
req.replayPartitionId(m_partitionId);
req.state(SrpState::Started);
req.beginTime(start);
req.endTime(end);
req.pace(speed);
ERROR_LOG(m_logger) << "Start Replay Partition: "
<< "id: " << m_id
<< ", partition id: " << m_partitionId
<< ", partition type: " << m_session->partitionType()
<< ", start: " << start
<< ", end: " << end
<< ", speed: " << speed;
if (m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->changeReplayStateRequest(req, this);
}))
{
int repliedId = m_requestHelper->getRepliedId();
if (repliedId > 0)
{
m_id = repliedId;
ERROR_LOG(m_logger) << "Replied replay id: " << repliedId;
emit replayStarted();
return true;
}
ERROR_LOG(m_logger) << "replay start didn't return a replay id!";
}
ERROR_LOG(m_logger) << "could not start replay: " << m_requestHelper->getErrorString() << " (" << m_requestHelper->getRepliedId() << ")";
enaDisa();
return false;
}
void SituationReplayControlWidget::onStartReplay()
{
double speed = m_ui->slSpeed->value();
speed /= 10;
qint64 startInSecs = getSecs(m_ui->dteStartTime->msecsSinceEpoch());
DEBUG_LOG(m_logger) << "onStartReplay startInSecs=" << startInSecs;
m_ui->slPeriodSlider->setValue(startInSecs);
startReplay(m_ui->dteStartTime->msecsSinceEpoch(), 0 , speed);
}
void SituationReplayControlWidget::onStopReplay()
{
stopReplay();
}
void SituationReplayControlWidget::onPauseResumeReplay()
{
if (m_state == SrpState::Resumed || m_state == SrpState::Started)
pauseReplay();
else if (m_state == SrpState::Paused)
resumeReplay();
}
void SituationReplayControlWidget::onStartPauseButtonToggled(bool checked)
{
if (checked)
{
if (m_state == SrpState::Paused)
{
onPauseResumeReplay();
m_ui->pbStartPause->setToolTip(tr("Pause"));
}
else
{
onStartReplay();
m_ui->pbStartPause->setToolTip(tr("Pause"));
}
}
else
{
onPauseResumeReplay();
m_ui->pbStartPause->setToolTip(tr("Continue"));
}
}
void SituationReplayControlWidget::onSpeedValueChanged()
{
double speed = m_ui->slSpeed->value() / 10.;
emit signalSetSpeed(speed);
if (m_id == 0 || (m_state != SrpState::Resumed && m_state != SrpState::Started))
return;
ChangeReplayStateRequest req;
req.id(m_id);
req.replayPartitionId(m_partitionId);
req.pace(speed);
m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->changeReplayStateRequest(req, this);
});
}
void SituationReplayControlWidget::onPeriodSliderChanged(int seconds)
{
m_ui->dteStartTime->setMsecsSinceEpoch(getMSecs(seconds));
}
void SituationReplayControlWidget::onDteStartChanged()
{
qint64 startInSecs = getSecs(m_ui->dteStartTime->msecsSinceEpoch());
QSignalBlocker block(m_ui->slPeriodSlider);
m_ui->slPeriodSlider->setValue(startInSecs);
}
qint64 SituationReplayControlWidget::getMSecs(qint64 sec)
{
return sec * 1000;
}
qint64 SituationReplayControlWidget::getSecs(qint64 msec)
{
return msec / 1000;
}
}
@@ -0,0 +1,121 @@
#pragma once
#include <SituationReplay/srp_ftc.h>
#include <SituationReplay/srp_dtc.h>
#include <SituationReplay/logger.h>
#include <Plugins/MarkerManagement/mrk_data_plugin_interface.h>
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <LtsSession/lts_session.h>
#include <LtsUtilsGuiDds/request_helper.h>
namespace MarkerManagement
{
class MarkerManagementDialogModel;
}
namespace Ui
{
class SituationReplayControlWidget;
}
class QTimer;
namespace SituationReplay
{
class SituationReplayControlWidget final : public QWidget
, protected Interface::Ftc::ChangeReplayStateReplyHandler
{
Q_OBJECT
public:
explicit SituationReplayControlWidget(QWidget *parent = nullptr);
~SituationReplayControlWidget();
bool init(LtsSession::LtsSession *session,
const std::shared_ptr<Interface::Dtc> &dtc,
const std::shared_ptr<Interface::Ftc> &ftc,
const std::shared_ptr<MarkerManagement::Interface::Dtc> &mrkDtc,
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMapGuiIfc,
int partitionId, bool useExistingReplay = true);
void onChangeReplayStateReply(const Core::FunctionReplyObject &replyObject) override final
{
m_requestHelper->requestReply(replyObject);
}
qint64 startTime() const;
void setStartTime(qint64 startTime);
int speed() const;
void setSpeed(int speed);
void showEditorWidget(bool visibility = true);
bool startReplay(qint64 start, qint64 end = 0 , double speed = 1.0f);
void pauseReplay();
void stopReplay();
void resumeReplay();
SrpState getReplayState() { return m_state; }
int getId() { return m_id; }
signals:
void signalSetStart(qint64 start);
void signalSetEnd(qint64 end);
void signalSetSpeed(double speed);
void signalSetMapFilter(const QByteArray &mapFilter);
void signalSetMapSettings(const QByteArray &mapSettings);
void replayStarted();
void replayPaused();
void replayStopped();
private slots:
void onSitReplayChanged(const SitReplay &data, DataModification modType);
void onPartitionTimeChanged(qint64 newPartitionTime);
void onMarkerClicked(const QModelIndex &index);
void enaDisa();
bool startReplayDelayed(qint64 start, qint64 end = 0 , double speed = 1.0f);
void onStartReplay();
void onStopReplay();
void onPauseResumeReplay();
void onStartPauseButtonToggled(bool checked);
void onSpeedValueChanged();
void onPeriodSliderChanged(int seconds);
void onDteStartChanged();
private:
void disableAllReplayButtons();
qint64 getMSecs(qint64 sec);
qint64 getSecs(qint64 msec);
Ui::SituationReplayControlWidget *m_ui;
LtsSession::LtsSession *m_session;
std::shared_ptr<SituationReplay::Interface::Dtc> m_dtc;
std::shared_ptr<SituationReplay::Interface::Ftc> m_ftc;
std::shared_ptr<MarkerManagement::Interface::Dtc> m_mrkDtc;
MarkerManagement::MarkerManagementDialogModel *m_markerModel;
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
std::shared_ptr<ExerciseManagement::Interface::Dtc> m_exmDtc;
LtsUtils::RequestHelper *m_requestHelper;
int m_id;
int m_partitionId;
SrpState m_state;
qint64 m_endTime;
bool m_toggleStartPauseButton;
QTimer *m_speedValueChangedTimer;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,361 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SituationReplayControlWidget</class>
<widget class="QWidget" name="SituationReplayControlWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>849</width>
<height>520</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Replay Control</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Current Partition Time:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblCurrentPartitionTime">
<property name="text">
<string notr="true">-</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="LtsDataView::LtsDataView" name="tvMarker" native="true">
<property name="showColumnCount" stdset="0">
<bool>false</bool>
</property>
<property name="toolButtonsVisible" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="lblStart">
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="slPeriodSlider">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::NoTicks</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblEnd">
<property name="text">
<string notr="true">0</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QToolButton" name="pbStartPause">
<property name="minimumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="text">
<string>|&gt; / ||</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/avm_start.svg</normaloff>
<normalon>:/style/avm_pause.svg</normalon>:/style/avm_start.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="pbStart">
<property name="minimumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="text">
<string notr="true">|&gt;</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/avm_start.svg</normaloff>:/style/avm_start.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="pbPause">
<property name="minimumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="text">
<string notr="true">||</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/avm_pause.svg</normaloff>:/style/avm_pause.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="pbStop">
<property name="minimumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="text">
<string notr="true">[]</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/style/avm_stop.svg</normaloff>:/style/avm_stop.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblStartTime">
<property name="text">
<string>Start Time:</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsDateTimeEdit" name="dteStartTime" native="true">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="withNowButton" stdset="0">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Speed [%]:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblSpeedVal">
<property name="text">
<string notr="true">&lt;VALUE&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="slSpeed">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>160</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="editorWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Set time as..:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbSetStart">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbSetEnd">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>End</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsDateTimeEdit</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_date_time_edit.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>slPeriodSlider</tabstop>
<tabstop>pbStartPause</tabstop>
<tabstop>pbStart</tabstop>
<tabstop>pbPause</tabstop>
<tabstop>pbStop</tabstop>
<tabstop>dteStartTime</tabstop>
<tabstop>slSpeed</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>