775 lines
24 KiB
C++
Executable File
775 lines
24 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* Exportable widget with replay controls
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Mike Wille, NLE, 2019-10-02
|
|
*/
|
|
|
|
|
|
#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> // manipulation of OperatorMapSettings
|
|
|
|
#include <QTimer>
|
|
|
|
|
|
namespace SituationReplay
|
|
{
|
|
|
|
SituationReplayControlWidget::SituationReplayControlWidget(QWidget *parent)
|
|
: QWidget(parent)
|
|
, m_ui(new Ui::SituationReplayControlWidget)
|
|
, m_dtc(nullptr)
|
|
, m_ftc(nullptr)
|
|
, m_mrkDtc(nullptr) // can be 0 !
|
|
, m_markerModel(nullptr)
|
|
, m_sitMapGuiIfc(nullptr) // can be 0 !
|
|
, 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);
|
|
|
|
// to avoid enabeling of apply button of lts_dialog
|
|
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, // can be 0 !
|
|
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMapGuiIfc, // can be 0 !
|
|
int partitionId, bool useExistingReplay)
|
|
{
|
|
m_session = session;
|
|
m_dtc = dtc;
|
|
m_ftc = ftc;
|
|
m_mrkDtc = mrkDtc; // can be 0 !
|
|
m_partitionId = partitionId;
|
|
m_sitMapGuiIfc = sitMapGuiIfc; // can be 0 !
|
|
|
|
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; // replay really exists
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
m_ui->dteStartTime->setRetrieveCurrentTimeCallback([]() { return QDateTime::currentMSecsSinceEpoch(); });
|
|
enaDisa();
|
|
|
|
|
|
connect(m_dtc.get(), &Interface::Dtc::sitReplayChanged,
|
|
this, &SituationReplayControlWidget::onSitReplayChanged);
|
|
// this, [this](const SituationReplay::SitReplay & _t1, DataModification _t2)
|
|
// {
|
|
// QTimer::singleShot(3000, this, [this, _t1, _t2]()
|
|
// {
|
|
// onSitReplayChanged(_t1, _t2);
|
|
// });
|
|
// });
|
|
|
|
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);
|
|
|
|
|
|
// set end time every new second
|
|
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();
|
|
|
|
// set start time if start time not taken from existing replay
|
|
// TODO: unclog this getDtc & waitForX mess
|
|
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)
|
|
{
|
|
//WARNING_LOG(m_logger) << "exc start time " << startTime;
|
|
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()); // 5 days ... just a guess
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING_LOG(m_logger) << "no exc dtc for getting exercise start time";
|
|
m_ui->dteStartTime->setMsecsSinceEpoch(QDateTime::currentDateTime().addDays(-5).toMSecsSinceEpoch()); // 5 days ... just a guess
|
|
}
|
|
}
|
|
|
|
|
|
// PeriodSlider, print start & end time
|
|
qint64 startInSecs = getSecs(m_ui->dteStartTime->msecsSinceEpoch());
|
|
qint64 endInSecs = QDateTime::currentSecsSinceEpoch();
|
|
|
|
m_ui->slPeriodSlider->setMinimum(startInSecs);
|
|
m_ui->slPeriodSlider->setMaximum(endInSecs);
|
|
|
|
{ // shorten lifetime of blocker
|
|
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)));
|
|
|
|
|
|
// Marker
|
|
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); // newest marker first
|
|
|
|
// may be delayed because data must be intiially read from opm here
|
|
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(); // prevent the user from clicking again while waiting ...
|
|
|
|
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) // nothing 2 do
|
|
{
|
|
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(); // prevent the user from clicking again while waiting ...
|
|
|
|
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(); // ... and bail out if operation didn't work out
|
|
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) // nothing 2 do
|
|
{
|
|
WARNING_LOG(m_logger) << "replay stop requested, but no replay active in this context";
|
|
return;
|
|
}
|
|
|
|
disableAllReplayButtons(); // prevent the user from clicking again while waiting ...
|
|
|
|
ChangeReplayStateRequest req;
|
|
req.id(m_id);
|
|
req.replayPartitionId(m_partitionId);
|
|
req.state(SrpState::Stopped);
|
|
|
|
// since this may potentially take some time, disable user interaction which may delete this widget for now
|
|
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(); // ... and bail out if operation didn't work out
|
|
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(); // prevent the user from clicking again while waiting ...
|
|
|
|
ChangeReplayStateRequest req;
|
|
req.id(m_id);
|
|
req.replayPartitionId(m_partitionId);
|
|
req.state(SrpState::Resumed);
|
|
req.beginTime(m_ui->dteStartTime->msecsSinceEpoch());
|
|
req.endTime(0); // infinite
|
|
req.pace(m_ui->slSpeed->value() / 10.);
|
|
|
|
if (!m_requestHelper->startSingleRequest([req, this]()
|
|
{
|
|
return m_ftc->changeReplayStateRequest(req, this);
|
|
}))
|
|
{
|
|
enaDisa(); // ... and bail out if operation didn't work out
|
|
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));
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief
|
|
* @details Executed if the user double clicked on the Event in list. Set the map settings and focus the event on the map if the marker is an situation marker ans has an valid position
|
|
* @param index
|
|
*/
|
|
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)
|
|
// && m_session->getForeignGuiInterface(fltBuildingComponentGuiIfc) // Nachtrag zu GUEZE-1769: since fltBuildingComponentIfc is optional:
|
|
)
|
|
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";
|
|
|
|
|
|
// set filter from marker
|
|
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
|
|
{
|
|
// this path will be taken if marker is created automatically (like CES)
|
|
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()));
|
|
}
|
|
}
|
|
|
|
|
|
// set map settings from marker
|
|
if (appFilter)
|
|
{
|
|
QByteArray mapSettings(QByteArray::fromRawData(marker.mapSettings().c_str(), marker.mapSettings().size()));
|
|
DEBUG_LOG(m_logger) << "set map settings from marker " << (mapSettings.toStdString());
|
|
|
|
// Layer EmergencyCall should not be modified.
|
|
// So remove from data to be restored:
|
|
SituationMap::OperatorMapSettings oms;
|
|
oms.fromJson(mapSettings);
|
|
DEBUG_LOG(m_logger) << ">>>> oms.orderedLayers.size() " << oms.orderedLayers.size();
|
|
|
|
static const QLatin1String LayerNameEmergencyCall("EmergencyCall");
|
|
// remove entry: (EmergencyCall ist most likely at the end)
|
|
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);
|
|
|
|
// write back:
|
|
mapSettings = oms.toJson();
|
|
|
|
// apply: oms.orderedLayers.end()
|
|
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); // otherwise 'valueChanged' would do another request
|
|
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);
|
|
|
|
/*DEBUG*/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;
|
|
/*DEBUG*/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(); // ... bail (startReplay does a disableAllButtons(..))
|
|
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 /* infinite */, speed);
|
|
}
|
|
|
|
|
|
void SituationReplayControlWidget::onStopReplay() // TODO: InterfaceImpl::startReplay needs this method to check if there is currently a replay running!!
|
|
{
|
|
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)) // nothing 2 do
|
|
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;
|
|
}
|
|
|
|
} // namespace SituationReplay
|