Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+601
@@ -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 & 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>
|
||||
Reference in new issue
Block a user