1056 lines
42 KiB
C++
Executable File
1056 lines
42 KiB
C++
Executable File
/**
|
||
* @RDE_HEADER@
|
||
* HMI Plugin for ExerciseManangement - Exercise Overview Dialog
|
||
* $Id$
|
||
* $HeadURL$
|
||
* $Author$
|
||
* Created by Christian Ehrlicher, SLSE, 2016-02-29
|
||
*/
|
||
|
||
|
||
#include "snapshot_dialog.h"
|
||
#include "ui_snapshot_dialog.h"
|
||
|
||
#include "snapshot_dialog_model.h"
|
||
#include "mrk_create_snapshot.h"
|
||
|
||
#include <LtsUtilsCore/dds_vector.h>
|
||
#include <LtsUtilsCore/dds_vector_to_pixmap.h>
|
||
#include <LtsSession/lts_session_data.h>
|
||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||
#include <LtsAppManager/lts_app_manager.h>
|
||
#include <LtsPrinting/printing.h>
|
||
|
||
#include <Plugins/PlanEditor/PlanEditorPlugin/plan_editor_gui_plugin_interface.h>
|
||
#include <Plugins/MarkerManagement/Gui/Common/mrk_apply_filter.h>
|
||
|
||
// PlanOverlay
|
||
#include <Plugins/PlanOverlays/plan_overlays_plugin_interface.h>
|
||
|
||
#include <Services/PlanEditor/ped_operator_rights.h>
|
||
#include <FilterManagement/flt_data_plugin_aes_display_filter.h>
|
||
#include <Map/operator_map_settings.h>
|
||
|
||
#include <QImage>
|
||
#include <QJsonDocument>
|
||
#include <QJsonObject>
|
||
#include <QJsonParseError>
|
||
#include <QTimer>
|
||
|
||
#include <ngltools/ngltools_dtg.h>
|
||
|
||
namespace MarkerManagement
|
||
{
|
||
const int snapShotOverlayId = -4711;
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
// SnapshotDialog
|
||
//-----------------------------------------------------------------------------------------------------
|
||
SnapshotDialog::SnapshotDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
|
||
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
|
||
, m_menuGroup(menuGroup)
|
||
, m_model(nullptr)
|
||
, m_ui(new Ui::SnapshotDialog)
|
||
, m_session(session)
|
||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||
, m_planEditorHasUpdatedThePlan(false)
|
||
, m_planEditorApp(nullptr)
|
||
, m_fileId(-1)
|
||
, m_logger(getLogger("SnapshotDialog"))
|
||
{
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||
m_ui->setupUi(this);
|
||
|
||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Show,
|
||
this, &SnapshotDialog::onShow);
|
||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit,
|
||
this, &SnapshotDialog::onEditMetaData);
|
||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove,
|
||
this, &SnapshotDialog::onRemoveSnapshots);
|
||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Save,
|
||
this, &SnapshotDialog::onSaveSettings);
|
||
|
||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Load,
|
||
this, &SnapshotDialog::onEditPlan);
|
||
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print,
|
||
this, &SnapshotDialog::onPrint);
|
||
|
||
//m_buttonBox->getButton(LtsWidgets::DialogButton::Save)->setEnabled(false);
|
||
m_buttonBox->getButton(LtsWidgets::DialogButton::Save)->setText(tr("Save Settings"));
|
||
|
||
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setText(tr("Edit Plan"));
|
||
|
||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked,
|
||
this, &SnapshotDialog::onEditMetaData);
|
||
|
||
// connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
|
||
// this, &SnapshotDialog::onSelectionChanged);
|
||
|
||
setOnlineHelpFilename(QStringLiteral("Situation-Snapshots"));
|
||
m_ui->widget->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
|
||
session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui);
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
SnapshotDialog::~SnapshotDialog()
|
||
{
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||
// plan editor app delete-flagged in aboutToClose
|
||
delete m_ui;
|
||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::retranslate()
|
||
{
|
||
translate(m_ui, tr("Snapshots"));
|
||
}
|
||
|
||
/*
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::onSelectionChanged()
|
||
{
|
||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||
const MarkerManagement::Snapshot & snapshot = m_model->getRowData(idx.row());
|
||
|
||
if (snapshot.id() != m_currentSnapshot.id())
|
||
{
|
||
m_buttonBox->getButton(LtsWidgets::DialogButton::Save)->setEnabled(false);
|
||
}
|
||
}
|
||
*/
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::onShow()
|
||
{
|
||
const QModelIndex &idx = m_ui->widget->currentIndex();
|
||
const MarkerManagement::Snapshot &snapshot = m_model->getRowData(idx.row());
|
||
|
||
if (snapshot.id() <= 0)
|
||
return;
|
||
|
||
m_currentSnapshot = snapshot; // fileContendId is the fileId of previewImage
|
||
|
||
showSnapshot();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::onRefreshCurrent(const Snapshot &snapshot)
|
||
{
|
||
INFO_LOG(m_logger) << LOGFUNCTION << " current SnapshotId: " << snapshot.id();
|
||
|
||
// show Snapshot only if current snapshot changed from outside
|
||
if (snapshot.id() != m_currentSnapshot.id())
|
||
return;
|
||
|
||
m_currentSnapshot = snapshot;
|
||
showSnapshotInternal(m_currentSnapshot, false); // applyFilter
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::showSnapshot()
|
||
{
|
||
INFO_LOG(m_logger) << LOGFUNCTION << " current SnapshotId: " << m_currentSnapshot.id();
|
||
showSnapshotInternal(m_currentSnapshot, true); // applyFilter
|
||
|
||
enaDisa();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
bool SnapshotDialog::applyFilter(const Snapshot &snapshot)
|
||
{
|
||
const QByteArray filterContent(QByteArray::fromRawData(snapshot.filter().c_str(), snapshot.filter().size()));
|
||
|
||
if (filterContent.isEmpty())
|
||
{
|
||
ERROR_LOG(m_logger) << "filterContent is empty, snapshot.id()="<< snapshot.id();
|
||
return false;
|
||
}
|
||
|
||
// 1) shortcut for our session/widget:
|
||
MarkerManagementApplyFilter appFilter(m_session, m_fltParticipantIfc, m_fltAesIfc, m_fltBuildingComponentIfc);
|
||
|
||
if (!appFilter.applyFilter(filterContent))
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " Error while applying filters";
|
||
return false;
|
||
}
|
||
|
||
// 2) shortcut for session/widget of PlanEditor :
|
||
// but only if snapshot.id and PlanEditor.m_currentSnapshot.id match:
|
||
if (m_planEditorApp && (m_currentSnapshot.id() == snapshot.id()))
|
||
{
|
||
const int partitionId = m_session->partitionId();
|
||
auto pe_session = m_planEditorApp->getSession(IDL::PartitionType::Replay, partitionId);
|
||
if (pe_session)
|
||
{
|
||
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> pe_fltParticipantIfc;
|
||
std::shared_ptr<FilterManagement::ForeignAesGuiInterface> pe_fltAesIfc;
|
||
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> pe_fltBuildingComponentIfc;
|
||
pe_session->getForeignGuiInterface<FilterManagement::ForeignFltParticipantGuiInterface>(pe_fltParticipantIfc); // not in global
|
||
pe_session->getForeignGuiInterface<FilterManagement::ForeignAesGuiInterface>(pe_fltAesIfc); // not in global
|
||
pe_session->getForeignGuiInterface<FilterManagement::ForeignFltBuildingComponentGuiInterface>(pe_fltBuildingComponentIfc); // not in global
|
||
if (pe_fltParticipantIfc && pe_fltAesIfc)
|
||
{
|
||
MarkerManagementApplyFilter appFilter2(pe_session, pe_fltParticipantIfc, pe_fltAesIfc, pe_fltBuildingComponentIfc);
|
||
if (!appFilter2.applyFilter(filterContent))
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << "Error while applying filters";
|
||
return false;
|
||
}
|
||
} else
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << "getForeignGuiInterface failed";
|
||
} else
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << "Internal error - can not get previously created session!";
|
||
}
|
||
// : shortcut for session/widget of PlanEditor
|
||
|
||
return true;
|
||
}
|
||
|
||
void SnapshotDialog::tableColumnOrganiserSetting()
|
||
{
|
||
//LtsColumnOrganiser
|
||
m_ui->widget->setColumnsOrganiserEnabled(identifier(), true);
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
bool SnapshotDialog::showSnapshotInternal(const Snapshot &snapshot, bool bApplyFilter)
|
||
{
|
||
auto spSitMapGuiIfc = m_sitMapGuiIfc.lock();
|
||
SituationMap::SitMapUpdatesEnabledHelper sitMapHelper(spSitMapGuiIfc);
|
||
|
||
const int partitionId = m_session->partitionId();
|
||
INFO_LOG(m_logger) << LOGFUNCTION << " current Snapshot: " << snapshot
|
||
<< ", replayPartition: " << partitionId
|
||
<< ", applyFilter=" << bApplyFilter;
|
||
|
||
SituationReplay::ChangeReplayStateRequest req;
|
||
req.id(0);
|
||
req.replayPartitionId(partitionId);
|
||
req.state(SituationReplay::SrpState::Started);
|
||
req.beginTime(snapshot.timeStamp());
|
||
req.endTime(snapshot.timeStamp()); // snapshot
|
||
req.pace(0);
|
||
|
||
if (!m_requestHelper->startSingleRequest([req, this]() { return m_srpFtc->changeReplayStateRequest(req, this); }))
|
||
{
|
||
ERROR_LOG(m_logger) << "Replay could not be started for partition id = " << partitionId;
|
||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Replay could not be started for partition with id %1").arg(partitionId));
|
||
return false;
|
||
}
|
||
|
||
bool success = true;
|
||
|
||
// Filter:
|
||
if (bApplyFilter)
|
||
if (!applyFilter(snapshot))
|
||
{
|
||
ERROR_LOG(m_logger) << "applyFilter failed, partition id = " << partitionId;
|
||
success = false;
|
||
}
|
||
|
||
if (spSitMapGuiIfc)
|
||
{
|
||
|
||
std::shared_ptr<PlanOverlaysPlugin::ForeignGuiInterface> ovrDtc;
|
||
if (m_session->getForeignGuiInterface<PlanOverlaysPlugin::ForeignGuiInterface>(ovrDtc))
|
||
{
|
||
INFO_LOG(m_logger) << LOGFUNCTION << " unloadAllPlans via PlanOverlaysPlugin to update dialog";
|
||
ovrDtc->unloadAllPlans();
|
||
}
|
||
|
||
// SitMapForeignInterface => set Settings
|
||
{
|
||
const QByteArray ba(QByteArray::fromRawData(snapshot.mapSettings().c_str(), snapshot.mapSettings().size()));
|
||
spSitMapGuiIfc->setOperatorMapSettingsJson(ba);
|
||
|
||
const QByteArray planOverlay(snapshot.planOverlay().c_str(), snapshot.planOverlay().size());
|
||
if (!planOverlay.isEmpty())
|
||
{
|
||
// this is editable Plan/Overlay of snapshot:
|
||
{
|
||
const bool bIsMapReady = spSitMapGuiIfc->isMapReady();
|
||
INFO_LOG(m_logger) << LOGFUNCTION << " bIsMapReady = " << bIsMapReady;
|
||
|
||
if (bIsMapReady)
|
||
{
|
||
if (!spSitMapGuiIfc->planOverlaySetContent(snapShotOverlayId, tr("Snapshot-PlanOverlay"), planOverlay, true))
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " Error add planOverlay to snapshot, SnapshotId: " << snapshot.id()
|
||
<< " planOverlay.size()=" << planOverlay.size()
|
||
<< " planOverlay=" << planOverlay;
|
||
success = false;
|
||
}
|
||
} else {
|
||
// GUEZE-811 3D Lage Filter werde nicht korrekt abgebaut... wenn 2D-Snap
|
||
// mit SnapshotPlan auf 3D-Topic folgt...
|
||
// Szenario: 2D-Snapshuss wird wiedergegeben (App Snapshot|Script)
|
||
// und SitMap muss dafür von 3D auf 2D wechseln.
|
||
// Dabei werden die Overlays via MapOperatorSettings zunächst vorbereitet.
|
||
// Dabei wurde aber in MapImpl::restoreOperatorMapSettings der SNAPSHOT-Overlay
|
||
// als herkömmlicher Overlay vorbereitet.
|
||
// Beim nachfolgendem OverlayHandlerImpl::setOverlay usw. ergaben sich Fehler
|
||
// wg. LayerType::SnapshotOverlay vs. LayerType::Overlay.
|
||
// Mit dem FixPart1 wird in restoreOperatorMapSettings der snapShotOverlayId == -4711
|
||
// als isSnapshot==true eintragen.
|
||
// Mit FixPart2 bei SnapshotDialog::showSnapshotInternal ein
|
||
// setMapReadyCallback genutzt, weil die SitMap noch nicht mapReady ist.
|
||
// Mit FixPart3 bei InterfaceImpl::snapshotAdjustSitMap ebenfalls ein
|
||
// setMapReadyCallback genutzt, weil die SitMap noch nicht mapReady ist.
|
||
|
||
// dirty hack: try again
|
||
// QTimer::singleShot(1000, this, [this, snapshot, bApplyFilter]() {
|
||
// showSnapshotInternal(snapshot, bApplyFilter);
|
||
// });
|
||
|
||
// QTimer::singleShot(1000, this, [this, spSitMapGuiIfc, snapShotOverlayId, planOverlay, snapshot]() {
|
||
// if (!spSitMapGuiIfc->planOverlaySetContent(snapShotOverlayId, tr("Snapshot-PlanOverlay"), planOverlay, true))
|
||
// {
|
||
// ERROR_LOG(m_logger) << LOGFUNCTION << " Error add planOverlay to snapshot, SnapshotId: " << snapshot.id()
|
||
// << " planOverlay.size()=" << planOverlay.size()
|
||
// << " planOverlay=" << planOverlay;
|
||
// }
|
||
// });
|
||
|
||
const int snapshotId = snapshot.id();
|
||
auto onMapIsReadyFn = [this, spSitMapGuiIfc, planOverlay, snapshotId]() {
|
||
INFO_LOG(m_logger) << LOGFUNCTION << " try again: do planOverlaySetContent...";
|
||
if (!spSitMapGuiIfc->planOverlaySetContent(snapShotOverlayId, tr("Snapshot-PlanOverlay"), planOverlay, true))
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " Error add planOverlay to snapshot, SnapshotId: " << snapshotId
|
||
<< " planOverlay.size()=" << planOverlay.size()
|
||
<< " planOverlay=" << planOverlay;
|
||
}
|
||
};
|
||
if (!spSitMapGuiIfc->setMapReadyCallback(this, onMapIsReadyFn))
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << ", setMapReadyCallback failed, SnapshotId: " << snapshotId;
|
||
|
||
}
|
||
} // : this is editable Plan/Overlay of snapshot
|
||
|
||
}
|
||
}
|
||
|
||
// SitMapForeignInterface => restore MovementTracks
|
||
{
|
||
const QByteArray ba(QByteArray::fromRawData(snapshot.movementTracks().c_str(), snapshot.movementTracks().size()));
|
||
if (!spSitMapGuiIfc->setMovementTrackManagerSettingsJSon(ba))
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " Error setMovementTrackManagerSettingsJSon, SnapshotId: " << snapshot.id();
|
||
success = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
QString name = tr("Snapshot '%1'").arg(QString::fromStdString(m_currentSnapshot.name()));
|
||
m_session->baseLayout()->setCustomText(name);
|
||
spSitMapGuiIfc->showExerciseTimeString(true);
|
||
return success;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::onEditPlan()
|
||
{
|
||
// the user-selected snapshot should be displayed in the viewer while the according plan is loaded by the planEditor:
|
||
// (but don´t reload if already loaded to not discard changes to center and scale)
|
||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||
const MarkerManagement::Snapshot &snapshot = m_model->getRowData(idx.row());
|
||
|
||
// show snapshot if necessary
|
||
// another than the current is requested to be modified with planEditor
|
||
if (snapshot.id() != m_currentSnapshot.id())
|
||
onShow();
|
||
|
||
if (m_currentSnapshot.id() <= 0)
|
||
return;
|
||
|
||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
* ToDo: showing message like the following
|
||
*
|
||
* const QString & msg = tr("Launching PlanEditor to edit snapshot plan. Saving the plan to snap shot will be done automatically at finish of planeditor.");
|
||
*
|
||
* LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Launching PlanEditor"), LtsWidgets::Behaviour::Popup );
|
||
*
|
||
* with the difference that the message should be shown only for a short time interval and will be removed from screen without any user interaction.
|
||
* Eventually it would be nice to add the name of snapshot to the message.
|
||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||
|
||
// Keep in mind operator rights of plan editor here. Has the user the required rights to start the plan editor?
|
||
|
||
if (!LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::PlanEditor::TacticalPlansEditSnapShot))
|
||
{
|
||
QString msg = tr("Operator right to launching Plan Editor to edit snapshot plans is missing");
|
||
LtsWidgets::LtsMessageDialog::showMessage(this, msg, tr("Launching Plan Editor is forbidden"), LtsWidgets::Behaviour::Popup );
|
||
return;
|
||
}
|
||
|
||
m_planEditorHasUpdatedThePlan = false;
|
||
|
||
LtsSession::DdsConnectionParams connParams(m_session->connParams());
|
||
m_planEditorApp = LtsAppManager::LtsAppManager::getInstance()->createApp(LtsAppDescriptor::App::PlanEditor, connParams);
|
||
if (!m_planEditorApp)
|
||
{
|
||
// In case of failure createApp will show an error message
|
||
ERROR_LOG(m_logger) << "Creating Plan Editor-Snapshot failed.";
|
||
return;
|
||
}
|
||
|
||
// (re-) enable btn 'start PlanEditor' if planEditor is finished
|
||
// QueuedConnection since this signal is fired during the destruction process and
|
||
// onPlaneditorFinished creates a new local eventloop...
|
||
connect(m_planEditorApp.data(), &QObject::destroyed, this, &SnapshotDialog::onPlaneditorFinished, Qt::QueuedConnection);
|
||
|
||
LtsSession::LtsSession *session = m_planEditorApp->getSession(IDL::PartitionType::Replay, connParams.partitionId);
|
||
session->presetBaseLayoutAsSecondaryWidget(); // see https://devhub.defence-elec.de/confluence/x/yLjeDg 13.1
|
||
// session->setDependency(m_session); // prevents mmm to let that secondary widget be placed above this app => jetzt doch: GUEZE-2619
|
||
|
||
if (session->isInitializationDone())
|
||
slotReplaySessionForPlanEditorStarted();
|
||
else
|
||
connect(session, &LtsSession::LtsSession::signalDoneInitializingSession,
|
||
this, &SnapshotDialog::slotReplaySessionForPlanEditorStarted); // wait until the new replay session is initialized
|
||
|
||
enaDisa();
|
||
}
|
||
|
||
void SnapshotDialog::onPlaneditorFinished()
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " onPlaneditorFinished"
|
||
<< " m_planEditorHasUpdatedThePlan=" << m_planEditorHasUpdatedThePlan;
|
||
|
||
// User has has saved the Plan for snapshot before PE is finished.
|
||
// Due to onRefreshCurrent the data is updated. (and ReplayStartRequested)
|
||
// So an additional showSnapshot will cause an additonal ReplayStartRequested
|
||
// The ReplayProcess doesn´t like to requests with such a small amount of time (~300ms)
|
||
// so skip showSnapshot here:
|
||
// showSnapshot();
|
||
|
||
if (m_planEditorHasUpdatedThePlan)
|
||
{
|
||
const QString &title = QString::fromStdString(m_currentSnapshot.name());
|
||
saveSnapshotPreviewInLibrary(title);
|
||
}
|
||
|
||
enaDisa();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::slotReplaySessionForPlanEditorStarted()
|
||
{
|
||
const int partitionId = m_session->partitionId();
|
||
auto session = m_planEditorApp->getSession(IDL::PartitionType::Replay, partitionId);
|
||
if (!session)
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " Internal error - can not get previously created session!";
|
||
return;
|
||
}
|
||
|
||
disconnect(session, &LtsSession::LtsSession::signalDoneInitializingSession,
|
||
this, nullptr);
|
||
|
||
if (!m_planEditorApp)
|
||
return;
|
||
if (!m_srpFtc)
|
||
return;
|
||
|
||
std::shared_ptr<SituationMap::ForeignGuiInterface> sitMapGuiIfc;
|
||
std::shared_ptr<PlanEditorPlugin::ForeignGuiInterface> planEditorIfc;
|
||
|
||
session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(sitMapGuiIfc);
|
||
session->getForeignGuiInterface<PlanEditorPlugin::ForeignGuiInterface>(planEditorIfc);
|
||
if (!sitMapGuiIfc || !planEditorIfc)
|
||
{
|
||
WARNING_LOG(m_logger) << "Can not create plan editor app - found not all required interfaces";
|
||
m_planEditorApp->deleteLater();
|
||
m_planEditorApp = nullptr;
|
||
return;
|
||
}
|
||
|
||
|
||
// get Settings from SitMap => SitMapForeignInterface
|
||
|
||
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " current SnapshotId: " << m_currentSnapshot.id()
|
||
<< ", PlanEditor - partitionId = " << partitionId;
|
||
|
||
SituationReplay::ChangeReplayStateRequest req;
|
||
req.id(0);
|
||
req.replayPartitionId(partitionId);
|
||
req.state(SituationReplay::SrpState::Started);
|
||
req.beginTime(m_currentSnapshot.timeStamp());
|
||
req.endTime(m_currentSnapshot.timeStamp());
|
||
req.pace(0);
|
||
|
||
if (!m_requestHelper->startSingleRequest([req, this]() { return m_srpFtc->changeReplayStateRequest(req, this); }))
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " Replay could not be started for partition id = " << partitionId;
|
||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Replay could not be started for partition with id %1").arg(partitionId));
|
||
m_planEditorApp->deleteLater();
|
||
return;
|
||
}
|
||
|
||
#define PlanEditorForSnapshot3D
|
||
#ifdef PlanEditorForSnapshot3D
|
||
{
|
||
const QByteArray ba(QByteArray::fromRawData(m_currentSnapshot.mapSettings().c_str(), m_currentSnapshot.mapSettings().size()));
|
||
|
||
QJsonParseError parserError;
|
||
const QJsonDocument jDoc(QJsonDocument::fromJson(ba, &parserError));
|
||
if (parserError.error != QJsonParseError::NoError)
|
||
{
|
||
ERROR_LOG(m_logger) << "Error parsing json document: " << parserError.errorString();
|
||
return;
|
||
}
|
||
|
||
SituationMap::OperatorMapSettings oms;
|
||
oms.fromJsonObject(jDoc.object());
|
||
|
||
if (oms.mode == SituationMap::Mode::Mode_3D)
|
||
{
|
||
DEBUG_LOG(m_logger) << " PlanEditor in 3D not supported yet, use 2D";
|
||
oms.mode = SituationMap::Mode::Mode_2D;
|
||
sitMapGuiIfc->setOperatorMapSettingsJson(oms.toJson()); // SitMapForeignInterface => set Settings
|
||
} else {
|
||
sitMapGuiIfc->setOperatorMapSettingsJson(ba); // SitMapForeignInterface => set Settings
|
||
}
|
||
}
|
||
#else
|
||
const QByteArray ba(QByteArray::fromRawData(m_currentSnapshot.mapSettings().c_str(), m_currentSnapshot.mapSettings().size()));
|
||
sitMapGuiIfc->setOperatorMapSettingsJson(ba); // SitMapForeignInterface => set Settings
|
||
#endif // PlanEditorForSnapshot3D
|
||
|
||
|
||
applyFilter(m_currentSnapshot);
|
||
|
||
planEditorIfc->setPlanToEdit( QByteArray::fromStdString(m_currentSnapshot.planOverlay()) ); // read plan from snapshot
|
||
|
||
planEditorIfc->addSaveSnapshotAction(QIcon(), tr("Save Plan to Snapshot"), [this](const QByteArray & planXMLContent) -> bool
|
||
{
|
||
return saveSnapshotPlan(planXMLContent);
|
||
});
|
||
|
||
|
||
|
||
|
||
// const QByteArray filterContent(QByteArray::fromRawData(snapshot.filter().c_str(), snapshot.filter().size()));
|
||
// if (filterContent.isEmpty())
|
||
// ERROR_LOG(m_logger) << "filterContent is empty, snapshot.id()="<< snapshot.id();
|
||
|
||
// std::shared_ptr<FilterManagement::ForeignAesGuiInterface> pe_fltIfc;
|
||
// session->getForeignGuiInterface<FilterManagement::ForeignAesGuiInterface>(pe_fltIfc); // not in global
|
||
// if (pe_fltIfc)
|
||
// {
|
||
// MarkerManagementApplyFilter appFilter(session, pe_fltIfc);
|
||
// if (!appFilter.applyFilter(filterContent))
|
||
// {
|
||
// ERROR_LOG(m_logger) << LOGFUNCTION << " Error while applying filters";
|
||
// }
|
||
// } else
|
||
// ERROR_LOG(m_logger) << LOGFUNCTION << " getForeignGuiInterface failed";
|
||
|
||
|
||
m_buttonBox->getButton(LtsWidgets::DialogButton::Load)->setEnabled(false); // start PlanEditor only once
|
||
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::prepareIndex(const QModelIndex &idx)
|
||
{
|
||
const MarkerManagement::Snapshot &snapshot = m_model->getRowData(idx.row());
|
||
|
||
DEBUG_LOG(m_logger) << "Prepare index for snapshot with id = " << snapshot.id();
|
||
|
||
const int fileId = snapshot.fileContentId();
|
||
if (fileId > 0) // found the snapshot in db
|
||
{
|
||
DEBUG_LOG(m_logger) << "Loading file content with id = " << fileId;
|
||
|
||
QByteArray content;
|
||
if (m_flmGui->loadContent(fileId, content) && content.size() > 0)
|
||
{
|
||
QString timeStr = DTG::toStringMSec(snapshot.timeStamp());
|
||
|
||
QString name = QString::fromStdString(snapshot.name());
|
||
m_descriptions.append( QString::fromStdString(snapshot.description()));
|
||
m_imageTitles.append( name + QStringLiteral(" (")+ timeStr + QStringLiteral(")"));
|
||
m_images.append(QImage::fromData(content));
|
||
|
||
DEBUG_LOG(m_logger) << " title=" << m_imageTitles.last()
|
||
<< " description=" << m_descriptions.last()
|
||
<< " content.size=" << content.size();
|
||
}
|
||
else
|
||
{
|
||
ERROR_LOG(m_logger) << "Cannot retrieve file content for fileId = " << fileId;
|
||
}
|
||
}
|
||
else
|
||
WARNING_LOG(m_logger) << "Not found: file id = 0 for snapshot id = " << snapshot.id();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::onPrint()
|
||
{
|
||
const QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||
m_descriptions.clear();
|
||
m_imageTitles.clear();
|
||
m_images.clear();
|
||
|
||
DEBUG_LOG(m_logger) << "selectedRows.size()=" << selectedRows.size();
|
||
for (const QModelIndex &idx : selectedRows)
|
||
prepareIndex(idx);
|
||
|
||
if (m_images.size() > 0)
|
||
LtsPrinting::printImages(m_session, this, tr("Snapshots"), m_images, m_imageTitles, m_descriptions);
|
||
else
|
||
ERROR_LOG(m_logger) << "No snapshots selected or no valid images to print";
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
bool SnapshotDialog::saveSnapshotPlan(const QByteArray &planXMLContent)
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " save snapshot";
|
||
|
||
// store planXMLContent in snapshot
|
||
m_currentSnapshot.planOverlay(planXMLContent.constData());
|
||
|
||
bool ok = m_requestHelper->startSingleRequest([this]()
|
||
{
|
||
return m_mrkFtc->snapshotModifyRequest(m_currentSnapshot,this);
|
||
});
|
||
|
||
if (!ok)
|
||
{
|
||
ERROR_LOG(m_logger) << "Error while updating snapshot plan overlay";
|
||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Error while updating snapshot plan overlay"), tr("Saving Plan to Snapshot") );
|
||
}
|
||
else
|
||
{
|
||
m_planEditorHasUpdatedThePlan = true;
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
bool SnapshotDialog::init(const std::shared_ptr<MarkerManagement::Interface::Dtc> &mrkDtc,
|
||
const std::shared_ptr<MarkerManagement::Interface::Ftc> &mrkFtc,
|
||
const std::shared_ptr<FileManagement::Interface::Dtc> &flmDtc,
|
||
const std::shared_ptr<FileManagement::Interface::Ftc> &flmFtc,
|
||
const std::shared_ptr<OperatorManagement::Interface::Dtc> &opmDtc,
|
||
const std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> &fltParticipipantIfc,
|
||
const std::shared_ptr<FilterManagement::ForeignAesGuiInterface> &fltAesIfc,
|
||
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> &fltBuildingComponentIfc
|
||
)
|
||
{
|
||
m_mrkDtc = mrkDtc;
|
||
m_mrkFtc = mrkFtc;
|
||
m_flmDtc = flmDtc;
|
||
m_flmFtc = flmFtc;
|
||
m_opmDtc = opmDtc;
|
||
m_fltParticipantIfc = fltParticipipantIfc;
|
||
m_fltAesIfc = fltAesIfc;
|
||
m_fltBuildingComponentIfc = fltBuildingComponentIfc;
|
||
|
||
|
||
m_model = new SnapshotDialogModel(this);
|
||
m_model->initModel(m_mrkDtc, m_opmDtc, m_flmDtc, m_flmGui);
|
||
auto proxy = new SnapshotDialogFilterProxyModel(this);
|
||
proxy->setSourceModel(m_model);
|
||
m_ui->widget->setModel(proxy);
|
||
m_ui->widget->hideColumn(SnapshotDialogModel::Columns::ColImage);
|
||
m_ui->widget->setInitialSearchContent(SnapshotDialogModel::ColOperator,
|
||
LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
|
||
|
||
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
|
||
this, &SnapshotDialog::enaDisa);
|
||
connect(m_model, &SnapshotDialogModel::modelChanged,
|
||
this, &SnapshotDialog::onRefreshCurrent);
|
||
|
||
m_session->getFtc<SituationReplay::DataInterface>(m_srpFtc);
|
||
if (!m_srpFtc)
|
||
return false;
|
||
|
||
std::shared_ptr<SituationMap::ForeignGuiInterface> spSitMapGuiIfc;
|
||
m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(spSitMapGuiIfc);
|
||
if (!spSitMapGuiIfc)
|
||
return false;
|
||
m_sitMapGuiIfc = spSitMapGuiIfc;
|
||
|
||
// pay attention to mapReady:
|
||
// A small delay is required. Otherwise SituationMapInit does not exists:
|
||
QTimer::singleShot(1000, this, [this, spSitMapGuiIfc]() {
|
||
if (!spSitMapGuiIfc->setMapReadyCallback(this, [this]() { enaDisa(); }))
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " setMapReadyCallback failed"
|
||
<< ", m_session->toString " << m_session->toString()
|
||
<< ", this=" << this;
|
||
});
|
||
|
||
enaDisa();
|
||
|
||
return true;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::aboutToClose()
|
||
{
|
||
DEBUG_LOG(m_logger) << "aboutToClose - start";
|
||
if (m_planEditorApp)
|
||
{
|
||
m_planEditorApp->disconnect(this); // disconnect me from m_planEditorApp
|
||
//We get the session and "close the baseLayout" which will result in a perfect cleanup of the PlanEditor
|
||
const int partitionId = m_session->partitionId();
|
||
auto pe_session = m_planEditorApp->getSession(IDL::PartitionType::Replay, partitionId);
|
||
if (pe_session)
|
||
{
|
||
pe_session->baseLayout()->close();
|
||
}
|
||
m_planEditorApp->deleteLater();
|
||
}
|
||
m_planEditorApp = nullptr;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::enaDisa()
|
||
{
|
||
m_buttonBox->setToolTip(LtsWidgets::DialogButton::Load, QString());
|
||
|
||
// do not change selected row, if PlanEditor is running.
|
||
m_ui->widget->setEnabled(m_planEditorApp.isNull());
|
||
|
||
QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||
const int cntSelectedRows = selectedRows.size();
|
||
|
||
// BTN Edit
|
||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, (cntSelectedRows == 1));
|
||
// BTN Remove
|
||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, (cntSelectedRows > 0));
|
||
// BTN Print
|
||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Print, (cntSelectedRows > 0));
|
||
|
||
// BTN Save (Save Settings)
|
||
{
|
||
const QModelIndex &idx = m_ui->widget->currentIndex();
|
||
const MarkerManagement::Snapshot &userSelSnapshot = m_model->getRowData(idx.row());
|
||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Save, (m_currentSnapshot.id() > 0) && (userSelSnapshot.id() == m_currentSnapshot.id()));
|
||
}
|
||
|
||
|
||
// show btn:
|
||
bool mapReady = false;
|
||
bool snapshotIn2D = false;
|
||
auto spSitMapGuiIfc = m_sitMapGuiIfc.lock();
|
||
if (spSitMapGuiIfc != nullptr)
|
||
mapReady = spSitMapGuiIfc->isMapReady();
|
||
|
||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||
const MarkerManagement::Snapshot &snapshot = m_model->getRowData(idx.row());
|
||
|
||
QJsonParseError error;
|
||
QJsonDocument doc(QJsonDocument::fromJson(QByteArray::fromRawData(snapshot.mapSettings().c_str(),
|
||
snapshot.mapSettings().size()), &error));
|
||
|
||
if (error.error == QJsonParseError::NoError)
|
||
{
|
||
QJsonObject root(doc.object());
|
||
const int mode = root[QStringLiteral("mode")].toInt(-1);
|
||
snapshotIn2D = (mode == int(SituationMap::MapMode::MapMode_2D));
|
||
}
|
||
|
||
QStringList errors;
|
||
if (cntSelectedRows != 1)
|
||
errors += tr("Select one snapshot to edit");
|
||
if (!spSitMapGuiIfc)
|
||
errors += tr("Map interface missing");
|
||
if (m_planEditorApp)
|
||
errors += tr("Plan editor already open");
|
||
if (error.error != QJsonParseError::NoError)
|
||
errors += tr("Snapshot is missing critical map informations");
|
||
if (!snapshotIn2D)
|
||
errors += tr("Unable to edit a snapshot that was taken in 3D mode - edit the snapshot and save it while in 2D mode");
|
||
if (!mapReady)
|
||
errors += tr("Situation isn't ready yet. Please try again later.");
|
||
|
||
m_buttonBox->setToolTip(LtsWidgets::DialogButton::Load, errors.join(QStringLiteral("<br />")));
|
||
|
||
// BTN Show
|
||
bool bSelectedSnapshotActuallyInEditor = true;
|
||
if (m_planEditorApp)
|
||
bSelectedSnapshotActuallyInEditor = snapshot.id() == m_currentSnapshot.id();
|
||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Show, (cntSelectedRows == 1) && mapReady && bSelectedSnapshotActuallyInEditor);
|
||
|
||
// BTN Load (Edit Plan)
|
||
const bool bHasPlanEditor =
|
||
LtsSessionData::LtsSessionData::getInstance()->hasOperatorRight(OperatorRights::PlanEditor::TacticalPlansEditSnapShot) &&
|
||
LtsAppManager::LtsAppManager::getInstance()->hasApp(LtsAppDescriptor::App::PlanEditor);
|
||
m_buttonBox->setButtonVisible(LtsWidgets::DialogButton::Load, bHasPlanEditor);
|
||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Load, (cntSelectedRows == 1) && mapReady && m_planEditorApp.isNull() /*&& snapshotIn2D*/);
|
||
|
||
// BTN Remove
|
||
const QVector<int> &selectedSnapIds = selectedSnapshotIds();
|
||
if (selectedSnapIds.isEmpty())
|
||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, false);
|
||
else
|
||
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, !selectedSnapIds.contains(m_currentSnapshot.id()));
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::onEditMetaData()
|
||
{
|
||
const QModelIndex idx = m_ui->widget->currentIndex();
|
||
const MarkerManagement::Snapshot snapshot = m_model->getRowData(idx.row());
|
||
|
||
if (snapshot.id() <= 0)
|
||
return;
|
||
|
||
INFO_LOG(m_logger) << "current SnapshotId: " << snapshot.id();
|
||
|
||
if (snapshot.operatorId() == LtsSessionData::LtsSessionData::getInstance()->getOperatorId())
|
||
{ // If snapshot is owned by current operator
|
||
addDialog(LtsWidgets::initDialog(new SnapshotCreateDialog(this),
|
||
m_mrkFtc, m_flmDtc, m_flmFtc, m_sitMapGuiIfc, m_fltParticipantIfc, m_fltAesIfc, m_fltBuildingComponentIfc, m_session, snapshot),
|
||
m_menuGroup, QStringLiteral("EditSnapshot%1").arg(snapshot.id()));
|
||
}
|
||
else
|
||
{ // If snapshot belongs to an other operator
|
||
// Show message 'Want to copy?' then do nothing or copy
|
||
switch (LtsWidgets::LtsMessageDialog::showMessage(this,
|
||
tr("You are not allowed to edit the snapshots of other operators.\nDo you want to make a copy of it?"),
|
||
QString(),
|
||
LtsWidgets::Behaviour::Modal,
|
||
LtsWidgets::Button::Yes | LtsWidgets::Button::No))
|
||
{
|
||
case LtsWidgets::Button::No:
|
||
// Do nothing
|
||
break;
|
||
case LtsWidgets::Button::Yes:
|
||
// Make a new snap with old data
|
||
{
|
||
Snapshot req(snapshot);
|
||
req.id(0);
|
||
req.name((tr("Copy - %1").arg(QString::fromStdString(snapshot.name()))).toStdString());
|
||
req.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
|
||
req.fileContentId(0); //no preview image when copying a snapshot, later by edit metadata when we change the name, a new image will be saved
|
||
m_requestHelper->startSingleRequest([req, this]()
|
||
{
|
||
return m_mrkFtc->snapshotModifyRequest(req, this);
|
||
});
|
||
}
|
||
break;
|
||
default:
|
||
// Can't happen but satisfies the compiler
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
QVector<int> SnapshotDialog::selectedSnapshotIds() const
|
||
{
|
||
const QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||
|
||
QVector<int> selectedSnapshotIds;
|
||
selectedSnapshotIds.reserve(selectedRows.size());
|
||
|
||
for (const QModelIndex &idx : selectedRows)
|
||
{
|
||
if (!idx.isValid())
|
||
continue;
|
||
const MarkerManagement::Snapshot snapshot = m_model->getRowData(idx.row());
|
||
if (snapshot.id() <= 0)
|
||
continue;
|
||
selectedSnapshotIds.push_back(snapshot.id());
|
||
} // for
|
||
return selectedSnapshotIds;
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::onRemoveSnapshots()
|
||
{
|
||
const QModelIndexList selectedRows = m_ui->widget->selectedRows();
|
||
for (const QModelIndex &idx : selectedRows)
|
||
{
|
||
if (!idx.isValid())
|
||
continue;
|
||
const MarkerManagement::Snapshot &snapshot = m_model->getRowData(idx.row());
|
||
if (snapshot.id() <= 0)
|
||
continue;
|
||
Core::RemoveElementRequest req(snapshot.id());
|
||
m_requestHelper->addRequest([req, this]()
|
||
{
|
||
return m_mrkFtc->snapshotRemoveRequest(req, this);
|
||
});
|
||
if (snapshot.fileContentId() > 0)
|
||
{
|
||
Core::RemoveElementRequest req1(snapshot.fileContentId());
|
||
m_requestHelper->addRequest([req1, this]()
|
||
{
|
||
return m_flmFtc->fileContentRemoveRequest(req1, this);
|
||
});
|
||
}
|
||
}
|
||
m_requestHelper->startRequests();
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::saveSnapshotFilter()
|
||
{
|
||
// Save MapSetting Changes
|
||
auto spSitMapGuiIfc = m_sitMapGuiIfc.lock();
|
||
if (!spSitMapGuiIfc)
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << ", no m_sitMapGuiIfc, return";
|
||
return;
|
||
}
|
||
|
||
// Save Filter, Filter = {operatorMapSettings, AesFilter, SymbolAppearance, (possibly modified) MovementTracks}
|
||
|
||
// 1) operatorMapSettings/OMS
|
||
const QByteArray mapSettings = spSitMapGuiIfc->operatorMapSettingsJson();
|
||
Snapshot req(m_currentSnapshot);
|
||
req.mapSettings(mapSettings.data());
|
||
req.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
|
||
|
||
DEBUG_LOG(m_logger) << "File content id (of preview image) = " << m_currentSnapshot.fileContentId();
|
||
req.fileContentId(m_fileId);
|
||
|
||
// 2,3) AesFilter, SymbolAppearance, BuildingComponents
|
||
MarkerManagementApplyFilter appFilter(m_session, m_fltParticipantIfc, m_fltAesIfc, m_fltBuildingComponentIfc);
|
||
const QByteArray &filterParams = appFilter.getFilterParams();
|
||
req.filter(filterParams.constData());
|
||
|
||
// 4) MovementTracks
|
||
const QByteArray &movementTracks = spSitMapGuiIfc->movementTrackManagerSettingsJson();
|
||
req.movementTracks(movementTracks.constData());
|
||
|
||
// 'planOverlay' is editable Plan/Overlay of snapshot:
|
||
// it can be empty. A size is 0 will be ignored, means old value will remain at svc :-)
|
||
|
||
if (!m_requestHelper->startSingleRequest([req, this]() { return m_mrkFtc->snapshotModifyRequest(req, this);}))
|
||
ERROR_LOG(m_logger) << "Saving snapshot filter failed";
|
||
else
|
||
{
|
||
__unchange__();
|
||
|
||
// Do not update m_currentSnapshot. It´s done via onRefreshCurrent. Avoid race condition
|
||
// m_currentSnapshot = req;
|
||
}
|
||
}
|
||
|
||
//-----------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::onSaveSettings()
|
||
{
|
||
// Update in Library
|
||
|
||
const MarkerManagement::Snapshot &snapshot = m_currentSnapshot;
|
||
const QString title = QString::fromStdString(snapshot.name());
|
||
m_fileId = snapshot.fileContentId();
|
||
|
||
saveSnapshotPreviewInLibrary(title);
|
||
}
|
||
|
||
// TODO: dup code, same in mrk_create_snapshot
|
||
//------------------------------------------------------------------------------------------------------------------------
|
||
void SnapshotDialog::saveSnapshotPreviewInLibrary(const QString &snapshotTitle)
|
||
{
|
||
QString dtg = DTG::toStringMSec(QDateTime::currentMSecsSinceEpoch());
|
||
dtg.replace(QLatin1Char(' '), QLatin1Char('_'));
|
||
const QString title = QStringLiteral("Snapshot_%1_%2_%3")
|
||
.arg(dtg)
|
||
.arg(LtsSessionData::LtsSessionData::getInstance()->getOperatorId())
|
||
.arg(snapshotTitle.left(20));
|
||
|
||
DEBUG_LOG(m_logger) << "saveSnapshotPreviewInLibrary: " << title;
|
||
|
||
auto spSitMapGuiIfc = m_sitMapGuiIfc.lock();
|
||
if (!spSitMapGuiIfc->isMapReady())
|
||
{
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " sitMapGuiInterface not ready";
|
||
return;
|
||
}
|
||
|
||
LtsWidgets::LtsBaseLayoutWidget *blw = m_session->baseLayout();
|
||
|
||
bool menuVisible = blw->isMenuVisible();
|
||
bool topBarVisible = blw->isTopBarVisible();
|
||
|
||
// make room for a full sized snapshot by removing the top bar, the detail bar and the menu - reshow after the image was successfully created
|
||
blw->setMenuVisible(false);
|
||
blw->setTopBarVisible(false);
|
||
blw->hideVisibleLayouts();
|
||
|
||
std::function<void(const QImage &)> onImage = [this, title, menuVisible, topBarVisible](const QImage & image)
|
||
{
|
||
int initialFolderId = 1;
|
||
int snapshotFolderId = 1;
|
||
// folder_id = 1 -> Global documents as initial folder for admin session
|
||
|
||
if (m_session->exerciseId() > 0)
|
||
{
|
||
initialFolderId = m_flmDtc->getExerciseFolderId(m_session->exerciseId());
|
||
snapshotFolderId = m_flmDtc->findFolder(initialFolderId, QStringLiteral("Snapshots"));
|
||
}
|
||
|
||
DEBUG_LOG(m_logger) << "Initial folder Id = " << initialFolderId
|
||
<< " snapshotFolderId =" << snapshotFolderId;
|
||
|
||
const int folderId = snapshotFolderId > 0 ? snapshotFolderId : initialFolderId;
|
||
|
||
FileManagement::FileContentModifyRequest request;
|
||
request.id(m_currentSnapshot.fileContentId());
|
||
request.name(title.toStdString());
|
||
request.isTemplate(false);
|
||
request.folderId(folderId);
|
||
request.fileCategory(FileManagement::FileCategory::Exercise);
|
||
request.fileStatus(FileManagement::FileStatus::Valid);
|
||
request.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
|
||
bool bIsPng;
|
||
request.content() = LtsUtils::fromImage(image, &bIsPng);
|
||
request.fileType(bIsPng ? FileManagement::FileType::Png : FileManagement::FileType::Jpg);
|
||
request.isUsedBy(true);
|
||
request.usedBy(1);
|
||
request.lastModified(QDateTime::currentMSecsSinceEpoch());
|
||
|
||
if (m_session->exerciseId() > 0)
|
||
request.exerciseId(m_session->exerciseId());
|
||
|
||
if (m_requestHelper->startSingleRequest([this, request]()
|
||
{
|
||
return m_flmFtc->fileContentModifyRequest(request, this);
|
||
}))
|
||
{
|
||
m_fileId = m_requestHelper->getRepliedId();
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " Saved file in library with id = " << m_fileId;
|
||
|
||
saveSnapshotFilter();
|
||
|
||
if (m_currentSnapshot.fileContentId() != m_fileId)
|
||
{
|
||
DEBUG_LOG(m_logger) << LOGFUNCTION << " One more request needed!"; // should never happen at snapshot_dialog.cpp/modification
|
||
m_currentSnapshot.fileContentId(m_fileId);
|
||
}
|
||
} else {
|
||
ERROR_LOG(m_logger) << LOGFUNCTION << " Saved file in library with id = " << m_fileId << " failed";
|
||
}
|
||
|
||
// done!
|
||
LtsWidgets::LtsBaseLayoutWidget *blw = m_session->baseLayout();
|
||
blw->setMenuVisible(menuVisible);
|
||
blw->setTopBarVisible(topBarVisible);
|
||
blw->resetLayoutVisibility();
|
||
|
||
};
|
||
|
||
if (!spSitMapGuiIfc->toImage(this, onImage)) // => async
|
||
{
|
||
// reset directly after toImage failed
|
||
blw->setMenuVisible(menuVisible);
|
||
blw->setTopBarVisible(topBarVisible);
|
||
blw->resetLayoutVisibility();
|
||
return;
|
||
}
|
||
}
|
||
|
||
} // namespace MarkerManagement
|