Initial commit

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

No files matched your search

+28
View File
@@ -0,0 +1,28 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2016-02-29
#
ADD_SUBDIRECTORY(Data)
ADD_SUBDIRECTORY(Gui)
#
# Gui Plugin Interface
#
ADD_INTERFACE_LIBRARY(MrkGuiPluginInterface
${CMAKE_CURRENT_SOURCE_DIR}/mrk_gui_plugin_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/..
GuiPluginInterface
)
#
# Data Plugin Interface
#
ADD_INTERFACE_LIBRARY(MrkDataPluginInterface
${CMAKE_CURRENT_SOURCE_DIR}/mrk_data_plugin_interface.h
${CMAKE_CURRENT_SOURCE_DIR}/..
DataPluginInterface
svcMrkCommon
)
+20
View File
@@ -0,0 +1,20 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Mike Wille, SLSE, 2016-09-06
#
#
# Data Plugin
#
NGL_ADD_LIBRARY(WS MrkDataPlugin MODULE mrk_data_plugin.cpp mrk_data_plugin.h)
NGL_TARGET_LINK_LIBRARIES(MrkDataPlugin
Qt5::Core
Qt5::Widgets #QColor/QApplication for trackentry
MrkDataPluginInterface
svcMrkClient
NGLLogger
LtsSessionDataDds
)
NGL_INSTALL_TARGET(MrkDataPlugin)
+53
View File
@@ -0,0 +1,53 @@
/**
* @RDE_HEADER@
* Data Plugin for ExerciseManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "mrk_data_plugin.h"
#include <Plugins/MarkerManagement/mrk_gui_plugin_interface.h>
#include <PluginInterfaces/data_plugin_interface.h>
#include <DDS/DDSConnector/dds_connector.h>
#include <LtsSession/lts_session_data_dds.h>
namespace MarkerManagement
{
std::shared_ptr<DataPluginBase::Interface> DataPlugin::createDataInterface(LtsSession::LtsSessionDataDds *session)
{
std::shared_ptr<MarkerManagement::Interface::Dtc> dtc;
std::shared_ptr<MarkerManagement::Interface::Ftc> ftc;
if (!session->createTopicClient(dtc, ftc))
return std::shared_ptr<DataPluginBase::Interface>();
return std::make_shared<DataInterfaceImpl>(dtc, ftc);
}
DataInterfaceImpl::DataInterfaceImpl(const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<MarkerManagement::Interface::Ftc> &ftc)
: DataInterface()
, m_dtc(dtc)
, m_ftc(ftc)
, m_foreignInterface(std::make_shared<ForeignInterfaceImpl>(dtc, ftc))
{}
ForeignInterfaceImpl::ForeignInterfaceImpl(const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<MarkerManagement::Interface::Ftc> &ftc)
: m_dtc(dtc)
, m_ftc(ftc)
{}
bool ForeignInterfaceImpl::setMarker(const Marker &marker, Interface::Ftc::MarkerModifyReplyHandler *handler)
{
return m_ftc->markerModifyRequest(marker, handler);
}
} // namespace MarkerManagement
+68
View File
@@ -0,0 +1,68 @@
/**
* @RDE_HEADER@
* HMI Plugin for ExerciseManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <Plugins/MarkerManagement/mrk_data_plugin_interface.h>
#include <PluginInterfaces/data_plugin_interface.h>
namespace MarkerManagement
{
class DataPlugin final : public QObject, public DataPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "data:3:mrk")
Q_INTERFACES(DataPluginBase::Plugin)
Q_OBJECT
public:
DataPlugin() = default;
~DataPlugin() = default;
QString pluginName() const override { return QStringLiteral("MarkerManagement"); }
std::shared_ptr<DataPluginBase::Interface> createDataInterface(LtsSession::LtsSessionDataDds *session) override;
bool availableInPartition(IDL::PartitionType ) const override { return true; }
};
class DataInterfaceImpl final : public DataInterface
{
public:
DataInterfaceImpl(const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<MarkerManagement::Interface::Ftc> &ftc);
std::shared_ptr<MarkerManagement::Interface::Dtc> getDtc() override { return m_dtc; }
std::shared_ptr<MarkerManagement::Interface::Ftc> getFtc() override { return m_ftc; }
std::shared_ptr<ForeignDataInterface> getForeignDataInterface() override { return m_foreignInterface; }
private:
std::shared_ptr<MarkerManagement::Interface::Dtc> m_dtc;
std::shared_ptr<MarkerManagement::Interface::Ftc> m_ftc;
std::shared_ptr<ForeignDataInterface> m_foreignInterface;
};
class ForeignInterfaceImpl final : public QObject, public ForeignDataInterface
{
Q_OBJECT
public:
ForeignInterfaceImpl(const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<MarkerManagement::Interface::Ftc> &ftc);
// ForeignInterface
bool setMarker(const Marker &marker, MarkerManagement::Interface::Ftc::MarkerModifyReplyHandler *handler) override;
std::shared_ptr<MarkerManagement::Interface::Dtc> getDtc() override { return m_dtc; }
private:
std::shared_ptr<MarkerManagement::Interface::Dtc> m_dtc;
std::shared_ptr<MarkerManagement::Interface::Ftc> m_ftc;
};
} // namespace MarkerManagement
+8
View File
@@ -0,0 +1,8 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2016-02-29
#
ADD_SUBDIRECTORY(MarkerEdit)
ADD_SUBDIRECTORY(Common)
+39
View File
@@ -0,0 +1,39 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Mike Wille, SLSE, 2016-09-06
#
#
# Data Plugin
#
SET(mrk_common_gui_SRCS
mrk_dialog_model.cpp
mrk_dialog_model.h
mrk_apply_filter.cpp
mrk_apply_filter.h
CustomViews/mrk_marker.cpp
CustomViews/mrk_marker.h
)
NGL_WRAP_UI(mrk_common_gui_SRCS
CustomViews/mrk_marker.ui
)
NGL_ADD_LIBRARY2(WS MrkCommon SHARED ${mrk_common_gui_SRCS})
NGL_TARGET_LINK_LIBRARIES(MrkCommon
PRIVATE
NGLLogger
LtsSession
LtsSessionData
LtsUtilsGuiDds
OpmDataPluginInterface
FltDataPluginInterface
ngltools
PUBLIC
MrkDataPluginInterface
Qt5::Widgets
LtsWidgets
LtsDataView
)
@@ -0,0 +1,64 @@
/**
* @RDE_HEADER@
* CustomView for Exercises
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, NLE, 2019-08-01
*/
#include "mrk_marker.h"
#include "ui_mrk_marker.h"
#include "mrk_dialog_model.h"
#include <LtsUtilsCore/dds_vector_to_pixmap.h>
namespace MarkerManagement
{
CustomViewMarker::CustomViewMarker(QWidget *parent)
: AbstractDisplayWidget(parent)
, m_ui(new Ui::CustomViewMarker)
{
m_ui->setupUi(this);
m_ui->image->setMenuEnabled(false); // no menu !
m_ui->image->setDrawOuterRect(false);
#ifndef LTS_DEBUG
m_ui->lbOperator->setVisible(false);
#endif
}
CustomViewMarker::~CustomViewMarker()
{
delete m_ui;
}
bool CustomViewMarker::init(const QModelIndex &idx)
{
if (!idx.isValid())
return false;
const QString mrkNote = rowData(idx, MarkerManagement::MarkerManagementDialogModel::ColNote).toString();
m_ui->lbMarkerNote->setText(mrkNote);
m_ui->lbMarkerNote->setToolTip(mrkNote);
m_ui->lbOperator->setText(rowData(idx, MarkerManagement::MarkerManagementDialogModel::ColOperator).toString());
m_ui->lbTimestamp->setText(rowData(idx, MarkerManagement::MarkerManagementDialogModel::ColTime).toString());
m_ui->lbType->setText(rowData(idx, MarkerManagement::MarkerManagementDialogModel::ColType).toString());
m_ui->lbOffset->setText(rowData(idx, MarkerManagement::MarkerManagementDialogModel::ColOffset).toString());
QPixmap img;
int fileId = rowData(idx, MarkerManagement::MarkerManagementDialogModel::ColFileId).toInt();
if (fileId > 0)
{
QByteArray imgData = rowData(idx, MarkerManagement::MarkerManagementDialogModel::ColImage).toByteArray();
img = LtsUtils::getPixmap(imgData);
}
if (!img.isNull())
m_ui->image->setPixmap(img);
return true;
}
} // namespace MarkerManagement
@@ -0,0 +1,32 @@
/**
* @RDE_HEADER@
* CustomView for Exercises
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, NLE, 2019-08-01
*/
#pragma once
#include <Viewer/LtsDataView/abstract_display_widget.h>
#include <Plugins/MarkerManagement/Gui/Common/mrkcommon_export.h>
namespace Ui
{
class CustomViewMarker;
}
namespace MarkerManagement
{
class MRKCOMMON_EXPORT CustomViewMarker final : public LtsDataView::AbstractDisplayWidget
{
Q_OBJECT
public:
explicit CustomViewMarker(QWidget *parent = nullptr);
~CustomViewMarker();
bool init(const QModelIndex &idx) override;
private:
Ui::CustomViewMarker* m_ui;
};
} // namespace MarkerManagement
@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CustomViewMarker</class>
<widget class="QWidget" name="CustomViewMarker">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>351</width>
<height>140</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="LtsWidgets::LtsImageEditor" name="image">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>128</width>
<height>128</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>128</width>
<height>128</height>
</size>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lbMarkerNote">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string notr="true">&lt;Marker Note with wordwrap&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lbOperator">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string notr="true">&lt;Operator&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="lblType">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="lbTimestamp">
<property name="text">
<string notr="true">&lt;Timestamp&gt;</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="lbOffset">
<property name="text">
<string notr="true">&lt;Offset&gt;</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lbType">
<property name="text">
<string notr="true">&lt;Type&gt;</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblTime">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Time:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblOffset">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Offset:</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsImageEditor</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_image_editor.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,227 @@
#include "mrk_apply_filter.h"
#include <QJsonParseError>
#include <QJsonObject>
#include <FilterManagement/flt_data_plugin_aes_display_filter.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <FilterManagement/flt_building_cmpnt_settings.h>
#include <PluginInterfaces/gui_plugin_interface.h>
namespace MarkerManagement
{
MarkerManagementApplyFilter::MarkerManagementApplyFilter(LtsSession::LtsSession *session,
const std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> &fltParticipantIfc,
const std::shared_ptr<FilterManagement::ForeignAesGuiInterface> &fltAesIfc,
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> &fltBuildingComponenIfc)
: m_session(session)
, m_fltParticipantIfc(fltParticipantIfc)
, m_fltAesIfc(fltAesIfc)
, m_fltBuildingComponentIfc(fltBuildingComponenIfc)
, m_logger(getLogger("MarkerManagementApplyFilter"))
{
std::shared_ptr<SituationMap::ForeignGuiInterface> spSitMapGuiIfc;
m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(spSitMapGuiIfc);
if (!spSitMapGuiIfc)
{
ERROR_LOG(m_logger) << "No spSitMapGuiIfc";
return;
}
m_sitMapGuiIfc = spSitMapGuiIfc;
}
const QJsonObject MarkerManagementApplyFilter::getFilterParamsJson() const
{
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
QJsonObject obj;
// SymbolAppearance
{
auto fltParticipantIfc = m_fltParticipantIfc.lock();
if (fltParticipantIfc)
{
std::shared_ptr<FilterManagement::SymbolAppearanceSettings> symbolAppearanceSettings =
fltParticipantIfc->symbolAppearanceForOperator(operatorId, m_session->workspaceId());
obj[QStringLiteral("SymbolAppearanceJson")] = symbolAppearanceSettings->settingsToJson();
}
else
WARNING_LOG(m_logger) << "cannot get filter as SymApp filter ifc is missing";
}
// AesFilter
{
auto fltIfcPtr = m_fltAesIfc.lock();
if (fltIfcPtr)
{
std::shared_ptr<FilterManagement::AesDisplayFilter> aesDisplayFilter =
fltIfcPtr->aesFilterForOperator(operatorId, m_session->workspaceId());
obj[QStringLiteral("AesFilterJson")] = aesDisplayFilter->filterToJson();
}
else
WARNING_LOG(m_logger) << "cannot get filter as aes filter ifc is missing";
}
// BuildingComponentSettings
{
auto fltIfcPtr = m_fltBuildingComponentIfc.lock();
if (fltIfcPtr)
{
std::shared_ptr<FilterManagement::BuildingComponentSettings> buildingComponentSettings =
fltIfcPtr->buildingComponentSettingsForOperator(operatorId, m_session->workspaceId());
obj[QStringLiteral("BuildingComponentSettingsJson")] = buildingComponentSettings->bldCmpSettingsToJson();
}
else
WARNING_LOG(m_logger) << "cannot get filter as BldgCmpnt filter ifc is missing";
}
return obj;
}
QByteArray MarkerManagementApplyFilter::getFilterParams() const
{
QJsonDocument jDoc(getFilterParamsJson());
return jDoc.toJson(QJsonDocument::Compact);
}
bool MarkerManagementApplyFilter::applyFilter(const QByteArray &filterContent)
{
if (filterContent.isEmpty())
{
ERROR_LOG(m_logger) << "filterContent is empty";
return false;
}
QJsonParseError parserError;
const QJsonDocument jDoc(QJsonDocument::fromJson(filterContent, &parserError));
if (parserError.error != QJsonParseError::NoError)
{
ERROR_LOG(m_logger) << "Error parsing json document: " << parserError.errorString();
return false;
}
return applyFilter(jDoc.object());
}
bool MarkerManagementApplyFilter::applyFilter(const QJsonObject &filterContent)
{
//
// 1. AesFilter
//
FilterManagement::AesFilter aesFilter;
{
const QJsonObject innerObj = filterContent[QStringLiteral("AesFilterJson")].toObject();
if (innerObj.isEmpty())
ERROR_LOG(m_logger) << "inner content AesFilterJson is empty";
else
aesFilter.content(QJsonDocument(innerObj).toJson().constData());
}
//
// 2. SymbolAppearance
//
FilterManagement::SymbolAppearance symbolAppearance;
{
QJsonObject innerObj = filterContent[QStringLiteral("SymbolAppearanceJson")].toObject();
if (innerObj.isEmpty())
ERROR_LOG(m_logger) << "inner content SymbolAppearanceJson is empty";
else
symbolAppearance.content(QJsonDocument(innerObj).toJson().constData());
}
//
// 3. BuildingComponentSettings
//
FilterManagement::BuildingComponentFilter buildingComponentFilter;
{
QJsonObject innerObj = filterContent[QStringLiteral("BuildingComponentSettingsJson")].toObject();
if (innerObj.isEmpty())
ERROR_LOG(m_logger) << "inner content BuildingComponentSettingsJson is empty";
else
buildingComponentFilter.content(QJsonDocument(innerObj).toJson().constData());
}
//
// finally save to Flt to enable reading in App Snapshot (SituationMap)
//
// following block is taken from:
// void InterfaceImpl::filterLoad(const QString &settingsGroup, const QString &filterPresetId)
// (Lts/Plugins/OperatorManagement/Gui/OperatorSettings/opm_settings_gui_plugin.cpp)
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
const QString &wsId_context = m_session->workspaceId(); // aka context
auto fltIfcPtr = m_fltAesIfc.lock();
auto fltParticipantIfc = m_fltParticipantIfc.lock();
auto fltBldgCmpntIfc = m_fltBuildingComponentIfc.lock();
if (fltParticipantIfc && fltIfcPtr)
{
//
// 1. AesFilter
aesFilter.id(0);
aesFilter.operatorId(operatorId);
aesFilter.sampleTime(0);
aesFilter.ctx(wsId_context.toStdString());
std::shared_ptr<FilterManagement::AesDisplayFilter> aesDisplayFilter
= fltIfcPtr->aesFilterForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(), wsId_context);
aesDisplayFilter->setFilterFromData(aesFilter);
//
// 2. SymbolAppearance
symbolAppearance.id(0);
symbolAppearance.operatorId(operatorId);
symbolAppearance.sampleTime(0);
symbolAppearance.ctx(wsId_context.toStdString());
std::shared_ptr<FilterManagement::SymbolAppearanceSettings> appearanceSettings
= fltParticipantIfc->symbolAppearanceForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(), wsId_context);
appearanceSettings->setSettingsFromData(symbolAppearance);
} else
WARNING_LOG(m_logger) << "cannot set filter as at least one filter ifc is missing (fltParticipantIfc|fltIfcPtr)";
// Nachtrag zu GUEZE-1769: since fltBuildingComponentIfc is optional:
if (fltBldgCmpntIfc)
{
// 3. BuildingComponentSettings
//
buildingComponentFilter.id(0);
buildingComponentFilter.operatorId(operatorId);
buildingComponentFilter.sampleTime(0);
buildingComponentFilter.ctx(wsId_context.toStdString());
std::shared_ptr<FilterManagement::BuildingComponentSettings> buildingComponentSettings
= fltBldgCmpntIfc->buildingComponentSettingsForOperator(LtsSessionData::LtsSessionData::getInstance()->getOperatorId(), wsId_context);
buildingComponentSettings->setBldCmpSettingsFromData(buildingComponentFilter);
}
else
WARNING_LOG(m_logger) << "cannot set filter as at least one filter ifc is missing (fltBldgCmpntIfc)";
return true;
}
bool MarkerManagementApplyFilter::applyMapSettings(const QByteArray &content)
{
auto spSitMapGuiIfc = m_sitMapGuiIfc.lock();
if (spSitMapGuiIfc)
{
spSitMapGuiIfc->setOperatorMapSettingsJson(content);
return true;
}
return false;
}
}
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <MarkerManagement/logger.h>
#include <Plugins/MarkerManagement/Gui/Common/mrkcommon_export.h>
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <FilterManagement/Data/flt_data_plugin.h>
#include <FilterManagement/flt_participant_plugin_interface.h>
#include <FilterManagement/flt_aes_plugin_interface.h>
#include <FilterManagement/flt_building_cmpnt_plugin_interface.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
namespace MarkerManagement
{
class MRKCOMMON_EXPORT MarkerManagementApplyFilter : public QObject
{
Q_OBJECT
public:
explicit MarkerManagementApplyFilter(LtsSession::LtsSession *session,
const std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> &fltParticipantIfc,
const std::shared_ptr<FilterManagement::ForeignAesGuiInterface> &fltAesIfc,
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> &fltBuildingComponenIfc
);
bool applyFilter(const QJsonObject &filterContent);
bool applyFilter(const QByteArray &filterContent);
bool applyMapSettings(const QByteArray &content);
QByteArray getFilterParams() const;
const QJsonObject getFilterParamsJson() const;
private:
LtsSession::LtsSession *m_session;
// no hard dependency to avoid crash when app is closed before this dialog is closed
std::weak_ptr<FilterManagement::ForeignFltParticipantGuiInterface> m_fltParticipantIfc;
std::weak_ptr<FilterManagement::ForeignAesGuiInterface> m_fltAesIfc;
std::weak_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> m_fltBuildingComponentIfc;
std::weak_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
LOGGER_T m_logger;
};
} // namespace MarkerManagement
@@ -0,0 +1,299 @@
/**
* @RDE_HEADER@
* HMI Plugin for MarkerManangement - Marker Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "mrk_dialog_model.h"
#include <MarkerManagement/mrk_translation.h>
#include <OperatorManagement/opm_dtc.h>
#include <ngltools/ngltools_dtg.h>
#include <QBuffer>
#include <QSet>
#include <QTimer>
namespace MarkerManagement
{
//---------------------------------
// MarkerManagementDialogModel
//---------------------------------
MarkerManagementDialogModel::MarkerManagementDialogModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<Marker>({tr("Note"),
tr("Operator"),
tr("Type"),
tr("Streams"),
tr("Time"),
tr("Offset [s]"),
tr("File Id"),
tr("Image")},
parent)
, m_logger(getLogger("MarkerManagementDialogModel"))
{}
bool MarkerManagementDialogModel::initModel(const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<OperatorManagement::Interface::Dtc> &opmDtc,
const std::shared_ptr<FileManagement::ForeignGuiInterface> &flmGui,
bool ignoreTimezone)
{
m_ignoreTimezone = ignoreTimezone;
if (!dtc)
return false;
m_flmGui = flmGui;
if (opmDtc)
{
auto cbUser = [this](const OperatorManagement::User &user)
{
m_operatorNames.insert(user.id(), QString::fromStdString(user.name()));
};
connect(opmDtc.get(), &OperatorManagement::Interface::Dtc::userChanged, this, cbUser);
opmDtc->users(cbUser);
}
connect(dtc.get(), &MarkerManagement::Interface::Dtc::markerChanged,
this, &MarkerManagementDialogModel::onDataChanged);
dtc->markers([this](const MarkerManagement::Marker &data) { insertRow(data); });
connect(this, &MarkerManagementDialogModel::rowsInserted, this, &MarkerManagementDialogModel::updateOperatorNames);
connect(this, &MarkerManagementDialogModel::rowsRemoved, this, &MarkerManagementDialogModel::updateOperatorNames);
updateOperatorNames();
return true;
}
void MarkerManagementDialogModel::setTimezoneHoursOffset(int timezoneHoursOffset)
{
m_timezoneHoursOffset = timezoneHoursOffset;
emit dataChanged(index(0, ColTime), index(rowCount()-1, ColTime), {Qt::DisplayRole});
}
void MarkerManagementDialogModel::loadPreview(int fileContentId, int rowId)
{
if (fileContentId <= 0 || m_previews.contains(fileContentId))
{
requestNextFileContent();
return;
}
// sadly m_flmGui->loadContent() is not async...
if (m_bFlmRequestInProgress)
{
m_requestedIds.push_back({fileContentId, rowId});
return;
}
m_bFlmRequestInProgress = true;
QByteArray byteArray;
if (m_flmGui->loadContent(fileContentId, byteArray, true) && byteArray.size() > 0)
{
DEBUG_LOG(m_logger) << "m_previews.insert fileContentId=" << fileContentId
<< " size Preview=" << byteArray.size();
QString str = QStringLiteral("<html><center><img src='data:image/png;base64,%1'></center></html>").arg(QString::fromLatin1(byteArray.toBase64()));
m_previews.insert(fileContentId, str);
emit dataChanged(index(rowId, 0), index(rowId, ColImage), {Qt::ToolTipRole});
}
else
m_previews.insert(fileContentId, QString());
m_bFlmRequestInProgress = false;
requestNextFileContent();
}
void MarkerManagementDialogModel::requestNextFileContent()
{
if (!m_bFlmRequestInProgress && !m_requestedIds.isEmpty())
{
auto next = m_requestedIds.takeLast();
QTimer::singleShot(0, this, [this, next] { loadPreview(next.first, next.second);});
}
}
QVariant MarkerManagementDialogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (section == ColOperator && orientation == Qt::Horizontal && role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
return m_comboBoxFilterData;
return LtsWidgets::LtsAbstractTableModel<Marker>::headerData(section, orientation, role);
}
QVariant MarkerManagementDialogModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole && role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole && role != Qt::ToolTipRole)
return QVariant();
if (!indexIsValid(index))
return QVariant();
const int row = index.row();
const MarkerManagement::Marker &marker = m_vecData.at(row);
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
{
if (index.column() == ColOperator)
return marker.operatorId();
return QVariant();
}
if (role == Qt::ToolTipRole) // && index.column() == ColNote
{
const int fileContentId = marker.fileContentId();
if (fileContentId > 0)
{
auto it = m_previews.find(fileContentId);
if (it == m_previews.end())
{
auto that = const_cast<MarkerManagementDialogModel *>(this);
QTimer::singleShot(0, that, [that, fileContentId, row]() { that->loadPreview(fileContentId, row); });
return QVariant();
}
return it.value();
}
return QVariant();
}
if (role == Qt::DisplayRole)
{
switch (index.column())
{
case ColNote:
return QString::fromStdString(marker.note());
case ColOperator:
if (marker.operatorId() <= 0)
return tr("Global");
return m_operatorNames.value(marker.operatorId());
case ColType:
{
QStringList slTypes;
slTypes.reserve(marker.descriptions().size());
for (const MarkerManagement::MarkerDescription &desc : marker.descriptions())
slTypes.append(MarkerManagement::toString(desc.markerType()));
return slTypes.join(QStringLiteral(", "));
}
case ColStreams:
{
QString ret;
for (const MarkerManagement::MarkerDescription &desc : marker.descriptions())
{
if (desc.markerType() != MarkerManagement::MarkerType::Audio &&
desc.markerType() != MarkerManagement::MarkerType::Video)
continue;
if (!ret.isEmpty())
ret += QLatin1Char(',');
ret += QString::fromStdString(desc.content());
}
return ret;
}
case ColTime:
if (m_ignoreTimezone)
{
// TODO: ugly... (because returns the dt as string directly, breaking the MVC pattern) but if the A/V Topic Editor changes the timezone, this has to respond.... :( this (somewhat) breaks sorting for the A/V Topic Editor
// Not the job of the model (but for the view / delegate), but has to do it for now. \/
// \-------------------------------------/
return QDateTime::fromMSecsSinceEpoch(marker.timeStamp() + (m_timezoneHoursOffset * 3600 * 1000)).toString(QStringLiteral("dd.MM.yy HH:mm:ss"));
}
else
return QDateTime::fromMSecsSinceEpoch(marker.timeStamp() - marker.timeStampOffset());
case ColOffset:
return QVariant(marker.timeStampOffset() / 1000);
case ColFileId:
return marker.fileContentId();
case ColImage:
return m_previews.value(marker.fileContentId());
}
}
return QVariant();
}
void MarkerManagementDialogModel::updateOperatorNames()
{
QSet<int> operatorIds;
for (const auto &op : qAsConst(m_vecData))
operatorIds.insert(op.operatorId());
LtsWidgets::ComboboxFilterContent cfc;
LtsWidgets::ComboboxFilterData cfd;
cfc.data.reserve(operatorIds.size());
for (int operatorId : qAsConst(operatorIds))
{
cfd.data = operatorId;
cfd.text = m_operatorNames.value(operatorId);
cfc.data.push_back(cfd);
}
cfc.sortItems = true;
m_comboBoxFilterData = cfc.toVariant();
}
//
// MarkerSortFilterProxyModel
//
void MarkerSortFilterProxyModel::setSourceModel(QAbstractItemModel *model)
{
m_model = qobject_cast<MarkerManagementDialogModel*>(model);
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(model);
}
void MarkerSortFilterProxyModel::setOperatorId(int operatorId)
{
if (m_operatorId == operatorId)
return;
m_operatorId = operatorId;
invalidateFilter();
}
bool MarkerSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (!m_model || m_operatorId < 0 || source_row < 0 || source_row >= m_model->rowCount(source_parent))
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
const MarkerManagement::Marker &marker = m_model->m_vecData.at(source_row);
if (!m_showOtherUsersMarkers)
{
bool bAccepted = marker.operatorId() == 0 ||
marker.operatorId() == m_operatorId;
if (!bAccepted)
return false;
}
return LtsWidgets::LtsColumnFilterProxyModel::filterAcceptsRow(source_row, source_parent);
}
bool MarkerSortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_model || source_left.column() != source_right.column())
return LtsWidgets::LtsColumnFilterProxyModel::lessThan(source_left, source_right);
const Marker &left = m_model->m_vecData.at(source_left.row());
const Marker &right = m_model->m_vecData.at(source_right.row());
switch (source_left.column())
{
case MarkerManagementDialogModel::ColTime:
return left.timeStamp() < right.timeStamp();
default:
break;
}
return LtsWidgets::LtsColumnFilterProxyModel::lessThan(source_left, source_right);
}
void MarkerSortFilterProxyModel::setShowOtherUsersMarkers(bool show)
{
if (show == m_showOtherUsersMarkers)
return;
m_showOtherUsersMarkers = show;
invalidateFilter();
}
} // namespace MarkerManagement
+97
View File
@@ -0,0 +1,97 @@
/**
* @RDE_HEADER@
* HMI Plugin for MarkerManangement - Marker Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <MarkerManagement/mrk_dtc.h>
#include <MarkerManagement/logger.h>
#include <Plugins/MarkerManagement/Gui/Common/mrkcommon_export.h>
#include <FileManagement/flm_explorer_gui_plugin_interface.h>
#include <LtsWidgets/lts_abstract_table_model.h>
#include <LtsWidgets/lts_column_filter_proxy_model.h>
namespace OperatorManagement
{
namespace Interface
{
class Dtc;
}
}
namespace MarkerManagement
{
// --------------------------------------------------------
// MarkerManagementModel
// --------------------------------------------------------
class MRKCOMMON_EXPORT MarkerManagementDialogModel : public LtsWidgets::LtsAbstractTableModel<Marker>
{
Q_OBJECT
public:
enum Columns
{
ColNote,
ColOperator,
ColType,
ColStreams,
ColTime,
ColOffset,
ColFileId,
ColImage
};
explicit MarkerManagementDialogModel(QObject *parent = nullptr);
bool initModel(const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<OperatorManagement::Interface::Dtc> &opmDtc,
const std::shared_ptr<FileManagement::ForeignGuiInterface> &flmGui,
bool ignoreTimezone = false);
QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
QVariant data(const QModelIndex &index, int role = Qt::UserRole) const override final;
public slots:
void setTimezoneHoursOffset(int timezoneHoursOffset);
private slots:
void updateOperatorNames();
void loadPreview(int fileContentId, int rowId);
private:
void requestNextFileContent();
private:
QHash<int, QString> m_operatorNames;
QHash<int, QString> m_previews; // QString as base64 encoded image data
QVector<QPair<int, int>> m_requestedIds; // fileId, rowId
bool m_bFlmRequestInProgress {false};
QVariant m_comboBoxFilterData;
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
int m_timezoneHoursOffset {0};
bool m_ignoreTimezone {false};
LOGGER_T m_logger;
friend class MarkerSortFilterProxyModel;
};
class MRKCOMMON_EXPORT MarkerSortFilterProxyModel : public LtsWidgets::LtsColumnFilterProxyModel
{
Q_OBJECT
public:
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
void setSourceModel(QAbstractItemModel *model) override;
void setOperatorId(int operatorId);
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
void setShowOtherUsersMarkers(bool show);
private:
MarkerManagementDialogModel *m_model {nullptr};
int m_operatorId {-1};
bool m_showOtherUsersMarkers {false};
};
}
+69
View File
@@ -0,0 +1,69 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Christian Ehrlicher, SLSE, 2016-02-29
#
SET(mrk_edit_gui_SRCS
mrk_edit_gui_plugin.cpp
mrk_edit_gui_plugin.h
mrk_dialog.cpp
mrk_dialog.h
mrk_set_markers.cpp
mrk_set_markers.h
mrk_edit_dialog.cpp
mrk_edit_dialog.h
mrk_create_snapshot.cpp
mrk_create_snapshot.h
snapshot_dialog.cpp
snapshot_dialog.h
snapshot_dialog_model.cpp
snapshot_dialog_model.h
TopicEditor/topic_editor.h
TopicEditor/topic_editor.cpp
)
NGL_WRAP_UI(mrk_edit_gui_SRCS
mrk_dialog.ui
mrk_set_markers.ui
mrk_edit_dialog.ui
mrk_create_snapshot.ui
snapshot_dialog.ui
TopicEditor/topic_editor.ui
)
NGL_ADD_LIBRARY(WS MrkEditGuiPlugin MODULE ${mrk_edit_gui_SRCS})
NGL_TARGET_LINK_LIBRARIES(MrkEditGuiPlugin
LtsPrinting
NGLLogger
LtsSession
LtsSessionData
LtsPluginManager
MrkCommon
MrkGuiPluginInterface
MrkDataPluginInterface
OpmDataPluginInterface
FlmDataPluginInterface
AvmDataPluginInterface
SrmDataPluginInterface
SrpDataPluginInterface
FltDataPluginInterface
Qt5::Widgets
LtsWidgets
ngltools
nglsettings
LtsDataView
LtsUtilsGuiDds
LtsAppManager
ddsconnector
svcSrpClient
svcAvmCommon
TopicEditorBase
LtsScriptTimeline # TopicEditor
situationMap # SituationMap::OperatorMapSettings
)
NGL_INSTALL_TARGET(MrkEditGuiPlugin)
@@ -0,0 +1,162 @@
/**
* @RDE_HEADER@
* Topic Editor for the Snapshot Topic in the Script Editor
* $Id$
* $HeadURL$
* $Author$
*
* Created by Iuliana Ojog, SLSE, 2017-10-07
*/
#include "topic_editor.h"
#include "ui_topic_editor.h"
#include <LtsScriptTimeline/track_entry.h>
#include <LtsWidgets/lts_abstract_table_model.h>
#include <Plugins/MarkerManagement/Gui/MarkerEdit/snapshot_dialog_model.h>
#include <Services/MarkerManagement/mrk.hpp>
#include <TopicEditorBase/topic_previewer.h>
#include <QModelIndex>
#include <QModelIndexList>
#include <QSortFilterProxyModel>
namespace MarkerManagement
{
SnapshotTopicEditor::SnapshotTopicEditor(SnapshotDialogModel *snapshotModel, QSortFilterProxyModel *proxyModel, QWidget *parent)
: TopicEditorBase::TopicEditor(parent)
, m_snapshotModel(snapshotModel)
, m_proxyModel(proxyModel)
, m_snapshotId(0)
, m_ui(new Ui::SnapshotTopicEditor)
, m_logger(getLogger("SnapshotTopicEditor"))
{
m_ui->setupUi(this);
init(m_ui->widget);
if (snapshotModel != nullptr) // mrk plugin available
{
snapshotModel->setParent(this); // model was created without parent!
proxyModel->setParent(this);
proxyModel->setSourceModel(snapshotModel);
m_ui->snapshotsDataView->setModel(proxyModel);
#ifndef LTS_DEBUG
m_ui->snapshotsDataView->hideColumn(SnapshotDialogModel::ColFileId);
#endif
connect(m_ui->snapshotsDataView, &LtsDataView::LtsDataView::signalSelectionChanged,
this, &SnapshotTopicEditor::onSnapshotSelected);
}
else
{
m_ui->snapshotsDataView->hide(); // no markers, no view
}
setOnlineHelpFilename(QStringLiteral("Script_Editor-Add_Snapshot_Topic"));
m_buttonBox->setText(LtsWidgets::DialogButton::Import, tr("Refetch Snapshot"));
m_buttonBox->setToolTip(LtsWidgets::DialogButton::Import, tr("If the selected snapshot was modified after it was used in this topic, then click this button to reload the snapshot to its most recent version for this topic."));
m_buttonBox->connectButton(LtsWidgets::DialogButton::Import, this, &SnapshotTopicEditor::slotChangesMade /* we actually don't reload the snapshot, apply() does this :) */);
}
SnapshotTopicEditor::~SnapshotTopicEditor()
{
delete m_ui;
}
///////////////////////////////////////////////////////////////////////////////
// PRIVATE
void SnapshotTopicEditor::updateInternalData()
{
DEBUG_LOG(m_logger) << LOGFUNCTION;
m_ui->snapshotsDataView->selectionModel()->clear();
m_snapshotId = m_topicData.properties.value(QStringLiteral("snapshotId")).toInt(0/*invalid*/);
if (m_snapshotId > 0) // there is a snapshot id saved (not a new topic)
{
DEBUG_LOG(m_logger) << "snapshotId = " << m_snapshotId;
QModelIndex idx = m_snapshotModel->findIndexForId(m_snapshotId);
if (idx.isValid()) // the snapshot is still available on the system, tell its name and select it in the view
{
m_ui->snapshotsDataView->selectRow(m_proxyModel->mapFromSource(idx));
const MarkerManagement::Snapshot snapshot = m_snapshotModel->getRowData(idx.row());
DEBUG_LOG(m_logger) << "SnapShot Selected " << snapshot.id() ;
m_snapshotId = snapshot.id();
m_ui->lblName->setText(QString::fromStdString(snapshot.name()));
}
else // the snapshot does not exist anymore, but that's okay because all relevant data is saved
{
QString name = m_topicData.properties.value(QStringLiteral("snapshotName")).toString();
if (name.isEmpty())
name = QStringLiteral("<font color='red'>%1</font>").arg(tr("unknown"));
m_ui->lblName->setText(QStringLiteral("%1 <font color='red'>(%2)</font>").arg(name, tr("Snapshot not available anymore!")));
}
}
else // there is not a snapshot id saved, that means that this is a new topic
{
m_ui->lblName->setText(QStringLiteral("<font color='red'>%1</font>").arg(tr("Please select a valid snapshot")));
}
}
void SnapshotTopicEditor::retranslate()
{
translate(m_ui, tr("Snapshot Topic Editor"));
m_uiRequirements->clear();
m_uiRequirements->addRequirement(
{ m_ui->lblNamePre, [this]() { return (m_snapshotId > 0); }, tr("Invalid or no snapshot selected") }
);
}
///////////////////////////////////////////////////////////////////////////////
// PRIVATE SLOTS
void SnapshotTopicEditor::onSnapshotSelected()
{
const QModelIndex idx =m_ui->snapshotsDataView->currentIndex();
const MarkerManagement::Snapshot snapshot = m_snapshotModel->getRowData(idx.row());
if (snapshot.id() <= 0)
return;
m_snapshotId = snapshot.id();
DEBUG_LOG(m_logger) << "new snapshot id = " << m_snapshotId;
m_ui->lblName->setText(QString::fromStdString(snapshot.name()));
slotChangesMade();
}
bool SnapshotTopicEditor::apply2()
{
//const QModelIndex idx = m_ui->snapshotsDataView->currentIndex();
const QModelIndexList &idxList = m_ui->snapshotsDataView->selectionModel()->selectedRows(); // WARNING: do not use to get data! use getRowData instead!
if (idxList.count() != 1)
{
new LtsWidgets::LtsMessageDialogNew(this, tr("Invalid or no snapshot selected"));
return false;
}
const MarkerManagement::Snapshot snapshot = m_snapshotModel->getRowData(m_ui->snapshotsDataView->currentIndex().row());
if (snapshot.id() <= 0)
{
new LtsWidgets::LtsMessageDialogNew(this, tr("Invalid or no snapshot selected"));
return false;
}
setTopicDataProperty(QStringLiteral("snapshotName"), QString::fromStdString(snapshot.name()));
setTopicDataProperty(QStringLiteral("snapshotId"), m_snapshotId);
setTopicDataProperty(QStringLiteral("planOverlay"), QString::fromStdString(snapshot.planOverlay()));
setTopicDataProperty(QStringLiteral("snapshotFilter"), QString::fromStdString(snapshot.filter()));
setTopicDataProperty(QStringLiteral("timeStamp"), double(snapshot.timeStamp())); // QJsonValue's toInt is too small for int64
setTopicDataProperty(QStringLiteral("mapSettings"), QString::fromStdString(snapshot.mapSettings()));
setTopicDataProperty(QStringLiteral("fileContentId"), snapshot.fileContentId());
setDescription(m_ui->widget->description().isEmpty() ? QString::fromStdString(snapshot.name()) : m_ui->widget->description());
if (topicPreviewWidget()->description().isEmpty())
topicPreviewWidget()->setDescription(QString::fromStdString(snapshot.name()));
m_ui->widget->previewer()->setTopicData(m_topicData);
return true;
}
} // namespace MarkerManagement
@@ -0,0 +1,58 @@
/**
* @RDE_HEADER@
* Topic Editor for the Snapshot Topic in the Script Editor
* $Id$
* $HeadURL$
* $Author$
*
* Created by Iuliana Ojog, SLSE, 2017-10-07
*/
#pragma once
#include <LtsWidgets/lts_abstract_table_model.h>
#include <MarkerManagement/logger.h>
#include <Services/MarkerManagement/mrk.hpp>
#include <TopicEditorBase/topic_editor_base.h>
class QSortFilterProxyModel;
namespace Ui { class SnapshotTopicEditor; }
namespace MarkerManagement
{
class SnapshotDialogModel;
class SnapshotTopicEditor : public TopicEditorBase::TopicEditor
{
Q_OBJECT
public:
explicit SnapshotTopicEditor(
SnapshotDialogModel *snapshotModel, QSortFilterProxyModel *proxyModel, QWidget *parent = nullptr
);
~SnapshotTopicEditor();
private:
void updateInternalData() override final;
void retranslate() override final;
private slots:
void onSnapshotSelected();
bool apply2() override final;
private:
SnapshotDialogModel *m_snapshotModel{nullptr};
QSortFilterProxyModel *m_proxyModel{nullptr};
int m_snapshotId{0};
Ui::SnapshotTopicEditor *m_ui{nullptr};
NGL::INGLLogger &m_logger;
};
} // namespace MarkerManagement
@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SnapshotTopicEditor</class>
<widget class="QWidget" name="SnapshotTopicEditor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>868</width>
<height>388</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string notr="true">Script Editor</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLabel" name="lblName">
<property name="text">
<string notr="true">unknown</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="TopicEditorBase::TopicPreviewWidget" name="widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblNamePre">
<property name="text">
<string>Selected Snapshot:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="lbxAvailableSnapshots">
<property name="text">
<string>Available Snapshots:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2" rowspan="2">
<widget class="LtsDataView::LtsDataView" name="snapshotsDataView">
<property name="showColumnCount" stdset="0">
<bool>false</bool>
</property>
<property name="toolButtonsVisible">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>TopicEditorBase::TopicPreviewWidget</class>
<extends>QWidget</extends>
<header>TopicEditorBase/topic_preview_widget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,290 @@
/**
* @RDE_HEADER@
* MarkerManagement - Create Snapshot Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-05-22
*/
#include "mrk_create_snapshot.h"
#include "ui_mrk_create_snapshot.h"
#include <LtsSession/lts_session_data.h>
#include <LtsSession/lts_session.h>
#include <LtsPrinting/printing.h>
#include <LtsWidgets/lts_base_layout_widget.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <FilterManagement/flt_data_plugin_aes_display_filter.h>
#include <FilterManagement/flt_building_cmpnt_settings.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <ngltools/ngltools_dtg.h>
#include <LtsUtilsCore/dds_vector.h>
#include <LtsUtilsCore/dds_vector_to_pixmap.h>
#include <QDateTime>
#include <QImage>
#include <QJsonDocument>
#include <QDebug>
namespace MarkerManagement
{
//------------------------------------------------------------------------------------------------------------------------
SnapshotCreateDialog::SnapshotCreateDialog(QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_ui(new Ui::SnapshotCreateDialog)
, m_logger(getLogger("SnapshotCreateDialog"))
{
m_ui->setupUi(this);
m_uiRequirements->addRequirement({m_ui->lblName, [this]() { return (!m_ui->leName->text().isEmpty()); }});
setOnlineHelpFilename(QStringLiteral("Situation-Add_Snapshot"));
}
//------------------------------------------------------------------------------------------------------------------------
SnapshotCreateDialog::~SnapshotCreateDialog()
{
delete m_ui;
}
//------------------------------------------------------------------------------------------------------------------------
void SnapshotCreateDialog::retranslate()
{
translate(m_ui, m_editData, tr("Snapshot"));
}
//------------------------------------------------------------------------------------------------------------------------
bool SnapshotCreateDialog::init(const std::shared_ptr<MarkerManagement::Interface::Ftc> &mrk_ftc,
const std::shared_ptr<FileManagement::Interface::Dtc> &flm_dtc,
const std::shared_ptr<FileManagement::Interface::Ftc> &flm_ftc,
const std::weak_ptr<SituationMap::ForeignGuiInterface> &sitMapIfc,
const std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> &fltParticipantIfc,
const std::shared_ptr<FilterManagement::ForeignAesGuiInterface> &fltAesIfc,
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> &fltBuildingComponentIfc,
LtsSession::LtsSession *session,
const MarkerManagement::Snapshot &data)
{
if (!mrk_ftc || !fltAesIfc || !sitMapIfc.lock())
return false;
m_editData = data;
m_fileId = data.fileContentId();
m_mrkFtc = mrk_ftc;
m_flmDtc = flm_dtc;
m_flmFtc = flm_ftc;
m_sitMapGuiIfc = sitMapIfc;
m_fltParticpantIfc = fltParticipantIfc;
m_fltAesIfc = fltAesIfc;
m_fltBuildingComponentIfc = fltBuildingComponentIfc;
m_session = session;
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
ERROR_LOG(m_logger) << "flm gui missing - cannot create screenshots for a snapshot";
m_ui->cbSavePreview->setEnabled(false);
m_ui->cbSavePreview->setChecked(true);
if (m_editData.id() > 0) // edit mode
{
m_ui->leName->setText(QString::fromStdString(m_editData.name()));
m_ui->leDesc->setText(QString::fromStdString(m_editData.description()));
m_fileId = m_editData.fileContentId();
if (m_fileId > 0) // do not save preview on update metadata
m_ui->cbSavePreview->setChecked(false);
}
return true;
}
//------------------------------------------------------------------------------------------------------------------------
void SnapshotCreateDialog::sendSnapshotRequest()
{
qint64 partitionTime = m_session->partitionTime();
auto spSitMapGuiIfc = m_sitMapGuiIfc.lock();
const QByteArray &mapSettings = spSitMapGuiIfc->operatorMapSettingsJson();
const QByteArray &movementTracks = spSitMapGuiIfc->movementTrackManagerSettingsJson();
Snapshot req;
req.id(m_editData.id());
req.name(m_ui->leName->text().toStdString());
req.description(m_ui->leDesc->toPlainText().toStdString());
if (m_editData.id() > 0) // edit only snapshot metadata, rest unchanged
{
req.mapSettings(m_editData.mapSettings());
req.movementTracks(m_editData.movementTracks());
req.filter(m_editData.filter());
req.planOverlay(m_editData.planOverlay());
}
else // add snapshot
{
req.mapSettings(mapSettings.constData());
req.movementTracks(movementTracks.constData());
req.filter(getFilterParams().constData());
req.planOverlay(std::string());
}
req.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
req.timeStamp(partitionTime);
req.fileContentId(m_fileId);
DEBUG_LOG(m_logger) << "Edit/Create snapshot id = " << m_editData.id();
DEBUG_LOG(m_logger) << "File id = " << m_fileId;
if (m_requestHelper->startSingleRequest([req, this]()
{
return m_mrkFtc->snapshotModifyRequest(req, this);
}))
{
m_editData.id(m_requestHelper->getRepliedId());
DEBUG_LOG(m_logger) << "Saved snapshot with id = " << m_requestHelper->getRepliedId();
__unchange__();
closeRequest();
}
}
//------------------------------------------------------------------------------------------------------------------------
bool SnapshotCreateDialog::apply()
{
if (m_ui->cbSavePreview->isChecked())
saveSnapshotPreviewInLibrary();
else
sendSnapshotRequest();
return false; // wait for image before close window (returning false keeps the window open so we can do some async stuff)
}
//------------------------------------------------------------------------------------------------------------------------
QByteArray SnapshotCreateDialog::getFilterParams() const // TODO: is dup - use from MrkCommon instead
{
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
QJsonObject obj;
{ // AesFilter
std::shared_ptr<FilterManagement::AesDisplayFilter> aesDisplayFilter =
m_fltAesIfc->aesFilterForOperator(operatorId, m_session->workspaceId());
obj[QStringLiteral("AesFilterJson")] = aesDisplayFilter->filterToJson();
}
{ // SymbolAppearance
std::shared_ptr<FilterManagement::SymbolAppearanceSettings> symbolAppearanceSettings =
m_fltParticpantIfc->symbolAppearanceForOperator(operatorId, m_session->workspaceId());
obj[QStringLiteral("SymbolAppearanceJson")] = symbolAppearanceSettings->settingsToJson();
}
// BuildingComponent
// Nachtrag zu GUEZE-1769: since fltBuildingComponentIfc is optional:
if (m_fltBuildingComponentIfc)
{
std::shared_ptr<FilterManagement::BuildingComponentSettings> buildingComponentSettings =
m_fltBuildingComponentIfc->buildingComponentSettingsForOperator(operatorId, m_session->workspaceId());
obj[QStringLiteral("BuildingComponentSettingsJson")] = buildingComponentSettings->bldCmpSettingsToJson();
}
QJsonDocument jDoc(obj);
return jDoc.toJson(QJsonDocument::Compact);
}
//------------------------------------------------------------------------------------------------------------------------
void SnapshotCreateDialog::saveSnapshotPreviewInLibrary()
{
QString dtg = DTG::toStringMSec(QDateTime::currentMSecsSinceEpoch());
dtg.replace(QLatin1Char(' '), QLatin1Char('_'));
const QString title = ( m_ui->leName->text() + QStringLiteral(" (")+ dtg + QStringLiteral(")"));
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)
{
int exeFolderId = m_flmDtc->getExerciseFolderId(m_session->exerciseId());
snapshotFolderId = m_flmDtc->findFolder(exeFolderId, QStringLiteral("Snapshots"));
if (snapshotFolderId <= 0)
initialFolderId = exeFolderId;
}
DEBUG_LOG(m_logger) << "Initial folder Id = " << initialFolderId
<< " snapshotFolderId =" << snapshotFolderId;
const int folderId = snapshotFolderId > 0 ? snapshotFolderId : initialFolderId;
FileManagement::FileContentModifyRequest request;
request.id(m_editData.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) << "Saved file in library with id = " << m_fileId;
sendSnapshotRequest();
if (m_editData.fileContentId() != m_fileId)
{
DEBUG_LOG(m_logger) << "One more request needed!";
m_editData.fileContentId(m_fileId);
}
}
// 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
@@ -0,0 +1,89 @@
/**
* @RDE_HEADER@
* MarkerManagement - Rename Folder Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Iuliana Ojog, SLSE, 2017-05-22
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <Services/MarkerManagement/mrk_ftc.h>
#include <Services/FileManagement/flm_dtc.h>
#include <Services/FileManagement/flm_ftc.h>
#include <Services/MarkerManagement/logger.h>
#include <Plugins/FilterManagement/flt_participant_plugin_interface.h>
#include <Plugins/FilterManagement/flt_aes_plugin_interface.h>
#include <Plugins/FilterManagement/flt_building_cmpnt_plugin_interface.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
//#include <QModelIndex>
namespace Ui
{
class SnapshotCreateDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace MarkerManagement
{
class SnapshotCreateDialog final : public LtsWidgets::LtsDialog
, protected MarkerManagement::Interface::Ftc::SnapshotModifyReplyHandler
, protected FileManagement::Interface::Ftc::FileContentModifyReplyHandler
{
Q_OBJECT
public:
explicit SnapshotCreateDialog(QWidget *parent = nullptr);
~SnapshotCreateDialog();
bool init(const std::shared_ptr<MarkerManagement::Interface::Ftc> &mrk_ftc,
const std::shared_ptr<FileManagement::Interface::Dtc> &flm_dtc,
const std::shared_ptr<FileManagement::Interface::Ftc> &flm_ftc,
const std::weak_ptr<SituationMap::ForeignGuiInterface> &sitMapIfc,
const std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> &fltParticipantIfc,
const std::shared_ptr<FilterManagement::ForeignAesGuiInterface> &fltAesIfc,
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> &fltBuildingComponentIfc,
LtsSession::LtsSession *session,
const Snapshot &data = Snapshot());
bool apply() override final;
protected:
void retranslate() override;
QByteArray getFilterParams() const;
void onSnapshotModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onFileContentModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private:
void saveSnapshotPreviewInLibrary();
void sendSnapshotRequest();
private:
std::shared_ptr<MarkerManagement::Interface::Ftc> m_mrkFtc;
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
std::weak_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> m_fltParticpantIfc;
std::shared_ptr<FilterManagement::ForeignAesGuiInterface> m_fltAesIfc;
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> m_fltBuildingComponentIfc;
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
LtsUtils::RequestHelper *m_requestHelper{nullptr};
Ui::SnapshotCreateDialog *m_ui{nullptr};
MarkerManagement::Snapshot m_editData;
int m_fileId;
LtsSession::LtsSession *m_session{nullptr};
LOGGER_T m_logger;
};
} // namespace MarkerManagement
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SnapshotCreateDialog</class>
<widget class="QWidget" name="SnapshotCreateDialog">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>316</width>
<height>212</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Snapshot Management</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="3" column="0">
<widget class="QLineEdit" name="leName">
<property name="toolTip">
<string>Name</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblName">
<property name="toolTip">
<string>Snapshot Name</string>
</property>
<property name="text">
<string>Snapshot Name:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblDesc">
<property name="text">
<string>Description:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QTextEdit" name="leDesc">
<property name="toolTip">
<string>Description</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="cbSavePreview">
<property name="text">
<string>Save preview in library</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+178
View File
@@ -0,0 +1,178 @@
/**
* @RDE_HEADER@
* HMI Plugin for ExerciseManangement - Exercise Overview Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "mrk_dialog.h"
#include "ui_mrk_dialog.h"
#include "mrk_edit_dialog.h"
#include <MarkerManagement/Gui/Common/mrk_dialog_model.h>
#include <MarkerManagement/Gui/Common/CustomViews/mrk_marker.h>
#include <LtsSession/lts_session.h>
#include <LtsSession/lts_session_data.h>
#include <LtsPrinting/printing.h>
#include <QTreeView>
namespace MarkerManagement
{
//---------------------------------
// MarkerManagementDialog
//---------------------------------
MarkerManagementDialog::MarkerManagementDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::CloseOnly)
, m_menuGroup(menuGroup)
, m_model(nullptr)
, m_session(session)
, m_ui(new Ui::MarkerManagementDialog)
, m_dtc(nullptr)
, m_ftc(nullptr)
, m_flmFtc(nullptr)
, m_avmInterface(nullptr)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("MarkerManagementDialog"))
{
m_ui->setupUi(this);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Edit,
this, &MarkerManagementDialog::onEditMarker);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Remove,
this, &MarkerManagementDialog::onRemoveMarker);
m_buttonBox->connectButton(LtsWidgets::DialogButton::Print,
this, &MarkerManagementDialog::onPrint);
connect(m_ui->widget, &LtsDataView::LtsDataView::signalDoubleClicked,
this, &MarkerManagementDialog::onEditMarker);
connect(m_ui->chkOtherMarkers, &QCheckBox::toggled,
this, &MarkerManagementDialog::onShowOtherUsersMarkers);
setOnlineHelpFilename(QStringLiteral("Situation-Markers"));
}
MarkerManagementDialog::~MarkerManagementDialog()
{
delete m_ui;
}
void MarkerManagementDialog::retranslate()
{
translate(m_ui, tr("Marker"));
}
void MarkerManagementDialog::tableColumnOrganiserSetting()
{
//LtsColumnOrganiser
m_ui->widget->setColumnsOrganiserEnabled(identifier(), true);
}
bool MarkerManagementDialog::init(const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<MarkerManagement::Interface::Ftc> &ftc,
const std::shared_ptr<FileManagement::Interface::Ftc> &flmFtc,
const std::shared_ptr<AudioVideoManagement::ForeignDataInterface> &avmInterface,
const std::shared_ptr<FileManagement::ForeignGuiInterface> &flmGui)
{
if (!dtc || !ftc)
return false;
if (m_dtc)
return true;
m_dtc = dtc;
m_ftc = ftc;
m_flmFtc = flmFtc;
m_avmInterface = avmInterface;
m_flmGui = flmGui;
m_model = new MarkerManagementDialogModel(this);
MarkerSortFilterProxyModel *proxyModel = new MarkerSortFilterProxyModel(this);
proxyModel->setOperatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
proxyModel->setSourceModel(m_model);
m_model->initModel(dtc, nullptr, m_flmGui);
m_ui->widget->setModel(proxyModel, [this]() { return new CustomViewMarker(this); });
m_ui->widget->hideColumn(MarkerManagementDialogModel::ColImage);
m_ui->widget->hideColumn(MarkerManagementDialogModel::ColOperator);
m_ui->widget->hideColumn(MarkerManagementDialogModel::ColFileId);
m_ui->widget->hideColumn(MarkerManagementDialogModel::ColOffset);
#ifndef LTS_DEBUG
m_ui->widget->hideColumn(MarkerManagementDialogModel::ColStreams);
#endif
connect(m_ui->widget, &LtsDataView::LtsDataView::signalSelectionChanged,
this, &MarkerManagementDialog::enaDisa);
enaDisa();
return true;
}
void MarkerManagementDialog::enaDisa()
{
QModelIndexList selectedRows = m_ui->widget->selectedRows();
const int cntSelectedRows = selectedRows.size();
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Edit, (cntSelectedRows == 1));
m_buttonBox->setButtonEnabled(LtsWidgets::DialogButton::Remove, (cntSelectedRows > 0));
}
void MarkerManagementDialog::onEditMarker()
{
const QModelIndex idx = m_ui->widget->currentIndex();
if (!idx.isValid())
return;
const MarkerManagement::Marker marker = m_model->getRowData(idx.row());
if (marker.id() <= 0)
return;
DEBUG_LOG(m_logger) << "current MarkerId: " << marker.id();
AudioVideoManagement::StreamNameMapping *streamNameMapping = nullptr;
if (m_avmInterface)
streamNameMapping = m_avmInterface->streamNameMapping();
MarkerEditDialog *dialog = new MarkerEditDialog(marker.id(), m_dtc, m_ftc, streamNameMapping);
addDialog(dialog, m_menuGroup, QStringLiteral("EditMarker%1").arg(marker.id()));
}
void MarkerManagementDialog::onRemoveMarker()
{
const QModelIndex idx = m_ui->widget->currentIndex();
if (!idx.isValid())
return;
const MarkerManagement::Marker marker = m_model->getRowData(idx.row());
if (marker.id() <= 0)
return;
Core::RemoveElementRequest req(marker.id());
m_requestHelper->addRequest([req, this]()
{
return m_ftc->markerRemoveRequest(req, this);
});
if (marker.fileContentId() > 0)
{
Core::RemoveElementRequest req1(marker.fileContentId());
m_requestHelper->addRequest([req1, this]()
{
return m_flmFtc->fileContentRemoveRequest(req1, this);
});
}
m_requestHelper->startRequests();
}
void MarkerManagementDialog::onPrint()
{
LtsPrinting::printView(m_session, this, m_ui->widget->treeView());
}
void MarkerManagementDialog::onShowOtherUsersMarkers(bool isChecked)
{
MarkerSortFilterProxyModel *proxyModel = static_cast<MarkerSortFilterProxyModel*>(m_ui->widget->proxyModel());
if (!proxyModel)
return;
proxyModel->setShowOtherUsersMarkers(isChecked);
}
} // namespace MarkerManagement
+85
View File
@@ -0,0 +1,85 @@
/**
* @RDE_HEADER@
* MarkerManagement - Marker Overview Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <MarkerManagement/mrk_ftc.h>
#include <MarkerManagement/mrk_dtc.h>
#include <MarkerManagement/logger.h>
#include <Plugins/AudioVideoManagement/avm_data_plugin_interface.h>
#include <Plugins/FileManagement/flm_data_plugin_interface.h>
#include <LtsWidgets/lts_dialog.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <FileManagement/flm_ftc.h>
namespace Ui
{
class MarkerManagementDialog;
}
namespace LtsSession
{
class LtsSession;
}
namespace FileManagement
{
class ForeignGuiInterface;
}
namespace MarkerManagement
{
class MarkerManagementDialogModel;
// --------------------------------------------------------
// MarkerManagementDialog
// --------------------------------------------------------
class MarkerManagementDialog : public LtsWidgets::LtsDialog
, protected MarkerManagement::Interface::Ftc::MarkerRemoveReplyHandler
, protected FileManagement::Interface::Ftc::FileContentRemoveReplyHandler
{
Q_OBJECT
public:
explicit MarkerManagementDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
~MarkerManagementDialog();
bool init(const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<MarkerManagement::Interface::Ftc> &ftc,
const std::shared_ptr<FileManagement::Interface::Ftc> &flmFtc,
const std::shared_ptr<AudioVideoManagement::ForeignDataInterface> &avmInterface,
const std::shared_ptr<FileManagement::ForeignGuiInterface> &flmGui);
void onMarkerRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onFileContentRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private slots:
void enaDisa();
void onEditMarker();
void onRemoveMarker();
void onPrint();
void onShowOtherUsersMarkers(bool isChecked);
private:
void retranslate() override;
void tableColumnOrganiserSetting() override;
QString m_menuGroup;
MarkerManagementDialogModel *m_model;
LtsSession::LtsSession *m_session;
Ui::MarkerManagementDialog *m_ui;
std::shared_ptr<MarkerManagement::Interface::Dtc> m_dtc;
std::shared_ptr<MarkerManagement::Interface::Ftc> m_ftc;
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
std::shared_ptr<AudioVideoManagement::ForeignDataInterface> m_avmInterface;
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
};
}
+52
View File
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MarkerManagementDialog</class>
<widget class="QWidget" name="MarkerManagementDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>598</width>
<height>512</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Marker Management</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="chkOtherMarkers">
<property name="text">
<string>show other users Markers</string>
</property>
</widget>
</item>
<item>
<widget class="LtsDataView::LtsDataView" name="widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>250</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,165 @@
/**
* @RDE_HEADER@
* HMI Plugin for MarkerManangement - Marker Edit Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "mrk_edit_dialog.h"
#include "ui_mrk_edit_dialog.h"
#include <AudioVideoManagement/stream_name_mapping.h>
#include <QDateTime>
#include <QListWidgetItem>
#include <LtsSession/lts_session_data.h>
namespace MarkerManagement
{
MarkerEditDialog::MarkerEditDialog(int markerId,
const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<MarkerManagement::Interface::Ftc> &ftc,
AudioVideoManagement::StreamNameMapping *streamNameMapping,
bool readonly)
: LtsWidgets::LtsDialog(nullptr, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_markerId(markerId)
, m_dtc(dtc)
, m_ftc(ftc)
, m_streamNameMapping(streamNameMapping)
, m_ui(new Ui::MarkerEditDialog)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("MarkerEditDialog"))
{
m_ui->setupUi(this);
m_ui->lblDebug->hide();
m_ui->lblDebugMap->hide();
m_ui->lblDebugFilter->hide();
m_ui->pteDebugMap->hide();
m_ui->pteDebugFilter->hide();
if (readonly)
setUnchangeable();
MarkerManagement::Marker data = dtc->marker(m_markerId);
if (m_markerId > 0)
{
m_ui->teNote->setText(QString::fromStdString(data.note()));
m_ui->spOffset->setValue(data.timeStampOffset()/1000);
m_ui->lblTimeStamp->setText(QDateTime::fromMSecsSinceEpoch(data.timeStamp()).toString(Qt::TextDate));
createDescriptions(data);
}
#ifndef LTS_DEBUG
if (LtsSessionData::LtsSessionData::getInstance()->debugFlagValue(QStringLiteral("Marker.Debug")) == QVariant(true))
#endif
{
m_ui->lblDebug->show();
m_ui->lblDebugMap->show();
m_ui->lblDebugFilter->show();
m_ui->pteDebugMap->show();
m_ui->pteDebugFilter->show();
m_ui->pteDebugMap->setPlainText(QString::fromStdString(data.mapSettings()));
m_ui->pteDebugFilter->setPlainText(QString::fromStdString(data.filter()));
}
setNoTopicLock(); // as this topic is only related to an operator
}
MarkerEditDialog::~MarkerEditDialog()
{
delete m_ui;
}
void MarkerEditDialog::retranslate()
{
translate(m_ui, m_dtc->marker(m_markerId), tr("Marker"));
}
//private
void MarkerEditDialog::createDescriptions(const MarkerManagement::Marker &marker)
{
QIcon icon;
for (const auto &desc : marker.descriptions())
{
if (desc.markerType() == MarkerManagement::MarkerType::Situation)
icon = QIcon(QLatin1String("icon:set_marker_situation.svg"));
if (desc.markerType() == MarkerManagement::MarkerType::Audio)
icon = QIcon(QLatin1String("icon:set_markers_audio.svg"));
if (desc.markerType() == MarkerManagement::MarkerType::Video)
icon = QIcon(QLatin1String("icon:set_marker_video.svg"));
QString description;
if (desc.markerType() == MarkerManagement::MarkerType::Video)
description = toDisplayNames(QString::fromStdString(desc.content()));
else
description = QString::fromStdString(desc.content());
m_ui->lwDescriptions->addItem(new QListWidgetItem(icon, description));
}
}
/**
* For Video Markers, the content contains a list of internal video stream names.
* A stream name can possibly have a '*' at the end.
* Returns the same list but with the internal names translated to display names.
*/
QString MarkerEditDialog::toDisplayNames(const QString &videoStreams)
{
const QLatin1Char star('*');
const QStringList parts = videoStreams.split(QLatin1Char(','));
QStringList displayParts;
displayParts.reserve(parts.size());
for (const QString &p : parts)
{
QString internalStreamName = p.trimmed();
bool hasStar = false;
if (!internalStreamName.isEmpty())
hasStar = internalStreamName[internalStreamName.size()-1] == star;
if (hasStar)
internalStreamName.chop(1);
QString displayName = m_streamNameMapping->displayName(internalStreamName);
if (hasStar)
displayName.append(star);
displayParts.append(displayName);
}
return displayParts.join(QLatin1String(", "));
}
//private slots:
bool MarkerEditDialog::apply()
{
MarkerManagement::Marker request = m_dtc->marker(m_markerId);
if (request.note() == m_ui->teNote->toPlainText().toStdString() &&
request.timeStampOffset() == m_ui->spOffset->value())
return false; // nothing changed
request.note(m_ui->teNote->toPlainText().toStdString());
request.timeStampOffset(m_ui->spOffset->value() * 1000); // ms
// TODO: update marker image in library for fileId ?
int fileId = request.fileContentId();
if (fileId > 0)
{
}
return m_requestHelper->startSingleRequest([this, request]()
{
return m_ftc->markerModifyRequest(request, this);
});
}
} //namespace markerManagement
@@ -0,0 +1,66 @@
/**
* @RDE_HEADER@
* HMI Plugin for MarkerManagement - Marker Edit Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <MarkerManagement/mrk_ftc.h>
#include <MarkerManagement/mrk_dtc.h>
#include <MarkerManagement/logger.h>
#include <LtsUtilsGuiDds/request_helper.h>
namespace Ui
{
class MarkerEditDialog;
}
namespace AudioVideoManagement
{
class StreamNameMapping;
}
namespace MarkerManagement
{
// --------------------------------------------------------
// MarkerEditDialog
// --------------------------------------------------------
class MarkerEditDialog : public LtsWidgets::LtsDialog,
protected MarkerManagement::Interface::Ftc::MarkerModifyReplyHandler
{
Q_OBJECT
public:
explicit MarkerEditDialog(int markerId,
const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<MarkerManagement::Interface::Ftc> &ftc,
AudioVideoManagement::StreamNameMapping *streamNameMapping,
bool readonly = false);
~MarkerEditDialog();
void onMarkerModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private:
void retranslate() override;
void createDescriptions(const MarkerManagement::Marker &marker);
QString toDisplayNames(const QString &videoStreams);
bool apply() override final;
private:
int m_markerId;
std::shared_ptr<MarkerManagement::Interface::Dtc> m_dtc;
std::shared_ptr<MarkerManagement::Interface::Ftc> m_ftc;
AudioVideoManagement::StreamNameMapping *m_streamNameMapping;
Ui::MarkerEditDialog *m_ui;
LtsUtils::RequestHelper *m_requestHelper;
LOGGER_T m_logger;
};
}//namespace MarkerManagement
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MarkerEditDialog</class>
<widget class="QWidget" name="MarkerEditDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>436</width>
<height>614</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="lblTime">
<property name="text">
<string>Time:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="lblTimeStamp">
<property name="text">
<string notr="true">TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Offset:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spOffset"/>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lblNote">
<property name="text">
<string>Note:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QTextEdit" name="teNote">
<property name="toolTip">
<string>Note</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QListWidget" name="lwDescriptions">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblDebug">
<property name="text">
<string>Debug:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="lblDebugMap">
<property name="text">
<string>Map Settings:</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QPlainTextEdit" name="pteDebugMap">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="lblDebugFilter">
<property name="text">
<string>Filter:</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QPlainTextEdit" name="pteDebugFilter">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="9" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,872 @@
/**
* @RDE_HEADER@
* GUI Plugin for ExerciseManangement
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "mrk_edit_gui_plugin.h"
#include "mrk_dialog.h"
#include "mrk_set_markers.h"
#include "snapshot_dialog.h"
#include "mrk_create_snapshot.h"
#include "TopicEditor/topic_editor.h"
#include "snapshot_dialog_model.h"
#include "mrk_edit_dialog.h"
#include <LtsWidgets/lts_events.h>
#include <LtsWidgets/lts_global_wait_dialog.h>
#include <MarkerManagement/mrk_operator_rights.h>
#include <MarkerManagement/Gui/Common/mrk_apply_filter.h>
#include <MarkerManagement/Gui/Common/mrk_dialog_model.h>
#include <OperatorManagement/opm_data_plugin_interface.h>
#include <LtsAppManager/lts_app_manager.h>
#include <Plugins/FileManagement/flm_data_plugin_interface.h>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QTimer>
#include <QCoreApplication>
namespace MarkerManagement
{
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
{
return std::make_shared<InterfaceImpl>(session);
}
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
: GuiPluginBase::Interface(session, getLogger("Plugins.Gui.Mrk.Edit"))
, m_requestHelper(nullptr)
, m_replayPartitionId(-1)
, m_markerAvailable(true)
, m_snapshotsAvailable(true)
, m_scriptsMrkIfc(nullptr)
{
qApp->installEventFilter(this);
}
bool InterfaceImpl::fetchInterfaces()
{
if (!m_session->getDtc<MarkerManagement::DataInterface>(m_dtc))
m_markerAvailable = false;
if (!m_session->getFtc<MarkerManagement::DataInterface>(m_ftc))
m_markerAvailable = false;
m_session->getForeignDataInterface_NEW<AudioVideoManagement::ForeignDataInterface>(m_avmInterface); // optional
m_session->getForeignDataInterface_NEW<FileManagement::ForeignGuiInterface>(m_flmGui); // optional
if (!m_session->getDtc<OperatorManagement::DataInterface>(m_opmDtc))
WARNING_LOG(m_logger) << "No Opm Dtc, no Snapshots";
if (!m_session->getDtc<FileManagement::DataInterface>(m_flmDtc))
WARNING_LOG(m_logger) << "No Flm Dtc, no Snapshots";
if (!m_session->getFtc<FileManagement::DataInterface>(m_flmFtc))
WARNING_LOG(m_logger) << "No Flm Ftc, no Snapshots";
if (!m_session->getForeignGuiInterface<SituationMap::ForeignGuiInterface>(m_sitMapGuiIfc))
WARNING_LOG(m_logger) << "No SitMap, no Snapshots";
if (!m_session->getDtc<SituationReplayManagement::DataInterface>(m_coreDtc))
{
WARNING_LOG(m_logger) << "No ReplayManagement!!";
return false;
}
if (m_session->app() == LtsAppDescriptor::App::Scripts
&& !m_session->getForeignGuiInterface<SituationReplay::ForeignGuiInterface>(m_srpIfc))
{
WARNING_LOG(m_logger) << "Scripts: MarkerManagement: no srp, no topic!";
return false;
}
// Snapshots
fetchInterfacesReplay();
return true;
}
bool InterfaceImpl::fetchInterfacesReplay()
{
m_snapshotsAvailable = true;
if (!m_session->getForeignDataInterface<SituationReplayManagement::DataInterface>(m_srmForeign))
{
WARNING_LOG(m_logger) << "No Srm, no Snapshots";
m_snapshotsAvailable = false;
}
if (!LtsAppManager::LtsAppManager::getInstance()->hasApp(LtsAppDescriptor::App::Snapshot))
{
DEBUG_LOG(m_logger) << "No Snapshot App? no Snapshots!"; //Only Debug because intentional
m_snapshotsAvailable = false;
}
if (!m_session->getDtc<OperatorManagement::DataInterface>(m_opmDtc))
{
WARNING_LOG(m_logger) << "No Opm, no Snapshots";
m_snapshotsAvailable = false;
}
if (!m_session->getForeignGuiInterface<FilterManagement::ForeignFltParticipantGuiInterface>(m_fltParticipantIfc))
{
WARNING_LOG(m_logger) << "No Flt/Part, no Snapshots";
m_snapshotsAvailable = false;
}
if (!m_session->getForeignGuiInterface<FilterManagement::ForeignAesGuiInterface>(m_fltAesIfc))
{
WARNING_LOG(m_logger) << "No Flt/Aes, no Snapshots";
m_snapshotsAvailable = false;
}
if (!m_session->getForeignGuiInterface<FilterManagement::ForeignFltBuildingComponentGuiInterface>(m_fltBuildingComponentIfc))
{
DEBUG_LOG(m_logger) << "No Flt/BuildingComponent";
// Nachtrag zu GUEZE-1769: since fltBuildingComponentIfc is optional:
// m_snapshotsAvailable = false;
}
if (!m_session->getForeignGuiInterface<FileManagement::ForeignGuiInterface>(m_flmGui))
{
WARNING_LOG(m_logger) << "No Flm, no Snapshots";
m_snapshotsAvailable = false;
}
return true;
}
void InterfaceImpl::clearInterfaces()
{
m_dtc = nullptr;
m_ftc = nullptr;
m_flmDtc = nullptr;
m_flmFtc = nullptr;
m_avmInterface = nullptr;
m_sitMapGuiIfc = nullptr;
m_coreDtc = nullptr;
m_srpIfc = nullptr;
m_srmForeign = nullptr;
m_opmDtc = nullptr;
m_fltParticipantIfc = nullptr;
m_fltAesIfc = nullptr;
m_fltBuildingComponentIfc = nullptr;
m_flmGui = nullptr;
}
QString InterfaceImpl::menuGroup() const
{
return tr("Marker Management");
}
void InterfaceImpl::showMarker(int markerId)
{
AudioVideoManagement::StreamNameMapping *streamNameMapping = nullptr;
if (m_avmInterface)
streamNameMapping = m_avmInterface->streamNameMapping();
m_session->addWidget(new MarkerEditDialog(markerId, m_dtc, m_ftc, streamNameMapping, false /* show only */),
menuGroup(), QStringLiteral("EditMarker%1").arg(markerId));
}
MarkerManagementDialogModel *InterfaceImpl::createMarkerModel()
{
if (!m_markerAvailable)
return nullptr;
MarkerManagementDialogModel *model = new MarkerManagementDialogModel; // unparented!
model->initModel(m_dtc, m_opmDtc, m_flmGui);
return model;
}
SnapshotDialogModel *InterfaceImpl::createSnapshotModel()
{
if (!m_snapshotsAvailable)
return nullptr;
SnapshotDialogModel *model = new SnapshotDialogModel; // unparented!
model->initModel(m_dtc, m_opmDtc, m_flmDtc, m_flmGui);
return model;
}
QSortFilterProxyModel *InterfaceImpl::createSnapshotFilterProxyModel()
{
if (!m_snapshotsAvailable)
return nullptr;
return new SnapshotDialogFilterProxyModel;
}
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
{
QVector<LtsWidgets::PluginData> ret;
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.menuText = tr("Markers");
plData.identifier = QLatin1String("mrkMarkerEdit");
plData.menuIcon = QIcon(QLatin1String("icon:set_marker_situation.svg"));
plData.operatorRight = OperatorRights::MarkerShow;
plData.exercisePart = LtsWidgets::ExercisePart::eExecution;
plData.createWidgetFunc = [this](QWidget *parent)
{
return LtsWidgets::initDialog(new MarkerManagementDialog(menuGroup(), m_session, parent),
m_dtc, m_ftc, m_flmFtc, m_avmInterface, m_flmGui);
};
ret.append(plData);
plData.menuText = tr("Add Marker");
plData.identifier = QLatin1String("mrkMarkerAdd");
plData.menuIcon = QIcon(QLatin1String("icon:set_marker.svg"));
plData.operatorRight = OperatorRights::MarkerEdit;
plData.exercisePart = LtsWidgets::ExercisePart::eExecution;
plData.createWidgetFunc = [this](QWidget *parent)
{
return LtsWidgets::initDialog(new SetMarkers(m_session, parent),
m_dtc, m_ftc, m_flmDtc, m_flmFtc, m_sitMapGuiIfc, m_fltParticipantIfc, m_fltAesIfc, m_fltBuildingComponentIfc, m_avmInterface);
};
ret.append(plData);
// Snapshots
fetchInterfacesReplay();
if (m_snapshotsAvailable)
{
// Snapshots
if (m_session->app() == LtsAppDescriptor::App::Snapshot)
{
LtsWidgets::PluginData plDataSN;
plDataSN.menuGroup = menuGroup();
plDataSN.menuText = tr("Snapshots");
plDataSN.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndAddAction;
plDataSN.identifier = QLatin1String("mrkSnapshots");
plDataSN.menuIcon = QIcon(QLatin1String("icon:snapshots.svg"));
plDataSN.operatorRight = OperatorRights::SnapshotShow;
plDataSN.exercisePart = LtsWidgets::ExercisePart::eExecution;
plDataSN.createWidgetFunc = [this](QWidget *parent)
{
return LtsWidgets::initDialog(new SnapshotDialog(menuGroup(), m_session, parent),
m_dtc, m_ftc, m_flmDtc, m_flmFtc, m_opmDtc, m_fltParticipantIfc, m_fltAesIfc, m_fltBuildingComponentIfc);
};
ret.append(plDataSN);
}
else
{
LtsWidgets::PluginData plDataS;
plDataS.menuGroup = menuGroup();
plDataS.menuText = tr("Snapshots");
plDataS.identifier = QLatin1String("mrkSnapshots");
plDataS.menuIcon = QIcon(QLatin1String("icon:snapshots.svg"));
plDataS.operatorRight = OperatorRights::SnapshotShow;
plDataS.exercisePart = LtsWidgets::ExercisePart::eExecution;
plDataS.directFunc = [this](const LtsWidgets::PluginData &)
{
return startSnapshot();
};
ret.append(plDataS);
// Zusaetzlich auch in 'Apps' aufschalten
//????? wie kann man das auch in 'Apps' anzeigen die keinen exercisePart haben ?? z.B. RessourcenManagement, Timeline
plDataS.menuGroup = tr("Apps");
plDataS.exercisePart = LtsWidgets::ExercisePart::eSpecial;
ret.append(plDataS);
}
// Add Snapshot
{
LtsWidgets::PluginData plDataAS;
plDataAS.menuGroup = menuGroup();
plDataAS.menuText = tr("Add Snapshot");
plDataAS.identifier = QLatin1String("mrkCreateSnapshot");
plDataAS.menuIcon = QIcon(QLatin1String("icon:create_snapshot.svg"));
plDataAS.operatorRight = OperatorRights::SnapshotEdit;
plDataAS.exercisePart = LtsWidgets::ExercisePart::eExecution;
plDataAS.createWidgetFunc = [this](QWidget *parent)
{
return LtsWidgets::initDialog(new SnapshotCreateDialog(parent),
m_ftc, m_flmDtc, m_flmFtc, m_sitMapGuiIfc, m_fltParticipantIfc, m_fltAesIfc, m_fltBuildingComponentIfc, m_session);
};
ret.append(plDataAS);
}
}
return ret;
}
void InterfaceImpl::startSnapshot()
{
if (!m_requestHelper)
m_requestHelper = new LtsUtils::RequestHelper(this);
m_replayPartitionId = -1;
try
{
DEBUG_LOG(m_logger) << "replayPartitionCreateRequest ...";
m_replayPartitionId = m_srmForeign->replayPartitionCreateRequest(m_session->exerciseId(),
LtsSessionData::LtsSessionData::getInstance()->getWorkstationId(),
LtsSessionData::LtsSessionData::getInstance()->getOperatorId(),
Core::ReplayType_def::SnapshotData);
DEBUG_LOG(m_logger) << "replayPartitionCreateRequest ...DONE";
}
// exception is basclass of runtime_error:
catch(const std::runtime_error &rterr)
{
ERROR_LOG(m_logger) << "Failed to start replay partition for snapshot. std::runtime_error";
ERROR_LOG(m_logger) << "Failed to start replay partition for snapshot. std::runtime_error: " << rterr.what();
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("Failed to start replay partition for snapshot!"));
return;
}
catch(const std::exception &exception)
{
ERROR_LOG(m_logger) << "Failed to start replay partition for snapshot. Exception: " << exception.what();
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("Failed to start replay partition for snapshot!"));
return;
}
catch(...)
{
ERROR_LOG(m_logger) << "Failed to start replay partition for snapshot. Exception: ... ";
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("Failed to start replay partition for snapshot!"));
return;
}
if (m_replayPartitionId < 0)
{
ERROR_LOG(m_logger) << "Failed to start replay partition for snapshot - invalid replay partition id!";
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("Failed to start replay partition for snapshot - invalid replay partition id!"));
return;
}
LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(tr("Waiting for Snapshot app"));
//if (!LtsSessionData::LtsSessionData::getInstance()->isTablet()) // default behaviour (no tablet): wait for replay partition for 15 seconds
{
QTimer *t = new QTimer(this);
t->setInterval(250);
t->setProperty("tries", 0); // HACK
connect(t, &QTimer::timeout,
this, [this, t]()
{
int tries = t->property("tries").toInt();
Core::ReplayPartition replay = m_coreDtc->replayPartition(m_replayPartitionId);
if (replay.id() == m_replayPartitionId)
{
t->stop();
m_replayPartitionId = -1;
startSnapshotApp(replay);
return;
}
if (tries > 30)
{
LtsWidgets::LtsGlobalWaitDialog::getInstance()->done();
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("Cannot start Snapshot because replay partition timed out", "same as in pre_script_dialog.cpp"));
t->stop();
return;
}
t->setProperty("tries", ++tries);
});
t->start();
}
// else // backup solution: windows tablet replay hack
// {
// QTimer *t1 = new QTimer(this);
// t1->setInterval(3000);
// t1->setSingleShot(true);
// connect(t1, &QTimer::timeout,
// this, [this]()
// {
// QPointer<LtsPluginManager::LtsPluginManager> app(LtsAppManager::LtsAppManager::getInstance()->createApp(LtsAppDescriptor::App::Situation,
// m_session->connParams(), QString(), true));
// QTimer *t2 = new QTimer(this);
// t2->setInterval(10000);
// t2->setSingleShot(true);
// connect(t2, &QTimer::timeout,
// this, [app]()
// {
// if (app)
// app->deleteLater();
// });
// t2->start();
// });
// t1->start();
// }
}
void InterfaceImpl::onReplayPartitionChanged(const Core::ReplayPartition &data, DataModification mod)
{
if (mod != DataModification::eAdded)
return;
if (m_replayPartitionId < 0)
return;
if (data.id() == m_replayPartitionId)
{
m_replayPartitionId = -1;
startSnapshotApp(data);
}
}
void InterfaceImpl::startSnapshotApp(const Core::ReplayPartition &data)
{
LtsWidgets::LtsGlobalWaitDialog::getInstance()->done();
const LtsSession::DdsConnectionParams connParams(data);
// appid enum is in ltssession
LtsAppManager::LtsAppManager::getInstance()->createApp(LtsAppDescriptor::App::Snapshot, connParams);
}
TopicEditorBase::TopicEditor *InterfaceImpl::createTopicEditor(const TopicEditorBase::TopicData &data)
{
SnapshotTopicEditor *editor = new SnapshotTopicEditor(createSnapshotModel(), createSnapshotFilterProxyModel());
editor->setTopicData(data);
return editor;
}
bool InterfaceImpl::applyFilter(const Snapshot &snapshot, NGL::INGLLogger &logger)
{
const QByteArray filterContent(QByteArray::fromRawData(snapshot.filter().c_str(), snapshot.filter().size()));
if (filterContent.isEmpty())
{
WARNING_LOG(logger) << "filterContent is empty, snapshot.id(): " << snapshot.id();
return false;
}
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> fltParticpantIfc;
std::shared_ptr<FilterManagement::ForeignAesGuiInterface> fltAesIfc;
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> fltBuildingComponentIfc;
m_session->getForeignGuiInterface<FilterManagement::ForeignFltParticipantGuiInterface>(fltParticpantIfc); // not in global
m_session->getForeignGuiInterface<FilterManagement::ForeignAesGuiInterface>(fltAesIfc); // not in global
m_session->getForeignGuiInterface<FilterManagement::ForeignFltBuildingComponentGuiInterface>(fltBuildingComponentIfc); // not in global
if (fltParticpantIfc && fltAesIfc)
{
MarkerManagementApplyFilter appFilter(m_session, fltParticpantIfc, fltAesIfc, fltBuildingComponentIfc);
if (appFilter.applyFilter(filterContent))
{
return true;
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << "Error while applying filters";
}
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << "No Filter Ifc (Part or Aes) to apply filters";
}
return false;
}
bool InterfaceImpl::snapshotAdjustSitMap(const Snapshot &snapshot, bool bApplyFilter,
QByteArray &originalMapSettings,
SituationMap::ForeignGuiInterface *sitMapGuiIfc,
NGL::INGLLogger &logger)
{
bool success = true;
if (sitMapGuiIfc == nullptr) // not specified? use this session's sitmap ifc
{
std::shared_ptr<SituationMap::ForeignGuiInterface> sitMapIfc;
if (m_session->getForeignGuiInterface(sitMapIfc))
{
sitMapGuiIfc = sitMapIfc.get();
}
}
// SitMapForeignInterface => set Settings
if (sitMapGuiIfc != nullptr)
{
const QByteArray ba(QByteArray::fromRawData(snapshot.mapSettings().c_str(), snapshot.mapSettings().size()));
originalMapSettings = sitMapGuiIfc->operatorMapSettingsJson(); // out param !
// TODO: save filters, but filters are not even set by applyFilter() ... ?
sitMapGuiIfc->setOperatorMapSettingsJson(ba);
const int snapShotOverlayId = -4711; // TODO: ???
if (sitMapGuiIfc->planOverlayList().contains(snapShotOverlayId))
{
sitMapGuiIfc->planOverlayRemove(snapShotOverlayId);
}
const QByteArray &planOverlay = QByteArray(snapshot.planOverlay().c_str(), snapshot.planOverlay().size());
if (!planOverlay.isEmpty())
{
const bool bIsMapReady = sitMapGuiIfc->isMapReady();
DEBUG_LOG(m_logger) << LOGFUNCTION << " bIsMapReady = " << bIsMapReady;
if (bIsMapReady)
{
if (!sitMapGuiIfc->planOverlaySetContent(snapShotOverlayId, QStringLiteral("AdjustOverlay"), planOverlay, true))
{
WARNING_LOG(logger) << "Error add planOverlay to snapshot "
<< " 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.
auto onMapIsReadyFn = [sitMapGuiIfc, snapShotOverlayId, planOverlay]() {
qDebug() << " try again: do planOverlaySetContent...";
if (!sitMapGuiIfc->planOverlaySetContent(snapShotOverlayId, QStringLiteral("AdjustOverlay"), planOverlay, true))
qCritical() << "Error add planOverlay to snapshot "
<< " planOverlay.size(): " << planOverlay.size()
<< " planOverlay: " << planOverlay;
};
if (!sitMapGuiIfc->setMapReadyCallback(this, onMapIsReadyFn))
ERROR_LOG(m_logger) << LOGFUNCTION << ", setMapReadyCallback failed, snapShotOverlayId: " << snapShotOverlayId;
}
}
}
else
{
WARNING_LOG(logger) << "No Situation Map Gui Ifc available to set the plan on ..";
}
// Filter:
if (bApplyFilter && !applyFilter(snapshot, logger))
{
WARNING_LOG(logger) << "applyFilter failed";
return false;
}
if (sitMapGuiIfc)
sitMapGuiIfc->forceUpdate();
return success;
}
bool InterfaceImpl::snapshotAdjustSitMap(const Snapshot &snapshot, bool bApplyFilter, /*int replayPartitionId,*/
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMapGuiIfc,
NGL::INGLLogger &logger)
{
SituationMap::ForeignGuiInterface *ifc = sitMapGuiIfc.get();
QByteArray x;
return snapshotAdjustSitMap(snapshot, bApplyFilter, x, ifc, logger);
}
void InterfaceImpl::setScriptsMrkIfc(MarkerManagement::ForeignGuiInterface* sitMapMrkIfc)
{
m_scriptsMrkIfc = sitMapMrkIfc;
}
void InterfaceImpl::resetReplay()
{
std::shared_ptr<SituationMap::ForeignGuiInterface> sitMapIfc;
if (m_session->getForeignGuiInterface(sitMapIfc))
{
const int snapShotOverlayId = -4711; // TODO: ???
if (m_sitMapGuiIfc->planOverlayList().contains(snapShotOverlayId))
m_sitMapGuiIfc->planOverlayRemove(snapShotOverlayId);
// vermeide unnötig viele Umschaltungen zw. 2D/3D -> KEIN setOperatorMapSettingsJson(originalMapSettings);
// if (!originalMapSettings.isEmpty())
// m_sitMapGuiIfc->setOperatorMapSettingsJson(originalMapSettings);
}
else
{
WARNING_LOG(m_logger) << "could not reset sit map original settings - leaving settings as is...";
}
}
TopicReplay::Interface *InterfaceImpl::createInterface(TopicEditorBase::TopicType)
{
std::shared_ptr<MarkerManagement::Interface::Dtc> mrkDtc;
if (!m_session->getDtc<MarkerManagement::DataInterface>(mrkDtc))
WARNING_LOG(m_logger) << "mrk dtc missing - snapshot topics cannot live fetch data but instead uses data saved inside the topic";
return new TopicReplayInterface(m_srpIfc, mrkDtc, m_scriptsMrkIfc /* to redirect snapshot data to the mrk ifc of the sitMapApp */, m_logger);
}
//------------------------------------------------------------------------------
TopicReplayInterface::TopicReplayInterface(const std::shared_ptr<SituationReplay::ForeignGuiInterface> &srpIfc,
const std::shared_ptr<MarkerManagement::Interface::Dtc> &mrkDtc,
MarkerManagement::ForeignGuiInterface *parentIfc,
NGL::INGLLogger &logger)
: m_srpIfc(srpIfc)
, m_logger(logger)
, m_parentIfc(parentIfc)
, m_mrkDtc(mrkDtc)
{}
TopicReplayInterface::~TopicReplayInterface()
{
if (m_srpIfc != nullptr)
m_srpIfc->stopReplay();
m_parentIfc->resetReplay();
}
// Script Playback Controls:
bool TopicReplayInterface::playbackInit(const QJsonObject &attributes)
{
if (m_srpIfc == nullptr)
{
WARNING_LOG(m_logger) << "MarkerManagement:TopicReplayInterface::playbackInit: no srp ifc, no playback";
return false;
}
// fetch a live version of the snapshot ..
if (m_mrkDtc)
m_snapshot = m_mrkDtc->snapshot(attributes[QStringLiteral("snapshotId")].toInt(0 /* invalid */));
// .. or use the saved backup data from the topic if snapshot does not exist anymore
if (m_snapshot.id() <= 0 || m_snapshot.timeStamp() < 1)
{
WARNING_LOG(m_logger) << "cannot fetch live snapshot data (maybe snapshot with id '"<<attributes[QStringLiteral("snapshotId")].toInt(0 /* invalid */)<<"' was deleted), using saved data - timestamp: " << m_snapshot.timeStamp();
m_snapshot.planOverlay(attributes[QStringLiteral("planOverlay")].toString().toUtf8().data());
m_snapshot.filter(attributes[QStringLiteral("snapshotFilter")].toString().toUtf8().data());
m_snapshot.timeStamp(qRound64(attributes[QStringLiteral("timeStamp")].toDouble()));
m_snapshot.mapSettings(attributes[QStringLiteral("mapSettings")].toString().toUtf8().data());
}
if (m_snapshot.timeStamp() < 1)
{
WARNING_LOG(m_logger) << "invalid snapshot timestamp for playback: " << QString::fromUtf8(QJsonDocument(attributes).toJson());
return false;
}
int scriptsExerciseId = attributes[QStringLiteral("scriptsExerciseId")].toInt(0);
if (scriptsExerciseId == 0)
{
WARNING_LOG(m_logger) << "invalid script's exercise id for playback: "
<< attributes[QStringLiteral("scriptsExerciseId")].toVariant().toString();
return false;
}
if (m_parentIfc == nullptr || !m_parentIfc->snapshotAdjustSitMap(m_snapshot, true, m_originalMapSettings, nullptr, m_logger))
{
WARNING_LOG(m_logger) << "Cannot adjust Situation Map Ifc from Snapshot app";
return false;
}
return true;
}
bool TopicReplayInterface::playbackStart(int /*secondsOffset - ignore offset as a snapshot is always at second timeStamp()*/)
{
return m_srpIfc->startReplay(m_snapshot.timeStamp(), m_snapshot.timeStamp(), 0 /* stop directly after start to simulate a snapshot */);
}
bool TopicReplayInterface::playbackPause()
{
// TODO: make them return a bool
/*return */m_srpIfc->pauseReplay();
return true;
}
bool TopicReplayInterface::exportTopic(const QJsonObject &, const QString &, TopicEditorBase::ExportNotifier *notifier)
{
// nothing to do here
notifier->setExportSuccessful({});
return true;
}
QVector<TopicEditorBase::TopicData> TopicReplayInterface::additionalTrackEntries(const QJsonObject &attributes) const
{
int fileContentId = attributes[QStringLiteral("fileContentId")].toInt();
if (!fileContentId)
return {};
TopicEditorBase::TopicData data;
data.topicType = TopicEditorBase::TopicType::Image;
data.properties = QJsonObject({{QStringLiteral("FileId"), fileContentId}});
return { data };
}
bool InterfaceImpl::eventFilter(QObject *obj, QEvent *event)
{
if (obj == qApp && !event->isAccepted() &&
(event->type() == LtsWidgets::SetMarkerEvent::setMarkerEventId() ||
event->type() == LtsWidgets::AddMarkerEvent::addMarkerEventId() ||
event->type() == LtsWidgets::AddSnapshotEvent::addSnapshotEventId() ||
event->type() == LtsWidgets::SaveSnapshotEvent::saveSnapshotEventId()))
{
ERROR_LOG(m_logger) << "Filtering voice commands (add/set marker, add/save snapshot)";
if (event->type() == LtsWidgets::SetMarkerEvent::setMarkerEventId())
{
DEBUG_LOG(m_logger) << "Set marker";
auto ev = static_cast<LtsWidgets::SetMarkerEvent*>(event);
DEBUG_LOG(m_logger) << "Event description = " << ev->getDescription();
MarkerManagement::Marker req;
auto &descriptions = req.descriptions();
MarkerManagement::MarkerDescription ma;
ma.markerType() = MarkerManagement::MarkerType::Situation;
descriptions.push_back(ma);
// save mapSettings and filter
if (!m_sitMapGuiIfc)
return false;
const QByteArray mapSettings = m_sitMapGuiIfc->operatorMapSettingsJson();
req.mapSettings(mapSettings.constData());
//TODO: get filterParams
//req.filter(getFilterParams().constData());
if (ev->getDescription().size() > 0)
req.note(ev->getDescription().toStdString());
req.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
req.timeStamp(QDateTime::currentMSecsSinceEpoch());
req.timeStampOffset(10000);
req.fileContentId(0);
if (!m_requestHelper)
m_requestHelper = new LtsUtils::RequestHelper(this);
if (m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->markerModifyRequest(req, this);
}))
{
req.id(m_requestHelper->getRepliedId());
DEBUG_LOG(m_logger) << "Saved Marker with id = " << m_requestHelper->getRepliedId();
}
}
if (event->type() == LtsWidgets::AddMarkerEvent::addMarkerEventId())
{
DEBUG_LOG(m_logger) << "init dialog Add marker";
LtsWidgets::LtsBaseLayoutWidget *baseLayout = m_session->baseLayout();
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.identifier = QLatin1String("mrkMarkerAdd");
LtsWidgets::LtsDialog *ltsDialog = baseLayout->getWidget(plData.menuGroup, plData.identifier, plData.layoutArea);
if (ltsDialog)
{
baseLayout->focusTab(plData.menuGroup, plData.identifier, plData.layoutArea);
}
else
{
auto dialog = LtsWidgets::initDialog(new SetMarkers(m_session, baseLayout),
m_dtc, m_ftc, m_flmDtc, m_flmFtc, m_sitMapGuiIfc, m_fltParticipantIfc, m_fltAesIfc, m_fltBuildingComponentIfc, m_avmInterface);
if (dialog)
baseLayout->addWidget(dialog, plData.menuGroup, plData.identifier, plData.layoutArea, plData.closable);
}
return true;
}
if (event->type() == LtsWidgets::AddSnapshotEvent::addSnapshotEventId() && m_snapshotsAvailable)
{
DEBUG_LOG(m_logger) << "init dialog Add snapshot";
LtsWidgets::LtsBaseLayoutWidget *baseLayout = m_session->baseLayout();
LtsWidgets::PluginData plData;
plData.menuGroup = menuGroup();
plData.identifier = QLatin1String("mrkCreateSnapshot");
LtsWidgets::LtsDialog *ltsDialog = baseLayout->getWidget(plData.menuGroup, plData.identifier, plData.layoutArea);
if (ltsDialog)
{
baseLayout->focusTab(plData.menuGroup, plData.identifier, plData.layoutArea);
}
else
{
auto dialog = LtsWidgets::initDialog(new SnapshotCreateDialog(baseLayout),
m_ftc, m_flmDtc, m_flmFtc, m_sitMapGuiIfc, m_fltParticipantIfc, m_fltAesIfc, m_fltBuildingComponentIfc, m_session);
if (dialog)
baseLayout->addWidget(dialog, plData.menuGroup, plData.identifier, plData.layoutArea, plData.closable);
}
return true;
}
if (event->type() == LtsWidgets::SaveSnapshotEvent::saveSnapshotEventId() && m_snapshotsAvailable)
{
DEBUG_LOG(m_logger) << "Save snapshot";
auto ev = static_cast<LtsWidgets::SaveSnapshotEvent*>(event);
DEBUG_LOG(m_logger) << "Event description = " << ev->getDescription();
qint64 partitionTime = m_session->partitionTime();
//auto spSitMapGuiIfc = m_sitMapGuiIfc.lock();
const QByteArray &mapSettings = m_sitMapGuiIfc->operatorMapSettingsJson();
const QByteArray &movementTracks = m_sitMapGuiIfc->movementTrackManagerSettingsJson();
MarkerManagement::Snapshot req;
req.id(0);
req.name(ev->getDescription().toStdString());
req.description(ev->getDescription().toStdString());
req.mapSettings(mapSettings.constData());
req.movementTracks(movementTracks.constData());
//TODO: get filter params
//req.filter(getFilterParams().constData());
req.planOverlay(std::string());
req.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
req.timeStamp(partitionTime);
req.fileContentId(0);
if (!m_requestHelper)
m_requestHelper = new LtsUtils::RequestHelper(this);
if (m_requestHelper->startSingleRequest([req, this]()
{
return m_ftc->snapshotModifyRequest(req, this);
}))
{
req.id(m_requestHelper->getRepliedId());
DEBUG_LOG(m_logger) << "Saved Snapshot with id = " << m_requestHelper->getRepliedId();
}
}
}
return QObject::eventFilter(obj, event);
}
} // namespace MarkerManagement
@@ -0,0 +1,169 @@
/**
* @RDE_HEADER@
* Gui Plugin for MarkerManagement
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <MarkerManagement/logger.h>
#include <MarkerManagement/mrk_ftc.h>
#include <MarkerManagement/mrk_dtc.h>
#include <FileManagement/flm_ftc.h>
#include <FileManagement/flm_dtc.h>
#include <OperatorManagement/opm_dtc.h>
#include <DDS/Core/core_dtc.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsSession/lts_session.h>
#include <PluginInterfaces/gui_plugin_interface.h>
#include <Plugins/MarkerManagement/mrk_data_plugin_interface.h>
#include <Plugins/MarkerManagement/mrk_gui_plugin_interface.h>
#include <Plugins/AudioVideoManagement/avm_data_plugin_interface.h>
#include <Plugins/SituationReplayManagement/srm_data_plugin_interface.h>
#include <Plugins/SituationReplay/srp_gui_plugin_interface.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <Plugins/FilterManagement/flt_data_plugin_interface.h>
#include <Plugins/FilterManagement/flt_participant_plugin_interface.h>
#include <Plugins/FilterManagement/flt_aes_plugin_interface.h>
#include <Plugins/FilterManagement/flt_building_cmpnt_plugin_interface.h>
#include <Plugins/FileManagement/flm_explorer_gui_plugin_interface.h>
class QSortFilterProxyModel;
namespace MarkerManagement
{
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
{
Q_PLUGIN_METADATA(IID "gui:3:mrk")
Q_INTERFACES(GuiPluginBase::Plugin)
Q_OBJECT
public:
GuiPlugin() = default;
~GuiPlugin() = default;
QString pluginName() override { return QLatin1String("MarkerManagementGuiPlugin"); }
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
bool availableInPartition(IDL::PartitionType partition) const override
{
return partition == IDL::PartitionType::Exercise ||
partition == IDL::PartitionType::Replay;
}
};
class InterfaceImpl;
class TopicReplayInterface : public QObject, public TopicReplay::Interface
{
Q_OBJECT
public:
TopicReplayInterface(const std::shared_ptr<SituationReplay::ForeignGuiInterface> &srpIfc,
const std::shared_ptr<MarkerManagement::Interface::Dtc> &mrkDtc,
MarkerManagement::ForeignGuiInterface *parentIfc,
NGL::INGLLogger &logger);
~TopicReplayInterface();
// Script Playback Controls:
bool playbackInit(const QJsonObject &attributes) override;
bool playbackStart(int secondsOffset) override;
bool playbackPause() override;
bool exportTopic(const QJsonObject &, const QString &, TopicEditorBase::ExportNotifier *notifier) override;
QVector<TopicEditorBase::TopicData> additionalTrackEntries(const QJsonObject &attributes) const override;
private:
std::shared_ptr<SituationReplay::ForeignGuiInterface> m_srpIfc;
Snapshot m_snapshot;
NGL::INGLLogger &m_logger;
QByteArray m_originalMapSettings;
MarkerManagement::ForeignGuiInterface *m_parentIfc;
std::shared_ptr<MarkerManagement::Interface::Dtc> m_mrkDtc;
};
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface, public ForeignGuiInterface
, protected SituationReplayManagement::Interface::Ftc::ReplayPartitionCreateReplyHandler
, protected MarkerManagement::Interface::Ftc::MarkerModifyReplyHandler
, protected MarkerManagement::Interface::Ftc::SnapshotModifyReplyHandler
{
Q_OBJECT
public:
explicit InterfaceImpl(LtsSession::LtsSession *session);
bool fetchInterfaces() override;
bool fetchInterfacesReplay();
void clearInterfaces() override;
QString menuGroup() const override;
QVector<LtsWidgets::PluginData> getActions() override;
bool availableInPartition(IDL::PartitionType partition) const override { return partition == IDL::PartitionType::Exercise || partition == IDL::PartitionType::Replay; }
MarkerManagement::MarkerManagementDialogModel *createMarkerModel() override final;
MarkerManagement::SnapshotDialogModel *createSnapshotModel() override final;
QSortFilterProxyModel *createSnapshotFilterProxyModel();
// Script Editor Topic Editor:
TopicEditorBase::TopicEditor *createTopicEditor(const TopicEditorBase::TopicData &data) override final;
// Script Player:
TopicReplay::Interface *createInterface(TopicEditorBase::TopicType) override final;
void showMarker(int markerId) override final;
bool snapshotAdjustSitMap(const Snapshot &snapshot, bool bApplyFilter,
const std::shared_ptr<SituationMap::ForeignGuiInterface> &sitMapGuiIfc,
NGL::INGLLogger &logger);
bool snapshotAdjustSitMap(const Snapshot &snapshot, bool bApplyFilter,
QByteArray &originalMapSettings,
SituationMap::ForeignGuiInterface *sitMapGuiIfc,
NGL::INGLLogger &logger) override;
void setScriptsMrkIfc(MarkerManagement::ForeignGuiInterface* sitMapMrkIfc) override;
void resetReplay() override;
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private:
bool applyFilter(const Snapshot &snapshot, NGL::INGLLogger &logger);
void startSnapshot();
void onReplayPartitionCreateReply(const Core::FunctionReplyObject &reply) override { m_requestHelper->requestReply(reply); }
void onReplayPartitionChanged(const Core::ReplayPartition &data, DataModification mod);
void startSnapshotApp(const Core::ReplayPartition &data);
void onMarkerModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onSnapshotModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private:
std::shared_ptr<MarkerManagement::Interface::Dtc> m_dtc;
std::shared_ptr<MarkerManagement::Interface::Ftc> m_ftc;
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
std::shared_ptr<Core::Interface::Dtc> m_coreDtc;
std::shared_ptr<AudioVideoManagement::ForeignDataInterface> m_avmInterface;
std::shared_ptr<SituationReplayManagement::ForeignDataInterface> m_srmForeign;
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
std::shared_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> m_fltParticipantIfc;
std::shared_ptr<FilterManagement::ForeignAesGuiInterface> m_fltAesIfc;
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> m_fltBuildingComponentIfc;
std::shared_ptr<SituationReplay::ForeignGuiInterface> m_srpIfc;
LtsUtils::RequestHelper *m_requestHelper;
int m_replayPartitionId;
bool m_markerAvailable;
bool m_snapshotsAvailable;
MarkerManagement::ForeignGuiInterface *m_scriptsMrkIfc;
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
friend class TopicReplayInterface;
};
} // namespace MarkerManagement
@@ -0,0 +1,440 @@
#include "mrk_set_markers.h"
#include "ui_mrk_set_markers.h"
#include <nglsettings/nglsettings_settings.h>
#include <LtsSession/lts_session_data.h>
#include <LtsUtilsCore/dds_vector.h>
#include <LtsUtilsCore/dds_vector_to_pixmap.h>
#include <LtsUtilsCore/await.h>
#include <LtsWidgets/lts_global_wait_dialog.h>
#include <ngltools/ngltools_dtg.h>
#include <AudioVideoManagement/ava_state.h>
#include <AudioVideoManagement/stream_name_mapping.h>
#include <FilterManagement/flt_data_plugin_aes_display_filter.h>
#include <FilterManagement/flt_symbol_appearance_settings.h>
#include <FilterManagement/flt_building_cmpnt_settings.h>
#include <Plugins/SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <QDateTime>
#include <QJsonDocument>
namespace
{
/**
* Select the item with the given internal stream name.
* internalStreamName may be Null in order to refer to "All" streams.
*/
void selectStream(QComboBox *cb, const QVariant &internalStreamName)
{
Q_ASSERT(cb);
Q_ASSERT(cb->count() > 0);
if (internalStreamName.isNull())
cb->setCurrentIndex(0);
for (int i = 1; i < cb->count(); ++i)
{
if (cb->currentData().toString() == internalStreamName)
{
cb->setCurrentIndex(i);
return;
}
}
// no matching item found
cb->setCurrentIndex(0);
}
bool containsStream(QComboBox *cb, const QString &internalStreamName)
{
Q_ASSERT(cb);
for (int i = 1; i < cb->count(); ++i) // start at 1; 0 is "All" streams
{
if (cb->itemData(i).toString() == internalStreamName)
return true;
}
return false;
}
} // anonymous namespace
namespace MarkerManagement
{
FinishedSignal::FinishedSignal():QObject(){}
SetMarkers::SetMarkers(LtsSession::LtsSession *session, QWidget *parent)
: LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_session(session)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_ui(new Ui::SetMarkers)
, m_logger(getLogger("MarkerCreateDialog"))
{
m_ui->setupUi(this);
m_ui->dteMarkerTime->setRetrieveCurrentTimeCallback([this]() { return m_session->partitionTime(); });
m_ui->dteMarkerTime->setMsecsSinceEpoch(m_session->partitionTime());
connect(m_ui->cbAudio, &QCheckBox::stateChanged, this, &SetMarkers::onAudioClicked);
connect(m_ui->cbVideo, &QCheckBox::stateChanged, this, &SetMarkers::onVideoClicked);
setOnlineHelpFilename(QStringLiteral("Situation-Add_Marker"));
}
SetMarkers::~SetMarkers()
{
delete m_ui;
}
void SetMarkers::retranslate()
{
translate(m_ui, QString(), true, tr("Marker"));
m_uiRequirements->clear();
m_uiRequirements->addRequirement({m_ui->lblAudioStreams, [this]() {
return (!m_ui->cbAudio->isChecked()
|| m_ui->cbxAudioStreams->isEnabled()); }
});
m_uiRequirements->addRequirement({m_ui->lblVideoStreams, [this]() {
return (!m_ui->cbVideo->isChecked()
|| m_ui->cbxVideoStreams->isEnabled()); }
});
m_uiRequirements->addRequirement({m_ui->lblMarkerTypeText, [this]() { return (m_ui->cbAudio->isChecked() || m_ui->cbVideo->isChecked() || m_ui->cbSit->isChecked()); }, tr("Select at least one marker type.")});
m_uiRequirements->addRequirement({m_ui->lblNote, [this]() { return !m_ui->teNote->toPlainText().isEmpty(); }});
m_uiRequirements->addRequirement({m_ui->lblTime, [this]() { return (m_ui->dteMarkerTime->msecsSinceEpoch() > 0); } });
}
bool SetMarkers::init(const std::shared_ptr<MarkerManagement::Interface::Dtc> &mrk_dtc,
const std::shared_ptr<MarkerManagement::Interface::Ftc> &mrk_ftc,
const std::shared_ptr<FileManagement::Interface::Dtc> &flm_dtc,
const std::shared_ptr<FileManagement::Interface::Ftc> &flm_ftc,
const std::weak_ptr<SituationMap::ForeignGuiInterface> &sitMapIfc,
const std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> &fltParticipantIfc,
const std::shared_ptr<FilterManagement::ForeignAesGuiInterface> &fltAesIfc,
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> &fltBuildingComponentIfc,
const std::shared_ptr<AudioVideoManagement::ForeignDataInterface> &avmInterface,
const MarkerManagement::Marker &data)
{
if (!mrk_dtc || !mrk_ftc || !sitMapIfc.lock())
return false;
m_editData = data;
m_fileId = data.fileContentId();
m_dtc = mrk_dtc;
m_ftc = mrk_ftc;
m_flmDtc = flm_dtc;
m_flmFtc = flm_ftc;
m_sitMapGuiIfc = sitMapIfc;
m_fltParticipantIfc = fltParticipantIfc;
m_fltAesIfc = fltAesIfc;
m_fltBuildingComponentIfc = fltBuildingComponentIfc;
m_avmDataIfc = avmInterface;
if (m_avmDataIfc && m_avmDataIfc->hasAvsSession())
{
m_avaState = m_avmDataIfc->avaState();
m_streamNameMapping = m_avmDataIfc->streamNameMapping();
onAudioClicked();
onVideoClicked();
}
else
{
// Someone else has access to the AvaSession in a different exercise context -- or we don't even have the AVM-Plugin.
// Disable all Video/Audio stuff
m_ui->cbVideo->hide();
m_ui->cbAudio->hide();
m_ui->cbxVideoStreams->hide();
m_ui->cbxAudioStreams->hide();
m_ui->lblAudioStreams->hide();
m_ui->lblVideoStreams->hide();
m_ui->cbSit->setChecked(true);
m_ui->cbSit->setEnabled(false);
}
return true;
}
//private slots
bool SetMarkers::apply()
{
Waiter _(this);
try
{
// save image in library only when is a Situation type marker
if (m_ui->cbSit->isChecked())
saveMarkerInLibrary();
else
sendMarkerRequest();
}
catch(const std::exception &ex)
{
ERROR_LOG(m_logger) << "saving marker failed: " << ex.what();
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Failed to save marker. Please try again later."));
return false;
}
return true;
}
void SetMarkers::onAudioClicked()
{
Q_ASSERT(m_avaState);
const QStringList audioStreams = m_avaState->getRtProfile();
QString currentText;
if (!audioStreams.isEmpty())
currentText = audioStreams.first();
m_ui->cbxAudioStreams->clear();
m_ui->cbxAudioStreams->addItem(tr("All"));
for (const QString &audioChannel : audioStreams)
m_ui->cbxAudioStreams->addItem(audioChannel);
int idx = m_ui->cbxAudioStreams->findText(currentText);
if (idx >= 0)
m_ui->cbxAudioStreams->setCurrentIndex(idx);
if (m_ui->cbAudio->isChecked() && m_ui->cbxAudioStreams->count() > 1)
m_ui->cbxAudioStreams->setEnabled(true);
else
m_ui->cbxAudioStreams->setEnabled(false);
}
void SetMarkers::onVideoClicked()
{
Q_ASSERT(m_avaState);
const QStringList currentStreams = m_avaState->currentLiveVideoStreams();
QVariant currentStream;
if (m_ui->cbxVideoStreams->currentIndex() >= 0)
currentStream = m_ui->cbxVideoStreams->currentData();
m_ui->cbxVideoStreams->clear();
m_ui->cbxVideoStreams->addItem(tr("All")); // no UserData
for (const QString &streamName : currentStreams)
{
if (!containsStream(m_ui->cbxVideoStreams, streamName))
{
QString displayName = m_streamNameMapping->displayName(streamName);
m_ui->cbxVideoStreams->addItem(displayName, streamName);
}
}
selectStream(m_ui->cbxVideoStreams, currentStream);
if (m_ui->cbVideo->isChecked() && m_ui->cbxVideoStreams->count() > 1)
m_ui->cbxVideoStreams->setEnabled(true);
else
m_ui->cbxVideoStreams->setEnabled(false);
}
QByteArray SetMarkers::getFilterParams() const // TODO: is dup - use from MrkCommon instead
{
const int operatorId = LtsSessionData::LtsSessionData::getInstance()->getOperatorId();
QJsonObject obj;
{ // AesFilter
std::shared_ptr<FilterManagement::AesDisplayFilter> aesDisplayFilter =
m_fltAesIfc->aesFilterForOperator(operatorId, m_session->workspaceId());
obj[QStringLiteral("AesFilterJson")] = aesDisplayFilter->filterToJson();
}
{ // SymbolAppearance
std::shared_ptr<FilterManagement::SymbolAppearanceSettings> symbolAppearanceSettings =
m_fltParticipantIfc->symbolAppearanceForOperator(operatorId, m_session->workspaceId());
obj[QStringLiteral("SymbolAppearanceJson")] = symbolAppearanceSettings->settingsToJson();
}
// BuildingComponentSettings
// Nachtrag zu GUEZE-1769: since fltBuildingComponentIfc is optional:
if (m_fltBuildingComponentIfc)
{
std::shared_ptr<FilterManagement::BuildingComponentSettings> buildingComponentSettings =
m_fltBuildingComponentIfc->buildingComponentSettingsForOperator(operatorId, m_session->workspaceId());
obj[QStringLiteral("BuildingComponentSettingsJson")] = buildingComponentSettings->bldCmpSettingsToJson();
}
QJsonDocument jDoc(obj);
return jDoc.toJson(QJsonDocument::Compact);
}
//------------------------------------------------------------------------------------------------------------------------
void SetMarkers::sendMarkerRequest() noexcept(false)
{
Marker req;
auto &descriptions = req.descriptions();
MarkerManagement::MarkerDescription ma;
const QLatin1Char selectionIndicator = QLatin1Char('*');
//Situation
if (m_ui->cbSit->isChecked())
{
ma.markerType() = MarkerManagement::MarkerType::Situation;
descriptions.push_back(ma);
// save mapSettings and filter
auto spSitMapGuiIfc = m_sitMapGuiIfc.lock();
if (!spSitMapGuiIfc)
return;
const QByteArray mapSettings = spSitMapGuiIfc->operatorMapSettingsJson();
req.mapSettings(mapSettings.constData());
req.filter(getFilterParams().constData());
}
//Audio
if (m_ui->cbAudio->isChecked())
{
ma.markerType() = MarkerManagement::MarkerType::Audio;
QStringList slStreamlist;
slStreamlist.reserve(m_ui->cbxAudioStreams->count());
const bool allAudioStreamsSelected = m_ui->cbxAudioStreams->currentIndex() == 0;
for (int i = 1; i < m_ui->cbxAudioStreams->count(); i++) //start with 1 as 0 is "All"
{
slStreamlist += m_ui->cbxAudioStreams->itemText(i);
if (allAudioStreamsSelected || m_ui->cbxAudioStreams->currentIndex() == i) // mark current Stream
slStreamlist.last().append(selectionIndicator);
}
ma.content() = slStreamlist.join(QStringLiteral(", ")).toStdString();
descriptions.push_back(ma);
}
//Video
if (m_ui->cbVideo->isChecked())
{
ma.markerType() = MarkerManagement::MarkerType::Video;
QStringList slStreamlist;
slStreamlist.reserve(m_ui->cbxVideoStreams->count());
const bool allVideoStreamsSelected = m_ui->cbxVideoStreams->currentIndex() == 0;
for (int i = 1; i < m_ui->cbxVideoStreams->count(); i++) //start with 1 as 0 is "All"
{
slStreamlist += m_ui->cbxVideoStreams->itemData(i).toString(); // UserData is the internal stream name
if (allVideoStreamsSelected || m_ui->cbxVideoStreams->currentIndex() == i) // mark current stream
slStreamlist.last().append(selectionIndicator);
}
ma.content() = slStreamlist.join(QStringLiteral(", ")).toStdString();
descriptions.push_back(ma);
}
req.note(m_ui->teNote->toPlainText().toStdString());
req.operatorId(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
req.timeStamp(m_ui->dteMarkerTime->msecsSinceEpoch());
req.timeStampOffset(m_ui->cbxOffset->currentText().toInt() * 1000);
req.fileContentId(m_fileId);
DEBUG_LOG(m_logger) << "Start Marker request with file content Id = " << m_fileId;
auto id = m_ftc->markerModifyRequest(req); // throws!
m_editData.id(id);
DEBUG_LOG(m_logger) << "Saved marker with id = " << m_requestHelper->getRepliedId();
}
void SetMarkers::saveMarkerInLibrary() noexcept(false)
{
QString dtg = DTG::toStringMSec(m_ui->dteMarkerTime->msecsSinceEpoch());
dtg.replace(QLatin1Char(' '), QLatin1Char('_'));
const QString title = QStringLiteral("Marker_%1_%2_%3")
.arg(dtg)
.arg(LtsSessionData::LtsSessionData::getInstance()->getOperatorId())
.arg(m_ui->teNote->toPlainText().left(20)); // only 20 chars from note field
DEBUG_LOG(m_logger) << "saveMarkerInLibrary: " << title;
auto spSitMapGuiIfc = m_sitMapGuiIfc.lock();
if (!spSitMapGuiIfc->isMapReady())
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Cannot create a marker as the map is not ready yet."));
ERROR_LOG(m_logger) << LOGFUNCTION << " sitMapGuiInterface not ready";
return;
}
// toImage
std::unique_ptr<FinishedSignal> fig(new FinishedSignal);
QImage image;
auto onImage = [this, &fig, &image](const QImage &_image)
{
image = _image;
DEBUG_LOG(m_logger) << "onImage callback: image size (w, h) = (" << image.width() << ", " << image.height() << ")";
QMetaObject::invokeMethod(fig.get(), &FinishedSignal::finished, Qt::QueuedConnection);
};
if (!spSitMapGuiIfc->toImage(this, onImage)) // => async
{
ERROR_LOG(m_logger) << "Failed to save marker image from map";
return;
}
LtsUtils::awaitTimeout(10000, fig.get(), &FinishedSignal::finished, true); // blocks & throws!
const QImage img = image.scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation);
int folderId = 1;
// folderId = 1 -> Global documents by default for admin session
if (m_session->exerciseId() > 0)
{
int exFolderId = m_flmDtc->getExerciseFolderId(m_session->exerciseId());
if (exFolderId > 0)
folderId = m_flmDtc->findFolder(exFolderId, QStringLiteral("Markers"));
}
FileManagement::FileContentModifyRequest request;
request.id(m_fileId);
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(img, &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());
try
{
m_fileId = m_flmFtc->fileContentModifyRequest(request);
}
catch(const std::exception &ex)
{
ERROR_LOG(m_logger) << "failed to save image for marker: " << ex.what();
return;
}
DEBUG_LOG(m_logger) << "Saved file in library with id = " << m_fileId;
sendMarkerRequest(); // blocks & throws!
if (m_editData.fileContentId() != m_fileId)
{
DEBUG_LOG(m_logger) << "One more request needed!";
m_editData.fileContentId(m_fileId);
}
}
} // namespace MarkerManagement
@@ -0,0 +1,106 @@
/**
* @RDE_HEADER@
* HMI Plugin for MarkerManangement - Marker Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <LtsWidgets/lts_dialog.h>
#include <LtsSession/lts_session.h>
#include <MarkerManagement/mrk_dtc.h>
#include <MarkerManagement/mrk_ftc.h>
#include <MarkerManagement/logger.h>
#include <AudioVideoManagement/avm_data_plugin_interface.h>
#include <AudioVideoManagement/ava_types.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <FilterManagement/flt_participant_plugin_interface.h>
#include <FilterManagement/flt_aes_plugin_interface.h>
#include <FilterManagement/flt_building_cmpnt_plugin_interface.h>
#include <SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <FileManagement/flm_dtc.h>
#include <FileManagement/flm_ftc.h>
namespace Ui
{
class SetMarkers;
}
namespace AudioVideoManagement
{
class AvaState;
class StreamNameMapping;
}
namespace MarkerManagement
{
class FinishedSignal : public QObject
{
Q_OBJECT
public:
explicit FinishedSignal();
signals:
void finished();
};
class SetMarkers : public LtsWidgets::LtsDialog
, protected MarkerManagement::Interface::Ftc::MarkerModifyReplyHandler
, protected FileManagement::Interface::Ftc::FileContentModifyReplyHandler
{
Q_OBJECT
public:
explicit SetMarkers(LtsSession::LtsSession *session, QWidget *parent = nullptr);
~SetMarkers();
bool init(const std::shared_ptr<MarkerManagement::Interface::Dtc> &mrk_dtc,
const std::shared_ptr<MarkerManagement::Interface::Ftc> &mrk_ftc,
const std::shared_ptr<FileManagement::Interface::Dtc> &flm_dtc,
const std::shared_ptr<FileManagement::Interface::Ftc> &flm_ftc,
const std::weak_ptr<SituationMap::ForeignGuiInterface> &sitMapIfc,
const std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> &fltParticipantIfc,
const std::shared_ptr<FilterManagement::ForeignAesGuiInterface> &fltAesIfc,
const std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> &fltBuildingComponentIfc,
const std::shared_ptr<AudioVideoManagement::ForeignDataInterface> &avmInterface,
const MarkerManagement::Marker &data = Marker());
void onMarkerModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onFileContentModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
private slots:
void onAudioClicked();
void onVideoClicked();
private:
void retranslate() override;
bool apply() override final;
QByteArray getFilterParams() const;
void saveMarkerInLibrary() noexcept(false);
void sendMarkerRequest() noexcept(false);
std::shared_ptr<MarkerManagement::Interface::Dtc> m_dtc;
std::shared_ptr<MarkerManagement::Interface::Ftc> m_ftc;
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
std::weak_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc;
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> m_fltParticipantIfc;
std::shared_ptr<FilterManagement::ForeignAesGuiInterface> m_fltAesIfc;
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> m_fltBuildingComponentIfc;
std::shared_ptr<AudioVideoManagement::ForeignDataInterface> m_avmDataIfc;
MarkerManagement::Marker m_editData;
int m_fileId;
AudioVideoManagement::AvaState *m_avaState{nullptr};
AudioVideoManagement::StreamNameMapping *m_streamNameMapping{nullptr};
LtsSession::LtsSession *m_session;
LtsUtils::RequestHelper *m_requestHelper;
Ui::SetMarkers *m_ui;
LOGGER_T m_logger;
};
}//MarkerManagement
@@ -0,0 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SetMarkers</class>
<widget class="QWidget" name="SetMarkers">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>548</width>
<height>372</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Set Markers</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="lblTime">
<property name="text">
<string>Time:</string>
</property>
</widget>
</item>
<item>
<widget class="LtsWidgets::LtsDateTimeEdit" name="dteMarkerTime">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Offset [s]:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbxOffset">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string notr="true">10</string>
</property>
<item>
<property name="text">
<string notr="true">10</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">30</string>
</property>
</item>
<item>
<property name="text">
<string notr="true">50</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="lblMarkerTypeText">
<property name="text">
<string>Marker Type:</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbSit">
<property name="text">
<string>Situation</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbAudio">
<property name="text">
<string>Audio</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbVideo">
<property name="text">
<string>Video</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="lblAudioStreams">
<property name="text">
<string>Audio Streams:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbxAudioStreams">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="lblVideoStreams">
<property name="text">
<string>Video Streams:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbxVideoStreams">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="lblNote">
<property name="text">
<string>Note:</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="teNote">
<property name="toolTip">
<string>Note</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsWidgets::LtsDateTimeEdit</class>
<extends>QWidget</extends>
<header>LtsWidgets/lts_date_time_edit.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,142 @@
/**
* @RDE_HEADER@
* MarkerManagement - Marker Overview Dialog
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <FileManagement/flm_explorer_gui_plugin_interface.h>
#include <FilterManagement/Data/flt_data_plugin.h>
#include <FilterManagement/flt_participant_plugin_interface.h>
#include <FilterManagement/flt_aes_plugin_interface.h>
#include <FilterManagement/flt_building_cmpnt_plugin_interface.h>
#include <MarkerManagement/logger.h>
#include <MarkerManagement/mrk_dtc.h>
#include <MarkerManagement/mrk_ftc.h>
#include <OperatorManagement/opm_dtc.h>
#include <FileManagement/flm_dtc.h>
#include <FileManagement/flm_ftc.h>
#include <SituationMapPlugin/situation_map_gui_plugin_interface.h>
#include <SituationReplayManagement/srm_ftc.h>
#include <SituationReplay/srp_data_plugin_interface.h>
#include <SituationReplay/srp_ftc.h>
#include <LtsSession/lts_session.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <LtsWidgets/lts_dialog.h>
#include <QPointer>
namespace Ui
{
class SnapshotDialog;
}
namespace MarkerManagement
{
class SnapshotDialogModel;
// --------------------------------------------------------
// SnapshotDialog
// --------------------------------------------------------
class SnapshotDialog : public LtsWidgets::LtsDialog
, protected MarkerManagement::Interface::Ftc::SnapshotRemoveReplyHandler
, protected SituationReplayManagement::Interface::Ftc::ReplayPartitionRemoveReplyHandler
, protected SituationReplay::Interface::Ftc::ChangeReplayStateReplyHandler
, protected MarkerManagement::Interface::Ftc::SnapshotModifyReplyHandler
, protected FileManagement::Interface::Ftc::FileContentRemoveReplyHandler
, protected FileManagement::Interface::Ftc::FileContentModifyReplyHandler
, public FilterManagement::Interface::Ftc::AesFilterUpdateReplyHandler
, public FilterManagement::Interface::Ftc::SymbolAppearanceUpdateReplyHandler
{
Q_OBJECT
public:
explicit SnapshotDialog(const QString &menuGroup, LtsSession::LtsSession *session, QWidget *parent = nullptr);
~SnapshotDialog();
bool 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);
void showSnapshot();
protected:
void onSnapshotRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onReplayPartitionRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject);}
void onChangeReplayStateReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject);}
void onSnapshotModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onFileContentRemoveReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void onFileContentModifyReply(const Core::FunctionReplyObject &replyObject) override final { m_requestHelper->requestReply(replyObject); }
void slotReplaySessionForPlanEditorStarted();
// AesFilterUpdateReplyHandler interface
public:
void onAesFilterUpdateReply(const Core::FunctionReplyObject &reply) override final { m_requestHelper->requestReply(reply); }
// SymbolAppearanceUpdateReplyHandler interface
public:
void onSymbolAppearanceUpdateReply(const Core::FunctionReplyObject &reply) override final { m_requestHelper->requestReply(reply); }
protected:
void aboutToClose() override;
private slots:
void enaDisa();
void onEditMetaData();
void onRemoveSnapshots();
void onShow();
void onSaveSettings();
// void onSelectionChanged();
void onEditPlan();
void onPlaneditorFinished();
void onPrint();
void onRefreshCurrent(const Snapshot &snapshot);
private:
void retranslate() override;
bool applyFilter(const Snapshot &snapshot);
void tableColumnOrganiserSetting() override;
QVector<int> selectedSnapshotIds() const;
bool showSnapshotInternal(const Snapshot &snapshot, bool bApplyFilter);
bool saveSnapshotPlan(const QByteArray &planXMLContent);
void prepareIndex(const QModelIndex &idx);
void saveSnapshotFilter();
void saveSnapshotPreviewInLibrary(const QString &snapshotTitle);
QString m_menuGroup;
SnapshotDialogModel *m_model;
Ui::SnapshotDialog *m_ui;
std::shared_ptr<MarkerManagement::Interface::Dtc> m_mrkDtc;
std::shared_ptr<MarkerManagement::Interface::Ftc> m_mrkFtc;
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
std::shared_ptr<FileManagement::Interface::Ftc> m_flmFtc;
std::shared_ptr<OperatorManagement::Interface::Dtc> m_opmDtc;
std::shared_ptr<SituationReplay::Interface::Ftc> m_srpFtc;
std::weak_ptr<SituationMap::ForeignGuiInterface> m_sitMapGuiIfc; // no hard dependency to avoid crash when app is closed before this dialog is closed
std::shared_ptr<FilterManagement::ForeignFltParticipantGuiInterface> m_fltParticipantIfc;
std::shared_ptr<FilterManagement::ForeignAesGuiInterface> m_fltAesIfc;
std::shared_ptr<FilterManagement::ForeignFltBuildingComponentGuiInterface> m_fltBuildingComponentIfc;
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
LtsSession::LtsSession *m_session;
LtsUtils::RequestHelper *m_requestHelper;
MarkerManagement::Snapshot m_currentSnapshot;
bool m_planEditorHasUpdatedThePlan; // to saveSnapshotPreviewInLibrary if required
QPointer<LtsPluginManager::LtsPluginManager> m_planEditorApp;
int m_fileId; // of PreviewImage
QVector <QImage> m_images;
QVector <QString> m_imageTitles;
QVector <QString> m_descriptions;
LOGGER_T m_logger;
};
}
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SnapshotDialog</class>
<widget class="QWidget" name="SnapshotDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>598</width>
<height>512</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="LtsDataView::LtsDataView" name="widget">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>250</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>LtsDataView::LtsDataView</class>
<extends>QWidget</extends>
<header>LtsDataView/lts_data_view.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,259 @@
/**
* @RDE_HEADER@
* HMI Plugin for MarkerManangement - Marker Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#include "snapshot_dialog_model.h"
#include <FileManagement/flm_explorer_gui_plugin_interface.h>
#include <LtsUtilsCore/dds_vector_to_pixmap.h>
#include <ngltools/ngltools_dtg.h>
#include <QSet>
#include <QJsonDocument>
#include <QJsonObject>
#include <QBuffer>
#include <QTimer>
namespace MarkerManagement
{
//---------------------------------
// SnapshotDialogModel
//---------------------------------
SnapshotDialogModel::SnapshotDialogModel(QObject *parent)
: LtsWidgets::LtsAbstractTableModel<Snapshot>({tr("Name"),
tr("Description"),
tr("Time"),
tr("Operator"),
tr("File Id"),
tr("Image")},
parent)
, m_logger(getLogger("SnapshotDialogModel"))
{}
bool SnapshotDialogModel::initModel(const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<OperatorManagement::Interface::Dtc> &opmDtc,
const std::shared_ptr<FileManagement::Interface::Dtc> &flmDtc,
const std::shared_ptr<FileManagement::ForeignGuiInterface> &flmGui)
{
m_flmDtc = flmDtc;
m_flmGui = flmGui;
auto cbUser = [this](const OperatorManagement::User &user)
{
m_operatorNames[user.id()] = QString::fromStdString(user.name());
};
connect(opmDtc.get(), &OperatorManagement::Interface::Dtc::userChanged, this, cbUser);
opmDtc->users(cbUser);
connect(dtc.get(), &MarkerManagement::Interface::Dtc::snapshotChanged,
this, &SnapshotDialogModel::onDataChanged);
dtc->snapshots([this](const MarkerManagement::Snapshot &s) { insertRow(s); });
connect(this, &SnapshotDialogModel::rowsInserted, this, &SnapshotDialogModel::updateOperatorNames);
connect(this, &SnapshotDialogModel::rowsRemoved, this, &SnapshotDialogModel::updateOperatorNames);
updateOperatorNames();
connect(m_flmDtc.get(), &FileManagement::Interface::Dtc::fileContentChanged,
this, &SnapshotDialogModel::onFileContentChanged, Qt::UniqueConnection);
return true;
}
QVariant SnapshotDialogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (section == ColOperator && orientation == Qt::Horizontal && role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
return m_comboBoxFilterData;
return LtsWidgets::LtsAbstractTableModel<Snapshot>::headerData(section, orientation, role);
}
QVariant SnapshotDialogModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole && role != LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole && role != Qt::ToolTipRole)
return QVariant();
if (!indexIsValid(index))
return QVariant();
const int row = index.row();
const MarkerManagement::Snapshot &snapshot = m_vecData.at(row);
if (role == LtsWidgets::LtsColumnFilterProxyModel::ComboboxFilterRole)
{
if (index.column() == ColOperator)
return snapshot.operatorId();
return QVariant();
}
if (role == Qt::ToolTipRole) // && index.column() == ColNote
{
const int fileContentId = snapshot.fileContentId();
if (fileContentId > 0)
{
auto it = m_previews.find(fileContentId);
if (it == m_previews.end())
{
auto that = const_cast<SnapshotDialogModel *>(this);
QTimer::singleShot(0, that, [that, fileContentId, row]() { that->loadPreview(fileContentId, row); });
return QVariant();
}
return it.value();
}
return QVariant();
}
else if (role == Qt::DisplayRole)
{
switch (index.column())
{
case ColName:
return QString::fromStdString(snapshot.name());
case ColDescription:
return QString::fromStdString(snapshot.description());
case ColTime:
return QDateTime::fromMSecsSinceEpoch(snapshot.timeStamp());
case ColOperator:
return m_operatorNames.value(snapshot.operatorId());
case ColFileId:
return snapshot.fileContentId();
case ColImage:
return m_previews.value(snapshot.fileContentId());
}
}
return QVariant();
}
bool SnapshotDialogModel::onDataChanged(const MarkerManagement::Snapshot &data, DataModification modType)
{
bool bRet = LtsWidgets::LtsAbstractTableModel<Snapshot>::onDataChanged(data, modType);
if (bRet)
emit modelChanged(data);
return bRet;
} // void SnapshotDialogModel::onDataChanged(const MarkerManagement::Snapshot &data, DataModification modType)
void SnapshotDialogModel::onFileContentChanged(const FileManagement::FileContent &fileContent, DataModification modType)
{
// fileContent is loaded on demand.
// so this is just for _update_ purpose:
if (modType == DataModification::eModified)
{
const int fileContentId = fileContent.id();
// remove entry to ensure reload:
if (m_previews.contains(fileContentId))
m_previews.remove(fileContentId);
}
}
void SnapshotDialogModel::updateOperatorNames()
{
QSet<int> operatorIds;
for (const auto &op : qAsConst(m_vecData))
operatorIds.insert(op.operatorId());
LtsWidgets::ComboboxFilterContent cfc;
LtsWidgets::ComboboxFilterData cfd;
cfc.data.reserve(operatorIds.size());
for (int operatorId : qAsConst(operatorIds))
{
cfd.data = operatorId;
cfd.text = m_operatorNames.value(operatorId);
cfc.data.push_back(cfd);
}
cfc.sortItems = true;
m_comboBoxFilterData = cfc.toVariant();
}
void SnapshotDialogModel::loadPreview(int fileContentId, int rowId)
{
if (fileContentId <= 0 || m_previews.contains(fileContentId))
{
requestNextFileContent();
return;
}
// sadly m_flmGui->loadContent() is not async...
if (m_bFlmRequestInProgress)
{
m_requestedIds.push_back({fileContentId, rowId});
return;
}
m_bFlmRequestInProgress = true;
QByteArray byteArray;
if (m_flmGui->loadContent(fileContentId, byteArray, true) && byteArray.size() > 0)
{
DEBUG_LOG(m_logger) << "m_previews.insert fileContentId=" << fileContentId
<< " size Preview=" << byteArray.size();
QImage img = LtsUtils::getImage(byteArray);
// huge image, scale down:
img = img.scaled(200, 200, Qt::KeepAspectRatio, Qt::SmoothTransformation); // 200 200 as at marker
{ // Image to ba:
QBuffer buf;
buf.open(QIODevice::WriteOnly);
img.save(&buf, "PNG");
buf.close();
byteArray = buf.buffer();
}
QString str = QStringLiteral("<html><center><img src='data:image/png;base64,%1'></center></html>").arg(QString::fromLatin1(byteArray.toBase64()));
m_previews.insert(fileContentId, str);
emit dataChanged(index(rowId, 0), index(rowId, ColImage), {Qt::ToolTipRole});
}
else
m_previews.insert(fileContentId, QString());
m_bFlmRequestInProgress = false;
requestNextFileContent();
}
void SnapshotDialogModel::requestNextFileContent()
{
if (!m_bFlmRequestInProgress && !m_requestedIds.isEmpty())
{
auto next = m_requestedIds.takeLast();
QTimer::singleShot(0, this, [this, next] { loadPreview(next.first, next.second);});
}
}
QString SnapshotDialogModel::getOperatorName(int id)
{
return m_operatorNames[id];
}
//
// SnapshotDialogFilterProxyModel
//
void SnapshotDialogFilterProxyModel::setSourceModel(QAbstractItemModel *model)
{
m_model = qobject_cast<SnapshotDialogModel*>(model);
LtsWidgets::LtsColumnFilterProxyModel::setSourceModel(model);
}
bool SnapshotDialogFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_model || source_left.column() != source_right.column())
return LtsWidgets::LtsColumnFilterProxyModel::lessThan(source_left, source_right);
const Snapshot &left = m_model->m_vecData.at(source_left.row());
const Snapshot &right = m_model->m_vecData.at(source_right.row());
switch (source_left.column())
{
case SnapshotDialogModel::ColTime:
return left.timeStamp() < right.timeStamp();
default:
break;
}
return LtsWidgets::LtsColumnFilterProxyModel::lessThan(source_left, source_right);
}
} // namespace MarkerManagement
@@ -0,0 +1,98 @@
/**
* @RDE_HEADER@
* HMI Plugin for MarkerManangement - Marker Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <OperatorManagement/opm_dtc.h>
#include <FileManagement/flm_dtc.h>
#include <MarkerManagement/mrk_dtc.h>
#include <MarkerManagement/logger.h>
#include <LtsWidgets/lts_abstract_table_model.h>
#include <LtsWidgets/lts_column_filter_proxy_model.h>
namespace FileManagement
{
class ForeignGuiInterface;
}
namespace MarkerManagement
{
// --------------------------------------------------------
// SnapshotDialogModel
// --------------------------------------------------------
class SnapshotDialogModel final : public LtsWidgets::LtsAbstractTableModel<Snapshot>
{
Q_OBJECT
public:
enum Columns
{
ColName,
ColDescription,
ColTime,
ColOperator,
ColFileId,
ColImage
};
explicit SnapshotDialogModel(QObject *parent = nullptr);
~SnapshotDialogModel() = default;
bool initModel(const std::shared_ptr<MarkerManagement::Interface::Dtc> &dtc,
const std::shared_ptr<OperatorManagement::Interface::Dtc> &opmDtc,
const std::shared_ptr<FileManagement::Interface::Dtc> &flmDtc,
const std::shared_ptr<FileManagement::ForeignGuiInterface> &flmGui
);
QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override final;
bool onDataChanged(const MarkerManagement::Snapshot &data, DataModification modType) override final;
//int getFileContentId(int snapshotId);
QString getOperatorName(int id);
signals:
void modelChanged(const Snapshot &snapshot);
private Q_SLOTS:
void onFileContentChanged(const FileManagement::FileContent &fileContent, DataModification modType);
private:
void updateOperatorNames();
void loadPreview(int fileContentId, int rowId);
void requestNextFileContent();
private:
QHash<int, QString> m_operatorNames;
QHash<int, QString> m_previews; // QString as base64 encoded image data
QVector<QPair<int, int>> m_requestedIds; // fileId, rowId
bool m_bFlmRequestInProgress{false};
std::shared_ptr<FileManagement::Interface::Dtc> m_flmDtc;
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
QVariant m_comboBoxFilterData;
LOGGER_T m_logger;
friend class SnapshotDialogFilterProxyModel;
};
class SnapshotDialogFilterProxyModel final : public LtsWidgets::LtsColumnFilterProxyModel
{
Q_OBJECT
public:
using LtsWidgets::LtsColumnFilterProxyModel::LtsColumnFilterProxyModel;
void setSourceModel(QAbstractItemModel *model) override;
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
private:
std::shared_ptr<FileManagement::ForeignGuiInterface> m_flmGui;
SnapshotDialogModel *m_model{nullptr};
};
}
+47
View File
@@ -0,0 +1,47 @@
/**
* @RDE_HEADER@
* Data Plugin Interface for MarkerManagement (Interface for access from other Plugins)
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <PluginInterfaces/data_plugin_interface.h>
#include <MarkerManagement/mrk_dtc.h>
#include <MarkerManagement/mrk_ftc.h>
namespace MarkerManagement
{
class ForeignDataInterface;
/**
* @brief The DataInterface class provides the Topics Clients only for the GUI Plugins
*/
class DataInterface : public DataPluginBase::Interface
{
public:
using DataPluginBase::Interface::Interface;
virtual std::shared_ptr<MarkerManagement::Interface::Dtc> getDtc() = 0;
virtual std::shared_ptr<MarkerManagement::Interface::Ftc> getFtc() = 0;
virtual std::shared_ptr<ForeignDataInterface> getForeignDataInterface() = 0;
};
/**
* @brief The ForeignInterface class provides methods and signals for foreign plugins, that need
* access to the data of this DataPlugin
*/
class ForeignDataInterface
{
public:
ForeignDataInterface() = default;
virtual ~ForeignDataInterface() = default;
virtual std::shared_ptr<MarkerManagement::Interface::Dtc> getDtc() = 0;
virtual bool setMarker(const Marker &marker, MarkerManagement::Interface::Ftc::MarkerModifyReplyHandler *handler) = 0;
};
} // namespace MarkerManagement
+56
View File
@@ -0,0 +1,56 @@
/**
* @RDE_HEADER@
* HMI Plugin for Exercisemanagemt (Interface for access from other Plugins)
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2016-02-29
*/
#pragma once
#include <LtsWidgets/lts_abstract_table_model.h>
#include <PluginInterfaces/topic_replay_interface.h>
#include <TopicEditorBase/topic_editor_interface.h>
namespace NGL
{
class INGLLogger;
}
namespace MarkerManagement
{
class Marker;
class Snapshot;
}
class QAbstractTableModel;
namespace SituationMap
{
class ForeignGuiInterface;
}
namespace MarkerManagement
{
class MarkerManagementDialogModel;
class SnapshotDialogModel;
class ForeignGuiInterface : public TopicReplay::Factory, public TopicEditorBase::Interface
{
public:
ForeignGuiInterface() = default;
virtual ~ForeignGuiInterface() = default;
static QString pluginName() { return QStringLiteral("MrkEditGuiPlugin"); }
virtual MarkerManagementDialogModel *createMarkerModel() = 0;
virtual SnapshotDialogModel *createSnapshotModel() = 0;
virtual void showMarker(int markerId) = 0;
virtual void setScriptsMrkIfc(MarkerManagement::ForeignGuiInterface* sitMapMrkIfc) = 0;
virtual void resetReplay() = 0;
virtual bool snapshotAdjustSitMap(const Snapshot &snapshot, bool bApplyFilter,
QByteArray &originalMapSettings,
SituationMap::ForeignGuiInterface *sitMapGuiIfc,
NGL::INGLLogger &logger) = 0;
};
} // namespace MarkerManagement