Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,601 @@
/**
* @RDE_HEADER@
* Topic Editor for the Situation Replay in the Script Editor
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2017-04-04
*/
#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 <Viewer/SituationMap/Map/map.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) // mrk plugin available
{
m_markerModel->setParent(this); // model was created without parent!
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(); // no markers, no view
m_ui->lblMrk->hide();
}
// check if the new replay control widget editor can be used
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;
}
///////////////////////////////////////////////////////////////////////////////
// PRIVATE
void SituationReplayEditor::updateInternalData()
{
DEBUG_LOG(m_logger) << LOGFUNCTION;
if (m_firstUpdate)
{
m_firstUpdate = false;
retranslate();
// And again a workaround:
// NLDEVCTRL-1434 Filtereinstellung werden nicht übernommen.
// Bei Erstellen diese SituationReplayEditor werden die TopicDaten übermitteltet:
// SetTopicData ruft dann (indirekt) updateInternalData auf.
// Dabei werden dann fälschlichwerweise die _leeren_ m_filterSettings&m_currentSettings
// genutzt, um m_topicData zu überschreiben...
// Also müssen wir vorher m_filterSettings&m_currentSettings auf Stand bringen:
//
// apply_2 will be called via updateInternalLength.
// Within that at least m_filterSettings and m_currentSettings will be
// transfered to m_topic_data....
m_filterSettings = m_topicData.properties.value(QStringLiteral("filters"));
m_currentSettings = m_topicData.properties.value(QStringLiteral("settings"));
// load & show settings / filters not available for replay, as that topic doesn't store nor apply settings / filters
if (m_topicData.topicType == TopicEditorBase::TopicType::Situation)
{
m_buttonBox->getButton(LtsWidgets::DialogButton::Add)->show();
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->show();
}
}
if (!hasTopicDataProperties())
return;
// is positioned (cannot be positioned without data)!
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(); // has to be done here, as LtsDateTimeEdits cannot be signal-blocked, for whatever reason
m_ui->dteEndTime->setMsecsSinceEpoch(end);
m_ui->lblDuration->setText(tr("%1 sec").arg(m_topicData.duration));
if (!hasChanges) // only save new end time if the user didn't change anything - otherwise his changes will be also applied..
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; // clear
result2 += 500; // ceil (ms)
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();
}
///////////////////////////////////////////////////////////////////////////////
// PUBLIC SLOTS
void SituationReplayEditor::onEssentialsViewChanged(SituationReplay::ForeignGuiInterface *essentialsViewsSrpIfc,
SituationMap::ForeignGuiInterface *essentialsViewsSitMapIfc)
{
*m_essentialsViewsSrpIfc = essentialsViewsSrpIfc;
*m_essentialsViewsSitMapIfc = essentialsViewsSitMapIfc;
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Show, !!(*m_essentialsViewsSrpIfc));
}
///////////////////////////////////////////////////////////////////////////////
// PRIVATE SLOTS
//bool SituationReplayEditor::apply2()
//{
// INFO_LOG(m_logger) << "apply2";
// qint64 start = m_ui->dteStartTime->msecsSinceEpoch();
// qint64 end = m_ui->dteEndTime->msecsSinceEpoch();
// double speed = m_ui->sbSpeed->value();
// qint64 newLength = calcDuration(start, end, speed) / 1000; // as the TrackEntry cannot be larger than the actual replay content / time
// m_trackEntry->m_length = newLength;
// saveTopicData(QStringLiteral("start"), start);
// saveTopicData(QStringLiteral("speed"), speed);
// saveTopicData(QStringLiteral("end"), end);
// if (m_ui->cbFilterSettings->isChecked() && m_ui->cbFilterSettings->isVisible())
// {
// NOTICE_LOG(m_logger) << "m_filterSettings";
// saveTopicData(QStringLiteral("filters"), m_filterSettings);
// saveTopicData(QStringLiteral("settings"), m_currentSettings);
// }
// slotSomethingChanged();
// this->__unchange__();
// applied();
// return true;
//}
//* Original
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; // as the TrackEntry cannot be larger than the actual replay content / time
setDescription(m_ui->widget->description());
setTopicDataProperty(QStringLiteral("start"), start);
setTopicDataProperty(QStringLiteral("speed"), speed);
setTopicDataProperty(QStringLiteral("end"), end);
if (m_topicData.channel.isEmpty()) // not set
{
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()) // not set
return true;
LtsUtils::Promise *promise = new LtsUtils::Promise(nullptr, this); // empty promise, function set & executed by invoked slot
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")); // ay caramba
});
emit durationCheckRequested(duration, promise);
return false; // did not fail, but the promise is async. If the promise resolves, the effect of "return true" is executed => __unchange__ & emit signalTrackEntryChanged
}
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 /* otherwise race condition !!! */);
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;
}
// qint64 startTime = marker.timeStamp() - marker.timeStampOffset();
// m_ui->dteStartTime->setMsecsSinceEpoch(startTime);
// m_ui->dteEndTime->setMsecsSinceEpoch(marker.timeStamp() + (10 * 1000)/* TODO: default length? */);
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();
//m_ui->markerView->selectionModel()->clear(); TODO...?
slotChangesMade();
}
} // namespace SituationMap
@@ -0,0 +1,95 @@
/**
* @RDE_HEADER@
* Topic Editor for the Situation Replay in the Script Editor
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2017-04-04
*/
#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/* = nullptr*/,
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;
};
} // namespace SituationMap
@@ -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>